Adventure Kameras

Viele von Ihnen kennen sicher meine „Resident Evil“ Kameras aus AUM4. Erinnern wir uns noch mal daran, wie diese funktionieren: Wir bewegen unseren Player im Level, und die dem Player nächste Kamera wird aktiviert. Dieses System funktioniert in den meisten Games, aber manche von Ihnen hatten Probleme mit mehreren Gebäuden, während andere wiederum die Empfindlichkeit der Kameras in bestimmten Bereichen und für jede Kamera individuell verändern wollten. Der Code in diesem Artikel beschäftig sich mit diesen Problemen und löst sie.

view adv_camera{ }

starter init_cameras()
{
sleep (0.5);
camera.visible = off;
adv_camera.pos_x = 0;
adv_camera.pos_y = 0;
adv_camera.size_x = screen_size.x;
adv_camera.size_y = screen_size.y;
adv_camera.visible = on;
adv_camera.x = 820;
adv_camera.y = -1150;
adv_camera.z = 620;
adv_camera.pan = 120;
adv_camera.tilt = -25;
adv_camera.roll = 0;
}

Ich habe hier einen neuen View mit dem Namen “adv_camera” definiert. Die Starter-Funktion wartet solange, bis das Level geladen ist, schaltet den „Default“ View ab und setzt die Position sowie die Größe für „adv_camera“ und macht sie sichtbar. Die letzte Zeile im Code setzt die Startwerte für die Position und die Winkel für „adv_camera“; Das ist was der Spieler sehen wird, also der Startpunkt unseres Spiels.

// uses cam_number, cam_range
action detect_player
{
my.invisible = on; // hide the model
my.passable = on;
while (player == null) {wait (1);} // wait until the player is loaded
if (my.cam_number == 0) {beep; beep; beep; exit;}
if (my.cam_range == 0) {beep; beep; beep; exit;}
while (1)
{
temp.x = 360; // horizontal scanning angle
temp.y = 180; // vertical scanning angle
temp.z = my.cam_range; // scanning range
scan_entity (my.x, temp);
if (result > 0) // got something?
{
set_camera(my.cam_number); // then set the proper camera position and angles
}
wait (1);
}
}

Plazieren Sie ein paar Models im Level und geben Sie ihnen die “detect_player” Action. Diese Models werden damit zu unsichtbaren Scannern, welche nach dem Player suchen. Mit „cam_range“ kann die Scan-Reichweite festgelegt werden, mit „cam_number“ die Nummer in WED: der erste Scanner wird die Nummer 1 haben, der zweite die Nummer 2 und so weiter. Oh, und sollten Sie einmal vergessen, die Zahl festzulegen, egal ob in cam_number“ oder in „cam_range“, wird Ihnen die Engine eine hübsche Fehlermeldung ausspucken. Doch nun zu den Kameras. Wie funktionieren die? Ganz einfach, denn sie scannen einfach um sich herum, und wenn der Player zum Beispiel in Reichweite des 3. Scanners kommt, rufen wir die Funktion „set_camera(3)“ auf, welche Position und Winkel für die 3rd Person Kamera setzen wird.

function set_camera(number)
{
if (number == 1)
{
adv_camera.x = -40;
adv_camera.y = 340;
adv_camera.z = 1260;
adv_camera.pan = 270;
adv_camera.tilt = -72;
adv_camera.roll = 0;
}
........................
if (number == 5)
{
adv_camera.x = 1900;
adv_camera.y = 1460;
adv_camera.z = 800;
adv_camera.pan = 220;
adv_camera.tilt = -35;
adv_camera.roll = 0;
}
}

Die obige Funktion setzt die passende „adv_camera“ Position und deren Winkel abhängig von der Nummer welche wir als Parameter übergeben haben. Wenn der Player nahe an den Scanner mit der Nummer 1 kommt, wird die Kamera auf x= -40, y= 340, z= 1260, pan= 270, tilt= -72 und roll= 0 gesetzt. Ist das verständlich? Ich bin sicher das einige von Ihnen jetzt wissen wollen, wie ich ausgerechnet auf diese Werte gekommen bin, welche hier in der Funktion „set_camera“ benutzt werden. Das war ganz einfach: Ich habe das Level fertig gemacht, es gebuildet und gestartet als wmb Datei ohne irgendein Script, und bin dann mit der Kamera auf eine passende Position für die erste „adv_camera“ geflogen und habe aus dem Debug-Panel (F11) die entsprechenden Werte abgelesen. Das habe ich mit jeder Kamera-Position im Spiel gemacht.

Die Falle

Dieser Code ist für die User unter Ihnen gemacht, die meinen “intelligent Music” Artikel aus AUM38 gut fanden. Es ist ein Tor, welches sich schließt, sobald der Player über kleine Auslöser im Boden gelaufen ist.

action trap_trigger
{
while (player == null) {wait (1);}
while (vec_dist (player.x, my.x) > 50) {wait (1);} // play with 50
player_close = 1;
}

Die Trigger warten solange bis der Player geladen ist, und dann wiederum solange, bis die Distanz zwischen dem Player und den Triggern kleiner als 50 Quants ist. Das ist ein kritischer Wert, und ist stark von der Größe des Players und der Z-Position des Auslösers abhängig, deswegen sollten Sie damit experimentieren. Wenn der Player nun über einen der Auslöser drüber läuft, wird die Variable „player_close“ auf 1 gesetzt.

action trap_player
{
while (player_close == 0) {wait (1);}
snd_play (gate_wav, 100, 0);
while (my.z > 170)
{
my.z -= 30 * time;
wait (1);
}
}

Die Action über diesem Text wird der Tor-Entity zugewiesen; sie wartet solange bis „player_close“ auf 1 gesetzt wird, spielt dann den „gate_wav“ Sound und verringert ihren Z-Wert bis sie unter 170 Quants kommt. Mit diesem Wert sollten Sie etwas experimentieren. Vergewissern Sie sich das die Auslöser nicht zu nahe am Tor sind, sonst könnte es passieren, das der Player wieder entkommt. Man könnte natürlich auch die Fall-Geschwindigkeit erhöhen, indem 30*time mit 5+time oder 100+time ersetzt wird, je nachdem, wie Sie es benötigen.