workshop15

Top  Zurück  Weiter

Workshop 15: der Joystick

Wenn Sie vorhaben, einen Flugsimulator zu erstellen und erwarten, dass der sich auch verkauft, sollten Sie ihn besser mit einer Joystick-Unterstüzung versehen! Das gute daran ist, dass der Code dazu sehr einfach ist. Ok, es gibt auch eine schlechte Nachricht: wenn Sie diesen Workshop austesten wollen, brauchen Sie einen Joystick. Sollten Sie noch keinen Joystick besitzen, macht das auch nichts, Sie können dieses Projekt später, wenn Sie ihn dann haben, auch noch überprüfen.

Ok, also, wie fangen wir an? Zunächst einmal stecken Sie Ihren Joystick in den entsprechenden Stecker und dann öffnen Sie Windows' Kontroll-Panel:

w15_1

Das ist das Panel von Windows XP und wenn Sie eine andere Version des Betriebssystems haben, sehen Sie ein etwas anderes Bild. Zum Öffnen doppel-klicken Sie auf "Game Controllers":

w15_2

Sie sehen mein guter, altvertrauter Joystick wird als OK gemeldet. Klicken Sie auf Add um Ihren Joystick hinzuzufügen, falls Sie sowas noch nie gemacht haben. Die Installation sollte einfach vonstatten gehen und die meisten Joysticks funktionieren mit den Windows-Treibern ganz gut. Warten Sie bis die Installation beendet ist, klicken Sie dann auf Properties und Test und Sie haben das folgende Fenster vor sich:

w15_3

Wie sich vielleicht gedacht haben, sieht Ihr Bild anders aus, das hängt von Ihrem Joystik-Typus ab. Die "Test"-Seite ist dazu da, den Offset von X- und Y-Achse festlegen und die Knöpfe testen. Justieren Sie die Steuerung des Joysticks so, dass das Fadenkreuz ziemlich in der Mitte des weißen Quadrats sitzt.

Der Joystick ist korrekt eingerichtet und solange Sie Windows nicht reinstallieren, müssen Sie diesen Einstellungsprozess nicht nochmal durchlaufen. Auch hat das Einstellen des Joysticks gar nichts mit der Acknex-Engine zu tun und wenn Sie jemals einen Joystick benutzt haben, haben Sie die ganze Kalibriererei sowieso bereits erledigt!

Ok, kehren wir zu unserem geliebten Lite-C zurück: öffnen Sie den Ordner workshop15, laden und starten Sie dann das Skript script15.c :

w15_4

Es ist dasselbe altbekannte Haus aber diesmal können wir die Kamera mithilfe des Joysticks bewegen! Mit dem ersten Joystick-Knopf erhöhen Sie die Kamera-Höhe (Z) und mit dem zweiten Knopf verringern Sie diese. Um die Kamera in ihre ursprüngliche Position zurückzuversetzen, drücken Sie beide Knöpfe gleichzeitig.

All das hört sich ziemlich kompliziert an, also gehe ich davon aus, dass der Code der Datei script15.c ziemlich einfach ist:

////////////////////////////////////////////////////////////////////
#include 
#include 

////////////////////////////////////////////////////////////////////

function main()
{
	video_mode = 7;
	level_load ("work15.wmb");
	wait (2);
   camera.pan = 0;
	while(1)
	{
		camera.y -= joy_force.x;
		camera.x += joy_force.y;
		if (joy_1) camera.z += 1;
		if (joy_2) camera.z -= 1;
		if (joy_1 && joy_2)
		{
			camera.x = 0;
			camera.y = 0;
			camera.z = 0;
		}
		wait(1);
	} 
}   

Der Code ist tatsächlich einfach! Sehen wir doch mal, was die Main-Funktion macht: sie setzt die Bildschirmauflösung auf 800 x 600 Pixel, lädt den Level, wartet für 2 Frames und setzt dann camera.pan auf 0 Grad. Das ist ein guter Kamerawinkel für dieses Level, denn so schaut die Kamera aufs Haus.

Das war der leichte Teil. Kümmern wir uns jetzt um den Code innerhalb des while (1)-Loops:

while(1)
{
  
camera.y-= joy_force.x;
  
camera.x += joy_force.y;
  
if (joy_1) camera.z += 1;
  
if (joy_2) camera.z -= 1;
  
if (joy_1 && joy_2)
  
{
   
camera.x = 0;
   
camera.y = 0;
   
camera.z = 0;
  
}
   
wait(1);
}

Im vorigen Workshop haben wir mouse_force.x und mouse_force.y kennengelernt. Nun, joy_force.x und joy_force.y machen dasselbe: ihre Werte wechseln in Abhängigkeit von der Geschwindigkeit mit der wir den Joystick bewegen, zwischen -1 und 1. Bewegen wir den Joystick nicht, werden joy_force.x und joy_force.y auf Null gesetzt, bewegen die Kamera also nicht.

Ich dachte, dass es mehr Spaß macht, die Kamera vorwärts zu bewegen (als sie nur zu drehen), also ändern joy_force.x und joy_force.y die X- und Y-Positionen der Kamera. Nein, es ist kein Fehler: joy_force.x ändert die y-Position der Kamera während joy_force.y ihre x-Position verändert. Schauen wir doch mal, weshalb das so ist...

Ist der Pan-Winkel der Kamera auf Null gesetzt, schauen wir in Richtung der x-Achse. Wenn wir den Joystick vor- und rückwärts bewegen, ändern wir aber trotzdem joy_force.y. Daher brauchen wir joy_force.y, um uns nach vorn bzw. hinten zu bewegen, das heißt also unsere x-Position zu verändern. In ähnlicher Weise brauchen wir joy_force.x, um uns seitlich zu bewegen, demnach also unsere y-Position zu verändern. Wenn Sie die Bewegungsrichtungen auf x- und y-Achse des Joysticks umkehren wollen, ersetzen Sie "-=" durch"+=" und "+=" durch "-=" in den beiden obigen Codezeilen.

Erinnern Sie sich, was ich Ihnen gesagt habe, als wir Tastatur und Maus besprochen haben? Jede Tastatur- oder Maustaste hat eine zugehörige Variable und die kann, wenn die entsprechende Taste gedrückt ist, auf "true" (ungleich Null) gesetzt werden. Mithilfe einer einzelnen Codezeile können wir prüfen ob eine bestimmte Taste gedrückt ist:

if (key_t)
{
  
// tu etwas, wenn die Taste "T" gedrückt ist
}

Dieselbe Methode läßt sich auf den Joystick anwenden:

if (joy_1)
{
   // tu etwas, wenn, wenn der erste Joystick-Knopf gedrückt ist.
}

Es wird Sie nicht überraschen, dass die Engine einen oder zwei Joysticks, mit bis zu jeweils 12 Knöpfen, steuern kann. Der oben angegebene Ausriß tut etwas wenn der erste Joystick-Knopf gedrückt wird.

Ok, also die Knöpfe joy_1 und joy_2 des Joysticks kontrollieren die Höhe (Z) der Kamera. Das ist nett, denn der Joystick selbst steuert ja über joy_force.x und joy_force.y x und y der Kamera. Trotzdem bereiten mir die letzten paar Code-Zeilen innerhalb der while-Schleife Kopfzerbrechen:

if (joy_1 && joy_2)
{
  
camera.x = 0;
  
camera.y = 0;
  
camera.z = 0;
}

Das sind die Code-Zeilen, die die Kamera in ihre ursprüngliche Position zurückversetzen (x = 0, y = 0, z = 0) - darüber gibt es keinen Zweifel. Moment mal: das geschieht, wenn wir beide Joystick-Knöpfe gleichzeitig drücken. Also muss (joy_1 && joy_2) soviel bedeuten wie: joy_1 ist wahr UND joy_2 ist wahr - beide Knöpfe werden gleichzeitig gedrückt! Bin ich clever oder was?

Diejenigen von Ihnen, die noch das Ein oder Andere über vec_set in Erinnerung haben, wissen, daß wir genausogut sowas wie das Folgende benutzen könnten, gell?

if (joy_1 && joy_2)
  vec_set (camera.x, vector(0, 0, 0));

Erinnern Sie sich an diese verschachtelten "if"-Anweisungen? Sie sind weiter nichts, als "if"-Anweisungen in anderen "if"-Anweisungen.

if (joy_1)
{
if (joy_2)
{
if (joy_3)
{
if (joy_4)
{
   // tu etwas, wenn die beiden ersten Joystick-Knöpfe gleichzeitig gedrückt sind
}
}
}

So, jetzt schreiben wir diesen häßlichen Code von oben nochmal neu und benutzen dazu den "UND" &&-Operatoren:

if (joy_1 && joy_2 && joy_3 && joy_4)
{
   // tu etwas, wenn die ersten vier Knöpfe des Joysticks gleichzeitig gedrückt werden
}

Ich weiß, ich weiß... Der Code ist sauberer, schöner, hübscher usw. Darum ist der "UND"-Operator ja erfunden worden und Sie sollten ihn auch verwenden wo immer Sie können.

Falls 'UND' Sie beeindruckt hat, habe ich noch mehr gute Nachrichten für Sie: 'UND' hat einen Bruder namens 'ODER'. Dieser 'Oder' " || "-Operator wird dann verwendet, wenn etwas wahr ist 'ODER' etwas anderes wahr ist, 'ODER' ... . Nehmen wir an, Sie wollen die Engine herunterfahren, sobald eine bestimmte var namens gold auf 1000, 2000 oder 3000 gesetzt ist. Sie könnten den Code so schreiben:

function some_function()
{
  if (gold == 1000)
  {
    sys_exit(NULL);
  }
    if (gold == 2000)
  {
    sys_exit(NULL);
  }
    if (gold == 3000)
  {
    sys_exit(NULL);
  }
}

Was soll ich sagen? Der Code würde funktionieren, aber der 'OR'-Operator lässt ihn so einfach aussehen:

function some_function()
{
  
if ((gold == 1000) || (gold == 2000) || (gold == 3000))
  
{
    
sys_exit(NULL);
  
}
}

Wichtiger Hinweis:
Wenn Ihr Joystick nicht angemessen kalibriert ist, kann es passieren, dass die Kamera bei einem Spiel (Ihrem oder dem eines anderen) unkontrolliert herumtrudelt. Stecken Sie den Joystick aus, wenn Sie ihn nicht brauchen oder sorgen Sie dafür, dass er sauber kalibriert ist.

Wichtiger Hinweis:
Wenn Sie (mit "&&" oder "II") verschiedene Aussagen gleichzeitig überprüfen, müssen Sie für jede Aussage eigene Klammern verwenden und brauchen ein weiteres Klammernpaar, um sie alle einzuschließen. Beispiel:

Problem:

Wenn a = 2 und b = 3 fahre die Engine herunter

Lösung:

if ((a == 2) && (b == 3))
{
  
sys_exit(NULL);
}

Wir sind fast am Ende des Workshops, also Kopf hoch! Hier ist Ihre Hausaufgabe: wie würden Sie den Code in script15.c umschreiben, wenn Sie wollten, dass der Player in der Lage ist, ENTWEDER die Höhe der Kamera (ihr z) mithilfe der Joystick-Knöpfe ODER per [A] (nach oben) bzw.[Z] (nach unten) zu verändern?

Lösung: Ersetzen Sie zwei Codezeilen in der Main-Funktion:

if (joy_1) wird ersetzt durch: if (joy_1 || key_a)
if (joy_2) wird ersetzt durch: if ((joy_2 || key_z)

Weiter: Debugging-Werkzeuge