Nachtsicht

Stellen Sie sich vor, Sie laufen in einem dunklen Level umher - aber Sie haben das Nachtsichtgerät! Sehen wir uns an, wie es gemacht wird.

Wir erstellen panels für die normalen Auflösungen:

panel nvision640_pan
{
bmap = nvision640_map;
layer = 20;
pos_x = 0;
pos_y = 0;
flags = overlay, refresh, d3d;
}

panel nvision800_pan
{
bmap = nvision800_map;
layer = 20;
pos_x = 0;
pos_y = 0;
flags = overlay, refresh, d3d;
}

panel nvision1024_pan
{
bmap = nvision1024_map;
layer = 20;
pos_x = 0;
pos_y = 0;
flags = overlay, refresh, d3d;
}

Danach definieren wir eine Sprite Entity:

entity fog_sprite
{
type = <fog+5.pcx>;
layer = 15;
x = 200;
y = 0;
z = 0;
flags = flare, bright;
}

Diese Funktion wird von der main zum Spielstart aufgerufen:
function init_nvision()
{
while (1)
{
if (key_n == 1) // press and hold "N" for night vision
{
if (video_mode == 6) // 640x480
{
nvision640_pan.visible = on;
nvision800_pan.visible = off;
nvision1024_pan.visible = off;
}
if (video_mode == 7) // 800x600
{
nvision640_pan.visible = off;
nvision800_pan.visible = on;
nvision1024_pan.visible = off;
}

if (video_mode == 8) // 1024x768
{
nvision640_pan.visible = off;
nvision800_pan.visible = off;
nvision1024_pan.visible = on;
}
camera.ambient = 100;
fog_sprite.visible = on;
if (random(1) > 0.97) // every few seconds
{
fog_sprite.frame = random(5); // pick a random "fog" frame number
}
}
else
{
nvision640_pan.visible = off;
nvision800_pan.visible = off;
nvision1024_pan.visible = off;
fog_sprite.visible = off;
camera.ambient = 0;
}
wait (1);
}
}

Wenn wir "N" drücken, dann wird das entsprechende Panel sichtbar gemacht (und die anderen beiden unsichtbar), je nach Auflösung. Der Nachtsichteffekt wird durch das Setzen des camera.ambient Wertes auf 100 erreicht.

Erinnern Sie sich an die fog_sprite Entity, die oben definiert wurde? Diese sorgt für die grüne Sicht durch das Gerät. Es ist ein Sprite mit mehreren Frames, welches vor dem Spieler plaziert wird; von Zeit zu Zeit ändern sich die Frames um Geräusche etc. zu simulieren. Sie können mit Hilfe von grünem Nebel das ganze noch “echter” aussehen lassen.

Wenn die “N”-Taste losgelassen wird, werden die Panels unsichtbar gemacht, das Sprite verschwindet und der camera.ambient Wert wird wieder auf 0 zurückgesetzt.

Taschenlampe mit Batterien

Der Code für die Taschenlampe benutzt folgende Idee: man erstellt ein unsichtbares Objekt eine große Distanz vor dem Spieler und führt einen trace vom Spieler dorthin aus. Wenn etwas getroffen wird (eine Wand etc.) bewegt man das Objekt an diese Stelle und läßt es Licht abstrahlen, so wie im Bild.

Schauen wir uns die Action der Taschenlampe an:

var max_dist = 10000; // use it for distances smaller than 10,000 quants

action flashlight_pickup
{
while (player == null) {wait (1);}
my.passable = on;
while (vec_dist (player.x, my.x) > 100) {wait (1);}
my.invisible = on;
my.lightred = 250;
my.lightgreen = 250;
my.lightblue = 170;
while (1)
{
while (energy > 0 && key_f == 1) // press the "F" key to use the flashlight
{
my.lightrange = 200;
temp.x = max_dist * cos(player.pan) * cos(camera.tilt) + player.x;
temp.y = max_dist * sin(player.pan) * cos(camera.tilt) + player.y;
temp.z = max_dist * sin(camera.tilt) + player.z;
trace_mode = ignore_models + use_box;
my.skill1 = trace (player.x, temp);
if (my.skill1 != 0)
{
temp.x = (my.skill1 - 30) * cos(player.pan) * cos(camera.tilt) + player.x;
temp.y = (my.skill1 - 30) * sin(player.pan) * cos(camera.tilt) + player.y;
temp.z = (my.skill1 - 30) * sin(camera.tilt) + player.z;
vec_set (my.pos, temp);
}
energy -= 0.5 * time;
wait (1);
}
my.lightrange = 0;
wait (1);
}
}

Das Taschenlampenmodel ist passierbar; sobald der Spieler nah genug kommt, wird es unsichtbar. Wenn genug Energie (Batterie) übrig ist und der Spieler die “F”-Taste drückt, berechnen wir eine Position 10000 Quants vor dem Spieler. Wenn Sie Mathe mögen, können Sie die Formeln prüfen; ich erkläre die Einfachste:

temp.z = max_dist * sin(camera.tilt) + player.z;

Wir führen einen trace zwischen dem Spieler und dem Taschenlampenobjekt aus und speichern das Ergebnis in skill1. Wenn es nicht 0 ist, haben wir etwas getroffen und berechnen so eine neue Distanz für den Spot, indem wir max_dist durch die ermittelte Distanz ersetzen. Wir möchten nicht, daß der Spot in der Wand sitzt, deshalb subtrahieren wir noch 30 Quants von dieser Distanz. Beachten Sie bitte, dass ich das Taschenlampenmodel selbst für das “Objekt” benutze; Sie können ein anderes nehmen, wenn Sie möchten, aber wieso sollten Sie?

Die Energie nimmt ab, solange “F” gedrückt ist. Wird diese Taste losgelassen, setzen wir die lightrange auf 0 und löschen damit das Licht.

Die Action für die Batterien ist simpel:

action battery_pickup
{
my.passable = on;
while (player == null) {wait (1);}
while (vec_dist (player.x, my.x) > 100) {wait (1);}
energy += battery;
ent_remove (me);
}

Wenn der Spieler nahe heran kommt, wird die Energie erhöht und das Batterieobjekt wird entfernt.