Verzögerung die auf Tastendrücke reagiert



  • Hallöchen 🙂

    ich programmier grad Snake, um mich ein bisschen mit Canvas vertraut zu machen... Nun habe ich folgenden Code in einer Schleife:

    switch(dir){
                            case 1: y = up(x, y); break;
                            case 2: x = right(x, y); break;
                            case 3: y = down(x, y); break;
                            case 4: x = left(x, y); break;
                            default: ShowMessage("Irgendwas stimmt hier nicht.");
                    }
                    Sleep(30);
    

    Die Schlange bewegt sich auch so weit, allerdings "schläft" das Programm währenddessen, d.h. es reagiert nicht auf Buttonklicks oder Tastatureingaben (was meiner Meinung nach am Sleep liegt). Wie bekomme ich es nun hin, dass er Tastendrücke mitbekommt (also Pfeiltasten, bzw. wasd)? Muss ich da irgendwie Interrupts einbinden (so kenne ich es bisher nur von meinem MicroController in C)?

    Ich bitte um einen kleinen Denkanstoß...

    Liebe Grüße,
    Psy



  • Hallo

    Du darfst den Hauptthread eben nicht mit Sleep blockieren. Du must in dem Key-Event die gedrückte Taste in einer Membervariable des Forms zwischenspeichern. Die Auswertung der Taste und die Bewegung der Schlange erfolgt dann mit einem Timer, der nach dem festgelegten Intervall die Spielfläche aktualisiert.

    bis bald
    akari



  • Danke für die schnelle Antwort.

    Brauche ich dann überhaupt noch die Sleep-Funktion?

    Und mein Code muss dann quasi in die FormKeyPress-Methode? Oder in die von der PaintBox?

    Hast du (bzw. jemand anders) eventuell Lust, mir einen kurzen "Code-Rohling" zu stellen, wo der grobe Aufbau erklärt ist? Mein kompletter Code sieht momentan noch so aus:

    //---------------------------------------------------------------------------
    
    #include <vcl.h>
    #include <Windows.h>
    #pragma hdrstop
    
    #include "Unit1.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    int dir = 2;
    
    int up(int x, int y){
            y -= 3;
            Form1->PaintBox1->Canvas->LineTo(x, y);
            return y;
    }
    
    int right(int x, int y){
            x += 3;
            Form1->PaintBox1->Canvas->LineTo(x, y);
            return x;
    }
    
    int down(int x, int y){
            y += 3;
            Form1->PaintBox1->Canvas->LineTo(x, y);
            return y;
    }
    
    int left(int x, int y){
            x -= 3;
            Form1->PaintBox1->Canvas->LineTo(x, y);
            return x;
    }
    
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
            : TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::PaintBox1Paint(TObject *Sender)
    {
            PaintBox1->Canvas->Brush->Color = clSilver;
            PaintBox1->Canvas->Rectangle(0, 0, 689, 537);
    
            PaintBox1->Canvas->Pen->Width = 5;
    
            PaintBox1->Canvas->MoveTo(200, 200);
            PaintBox1->Canvas->LineTo(200, 200);
    
            int x = 200, y = 200;
            for (int i=0; i<50; i++){
                    switch(dir){
                            case 1: y = up(x, y); break;
                            case 2: x = right(x, y); break;
                            case 3: y = down(x, y); break;
                            case 4: x = left(x, y); break;
                            default: ShowMessage("Irgendwas stimmt hier nicht.");
                    }
                    Sleep(30);
            }
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::bt_upClick(TObject *Sender)
    {
            dir = 1;
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::bt_rightClick(TObject *Sender)
    {     
            dir = 2;
    }
    //---------------------------------------------------------------------------
    
    void __fastcall TForm1::bt_downClick(TObject *Sender)
    {
            dir = 3;
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::bt_leftClick(TObject *Sender)
    {
            dir = 4;
    }
    


  • So wie akari schon geschrieben hat:
    verwende einen Timer, indem du dann die Aktualisierung durchführst: paintBox->Invalidate().

    Du darfst in dem Paint-Ereignis wirklich nur zeichnen, d.h. der Sleep muß ganz raus (und stattdessen stellst du das Timer-Intervall auf diesen Wert).

    P.S: Deine up, left, right und down - Funktionen sind auch suboptimal. Du solltest als Member (Methoden) der Form definieren und desweiteren mußt du dir die gesamte 'Snake' als Liste intern speichern und in der Paint-Methode immer wieder komplett zeichnen (Windows arbeitet ereignisbasiert!).



  • Ok danke, ich hab da aber noch ein paar kurze Fragen.

    1. Warum muss ich die komplette Form neu zeichnen?
    2. Muss ich den Timerwert der Prozessorgeschwindigkeit anpassen, oder ist er unabhängig davon?
    3. Wo finde ich eine gute Einleitung in das Thema Timer?
    4. Kann ich für die PaintBox keine KeyPress-Funktion erstellen? (muss ich sie also für die Form schreiben?)

    PS: Ja, ich werde die ganze Schlange dann in ein Array packen...



  • Hallo

    1. Hat doch niemand gesagt. Nur die PaintBox must du natürlich neu zeichnen (lassen)
    2. Der Timerwert wird in Millisekunden angegeben, und ist damit unabhängig von der Prozessorleistung
    3. In der Builder-Hilfe
    4. Ist nicht vorgesehen. Natürlich könntest du selber die entsprechenden WinAPI-Messages abfangen und eigene Events generieren, aber für dich dürfte es leichter sein die Form-Events zu fangen (KeyPreview nicht vergessen)

    bis bald
    akari



  • Ok sorry, ich weiß anscheinend weniger als dich dachte.

    3. Warum funktioniert die Borland Hilfe unter Windows 7 nicht?
    4. Was ist KeyPreview?



  • BCB-Hilfe schrieb:

    Beschreibung

    Hat KeyPreview den Wert true, erhält das Formular Tastaturereignisse vor dem aktiven Steuerelement (das in der Eigenschaft ActiveControl angegeben ist).
    Ist KeyPreview auf false gesetzt, gehen Tastaturereignisse an das aktive Steuerelement.
    Die Einstellung bezieht sich nicht auf Navigationstasten (TAB, Pfeiltasten usw.), da diese keine Tastaturereignisse auslösen.
    Die Standardeinstellung für KeyPreview ist false.





  • ich danke euch beiden 🙂



  • Super Sache... Es läuft. Jetzt muss ich die globalen Variablen nur noch wegbekommen, und dann weiter machen^^



  • Noch mal eine Frage...

    wenn ich jedes Mal die Schlange neu zeichne, flackert logischerweise die Paintbox... wie kann ich das umgehen?


Anmelden zum Antworten