C++ OpenGL: Punkt so lange bewegen, bis eine andere Taste gedrückt wird

Schlangenzahn

Newbie
Registriert
Nov. 2011
Beiträge
3
Hi,

ich habe vor Kurzem angefangen, mich mit OpenGL zu beschäftigen und möchte nun mein erstes kleines "Spiel" schreiben. In diesem soll man u.a. einen Punkt über ein Spielfeld bewegen (alles in 2D). Steuerung mit WASD.

Dabei soll sich nach dem Drücken einer Bewegungstaste mein Punkt so lange in eine Richtung bewegen, bis eine andere Bewegungstaste gedrückt wird oder der Punkt an den Spielfeldrand stößt.

Wenn ich in der Keyboard-Methode angebe, dass sich mein Punkt nach dem Drücken einer Taste um 1px in eine bestimmte Richtung bewegen soll, muss ich allerdings die entsprechende Taste gedrückt halten, um dafür zu sorgen, dass sich mein Punkt bewegt. Ich möchte aber, dass sich mein Punkt weiterbewegt, wenn man die Taste loslässt.
Habe versucht, dieses Problem mit einer while-Schleife zu lösen, damit sich der Punkt so lange bewegt, bis er an den Spielfeldrand stößt. Problem ist nur, dass sich der Punkt dann wirklich so lange bewegt, bis die while-Schleife durchlaufen ist. Auch wenn ich währenddessen eine andere Bewegungstaste drücke, läuft mein Punkt erstmal in die ursprüngliche Richtung weiter, bis der Rand des Spielfeldes erreicht ist.

Gibt es irgendeine gute Strategie, mit der ich es schaffe, dass sich mein Punkt wirklich nur so lange in eine Richtung bewegt, bis ich eine andere Bewegungstaste drücke? Habe bis jetzt noch kein Tutorial gefunden, das mir an dieser Stelle weitergeholfen hat. Bin für jeden Tipp dankbar :)
 
Du brauchst in der while Schleife dann zwei Bedingungen zum Abbruch der Bewegung, den Rand und die neue Taste.
Ähnlich wie (freitext) While punkt nicht rand und keine neue Taste (so in der Art, sehr frei Ausgedrückt).
 
so in der art wie das handy spiel snakae?... also mit der schlage?

Ja genau, sowas in der Größenordnung, zumindest was die Steuerung angeht.

Ähnlich wie (freitext) While punkt nicht rand und keine neue Taste (so in der Art, sehr frei Ausgedrückt).
Okay, sowas hab ich mir auch schon gedacht. Mein Problem ist allerdings, dass das anscheinend keine Auswirkung hat. Also meine Bedingung lautet im Freitext ca

case 'w':
while punkt nicht rand und taste == 'w'...

Ich nehme mal an, das Ganze hat keine Auswirkungen, da das Ganze sich ja im case 'w' abspielt und somit für den Kompiler die Taste noch 'w' ist.

Gibt es vielleicht irgendeinen Befehl, der überprüft ob eine neue Taste gedrückt wurde, oder eine Möglichkeit, die while-Bedingung so umzuschreiben, dass sie tatsächlich unterbricht, wenn eine neue Taste gedrückt wird?
 
Zuletzt bearbeitet:
Hab mich noch nicht mit OpenGL auseinandergesetzt, aber vllt sowas:

richtung kann 0-3 annehmen (4 Himmelsrichtungen)

Code:
boolean move = false;
int richtung = 0;

void bewegePunkt(int himmelsrichtung){
  ... //Deine Bewegungsfunktion
}

void onKeyDown(button){
  move=true;
  switch (button){
    'w': richtung = 0; break;
    'a': richtung = 1; break;
    's': richtung = 2; break;
    'd': richtung = 3; break;
  }
}

int main(){
  while (true){
    if (move)  {
      bewegePunkt(richtung);
    }
    interval() //Unterbrechungsfunktion, falls es zu schnell geht
  }
}

Warum ist das Codefenster so groß? ^^
 
Zuletzt bearbeitet:
Wie genau funktioniert dein Progamm? Normalerweise verwendest du zum Rendern eine Schleife im Stil von
Code:
while (!exit) {
  handle_keyboard();
  render();
}

Sinnvollerweise speicherst du dann deinen Punkt irgendwo als globale Variable (also Koordinaten und Bewegungsrichtung). Wenn der User dann eine Taste drückt änderst du die Bewegungsrichtung.

Innerhalb vom Main Loop brauchst du dann eine Timerfunktion die berechnet wie viel Zeit seit dem letzten Rendering vergangen ist. Die Bewegung des Punkts beziehst du dann auf diese Zeit. Sagen wir z.B. 10 Pixel pro Sekunde. Dann berechnest du quasi für jede Runde des Main Loop anhand der vergangenen Zeit wieviele Pixel sich der Punkt in die festgelegte Richtung bewegt hat. Dafür bitte als Datentyp float benutzen, weils sonst nicht klappt. Beispiel als Pseudocode:

Code:
float x = 0.0f, y = 0.0f;
float speedx = 0.0f, speedy = 0.0f;

void handle_keyboard() {
 if (w) {
  speedx = 0.0f;
  speedy = -10.0f;
 }
 else if (a) {
  speedx = -10.0f;
  speedy = 0.0f;
 }
 else if (s) {
  speedx = 0.0f;
  speedy = 10.0f;
 }
 else if (d) {
  speedx = 10.0f;
  speedy = 0.0f;
 }
}

void main() {
 float last = now(); // buchteile von sekunden
 while (!exit) {
  float current = now();
  float elapsed = (current - last);	// in bruchteilen von sekunden
  
  handle_keyboard();
  x += speedx * elapsed;
  y += speedy * elapsed;
  // todo: testen ob außerhalb vom bildschirmbereich ..
  
  render();
  last = current;
 }
}
 
Hi,
danke für euere ganzen Tipps, habs jetzt zum Laufen bekommen, in dem ich beim Drücken von W/A/S/D nur eine Himmelsrichtung zuweise, und dann in einer neuen Methode, die für die Bewegung zuständig ist eine Fallunterscheidung mache, je nachdem, auf welchen Wert die Himmelsrichtung gesetzt wurde (also ähnlich zum Beispiel von Augen1337).
 
Zurück
Oben