Sternenfeld

Die meisten Ihrer Spiele können ein Sternenfeld brauchen: der Effekt sieht gut aus und der Code ist überhaupt nicht kompliziert.

Ich muß zugeben, dass man an dem Bild nicht viel sehen kann, aber starten Sie die Demo und Sie werden es lieben; ansonsten bekommen Sie Ihr Geld zurück! Hier ist ein Screenshot des Levels aus dem WED:

Die Kamera ist im Ursprung plaziert und zeigt in Richtung des gelben Pfeils. Wissen Sie was? Der rote Punkt ist eine unsichtbare Entity, die Partikel erzeugt und diese bewegen sich auf die Kamera zu und sorgen für den Effekt. Die Wände sind mit einer normalen Textur versehen, aber ich habe nur eine kleine Lichtquelle nahe einer der Ecken des Raumes eingefügt, so dass alles wirklich dunkel wirkt.

function main()
{
fps_max = 50;
level_load (stars_wmb);
wait (3);
camera.pan = 0;
}

Die Main Funktion limitiert die Frame Rate auf 50, lädt das Level, wartet bis dies geschehen ist und setzt dann die Kamera auf die richtige Orientierung.

action particle_generator
{
my.invisible = on;
my.passable = on;
while(1)
{
effect (particle_init, 5, my.pos, normal);
wait (1);
}
}

Die Action oben gehört zu dem (roten) Model, das die Partikel generiert: sie macht das Model unsichtbar und passierbar und erzeugt dann 5 Partikel pro Frame an der Position des Models (my.pos).

function particle_init()
{
temp.x -= 2 + random (1) ;
temp.y += 1 - random (2);
temp.z += 1 - random (2);
vec_normalize (temp, 5);
vec_add (my.vel_x, temp);
my.bmap = star_pcx;
my.alpha = 50; // play with this value
my.size = 0.1;
my.flare = on;
my.bright = on;
my.move = on;
my.lifespan = 1000;
my.function = kill_particles;
}

Die Funktion zur Partikelsteuerung gibt ihnen eine zufällige positive Geschwindigkeit in x-Richtung und zufällige (positive oder negative) Geschwindigkeiten auf der y und z-Achse. Die Länge des “temp” Vektors wird auf 5 gesetzt; Sie müssen also nur diese eine Zahl ändern, wenn Sie temp.x, temp.y und temp.z gleichzeitig verringern oder vergrößern wollen.

Die nächsten Codezeilen addieren die “temp” Geschwindigkeit zur Geschwindigkeit des Partikels und setzen star_pcx als die Bitmap, die benutzt werden soll. Das Partikel hat anfangs einen Alpha Wert von 50 und eine geringe Größe (0,1); die Flages flare, bright und move sind gesetzt. Schließlich wird seine lifespan auf 1000 gesetzt und die entsprechende Funktion ist kill_particles.

function kill_particles()
{
my.size += 0.01 * time;
if (my.x <= 0)
{
my.lifespan = 0;
}
}

Die Größe des Partikels nimmt zu, wenn es auf die Kamera zufliegt; wenn es hinter die Kamera gerät (my.x <= 0) wird es gelöscht. Hier ist der gleiche Effekt mit den “beam” und “streak” Flags gesetzt. Der Code enthält die notwendigen Zeilen; wenn Sie die A5 Pro, A6 Commercial oder A6 Pro Version besitzen, können Sie die Kommentare entfernen.

Realistisches Wasser

Dieses Mal lernen wir, wie man einen wirklich gut aussehenden Wassereffekt erzeugt. Schauen Sie sich das Bild an, um zu sehen, was ich meine.

Als Erstes benutzen wir MED, um ein Terrain zu erstellen. Ich habe die Grundeinstellungen (33 x 33 Vertizes, 5 Quants / Triangle) verwendet und den ersten Vertex nach unten gezogen, wie im Bild.

Denken Sie daran, dies für jedes Terrain zu machen, das Sie für Wasser nutzen, ansonsten werden sich die Vertizes gar nicht bewegen. Wählen Sie irgendeine gut aussehende Skin und schon kann es losgehen.

define amplitude skill1;
define water_speed skill2;

define number_of_vertices 1089;

var vertex_array [number_of_vertices];
var counter;
var index;

Mein Terrain hat 33 * 33 = 1089 Vertizes; ändern Sie diesen Wert, wenn Ihr Terrain eine andere Größe hat. Ich habe ein Array definiert, das einen Wert pro Vertex aufnehmen kann und zwei Variablen, die als Zähler benutzt werden.

action nice_waves
{
my.transparent = on;
my.passable = on;
my.alpha = 75;
my.ambient = -100;
if (my.amplitude == 0)
{
my.amplitude = 2; // default wave amplitude value
}
if (my.water_speed == 0)
{
my.water_speed = 10; // default wave speed value
}

Das Terrain ist transparent und passable; der Transparenzfaktor ist 75, aber Sie können hier jeden anderen Wert nehmen. Der Skin in meiner Demo war nicht allzu dunkel, daher habe ich den Ambient auf einen negativen Wert gesetzt. Wenn Sie Skill1 im WED nicht sitzen, wird die Amplitude auf 2 eingestellt; wenn Sie water_speed vergessen einzurichten, wird das auf 10 gesetzt.

while (counter < number_of_vertices)
{
vertex_array[counter] = random(360); // set random values in vertex_array
counter += 1;
}

TDie erste Schleife füllt das vertex_array mit zufälligen Werten; hier ist ein mögliches Ergebnis mit my.amplitude == 5:

Wir werden die Sinus-Funktion für die Wellen verwenden, weil sie gut aussieht und einfach zu nutzen ist. Ich werde sie schnell erklären.

Wie Sie sehen sieht diese Funktion aus wie eine Welle – das ist ein gutes Zeichen! Wie Sie sehen spielt es keine Rolle, wie groß x ist, der Funktionswert liegt immer zwischen –1 und 1. Unsere Wellen werden eine Amplitude haben, die sich aus dem Wert der Sinus-Funktion (zwischen –1 und 1) multipliziert mit my.amplitude (skill1), der im WED gesetzt wird, ergibt. Falls ich my.amplitude auf 5 setze, ändern die Vertizes ihren z Wert zwischen –5 und 5, verstanden?

Wir haben zufällige Werte als Startpunkte gewählt, schauen wir uns das Bild an, um zu sehen, wie sie auf der Sinus-Kurve aussehen.

Ich konnte nicht alle Punkte einzeichnen, weil es 1089 Werte gewesen wären! Jeder Vertex startet bei seinem eigenen Wert aus dem vertex_array und seine z Koordinate (seine Höhe) wird sich wie im Bild oben angedeutet verändern. Zurück zu unserer Action:

while (1)
{
index = 0;
while (index < number_of_vertices)
{
vec_for_mesh(temp, my, index); // store the vertex coordinates in temp
temp.z = sin(counter + vertex_array[index]) * my.amplitude; // change the z component
vec_to_mesh(temp, my, index); // deform the terrain entity
index += 1;
}
counter += my.water_speed * time;
wait(1);
}
}

Wir starten mit dem ersten Vertex; wir sichern seine Koordinaten mit vec_for_mesh in temp, setzen temp.z auf den neuen Wert, den sie Sinus-Funktion multipliziert mit der Amplitude ergibt und ändern dann die Position des Vertex mit vec_to_mesh. Dies wiederholz sich für alle Vertizes ohne eine wait(1) Anweisung in der Schleife, weil wir dann 1089 Frames (5 bis 20 Sekunden) warten müssten, bis alle bearbeitet wären. Dies ist eine dieser Situationen, in denen wir eine Schleife ohne wait(1) verwenden können.

Die innere Schleife wird verlassen, wenn alle Vertizes ihre neue Höhe haben und dann erhöhen wir den Zähler, indem wir water_speed (mit einer “time”-Korrektur) addieren. Dies verschiebt alle Vertizes auf dem Graphen der Sinus-Funktion nach rechts; wie ich sagte kann der Zähler beliebig groß werden, weil die Sinus-Funktion niemals größer als 1 oder kleiner als –1 wird.

Dies beendet den Artikel! Vergessen Sie nicht, Ihr Terrain im WED entsprechend zu skalieren.