|
Anfängerecke |
Top Previous Next |
|
Deformierbare Terrains
Der folgende Code ist ein Remake einer meiner älteren Aum Artikel; diesmal ist der Code aber komplexer, flexibler und läuft schneller. Sie steuern einen Spieler aus der Egoperspektive, der mit einem Raketenwerfer in der Hand das Terrain nach Belieben verformen kann.
panel cross_pan
function main()
action terrain
Ich benutze ein Fadenkreuz-Panel namens cross_pan; die Werte für pos_x und pos_y stellen sicher, dass es bei einer Auflösung von 800 x 600 Pixeln in der Bildschirmmitte angezeigt wird. Die main Funktion lädt das Level und die Action namens “terrain” läßt das Terrain auf Kollision mit anderen Entities (unseren Raketen) reagieren und wählt die erforderliche Event Funktion (create_crate).
function create_crate()
Die obige Funktion wird aufgerufen, wenn etwas (wie z.B. unsere Raketen) mit dem Terrain kollidiert. Ich habe den Skill40 der Raketen auf "“2345"”gesetzt, damit nichts geschieht, wenn eine andere Entity (der Spieler z.B.) mit dem Terrain kollidiert. Wenn eine Rakete für die Kollision verantwortlich war, speichern wir ihre Position in der hit_coords Variable, setzen einen Index auf 1 und speichern einen großen Wert (50.000 Quants) in Skill2.
Unser Terrain hat 33 x 33 = 1089 Vertizes; die “while” Schleife geht sie durch und prüft, welcher am nächsten an hit_coords liegt. Wenn die Schleife durchlaufen wurde, ist der kürzeste Abstand in Skill2 und der entsprechende Vertex in Skill3 gespeichert. Das Terrain wird mit den Koordinaten aus Skill3 verformt.
function deform(vertex_number)
Diese Funktion verformt das Terrain, indem die Höhe des entsprechenden Punktes um 70% verringert wird; ändern Sie diesen Wert, wenn Sie möchten. Die letzte Zeile berechnet die Normalenvektoren erneut und ist dafür zuständig, dass dynamische Lichter auch nach der Deformation korrekt angezeigt werden.
Der Spieler hat eine simple Action:
action player_1st
function players_bullet()
function move_players_bullet()
Die Funktion players_bullet() startet jedes Mal, wenn der Spieler die linke Maustaste drückt; wir stellen sicher, dass nur eine Instanz der Funktion läuft und warten dann, bis die zuvor abgefeuerte Rakete verschwunden ist. Die folgenden Zeilen verhindern automatisches Feuern, lassen ein Geräusch ertönen und erzeugen ein Raketenmodel namens rocket1, das die Action move_players_bullet() erhält.
Diese Funktion stellt sicher, dass die Rakete die Ausrichtung des Spielers übernimmt und läßt sie auf Kollisionen mit anderen Entities und Blocks reagieren; die Event Funktion heißt remove_bullet. Die Rakete wird mit Hilfe der Werte in Skill1 bis Skill3 bewegt, die wie eine einzelne Variable (ein Vektor) behandelt werden. Skill40 wird auf den seltsamen Wert 12345 gesetzt, damit die Rakete vom Terrain als solche identifiziert werden kann. Die Rakete bewegt sich bis sie unsichtbar gemacht wird. Die Geschwindigkeit wird durch Setzen von Skill1 in der Schleife bestimmt und die zurückgelegte Distanz der Rakete wird in der lokalen Variable distance_covered aufaddiert. Sobald dieser Wert 100 übersteigt (auch dieser Wert kann nach belieben angepasst werden), wird Skill3 verringert, was dazu führt, dass die Rakete nach unten abdriftet. Die Rakete wird zu oden stürzen und einen Krater hinterlassen.
function remove_bullet()
function explosion_sprite()
Was geschieht, wenn die Rakete auf den Boden fällt? Sie wird unsichtbar und passierbar gemacht und an der Aufschlagsposition ertönt ein entsprechendes Geräusch. Desweiteren wird ein Explosionssprite mit der explosion_sprite Action erstellt.
Die letzte Funktion skaliert die Explosion korrekt, macht das Sprite passierbar und bright und spielt die Animation einmal durch, bevor das Sprite entfernt wird. Es ist eine einfache Methode, aber sie funktioniert gut.
Serious grass
Soweit ich weiß war Serious Sam das erste Spiel mit diesem Feature: der Spieler bewegt sich durchs Level und die Gras Sprites bzw. Models werden vor seinem Auge erzeugt, während diejenigen, die weiter entfernt sind automatisch entfernt werden. Auf diese Weise ist es möglich, gut aussehende Pflanzen zu haben, die sich nicht allzu negativ auf die CPU auswirken.
starter generate_grass()
Ich verwende eine starter Funktion, die wartet bis der Spieler existiert und dann ein Quadrat aus Gras erstellt, in dessen Zentrum der Spieler ist:
Wenn Sie sich die erste Bedingung ansehen, stellen Sie fest, dass die Pflanze nur erstellt wird, wenn die Distanz zum Spieler größer als 300 Quants ist; wir möchten ja nicht, dass ein Busch direkt vor dem Spieler auftaucht, nicht wahr? Die folgende Bedingung sorgt dafür, dass Pflanzen nur dann erstellt werden, wenn sich der Spieler bewegt; es macht nicht viel Sinn, die Models zu erzeugen, wenn der Spieler steht. Mit einem einfachen Trick kann ich ermitteln, ob sich der Spieler bewegt oder nicht; ich habe zwei Variablen namens player_position1 und player_position2, in denen die Position des Spielers vor und nach dem “wait(1)” gespeichert wird. Wenn sich der Spieler im letzten Frame bewegt hat, sind beide Variablen verschieden und das Grass wird erzeugt, falls number_of_bushes kleiner als 280 ist. Diese Variable zählt, wieviele Gras Models erzeugt wurden und begrenzt die Anzahl der Graspolygone im Level. Sie können diesen Wert erhöhen, aber dann müssen Sie auch den Nexus vergrößern (er sollte eine Größe von 100 für 1000 Pflanzen haben usw.)
Ich habe fast vergessen, Ihnen das zu sagen: es spielt während der ersten 300 Frames (total_frames < 300) keine Rolle, ob sich der Spieler bewegt oder die Anzahl der Büsche größer als 280 ist. Dies sorgt dafür, dass die Grasmodels am Anfang des Spiels in einer größeren Zahl erstellt werden, auch wenn sich der Spieler nicht bewegt und trotzdem realistische Pflanzen sehen möchte.
Ich verwende zwei verschiedene Pflanzenmodels namens grass1.mdl und grass2.mdl und beide werden mit der place_grass Funktion aufgerufen:
function place_grass()
Meine Fans haben vielleicht bemerkt, dass jedes Model 200 Quants oberhalb des Origins vom Spieler erzueugt wird, number_of_bushes erhöht wird, das Model passierbar und transparent gemacht wird, eine zufällige Ausrichtung bekommt und schließlich mit Hilfe einer trace Anweisung korrekt am Boden plaziert wird. Jedes Model hat eine interne while Schleife, welche die Transparenz kontrolliert und es durchsichtig macht, wenn der Spieler sich entfernt; ist der Spieler weiter als 1000 Quants entfernt, wird das Model entfernt und number_of_bushes wird verringert, wodurch ein brandneues Model erzeugt werden kann.
|