Home » Tutorials » Grafik und Spiele » Bewegungen in 3D-Welten

Bewegungen in 3D-Welten

GetInput und GetMousePos

Und jetzt folgt endlich der komplette Quelltext für die neuen „Bewegungs“-Methoden:

procedure TForm1.GetInput;
const xDiff=4.0; yDiff=2.0; zDiff=6.0;
begin
  // Links-Rechts-Bewegung
  if GetAsyncKeystate(VK_LEFT) < 0 then
  begin
    LookVector.x := ViewVector.x - xDiff * cos(TurnVector.y);
    LookVector.z := ViewVector.z + xDiff * sin(TurnVector.y);
  end;
  if GetAsyncKeystate(VK_RIGHT) < 0 then
  begin
    LookVector.x := ViewVector.x + xDiff * cos(TurnVector.y);
    LookVector.z := ViewVector.z - xDiff * sin(TurnVector.y);
  end;
  // Vor-Zurück-Bewegung
  if GetAsyncKeystate(VK_UP) < 0 then
  begin
    LookVector.x := ViewVector.x - zDiff * sin(TurnVector.y);
    LookVector.z := ViewVector.z - zDiff * cos(TurnVector.y);
  end;
  if GetAsyncKeystate(VK_DOWN) < 0 then
  begin
    LookVector.x := ViewVector.x + zDiff * sin(TurnVector.y);
    LookVector.z := ViewVector.z + zDiff * cos(TurnVector.y);
  end;
  // Rauf-Runter-Bewegung
  if GetAsyncKeystate(VK_PRIOR) < 0 then
    LookVector.y := ViewVector.y + yDiff;
  if GetAsyncKeystate(VK_NEXT)  < 0 then
    LookVector.y := ViewVector.y - yDiff;
  // Ende mit Esc
  if GetAsyncKeystate(VK_ESCAPE) < 0 then isRunning := false;
  // Neue View-Werte nur, wenn keine Kollision
  if not Collision then ViewVector := LookVector;
end;

procedure TForm1.GetMousePos;
const xDiff=0.05; yDiff=0.03;
var xMouse, yMouse: Integer; MousePos: TPoint;
begin
  GetCursorPos(MousePos);
  xMouse := (MousePos.x - Screen.Width  div 2);
  yMouse := (MousePos.y - Screen.Height div 2);
  // Drehen links/rechts
  if xMouse < 0 then TurnVector.y := TurnVector.y + xDiff;
  if xMouse > 0 then TurnVector.y := TurnVector.y - xDiff;
  // Schauen rauf/runter
  if yMouse < 0 then
    if TurnVector.x <  1 then TurnVector.x := TurnVector.x + yDiff;
  if yMouse > 0 then
    if TurnVector.x > -1 then TurnVector.x := TurnVector.x - yDiff;
  SetCursorPos(Screen.Width div 2, Screen.Height div 2);
end;

Im Grunde genommen hätten wir zwar für die Abfrage der Tastatur die Methode FormKeyDown benutzen können, aber eine direkte Abfrage über GetAsyncKeystate ist deutlich schneller und völlig ruckelfrei. Alle verwendeten Tasten und ihre Bedeutung sind in dieser Tabelle zusammengefasst:

VK_LEFT [Pfeil Links] Bewegung nach links
VK_RIGHT [Pfeil Rechts] Bewegung nach rechts
VK_UP [Pfeil Rauf] Bewegung vorwärts
VK_DOWN [Pfeil Runter] Bewegung rückwärts
VK_PRIOR [Bild Rauf] Bewegung nach oben
VK_NEXT [Bild Runter] Bewegung nach unten
VK_ESCAPE [Esc] Ende des Programms

Wie Ihr seht, landet die Kollisionskontrolle in der Methode GetInput, denn dort kann ja bereits ein Tastendruck bewirken, dass wir einem Hindernis zu nahe kommen. Deshalb fängt zuerst LookVector alle neu berechneten Werte ab, die vorher ViewVector direkt erhalten hat.
Dann werden die neuen Werte von LookVector mit den alten von ViewVector getestet. Und erst wenn die Bahn wirklich frei ist (= Kollisionstest ergibt false = not Collision), bekommt ViewVector alle Werte von LookVector.
Und diese neuen Werte bewirken dann, dass es weitergeht. Ergibt der Kollisionstest jedoch true, dann ändern sich die alten ViewVector-Werte eben nicht. Und wir bleiben einfach dort stehen, wo wir gerade in unserer Spielwelt sind. Erst eine Mausdrehung (oder der Rückwärtsgang), die uns vom Hindernis wegbringen, ermöglichen ein weiteres Fortkommen.
Es bedarf für die Bewegungen in unserer Spielwelt wohl einer gewissen Behutsamkeit im kombinierten Umgang mit Tasten und Maus. Auf jeden Fall solltet Ihr auch andere Werte für die verschiedenen Diff-Konstanten ausprobieren.
Eine letzte (kleine) Änderung gegenüber G4DGAME1.PAS betrifft die Form des Mauszeigers in der Methode TForm1.FormActivate:

Cursor := crCross;

Damit wird der Mauscursor zu einem kleinen Fadenkreuz.
Nun sind wir im Vergleich zum ersten Tutorial schon ein gehöriges Stück weiter: Endlich können wir uns frei bewegen und müssen nicht durch Wände gehen. (Man könnte auch die Kollisionskontrolle per Tastendruck ab- oder wieder anschaltbar machen.)
Mehr, auch z.B. über den Umgang mit Treppen und Türen sowie über die (nicht unbedingt freundliche) Begegnung mit anderen Wesen in der Spielwelt erfahrt Ihr in meinem Buch „Game Programming für Kids“ (www.mitp.de). Dort findet Ihr auch auf CD, was zur Spieleprogrammierung nötig ist wie z.B. eine komplette Delphi-Version, das Genesis3D-Paket, Editoren für Akteure, Objekte und Levels u.v.m.