Bei Sternenscrollern/Starscroller gibt es unzählige Varianten. Ein Klassiker ist der, bei dem die Sterne von hinten auf den Betrachter zufliegen und dabei immer größer und heller werden. Genau dies geschieht im folgenden Tutorial.
Das ist unser Resultat. Wozu man das brauchen kann? Credits, um eine Handlung zu erzählen oder als Hintergrund im Hauptmenü. Man kann natürlich die Kreise auch durch Sprites ersetzen, die Farbe ändern und vieles mehr. Durch den Korridor in der Mitte haben wir auch etwas Platz für Text, ohne das die Sterne nennenswert stören würden.
Wir erstellen zunächst ein Objekt. Wir brauchen hier nur zwei Events, nämlich Create und Draw.
Create-Event
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | starsAll = 1200; starsSpeed = 0.07; distance = 100; centerX = room_width/2; centerY = room_height/2; randomize(); for(var i=0; i<starsAll; i++) { var xx = random_range(0,room_width); var yy = random_range(0,room_height); var zz = random_range(0, room_width/4); star[i, 0] = xx; star[i, 1] = yy; star[i, 2] = zz; } |
Wir definieren die Anzahl der Sterne, die Geschwindigkeit und die Distanz zur Kamera bzw. zum Betrachter. Dann geben wir noch die Mitte des Raumes an.
Daraufhin starten wir den Zufallsgenerator und füllen das Array star[]
mit zufälligen Koordinator für x
, y
und z
. Jetzt, wo wir die Startkoordinaten der Sterne haben, können wir sie zeichnen.
Draw-Event
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | draw_set_color(c_white); for(var i=0; i<starsAll; i++) { zz = star[i,2] - starsSpeed; if (zz <1) { star[i,0] = random_range(0,room_width); star[i,1] = random_range(0,room_height); zz = room_width/4; } star[i,2] = zz; var sx = star[i,0] / zz; var sy = star[i,1] / zz; var r = ((sx*sy) / room_width)/8; if (r>1.5){r=1.5;} var perspective = distance / (distance - zz); draw_set_alpha(0.2+r); draw_circle(perspective*sx+centerX, perspective*sy+centerY, r/2, 0); draw_circle(centerX-(sx*perspective), centerY-(sy*perspective), r/2, 0); draw_circle(centerX-(sx*perspective), centerY+(sy*perspective), r/2, 0); draw_circle(centerX+(sx*perspective), centerY-(sy*perspective), r/2, 0); } |
Bevor wir in die Schleife gehen, setzen wir die Farbe.
In der Schleife verändern wir die Position eines jeden Sterns, bevor wir ihn zeichnen. zz
wird um starsSpeed
reduziert, um den Stern nach vorne zu bewegen. Wenn zz
kleiner als 1 ist, bedeutet dies, dass der Stern außerhalb des sichtbaren Bereichs ist und wird daher neu positioniert:
star[i,0]
undstar[i,1]
werden zufällig innerhalb des Raums neu generiert.zz
wird aufroom_width/4
gesetzt, um den Stern wieder in den sichtbaren Bereich zu bringen.
Die aktualisierte zz
-Koordinate wird im Array star
gespeichert.
sx
und sy
berechnen die Position des Sterns auf dem Bildschirm unter Berücksichtigung der Perspektive. r
berechnet den Radius des Sterns basierend auf sx
, sy
und der Breite des Raums. Wenn r
größer als 1.5 ist, wird er auf 1.5 begrenzt.
perspective
berechnet den Perspektivenfaktor basierend auf der Entfernung zur Kamera und der aktuellen zz
-Koordinate.
draw_set_alpha(0.2+r)
setzt die Transparenz des gezeichneten Sterns abhängig von r
. draw_circle
zeichnet den Stern an vier Positionen auf dem Bildschirm, um ein leuchtendes Effekt zu erzeugen. Dadurch entsteht der coole Eindruck, man würde durch eine Art Korridor fliegen.
Kurvenbewegung
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | draw_set_color(c_white); for(var i = 0; i < starsAll; i++) { zz = star[i, 2] - starsSpeed; if (zz < 1) { star[i, 0] = random_range(0, room_width); star[i, 1] = random_range(0, room_height); zz = room_width / 4; } star[i, 2] = zz; var sx = star[i, 0] / zz; var sy = star[i, 1] / zz; var r = ((sx * sy) / room_width) / 8; if (r > 1.5) { r = 1.5; } var perspective = distance / (distance - zz); // Kurvenbewegung var angle = zz * 0.01; // Steuert die Kurvenform var radius = room_width / 16; // Radius der Kurve var curveX = cos(angle) * radius; var curveY = sin(angle) * radius; draw_set_alpha(0.2 + r); // Draw-Circle mit Kurvenbewegung draw_circle(perspective * (sx + curveX) + centerX, perspective * (sy + curveY) + centerY, r / 2, 0); draw_circle(centerX - (sx + curveX) * perspective, centerY - (sy + curveY) * perspective, r / 2, 0); draw_circle(centerX - (sx + curveX) * perspective, centerY + (sy + curveY) * perspective, r / 2, 0); draw_circle(centerX + (sx + curveX) * perspective, centerY - (sy + curveY) * perspective, r / 2, 0); } |
In diesem Beispiel wird der Code für die Kurvenbewegung hinzugefügt, indem der Winkel (angle
) und der Radius (radius
) verwendet werden. Der Winkel wird basierend auf der zz
-Koordinate berechnet und beeinflusst die Kurvenform. Der Radius definiert die Größe der Kurve. Die Variablen curveX
und curveY
berechnen die Abweichung der X- und Y-Koordinaten entlang der Kurve.
Weniger lineare Bewegung
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | draw_set_color(c_white); for(var i = 0; i < starsAll; i++) { zz = star[i, 2] - starsSpeed; if (zz < 1) { star[i, 0] = random_range(0, room_width); star[i, 1] = random_range(0, room_height); zz = room_width / 4; } // Modifikation: Zufällige Verschiebung in horizontaler und vertikaler Richtung var offsetX = random_range(-1, 1); var offsetY = random_range(-1, 1); star[i, 0] += offsetX; star[i, 1] += offsetY; star[i, 2] = zz; var sx = star[i, 0] / zz; var sy = star[i, 1] / zz; var r = ((sx * sy) / room_width) / 8; if (r > 1.5) { r = 1.5; } var perspective = distance / (distance - zz); draw_set_alpha(0.2 + r); draw_circle(perspective * sx + centerX, perspective * sy + centerY, r / 2, 0); draw_circle(centerX - sx * perspective, centerY - sy * perspective, r / 2, 0); draw_circle(centerX - sx * perspective, centerY + sy * perspective, r / 2, 0); draw_circle(centerX + sx * perspective, centerY - sy * perspective, r / 2, 0); } |
In dieser Variation werden die Sterne zusätzlich zur linearen Bewegung um einen zufälligen Wert in horizontaler und vertikaler Richtung verschoben. Die Verschiebung wird durch die Variablen offsetX
und offsetY
gesteuert, die zufällige Werte im Bereich von -1 bis 1 erhalten. Die Verschiebung wird dann auf die X- und Y-Koordinaten jedes Sterns addiert.
Durch die Hinzufügung der zufälligen Verschiebung erhalten die Sterne eine gewisse Unregelmäßigkeit in ihrer Bewegung, was den Effekt interessanter und lebendiger macht.
Farbvariation
Machen wir es bunt. Hierzu müssen wir auch das Create-Event anpassen.
Create-Event
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | starsAll = 1200; starsSpeed = 0.07; distance = 100; centerX = room_width / 2; centerY = room_height / 2; randomize(); for (var i = 0; i < starsAll; i++) { var xx = random_range(0, room_width); var yy = random_range(0, room_height); var zz = random_range(0, room_width / 4); star[i, 0] = xx; star[i, 1] = yy; star[i, 2] = zz; // Modifikation: Zuweisung einer zufälligen Farbe zu jedem Stern var red = random_range(50, 255); // Zufälliger Rotwert (50-255) var green = random_range(50, 255); // Zufälliger Grünwert (50-255) var blue = random_range(50, 255); // Zufälliger Blauwert (50-255) star[i, 3] = make_colour_rgb(red, green, blue); } |
Draw-Event
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | for (var i = 0; i < starsAll; i++) { zz = star[i, 2] - starsSpeed; if (zz < 1) { star[i, 0] = random_range(0, room_width); star[i, 1] = random_range(0, room_height); zz = room_width / 4; } star[i, 2] = zz; var sx = star[i, 0] / zz; var sy = star[i, 1] / zz; var r = ((sx * sy) / room_width) / 8; if (r > 1.5) { r = 1.5; } var perspective = distance / (distance - zz); var color = star[i, 3]; // Farbe des aktuellen Sterns draw_set_alpha(0.2 + r); draw_set_color(color); // Verwenden der zugewiesenen Farbe draw_circle(perspective * sx + centerX, perspective * sy + centerY, r / 2, false); draw_circle(centerX - sx * perspective, centerY - sy * perspective, r / 2, false); draw_circle(centerX - sx * perspective, centerY + sy * perspective, r / 2, false); draw_circle(centerX + sx * perspective, centerY - sy * perspective, r / 2, false); } draw_set_alpha(1); // Zurücksetzen der Transparenz |
Man kann natürlich die RGB-Werte im Create-Event so manipulieren, dass sie nur eine bestimmte Farbschattierung hervorbringt. Möchte man bspw. Variationen von Hellblau haben, könnten die Zeilen so aussehen:
1 2 3 | var red = random_range(50, 150); // Zufälliger Rotwert (50-150) var green = random_range(100, 200); // Zufälliger Grünwert (100-200) var blue = random_range(200, 255); // Zufälliger Blauwert (200-255) |
Viel Spaß beim experimentieren!
Weiterführende Links
Horizontaler Sternenscroller und Parallax scrolling
Bitmap-Fonts im GameMaker
Sonnenblumen und der goldene Schnitt
Textscroller: Wellen und einzelne Farben