Intelligente Kameras

Viele von Ihnen haben mich gefragt, wie man am besten Kameras skriptet, die sich wie bei Resident Evil verhalten. Ich habe mir eine einfache Lösung ausgedacht, deren Vorteil es ist, dass sie andauernd auf den Spieler gerichtet sind, so verlieren sie nie den Helden aus den Augen, wenn Sie genug Kameras in ihr Level plazieren.

Dieses Beispiel wurde für 50 Kameras erstellt, aber Sie können so viele benutzen, wie Sie wollen. Um den Code auszuprobieren, binden Sie recam.wdl ein und rufen Sie fixed_cameras() in main auf. Stellen Sie einige Behelfsmodelle in Ihr Level (ich habe fish.mdl benutzt), setzen Sie deren Pan, Tilt und Roll Winkel in Wed und weisen Sie die recam-Aktion zu. Vergessen Sie nicht, Skill1 von 1..50 für diese Modelle zu setzen; Sie müssen diese nicht in einer speziellen Reihenfolge setzen, stellen Sie einfach sicher, dass nicht zwei verschiedene Kameras den gleichen Wert bei Skill1 im Wed eingetragen haben. Die Werte, die für Skill1 gesetzt wurden, werden vom Wdl-Skript benutzt, um die Kamera, mit der besten Sicht zu einem bestimmten Moment, zu wählen. Wenn Sie wollen, können Sie meine modifizierte office.wmp laden und starten, um ein Beispiel zu sehen.

Ich will die vorgefertigten Skripte nicht verändern, deswegen muss ich die aktuelle Ansicht ausschalten und die neue re_camera  Ansicht aktivieren. Sehen wir uns zuerst die recam-Aktion an:

action recam
{
      my.invisible = on;
      my.passable = on;
      re_camera.tilt = my.tilt;
      re_camera.roll = my.roll;
      if (my.skill1 == 0) {remove me; beep; beep; return;}
      while (1)
      {
           camera_position[my.skill1] = vec_dist(my.x, player.x);
           if (winner > camera_position[my.skill1] - 50)
           {
                re_camera.x = my.x;
                re_camera.y = my.y;
                re_camera.z = my.z;

                vec_set(temp, player.x); // re_camera's pan
                vec_sub(temp, my.x);
                vec_to_angle(re_camera.pan, temp);
          }
          wait (1);
     }
}
 

Die Behelfsmodelle werden unsichtbar und durchgängig gemacht, ihre Orientierung (Tilt, Roll) wird von re_camera benutzt. Pan wird mit jedem Frame neu berechnet, damit die Kamera immer auf den Spieler blickt, ohne ihn auch nur für eine Sekunde zu verlieren.

Ich benutze das Array camera_position[50] um den Abstand zwischen jeder Kamera und dem Spieler zu berechnen, camera_position[1] beinhaltet die Distanz zwischen der Kamera mit Skill1 = 1 und dem Spieler, camera_position[35] die Entfernung zwischen der Kamera mit Skill1 = 35 und dem Spieler, usw. Ich benutze eine einfache vec_dist(my.x,player.x)  Anweisung, um die Entfernung zwischen der Kamera und dem Spieler zu berechne. Ich habe eine Variable namens winner deklariert - dies ist die kürzeste Entfernung zwischen dem Spieler und jeder Kamera. Falls wir einen Gewinner finden, setzen wir re_camera auf die neuen (Fisch) Koordinaten und drehen sie andauernd zum Spieler mit Hilfe des einfachen vec_to_angle Befehls.

function fixed_cameras()
{
      camera.visible = off;
      re_camera.visible = on;
      while (1)
      {
           temp_counter += 1;
           if (temp_counter == 50)
           {
                temp_counter -= 49;
           }
           if (camera_position[temp_counter] < winner && camera_position[temp_counter] > 0)
           {
                winner = camera_position[temp_counter];
                found_camera = temp_counter;
           }
           else
           {
                winner = camera_position[found_camera];
           }
           wait (1);
     }
}

Die Funktion fixed_cameras beinhaltet eine While-Schleife, die fortlaufend nach Gewinnern sucht. Falls der Abstand zwischen der Kamera und dem Spieler kleiner als winner ist, wird diese Kamera aktiviert. Wir müssen sicherstellen, dass camera_position[temp_counter] größer als Null ist, denn unser Level könnte weniger als 50 Kameras benutzen - alle unbenutzten Werte im Array sind Null, aber dies sollte sie nicht gewinnen lassen.

Ich hoffe Sie haben Spass mit diesem Kameraskript.
 
 

Erdbeben

Falls Sie ein Erdbeben zu Ihrem 1st Person Spiel hinzufügen müssen, gibt es eine einfache Lösung: Speichern Sie die Augenhöhe (eye_height_up) des Spielers aus den vorgefertigten Skripten, dann spielen Sie damit und dem Roll Winkel des Spielers herum. Setzen Sie die Ausgangswerte zurück, sobald das Erdbeben vorbei ist, und alles wird wie zuvor funktionieren.

Die gute Sache an diesem Skript ist, dass der Spieler nicht bewegt wird, und daher nicht aus dem Level springen kann (dies können Sie natürlich mit einem Skript ändern), aber Ihr Kunde weiß das nicht, und wird so bestimmt in ein Lavabecken fallen, da er sich bewegen wird, um den Spieler in einer sicheren Gegend zu halten :)

Das Erdbeben startet, sobald Sie in ein Entity laufen (weisen Sie ihm die quakegen-Aktion zu, setzen Sie wenn Sie wollen das invisible-Flag). Ich würde eine sichtbare Stufe nehmen (als wmb entity kompiliert) die zu einer Seilbrücke führt, welche über dem Lavabecken hängt:

action quakegen
{
     my.enable_impact = on;
     my.event = earthquake;
}

function earthquake
{
     my.skill9 = eye_height_up;
     my.skill10 = random(100) + 20;
     my.skill11 = random(100) + 100;
     waitt(my.skill10);
     while (my.skill11 > 0)
     {
         if (random(1) > 0.9)
         {
             play_sound eq_snd, 30;
         }
         if (eye_height_up > 0.2)
         {
             eye_height_up += 0.1 - random(2)/10;
         }
         player.roll += 10 - random(20);
         my.skill11 -= 0.1 * time;
         waitt(2);
     }
     eye_height_up = my.skill9;
     player.roll = 0;
}
 

Skill10 legt die anfängliche Verzögerung fest (daher kann der Spieler nicht bemerken, wann / ob er das Erdbeben ausgelöst hat) und Skill11 gibt die Dauer an. Spielen Sie mit diesen Werten herum.