Planet Survivors – Teil 3

Diesen Monat kommen wir in das zweite Level des Spiels; das Schiff landet auf einer Plattform und wir spielen ein Brettspiel für mehr Munition und Schildenergie.

Ich habe ein paar Änderungen an der player_level1 Action vergenommen, aber keine Angst, wir gehen nicht alles durch. Die Hauptänderung ist eine neue Variable namens landing, welche die Landung des Schiffes kontrolliert. Ist diese null, dann fliegt das Schiff wie im vorigen Artikel, aber wenn landing auf 1 gesetzt wird, bereitet es sich auf die Landung vor.

while (players_shield > 0)
{
if (landing == 0)
{
// old stuff from Aum37 here
}
else // landing = 1
{
player.passable = on;
player.transparent = off;
camera.x = 500;
camera.y = -200;
camera.z = -2000;
lbase.visible = on;
crosshair_pan.visible = off;
my.pan = 0;
my.tilt = 0;
my.roll = 0;
my.y = 0;

Der “else” Teil läuft, wenn landing == 1 ist. Er macht den Spieler passierbar, damit er nicht mit Asteroiden kollidiert und schaltet die Transparenz aus. Wir wählen eine bestimmte (experimentelle) Position für die Kamera und machen die Landungsplattform (lbase) sichtbar. Schließlich verbergen wir das Fadenkreuz und setzen die Winkel und den y Wert des Schiffes zurück, weil der Spieler eine merkwürdige Position haben könnte, bevor er landet.

while (player.x < 0)
{
if (player.z > -2270) {player.z -= 14 * time;}
player.x += (vec_dist(player.x, lbase.x) / 60 + 2) * time;
vec_set(temp, player.x);
vec_sub(temp, camera.x);
vec_to_angle(camera.pan, temp);
engine_handle = ent_playsound (my, engine1_wav, 400);
my.skill15 = vec_dist(player.x, lbase.x);
if (my.skill15 < 1000)
{
snd_tune(engine_handle, 0, (my.skill15 / 10), 0);
}
wait (1);
}

Das Schiff sollte bei x = 0, y = 0 und z = -2270 landen. Wir erhöhen den x Wert in einer Schleife und verringern z (die Höhe). Die Geschwindigkeit auf der x-Achse hängt von der Distanz zwischden dem Spieler und der Plattform ab; sie wird langsam abnehmen, während der Spieler zur Landung ansetzt, wobei 2 * time die minimale Geschwindigkeit ist. Die Kamera ist die ganze Zeit auf das Schiff ausgerichtet und das Motorengeräusch wird je nach Distanz zwischen Spieler und Plattform unterschiedlich getuned. Das bedeutet, dass die Frequenz des Geräusches abnimmt, wenn das Schiff auf die Basis zufliegt.

sleep (2);
my.engine = off;
temp.x = -35;
temp.y = 0;
temp.z = -2285;
ent_create (human_mdl, temp, move_human);
return;
}
wait (1);
}

Das Schiff ist nun gelandet. Wir warten zwei weitere Sekunden und stoppen dann die Partikelgeneratoren (die Motoren). Wir setzen x = -35, y = 0 und z = -2285 (experimentell) und erzeugen an dieser Position eine human.mdl Entity mit der move_human Funktion. All diese Dinge liefen ja in einer Schleife ab, daher müssen wir diese mit return verlassen.

Das waren die größeren Änderungen am Code von AUM 37. Schauen wir uns die neuen Dinge an:

function compute_time()
{
sleep (130);
landing = 1;
}

Diese winzige Funktion wird von player_level1 aufgerufen; sie wartet bis der Soundtrack kurz vor dem Ende ist und setzt landing dann auf 1. Ich habe track1.wav diesen Monat nicht in die Datei aufgenommen, aus Rücksicht auf Benutzer von 56K Modems; benutzen Sie track1.wav aus AUM 37.

action landing_base
{
lbase = my;
my.invisible = on;
my.passable = on;
while (landing == 0) {wait (1);}
my.invisible = off;
}

Die Action für die Landeplattform; sie macht diese unsichtbar und passierbar und wartet dann bis landing auf 1 gesetzt wird, woraufhin die Basis sichtbar gemacht wird. Das ist nötig, weil unser Level eigentlich sehr klein ist, obgleich es dem unschuldigen Spieler unendlich lang vorkommt.

Schauen wir uns die Funktion an, die den kleinen Menschen steuert:

function move_human()
{
my.passable = on;
human = my;
my.pan = 270;
my.enable_touch = on;
my.event = logical_help;
while (my.y > -170)
{
my.y -= 1.4 * time;
ent_cycle("walk", my.skill1);
my.skill1 += 5 * time;
my.skill1 %= 100;
wait (1);
}
ent_cycle ("walk", 25);

Der Mensch ist passierbar und erhält zu Beginn einen Pan von 270 Grad. Er reagiert auf Berührung und startet die logical_help Funktion, wenn der Mauszeiger über ihm plaziert wird. Dieser kleine Mensch erscheint unter dem Schiff und bewegt sich mit einer Geschwindigkeit von 1,4 * time bis sein y-Wert kleiner ist als 170 Quants; die Geschwindigkeit seiner Walk Animation ist 5 * time. Die letzte Zeile bestimmt eine gute Standposition (25 ist wieder ein experimenteller Wert).

camera.x = -40;
camera.y = -140;
camera.z = -2100;
camera.pan = 270;
camera.tilt = -65;
camera.roll = 0;
mouse_map = logical_pcx;
mouse_mode = 2;
mouse_spot.x = 0;
mouse_spot.y = 0;
temp_bonus = 100;
sound_vol = 20;
while (logical_ended == 0)
{
temp_bonus -= 0.1 * time;
if (temp_bonus < 0) {temp_bonus = 0;}
mouse_pos.x = pointer.x;
mouse_pos.y = pointer.y;
wait (1);
}

Der Mensch ist nun am Spielbrett angekommen; wir wählen einen neuen Satz Kamerakoordinaten und Winkel, setzen einen neuen Mauszeiger, stellen die Originalwerte für den mouse_spot wieder her (diese waren anders für den Mauszeiger des Hauptmenüs) und setzen temp_bonus auf 100, welches der größtmögliche Bonus ist, den der Spieler erhalten kann, wenn er das Rätsel schnell löst. Ich habe die Asteroiden nicht angehalten, sie kollidieren also immer noch und erzeugen Hintergrundgeräusche; dies kann den Spieler ein wenig stören, daher verringern wir die Lautstärke aller Sounds auf 20%. Schließlich wird temp_bonus in einer Schleife heruntergezählt und wir erlauben die Bewegung der Maus, bis das Rätsel gelöst ist (also bis logical_ended == 1).

sleep (1);
sound_vol = 100;
while (my.pan > 90)
{
my.pan -= 25 * time;
wait (1);
}
while (my.y < -100)
{
my.y += 1.4 * time;
ent_cycle("walk", my.skill1);
my.skill1 += 5 * time;
my.skill1 %= 100;
wait (1);
}
ent_remove(my);

Hier ist das Rätsel gelöst; wir warten eine Sekunde, stellen die Lautstärke der Asteroiden wieder her und drehen den Menschen dann mit einer Geschwindigkeit von 25 * time zum Schiff hin. In einer Schleife wird er dann bewegt, während seine Walk Animation zu sehen ist. Er wird entfernt, bevor er das Ziel (das Schiff) erreicht hat, aber der Spieler kann das nicht sehen.

camera.x = 500;
camera.y = -200;
camera.z = -2000;
vec_set(temp, player.x);
vec_sub(temp, camera.x);
vec_to_angle(camera.pan, temp);
while (minimum_bonus > 0) {wait (1);}
sleep (1);
fade_factor = 1000;
player.engine = on;
my = player;
plasma_jet(65, 63);

Das Schiff bereitet sich auf den Start vor: wir nehmen wieder die alte Kameraposition und richten die Kamera am Schiff aus. Wir warten bis der Spieler den gesamten Bonus (Munition und Schildenergie) erhalten hat, warten dann eine weitere Sekunde und setzen dann einen Partikel fade_factor auf 1000. Das bedeutet, dass die Motorenpartikel schnell ausgeblendet werden; das ist nötig, weil das Schiff sich sehr schnell bewegen wird.

Die “engine” Flag wird gesetzt und wir sagen der Engine Partikelfunktion, dass “my”, also die Entity, für die Partikel erzeugt werden, der Spieler selbst ist. Die letzte Zeile startet die Plasma Strahlen.

while (vec_dist(camera.x, player.x) < 10000)
{
player.skill15 = min(100, vec_dist(player.x, lbase.x) / 10);
player.x += (player.skill15 + 1) * time;
player.z += 5 * time;
engine_handle = ent_playsound (player, engine1_wav, 1000);
if (player.skill15 < 10000)
{
snd_tune(engine_handle, 0, (player.skill15), 0);
}
vec_set(temp, player.x);
vec_sub(temp, camera.x);
vec_to_angle(camera.pan, temp);
wait (1);
}
beep;
exit;
}

Der letzte Teil der Funktion erhöht die x-Koordinate des Schiffes von 1 * time auf 101 * time, je nach Distanz zwischen Spieler und Plattform. Wir erhöhen auch den z-Wert, weil das Schiff ja startet und lassen wieder Motorengeräusche ertönen, mit einer Frequent, die von der x-Geschwindigkeit abhängt. Die Kamera folgt dem Schiff, bis dieses 10.000 Quants weit weg ist; wenn dies geschieht, lassen wir einen “Beep” ertönen und beenden die Engine; nächsten Monat kommt an diese Stelle eine level_load Anweisung.

Schauen wir uns die Actions und Funktionen für unser Brettspiel an:

starter init_logical()
{
mouse_range = 5000;
while ((tile1 == null) || (tile2 == null) || (tile3 == null) || (tile4 == null) || (tile5 == null) || (tile6 == null) || (tile7 == null) || (tile8 == null) || (tile9 == null)) {wait (1);}

Dies ist eine Starter Funktion, die dafür sorgt, dass die Entities auf Mausklicks reagieren, selbst wenn sie 5000 Quants von der Kamera entfernt sind. Wir warten bis alle farbigen Teile erzeugt wurden und berechnen dann die Werte für die Variablen status1 bis status9. Hier ist eine typische Brett-Situation:

Ich habe drei verschiedene Entities erstellt (rot, grün und blau) und habe sie wie im Bild angeordnet. Jedes Teil hat folgende Action zugewiesen:

action tile_1
{
tile1 = my;
}

Jedes rote Teil hat Flag1 gesetzt, jedes grüne hat flag2 und jedes blaue hat flag3 gesetzt. Die gute Nachricht ist, dass dieser Ansatz es erlaubt, die Teile beliebig anzuordnen, solange von jeder Sorte drei vorhanden sind. Ich habe eine Anfangskonfiguration gewählt, die sich in wenigen Zügen lösen läßt – schließlich ist dies erst das erste logische Level!

Schauen wir uns die Funktion weiter an:

while (1)
{
status1 = 1 * (tile1.flag1 == on) + 2 * (tile1.flag2 == on) + 3 * (tile1.flag3 == on);
status2 = 1 * (tile2.flag1 == on) + 2 * (tile2.flag2 == on) + 3 * (tile2.flag3 == on);
status3 = 1 * (tile3.flag1 == on) + 2 * (tile3.flag2 == on) + 3 * (tile3.flag3 == on);
status4 = 1 * (tile4.flag1 == on) + 2 * (tile4.flag2 == on) + 3 * (tile4.flag3 == on);
status5 = 1 * (tile5.flag1 == on) + 2 * (tile5.flag2 == on) + 3 * (tile5.flag3 == on);
status6 = 1 * (tile6.flag1 == on) + 2 * (tile6.flag2 == on) + 3 * (tile6.flag3 == on);
status7 = 1 * (tile7.flag1 == on) + 2 * (tile7.flag2 == on) + 3 * (tile7.flag3 == on);
status8 = 1 * (tile8.flag1 == on) + 2 * (tile8.flag2 == on) + 3 * (tile8.flag3 == on);
status9 = 1 * (tile9.flag1 == on) + 2 * (tile9.flag2 == on) + 3 * (tile9.flag3 == on);
if ((status1 == status2) && (status2 == status3))
{
if ((status4 == status5) && (status5 == status6))
{
give_bonus();
return;
}
}
if ((status1 == status4) && (status4 == status7))
{
if ((status2 == status5) && (status5 == status8))
{
give_bonus();
return;
}
}
wait (1);
}
}

Diese 9 Variablen können die Werte 1 (rotes Teil, flag1 == on), 2 (grünes Teil, flag2 == on) oder 3 (blaues Teil, flag3 == on) annehmen. Wenn die Variablen für die ersten drei Teile denselben Wert haben, dann befinden sich in der ersten Reihe (1-2-3) identische Farben. Die innere Abfrage prüft, ob das auch für die zweite Reihe (4-5-6) gilt. Wenn das der Fall ist, dann ist das Level gelöst, weil die dritte Reihe (7-8-9) keine Wahl mehr hat und ebenfalls drei gleiche Farben enthalten muß. Wir rufen give_bonus() auf und verlassen denn die Funktion. Das gleiche geschieht noch einmal für die Spalten.

Aber wie werden die Farben geändert? Wir haben dafür 6 Knöpfe (Entities): v1 bis v3 und h1 bis h3.

Ich habe als Beispiel auf die v3 Entity geklickt; die Teile werden eine Stufe nach oben geschoben und das oberste rutscht nach unten. Das gleiche geschieht mit den Knöpfen h1 bis h3, aber hier werden die Teile horizontal verschoben. Wir haben also 6 Knöpfe zum Verschieben, aber ihr Code ist beinahe identisch, also schauen wir uns einen einzelnen Knopf an.

action h1
{
my.ambient = -100;
my.enable_click = on;
my.event = h1_clicked;
}

Dieser Knopf reagiert auf Mausklicks und startet das h1_clicked Event, wenn er angeklickt wurde.

function h1_clicked()
{
my.ambient = 100;
sleep (0.2);
my.ambient = -100;
if (status2 == 1) // tile2 is a red tile?
{
ent_morph(tile1, tilered_wmb); // then change into a red tile
tile1.flag1 = off; // reset all the flags
tile1.flag2 = off;
tile1.flag3 = off;
tile1.flag1 = on; // tile1 will be a red tile from now on
}
if (status2 == 2) // tile2 is a green tile?
{
ent_morph(tile1, tilegreen_wmb); // then change into a green tile
tile1.flag1 = off; // // reset all the flags
tile1.flag2 = off;
tile1.flag3 = off;
tile1.flag2 = on; // tile1 will be a green tile from now on
}
if (status2 == 3) // tile2 is a blue tile?
{
ent_morph(tile1, tileblue_wmb); // then change into a blue tile
tile1.flag1 = off; // // reset all the flags
tile1.flag2 = off;
tile1.flag3 = off;
tile1.flag3 = on; // tile1 will be a blue tile from now on
}

Die gelben Knöpfe erhöhen ihren Ambient für 0,2 Sekunden, wenn sie angeklickt werden. Falls status2 (die Variable für das zweite Teil) gleich 1 ist, dann ist tile2 rot. Deshalb müssen wir aus dem ersten Teil ein rotes Teil machen (1 <-- 2 <-- 3). Wir setzen die Flags zurück und setzen das korrekte Flag für ein rotes Teil, also flag1. Ebenso verfahren wir, wenn status2 gleich 2 bzw. 3 ist.

if (status3 == 1) // tile3 is a red tile?
{
ent_morph(tile2, tilered_wmb); // then change into a red tile
tile2.flag1 = off; // reset all the flags
tile2.flag2 = off;
tile2.flag3 = off;
tile2.flag1 = on; // tile2 will be a red tile from now on
}
if (status3 == 2) // tile3 is a green tile?
{
ent_morph(tile2, tilegreen_wmb); // then change into a green tile
tile2.flag1 = off; // // reset all the flags
tile2.flag2 = off;
tile2.flag3 = off;
tile2.flag2 = on; // tile2 will be a green tile from now on
}
if (status3 == 3) // tile3 is a blue tile?
{
ent_morph(tile2, tileblue_wmb); // then change into a blue tile
tile2.flag1 = off; // // reset all the flags
tile2.flag2 = off;
tile2.flag3 = off;
tile2.flag3 = on; // tile2 will be a blue tile from now on
}

Hier funktioniert es genauso, allerdings wird das dritte Teil (status3) überprüft und sein Status auf das zweite übertragen.

if (status1 == 1) // tile1 is a red tile?
{
ent_morph(tile3, tilered_wmb); // then change into a red tile
tile3.flag1 = off; // reset all the flags
tile3.flag2 = off;
tile3.flag3 = off;
tile3.flag1 = on; // tile3 will be a red tile from now on
}
if (status1 == 2) // tile1 is a green tile?
{
ent_morph(tile3, tilegreen_wmb); // then change into a green tile
tile3.flag1 = off; // // reset all the flags
tile3.flag2 = off;
tile3.flag3 = off;
tile3.flag2 = on; // tile3 will be a green tile from now on
}
if (status1 == 3) // tile1 is a blue tile?
{
ent_morph(tile3, tileblue_wmb); // then change into a blue tile
tile3.flag1 = off; // // reset all the flags
tile3.flag2 = off;
tile3.flag3 = off;
tile3.flag3 = on; // tile3 will be a blue tile from now on
}
}
Der letzte Teil der Funktion prüft die Farbe vom ersten Teil (status1) und ändert diesen je nach der Farbe des Nachbarn (Teil 3, da dieses von der rechten Seite nach links gewandert ist!). Schauen wir uns zwei weitere kleine Funktionen an und wir sind fertig!

function give_bonus()
{
logical_ended = 1; // the logical level has ended
mouse_mode = 0; // // so hide the mouse
snd_play (victory_wav, 50, 0);
sleep (2);
minimum_bonus += temp_bonus; // add what's left of temp_bonus to minimum_bonus
while (minimum_bonus > 0)
{
snd_play (bonus_wav, 100, 0);
players_shield += 2;
players_ammo += 2;
minimum_bonus -= 2;
sleep (0.1);
}
sleep (1);
}

Die obige Funktion wird aufgerufen, sobald das Level gelöst ist. Sie verbirgt die Maus, läßt ein Siegesgeräusch ertönen, wartet 2 Sekunden und addiert dann zu der minimum_bonus Variable (10) das, was von temp_bonus übrig geblieben ist (diese war zu Beginn 100, aber wurde in einer Schleife mit der Zeit immer weniger). Ein Geräusch ertönt und wir erhöhen den Schildwert und die Munition um 10 bis 110 Punkte, je nachdem.

function logical_help()
{
logical_txt.visible = on;
sleep (5);
logical_txt.visible = off;
}

Die letzte Funktion wird aufgerufen, wenn der Mauszeiger auf den Menschen bewegt wird und zeigt für 5 Sekunden einen Hilfetext an. Ich habe dafür eine Schriftart mit fester Breite gewählt, die den Text unschön macht, aber für die A5 Engine lesbar.

Editierbarer Text

Na gut, ich weiß, der Titel sagt nicht allzu viel aus, aber ich bin ziemlich stolz auf diesen Artikel. Möchten Sie nicht in der Lage sein, einen Text in Ihre 3D Welt zu setzen, um vielleicht Banner für Ihr Sportspiel anzuzeigen oder den Namen des Gewinners bei einem Rennspiel oder einen Zugangscode, der sich ändert? Wir wissen, wie man reguläre Texte auf dem Schirm anzeigt, aber wäre es nicht schöner, wenn wir sie als Objekte der 3D Welt hätten? Das ist genau, was ich Ihnen heute zeigen werde. Es gibt eine schlechte Nachricht: der Code funktioniert nicht mit A5.

Die Idee ist recht einfach: wir definieren eine Schriftart-Bitmap als normale Bitmap (nicht als Font!) und lesen ihre Pixel. Wann immer wir einen Pixel mit RGB ungleich 000 entdecken, setzen wir einen Partikel in unser Level. Schauen wir uns also den Code an, ja?

bmap system_font = <system.pcx>;
string temp_str; // just a temporary string that holds your text

Wie Sie sehen wurde system_font mit Hilfe einer gewöhnlichen bmap Definition erklärt; temp_str wird unseren Text beinhalten (“Acknex rules!” in meiner Demo).

function create_text(my_string)
{
var number_of_chars;
var format;
var char_minx;
var char_miny;
var char_maxx;
var char_maxy;
var pixel_value;
var char_width;
var char_height;
var particle_width = 1.3;
var particle_height = 1.5;
var particle_space = 12;

Schauen wir uns die Variablen an:
- Number_of_chars ist die Anzahl der Zeichen im String (13 in der Demo);
- Format wird von bmap_lock zurückgeliegert und gibt die Art der Textur an;
- Char_minx ist der geringste x-Wert (in Pixeln) für das aktuelle Zeichen der Bitmap;
- Char_miny ist der geringste y-Wert (in Pixeln) für das aktuelle Zeichen der Bitmap;
- Char_maxx ist der größte x-Wert (in Pixeln) für das aktuelle Zeichen der Bitmap;
- Char_maxy ist der größte y-Wert (in Pixeln) für das aktuelle Zeichen der Bitmap;
- Pixel_value enthält den RGB Wert des aktuell gelesenen Pixels der Bitmap;
- Char_width und Char_height sind Breite und Höhe der Zeichen;
- Particle_width setzt die Breite der Buchstaben (x-Abstand zwischen 2 Partikeln);
- Particle_height setzt die Höhe der Buchstaben (y-Abstand zwischen 2 Partikeln);
- Particle_space setzt den Abstand zwischen den Buchstaben.
Spielen Sie mit den letzten drei Werten für dünnere oder dickere Texte mit derselben Bitmap.

char_width = bmap_width(system_font) / 32;
char_height = bmap_height(system_font) / 4;
number_of_chars = str_len(my_string);
format = bmap_lock(system_font, 0);

Die obigen Zeilen berechnen char_width (jede Zeile der Bitmap enthält 32 Zeichen) und char_height (4 Zeilen insgesamt). Wir ermitteln die Anzahl der Zeichen unseres Strings und beginnen, mit unserer Bitmap zu arbeiten.

while (number_of_chars > 0) // create the particles char by char
{
temp = str_to_asc(my_string);
str_clip (my_string, 1);
char_minx = (temp % 32) * char_width;
char_miny = int(temp / 32) * char_height;
char_maxx = char_minx + char_width;
char_maxy = char_miny + char_height;

Unsere partikelbasierten Zeichen werden einer nach dem anderen erzeugt, also nutzen wir eine Schleife, die genau das tut. Wir konvertieren das erste Zeichen unseres Textes in seinen ASCII Wert und entfernen ihn aus dem String, weil wir das nächste Mal das zweite, dann das dritte Zeichen und so weiter erhalten wollen. Wir ermitteln char_minx und char_miny, also den x und y Wert, wo unser Zeichen in der Bitmap beginnt und berechnen daraus char_maxx und char_maxy.

Das Bild zeigt diese Werte für das Zeichen “C” unserer Bitmap als Beispiel.

while(char_minx < char_maxx)
{
char_miny = char_maxy - char_height;
while(char_miny < char_maxy)
{
pixel_to_vec(pixel_value, temp, format, (pixel_for_bmap(system_font, char_minx, char_miny)));
if (pixel_value > 0)
{
vec_set (temp, vector (100, 80, -5));
temp.y += (char_maxx - char_minx) * particle_width + number_of_chars * particle_space;
temp.z += (char_maxy - char_miny) * particle_height;
effect(particle_text, 1, temp, nullvector);
}
char_miny += 1;
}
char_minx += 1;
}
number_of_chars -= 1;
}
bmap_unlock(system_font);
}

Mit Hilfe zweier Schleifen malen die Partikel das Zeichen “pixelweise”; die innere Schleife ist für die Spalten verantwortlich und die andere erhöht die x-Koordinate. Mit pixel_to_vec lesen wir den RGB Wert des Pixels (pixel_value) und wenn dieser nicht ganz schwarz ist, wird ein Partikel erstellt. Mit der vec_set Anweisung setzen wir die ungefähre Position des Textes in der 3D Welt; beachten Sie bitte, dass die Textgröße von particle_width, particle_height und particle_space abhängt, also variieren Sie (x = 100, y = 80, z = -5) aus der Demo, bis diese Werte für Ihr Level passend sind. Wenn Sie die Orientierung des Textes antlang der x-Achse ändern wollen, ersetzen Sie einfach “temp.y = ...;” durch “temp.x = ...;”. Die “effect” Zeile erzeugt die Partikel; Sie können mit ent_create kleine Sprites erstellen, falls Sie Partikel hassen, aber dann können Sie die Farbe nicht mehr ändern oder was Sie sonst mit ihnen vorhaben. Number_of_chars wird verringert, um mit dem nächsten Zeichen fortzufahren. Schließlich geben wir die Bitmap wieder frei, die mittlerweile müde sein muß... das war der schwierige Teil.

Schauen wir uns die Partikelfunktion an:

function particle_text()
{
my.size = 1;
my.red = 255;
my.green = 100;
my.blue = 100;
my.function = keep_particles;
}

function keep_particles()
{
my.lifespan = 100;
}

Wenn Sie einen größeren Text erstellen wollen, ändern Sie particle_width, particle_height und particle_space, aber vergessen Sie nicht, auch die Partikelgröße anzugleichen (1 in meiner Demo). Die folgenden Zeilen setzen die RGB Kombination der Partikelfarben und die letzte Zeile von particle_text setzt die Funktion keep_particles() als Aufpasser für die Partikel ein. Diese setzt einfach die lifespan jedes Partikels permanent auf 100, wodurch die Partikel ewig leben. Sie sollten die lifespan verringern, wenn Sie verschiedene Texte am gleichen Ort anzeigen wollen.

Schauen wir uns die Funktion an, die unser Skript testet:

function test_particles()
{
str_cpy (temp_str, "Acknex rules!");
create_text(temp_str);
}

on_t = test_particles;

Drücken Sie “T”, um den Text zu sehen. Die Funktion, die zu der “T” Taste gehört kopiert den Text nach temp_str und startet die häßliche Funktion die wir besprochen haben mit unserem String als Parameter.