A6 Commercial und A6 Pro beinhalten eine gute Physikengine und dieser Artikel zeigt, wie leicht es ist, sie zu verwenden.
Sehen wir uns zunächst die Main Funktion an:
function
main()
{
level_load (phdemo1_wmb);
camera.x = 0;
camera.y = -600;
camera.z = 40;
camera.pan = 90;
ball_pos.x = -95; // initial value, ranges from -95 to 105
ball_pos.y = 32;
ball_pos.z = 220;
ent_create (arrow_wmb, ball_pos, move_arrow);
}
Wir laden das Level und setzen Kameraposition und Winkel, damit sie auf das Brett schaut:
Ehe ich es vergesse, ich habe eine einfache, orientierte Bitmap für die Punktzahl verwendet.
Wir setzen ball_pos und erstellen einen grünen Pfeil (arrow_wmb). Der Pfeil bewegt sich die ganze Zeit wegen seiner Action:
function
move_arrow()
{
my.passable = on;
while (balls > 0)
{
while (my.x < 105)
{
my.x += 5 * time;
ball_pos.x = my.x;
wait (1);
}
while (my.x > -95)
{
my.x -= 5 * time;
ball_pos.x = my.x;
wait (1);
}
wait (1);
}
}
Der Pfeil ist passable und bewegt sich, solange wir nicht alle 5 Bälle benutzt haben (kommt gleich); er ändert seine x-Koordinate von –95 bis 105 mit zwei einfachen While-Schleifen. Beachten Sie, dass in jedem Frame die ball_pos.x an die arrow_wmb.x angeglichen wird.

Ok, wir haben also einen grünen Pfeil, der sich von links nach rechts und zurück bewegt. Mal sehen was geschieht, wenn wir die Space Taste drücken:
entity* ball_ptr;
on_space = create_ball;
function
create_ball()
{
if ((balls < 1) || (ball_ptr != null)) {return;}
ball_ptr = ent_create(ball_mdl, ball_pos, init_sphere);
balls -= 1;
}
Wir haben einen Pointer namens ball_ptr definiert. Wir werden 5 Bälle erstellen und dieser Pointer wird jedem Ball zum Zeitpunkt des Erstellens zugeordnet. Wenn wir keine Bälle mehr haben oder der Pointer auf den Ball nicht null ist (das heißt, es springt bereits ein Ball durch unser Level), wird die Funktion mit return beendet. Wenn noch mindestens ein Ball über ist, wird einer an der gegebenen ball_pos Position erstellt und die Funktion init_sphere läuft. Diese Funktion ist der einzige Teil der Demo, der auf die Physikengine zurückgreift; keine Sorge, wir gehen sie Zeile für Zeile durch.
function
init_sphere()
{
phent_settype(my, ph_rigid, ph_sphere);
Aktiviere Physikl für diesen Ball; er wird sich wie eine Kugel verhalten,
wenn es um Kollisionen geht.
phent_setmass(my, 1, ph_sphere);
Der Ball ist 1 kg schwer und verhält sich auch in punkto Rotation
wie eine Kugel.
phent_setfriction(my, 30);
Friction (Reibung) = 30 (kann ein Wert zwischen 0 und 100 sein)
phent_setelasticity(my, 30, 0);
Außerdem ist er elastisch (Der Wert ist auch 30 und könnte zwischen
0 und 100 liegen)
temp.x = 0;
temp.y = 0;
temp.z = -380;
ph_SetGravity(temp);
Dann setzen wir Gravitation (temp.z = -380 entspricht der Erdgravitation
g = 9,81 m/s*s)
while (my.z > -150) {wait (1);}
Wir warten bis der Ball am Boden angekommen ist
sleep (3);
Dann geben wir ihm 3 Sekunden, um herumzuspringen
phent_setelasticity(my, 0, 0);
Nun stellen wir das Springen ab
phent_setdamping(my, 0, 100);
Wir erhöhen den Dämpfungsfaktor, damit der Ball nicht so viel
rotiert
sleep (2);
Er rollt noch 2 Sekunden
phent_settype(my, 0, 0);
Nun stoppen wir den Ball. In der A6 Commercial können wir nur ein
Objekt zugleich verwenden.
ball_ptr = null;
Wir befreien den Zeiger, da wir ihn für einen neuen Ball brauchen
}
Dies ist der ganze Code, den der Ball braucht, um zu springen, abzuprallen und schließlich in einen der Körbe zu gelangen. Wenn Sie die A6 Commercial oder A6 Pro noch nicht haben, schauen Sie sich den Film an und sehen, was mit wenigen Zeilen Code erreicht werden kann. Es ist fast unmöglich, solch realistisches Verhalten ohne die Physik Engine zu erzielen.
Schreibtrainer
Es ist kein Geheimnis, dass man mit der Acknex Engine auch allerhand nützliche Anwendungsprogramme erstellen kann; in diesem Monat zeige ich Ihnen, wie sie einen Schreibtrainer programmieren. Die Idee ist simpel: der Spieler sieht einen Buchstaben vom Himmel fallen (bzw. von der Decke) und versucht dann, die entsprechende Taste auf dem Keyboard so schnell wie möglich zu drücken. Ist er nicht schnell genug, dann fallen die Buchstaben zu Boden und er verliert einen Punkt. Es gibt mehrere “Angriffswellen”, in denen die Buchstaben immer schneller und schneller werden.
Wenn das Level gestartet wird, sehen wir das folgende Bild:
Es sind eine Menge Elemente dargestellt, also sehen wir uns gleich den Code an:
text
start_txt
{
font = comic_font;
pos_x = 0;
pos_y = 200;
string = " Get ready, captain!\n Press any key to begin!";
flags = d3d, visible;
}
Der erste Text ist derjenige, der in der Mitte angezeigt wird. Ich verwende \n für den Zeilenumbruch. Mit Hilfe dieses Textes werde ich auch weitere Nachrichten anzeigen können.
text
score_txt
{
font = comic_font;
pos_x = 10;
pos_y = 10;
string = "Total:\nCorrect:\nWave:";
flags = d3d, visible;
}
Score_txt besteht aus den drei Zeilen Text in der oberen linken Ecke.
panel
score_pan
{
pos_x = 0;
pos_y = 0;
digits = 250, 10, 3, comic_font, 1, total_chars;
digits = 250, 50, 3, comic_font, 1, correct_chars;
digits = 250, 90, 3, comic_font, 1, wave;
flags = refresh, d3d, visible;
}
Dieses Panel zeigt die 3 Zahlenwerte an, die oben links in der Ecke erscheinen (Im Bild sind das 0, 0 und 1).
Schauen wir uns die Funktion an, die für die Buchstaben verantwortlich ist:
function
create_letters(number, interval)
{
while (number > 0)
{
letter = 1 + int(random(26));
temp.x = 0;
temp.y = 350;
temp.z = 450;
str_for_asc(temp_str, letter + 64);
str_cat(temp_str, ".wmb");
str_cpy(letter_str, temp_str);
str_trunc(letter_str, (str_len(letter_str) - 1));
ent_create(temp_str, temp, falling_letters);
letter_falls = 1;
while (letter_falls) {wait (1);}
str_cpy(temp_str, "");
number -= 1;
sleep(interval);
}
}
Sie erhält 2 Parameter: die Anzahl der erzeugten Buchstaben und das Intervall (in Sekunden) zwischen zwei aufeinanderfolgenden Buchstaben. Wenn ich die Funktion so aufrufe:
create_letters(4, 2);
dann werden 4 Buchstaben erzeugt, mit jeweils 2 Sekunden Abstand. Schauen wir sie uns genau an:
function
create_letters(number, interval)
{
while (number > 0)
Solange die Anzahl der Buchstaben, die
erstellt werden müssen größer ist als 0
{
letter = 1 + int(random(26));
Wähle zufällig eine Zahl zwischen
1 und 26
temp.x = 0;
temp.y = 350;
temp.z = 450;
Setze die Koordinaten für den Buchstaben vor den Spieler und oberhalb
str_for_asc(temp_str, letter + 64);
Konvertiere die Zahl zu dem ASCII Buchstaben,
der dazugehört (65..90)
str_cat(temp_str, ".wmb");
Füge ein “.wmb” hinzu, um z.B. so
etwas zu erhalten: p.wmb
str_cpy(letter_str, temp_str);
Kopiere den letter.wmb String in letter_str
str_trunc(letter_str, (str_len(letter_str) - 1));
Nun behalte nur das erste Zeichen aus dem String (also den gesuchten Buchstaben)
ent_create(temp_str, temp, falling_letters);
Erstelle den Buchstaben
letter_falls = 1;
Setze diese Variable auf 1 (wird anderswo
benötigt)
while (letter_falls) {wait (1);}
Warte bis die andere Funktion letter_falls
auf 0 setzt.
str_cpy(temp_str, "");
Setze temp_str zurück
number -= 1;
Verringere die Zahl der Buchstaben
sleep(interval);
Warte solange, wie das Intervall angibt und wiederhole alles
}
}
Wird ein Buchstabe erstellt, dann läuft für ihn die Funktion falling_letters():
function
falling_letters()
{
total_chars += 1;
my.enable_block = on;
my.event = destroy_letter;
falling_speed.x = 0;
falling_speed.y = 0;
falling_speed.z = -7;
falling_speed.z *= wave;
falling_speed.z *= time;
Wir erhöhen die Variable total_chars (was unter Total: oben angezeigt wird). Der Buchstabe wird auf Level Blocks reagieren, was sein destroy_letter Event auslösen wird. Falling_speed ist negativ in der Z-Variablen, also fällt der Buchstabe nach unten. Ich habe erzählt, dass das Programm in mehrern “Wellen” arbeitet. Daher benutzen wir eine Variable “wave”, die im ersten Level auf 1 gesetzt ist, im zweiten auf 2 usw. Schließlich wird falling_speed noch mit time multipliziert, um die Geschwinidgkeit unabhängig von der Framerate zu machen:
while ((my != null) && (my.event != null))
{
ent_move (falling_speed, nullvector);
str_for_key(temp_str, key_lastpressed);
if (str_cmpi(letter_str, temp_str) && key_any)
{
correct_chars += 1;
snd_play(key_wav, 30, 0);
letter_fades();
str_cpy(letter_str, "");
while (key_any) {wait (1);}
}
else
{
if (key_any)
{
destroy_letter();
}
}
wait (1);
}
}
Solange der Buchstabe existiert und sein event nicht auf null gesetzt wurde, bewegen wir ihn nach unten und holen uns die zuletzt gedrückte Taste. Dann vergleichen wir den Buchstaben mit der Taste, die der Spieler gedrückt hat. Stimmen diese beiden Strings überein, erhöhen wir correct_chars und lassen ein Geräusch erklingen. Eine kleine Funktion blendet den Buchstaben aus und wir setzen den String letter_str zurück, damit correct_chars nicht mehrmals für einen einzelnen Buchstaben erhöht wird. Dann warten wir, bis die gedrückte Taste losgelassen wurde.
Wenn der falsche Buchstabe erwischt wurde, wird die Funktion destroy_letter aufgerufen:
function
destroy_letter()
{
my.event = null;
ent_remove (me);
letter_falls = 0; // the letter has stopped
snd_play(error_wav, 50, 0);
}
Diese Funktion setzt das event auf null, entfernt den Buchstaben und sagt der Funktion create_letters, dass der aktuelle Buchstabe fort ist, so dass ein neuer erstellt werden kann. Dann wird ein anderes Geräusch abgespielt. Die Funktion, die für das Ausblenden zuständig ist, sieht einfach aus:
function
letter_fades()
{
my.alpha = 100;
my.transparent = on;
while (my.alpha > 5)
{
my.alpha -= 10 * time;
wait (1);
}
ent_remove (me);
letter_falls = 0; // the letter has disappeared, create a new one
}
Der Buchstabe wird transparent gemacht, aber mit einem Alpha Wert von 100 ist er immer noch zu sehen; sein Alpha Wert wird verringert, bis er kleiner ist als 5. Dann wird der Buchstabe entfernt und letter_falls wird zurückgesetzt, so dass ein neuer Buchstabe erscheinen kann.
Die letzte Funktion ist main(), sie sieht dieses Mal recht kompliziert aus, aber der Code ist nicht schwer:
function
main()
{
on_d = null;
randomize();
fps_max = 30;
level_load (tutor_wmb);
sleep (1);
camera.x = 0;
camera.y = -350;
camera.z = 150;
camera.pan = 90;
camera.ambient = 100;
Wir schalten die Debug Taste ab, da wir nicht wollen, dass das Debug Panel erscheint, wenn der Buchstabe “D” fällt. Wir stellen außerdem sicher, dass der Zufallsgenerator initialisiert wird, begrenzen die Frame Rate auf 30 fps und starten das Level. Wir warten eine Sekunde und setzen dann die Position der Kamera und den Winkel. Da ich sehr dunkle Texturen verwendet habe, setzen wir camera.ambient auf 100, damit das Level heller erscheint.
while (key_any == 0) {wait (1);}
start_txt.string = " First wave - prepare!";
sleep (2);
start_txt.visible = off;
create_letters(10, 2);
while(total_chars < 10) {wait (1);}
Erinnern Sie sich an die Texte oben? Diese sind zum Start sichtbar, schauen Sie auf die Flags, wenn Sie mir nicht glauben. Das heißt, dass der Text “Get ready, Captain! ...” zum Spielstart angezeigt wird. Wir warten bis der Spieler eine Taste drückt und ändern den angezeigten String in “First wave – prepare”. Wir warten 2 weitere Sekunden, verbergen den Text und erstellen 10 Buchstaben, alle 2 Sekunden, mit Hilfe unserer geliebten create_letters Funktion. Wir warten bis alle Buchstaben erstellt sind (total_chars == 10).
Von nun an geht es ähnlich weiter, keine Sorge, aber es gibt trotzdem Kommentare:
sleep (2); // wait for 2 more seconds
start_txt.string = " Second wave - prepare!";
start_txt.visible = on;
sleep (3); // for 3 seconds
start_txt.visible = off;
wave = 2;
create_letters (10, 1);
while(total_chars < 20) {wait (1);}
Wir warten 2 Sekunden, ändern den String für den Text und machen ihn sichtbar. Nach weiteren 3 Sekunden verbergen wir den Text, setzen wave auf 2 (um die Fallgeschwindigkeit zu erhöhen) und erstellen 10 weitere Buchstaben, die in Abständen von 1 Sekunde fallen, bis die zweite Welle auch abgeschlossen ist.
sleep (2);
start_txt.string = " Third wave - prepare!";
start_txt.visible = on;
sleep (3);
start_txt.visible = off;
wave = 3;
create_letters (10, 0.5);
while(total_chars < 30) {wait (1);}
sleep (5); // wait for 5 more seconds
start_txt.string = " Impressive result!";
start_txt.visible = on;
sleep (5);
exit;
}
Wieder wird 2 Sekunden gewartet, der String geändert und der Text für 3 Sekunden angezeigt. Wave wird auf 3 gesetzt und 10 weitere Buchstaben mit 0,5 Sekunden Abstand. Ist auch die dritte Welle vorbei, wird “Impressive result!” angezeigt, was nicht ganz der Wahrheit entspricht, da dieser Text auch angezeigt würde, wenn alle Buchstaben falsch waren. Der Text wird 5 Sekunden angezeigt, dann wird die Engine beendet. Genau wie dieser Artikel.