Anzeige
Tutorialbeschreibung

Flashteroids-Spieleentwicklung mit Actionscript

Flashteroids-Spieleentwicklung mit Actionscript

In diesem Tutorial möchte ich Euch zeigen wie man ein Arcadespiel a la Asteroids entwickelt.
Dieses Tutorial richtet sich an etwas fortgeschrittene User. Für absolute Flashneulinge ist es vielleicht zu schwer, aber ich denke hiermit kommt man ganz gut hinter die Verwendung von Actionscript.

In diesem Tutorial setze ich voraus, das Ihr:

  • mit den Werkzeugen arbeiten könnt
  • Actionscript schon einmal gesehen habt
  • eventuell ein kleines bisschen Mathe könnt

Viel Spass!


Hi Folks!

Obwohl die Meisten hier wahrscheinlich zu jung sind um aktiv Arcadegames gespielt zu haben, sollte der Name Asteroids wohl doch bekannt sein. Heute möchte ich Euch zeigen wie man ein solches Spiel in Flash entwickelt.

Für diese Tutorial solltet Ihr kein absoluter Flash Neuling mehr sein. Ihr solltet mit den Werkzeugen arbeiten können und schonmal ein oder zwei Tweens erstellt haben. Ein kleines bisschen Grundwissen in Actionscript ist bestimmt auch nicht verkehrt. Und ein paar Grundkenntnisse in Mathe können hier außerdem nicht schaden. Keine Angst, wir bleiben in 2 Dimensionen, das einzige was wir benötigen sind Sinus und Kosinus. Ich werde auf jeden Fall versuchen alles so genau und ausführlich wie Möglich zu erklären.


Vorbereitung:


Wir erstellen ein Flashdokument, nennen es Flashteroids, stellen die Framerate auf 25 Bilder, die Hintergrundfarbe bleibt weiß und die Bühnengröße stellen wir auf  600*450px.

So, dann wollen wir mal.

Zunächst ein paar Überlegungen was wir in unserem Spiel alles haben wollen.

-         Ein Hintergrundbild wäre nicht schlecht (zum Privaten Gebrauch tut es ein Bildchen aus dem Netz -Achtung Urheberrechte- also am besten von irgendeiner Stock Seite)

-         ein Bild von einem Asteroiden welches wir in einem Grafikprogramm à la Photoshop zurecht schneiden und als *.png veröffentlichen, so das nur der Asteroid, nicht aber sein Hintergrund zu sehen ist.

Wie wir diese Bilder in Flash einfügen dazu kommen wir gleich.


Schritt 1 unser Raumschiff:

Beginnen wir also mit unserem Raumschiff. Erstellen wir via Strg&F8 einen neuen MC und nennen ihn ‚ rschiff_symbol’. In diesen Zeichnen wir jetzt unser Raumschiff. Es sollte etwa 20 Pixel breit und 40 Pixel hoch sein,  mittig auf dem 0 Punkt  und mit der Nase nach Oben liegen. Gut, bestimmt hat die Welt schon bedrohlichere Raumschiffe gesehen, aber meins sieht nun mal so aus:

Bilder


Ich würde Euch empfehlen alle Bestandteile des Raumschiffes miteinander zu Gruppieren, das spart nachher deutlich Rechenleistung.

Wir werden später noch einige Veränderungen am Raumschiff vornehmen, z.Bsp. braucht jedes gescheite Raumschiff ja einen Laser. Um aber, wenn wir am Laser etc. arbeiten unser Raumschiff nicht kaputt zu machen bietet es sich an einen neuen MC zu erstellen in den wir unser ‚ rschiff_symbol’ reinlegen.

Ziehen wir also unser ‚ rschiff_symbol’ auf die Bühne, markieren es, drücken F8 und machen es so zu einem neuen MC. Diesen nennen wir ‚Raumschiff’. Wichtig ist, das wir den Harken bei ‚Export für Actionscript’ aktivieren. Als Bezeichner trägt er uns automatisch ‚Raumschiff’ ein. Wichtig ist außerdem auch hier wieder zu beachten, das sich der Schwerpunkt der Instanz ‚rschiff_symbol’ auf dem 0-Punkt des MCs Raumschiff befindet. Wir bestätigen mit OK und löschen die Instanz wieder von unserer Hauptbühne.

Schritt 2 der Anzeigebereich:

Kommen wir nun zum Weltraum. In der Vorbereitung haben wir uns ein schönes Weltraumbildchen besorgt. Dieses schneiden wir jetzt in einem Grafikprogramm auf eine Größe von 420*420 Pixel zu und speichern es als *.jpg.

Diese Bild importieren wir jetzt in Flash. Datei-> Importieren-> in Bibliothek importieren.

Jetzt ziehen wir diese Bild auf die Bühne, markieren es und drücken F8. Damit verwandeln wir es in einen Movieclip. Diesen nennen wir ‚Anzeige’. Wichtig ist nur, das wir unter ‚Registrierung’ den schwarzen Böppel in die Mitte setzen. Somit befindet sich im MC ‚Anzeige’ der Schwerpunkt unseres Hintergrundbildes genau auf dem 0-Punkt des MCs.

Bilder


Wir bestätigen mit OK und belassen die Instanz auf der Hauptzeitleiste. Hier geben wir ihr den Instanznamen ‚anzeige’. Außerdem benennen wir die Ebene auf der unsere Anzeige liegt ebenfalls als ‚Anzeige’ und sperren diese Ebene. Alle Aktionen die es später im Spiel gibt werden in dieser Anzeige stattfinden.

Schritt 3 der Asteroid:

Unseren Asteroid stellen wir in einem Grafikprogramm so frei , das kein Hintergrund mehr zu sehen ist. Außerdem skallieren wir ihn auf eine Größe von ca. 60*60px. Wir speichern den Asteroiden als *.png um die Transparenz zu erhalten. Jetzt importieren wir ihn in Flash, ziehen ihn auf die Bühne, machen einen MC daraus (markieren und Strg&F8 drücken), nennen den MC Asteroid und aktivieren wieder das Häkchen bei ‚Export für Actionscript’. Der Bezeichner ‚Asteroid’ trägt sich wieder automatisch ein. Wieder zurück auf der Hauptzeitleiste löschen wir die Instanz des Asteroiden von der Bühne.

Zusammenfassung:

 

- Auf unserer Bühne befindet sich nun nur Die Instanz unseres Weltraumbildes, verpackt in einem MC, mit dem Instanznamen ‚anzeige’
- In der Bibliothek liegen folgende MCs:

            - Anzeige
            - Unser Hintergrundbild
            - Das Bild des Asteroiden
            - der MC ‚Asteroid’
            - der MC ‚Raumschiff’
            - der MC ‚rschiff_symbol’

Kommen wir nun also zum etwas anspruchsvolleren Teil, dem Script.
Wir werden den gesamten Code so aufbauen, dass wir einen Konstruktor für unser Raumschiff erstellen und einen für unsere Asteroiden. Banal ausgedrückt schreiben wir also je eine Klasse, nur das wir diese nicht als ‚class’ auszeichnen, sondern, wie eine Methode nur als ‚function()’. Alle Elemente, die wir via Script einladen, werden in einem Array geführt. Anhand der Länge des Arrays können wir feststellen wie weit der User im Spielfortschritt ist, welche Objekte gerade aktuell sind und welches Objekt welches berührt.

Schritt 4 der erste Code:


Erstellen wir also auf der HZL (Hauptzeitleiste) eine neue Ebene und nennen sie Script. Dann markieren wir den ersten Frame in der Ebene, drücken F9 um ins Scriptfenster zu gelangen und schreiben hier erstmal ein stop(). In meinem Beispiel haben wir nur einen Frame, somit ist das stop eigentlich überflüssig, aber gehen wir einfach auf Nummer sicher.
Im Anschluss an dieses Stop erstellen wir unser Kontrollarray. Dies nennen wir Objektliste. Außerdem erstellen wir eine Variable, die unsere Eingeladenen Objekte durchgehend nummeriert. Später im Code brauchen wir auch noch die Hälfte der Breite und die Hälfte der Höhe unserer Anzeige. Was das nutzt sehen wir später.
Unsere Ersten Zeilen sehen also wie folgt aus:
stop();
var Objektliste:Array = new Array();


var InstanzNr:Number = 0;


var HalbeBreite:Number = anzeige._width/2;
var HalbeHoehe:Number = anzeige._height/2;

Jetzt beginnen wir mit dem Konstruktor ‘Raumschiff’ und dessen Aufruf. Zunächst die paar Zeilen, dann folgt die Erklärung:

Raumschiff = function (listposition) {


this.Schicht = listposition;


this.Clip = anzeige.attachMovie('Raumschiff', 'Raumschiff'+this.Schicht, this.Schicht, this);


};


Objektliste[0] = new Raumschiff(InstanzNr++);


Fangen wir von unten an. Objektliste[0] = new Raumschiff(InstanzNr++); steckt in das Array Objektliste an der IndexNr 0 ein Objekt und ruft es damit auf. Dieses Objekt ist unser Raumschiff Konstruktor ‚Raumschiff’.
An den Raumschiff Konstruktor übergeben wir den Parameter listposition. Er ist unsere vorhin erstellte InstanzNr +1. Den Übergebenen Parameter wandeln wir um in die Variable this.Schicht. this.Schicht = listposition;


In der Zeile this.Clip = anzeige.attachMovie('Raumschiff', 'Raumschiff'+this.Schicht, this.Schicht, this); Laden wir via attachMovie eine Instanz unseres Raumschiff- Objektes aus der Bib in die Anzeige, benennen es und setzen es mit this.clip gleich. Im Folgenden müssen wir also nicht immer  'Raumschiff'+this.Schicht, schreiben sondern können die Instanz ganz einfach über this.clip ansprechen.
Wie Ihr seht wird also erst im Konstruktor ein Objekt attacht, die Methode/ der Konstruktor wird aber nie direkt aufgerufen. Wir aktivieren ihn also nur dadurch, das wir ihn in das Array ‚Objektliste’ stecken.
Zu den Zeilen var HalbeBreite:Number = anzeige._width/2; und var HalbeHoehe:Number = anzeige._height/2; kommen wir wie gesagt später.

Bilder


Sollte das nicht der Fall sein vergewissert Euch, das die Anzeige auf der Bühne ihren Instanznamen ‚anzeige’ hat und das das ‚Raumschiff’ den Bezeichner ‚Raumschiff’ hat (Rechtsklick auf das Bib- Symbol und dann unter Verknüpfung )


Schritt 5 Flugvorbereitungen:



Dann wollen wir unserem Raumschiff mal das Fliegen beibringen. Erweitern wir also die Liste unserer Variablen am Anfang des Konstruktors Raumschiff (nach ‚Raumschiff = function (listposition) {‚vor ‚ this.Schicht = listposition;’ ) um folgende Einträge:

this.Richtung = 0;


this.VersatzX = 0;


this.VersatzY = 0;


this.Schub = 1;


maxGeschwindigkeit = 14;
this.verzoegerung = 0.98;


Zur Erklärung:

Anhand von  this.Richtung errechnen wir später die Flugrichtung und die Rotation unseres Raumschiffes.

this.VersatzX  gibt den Wert an um den wir später unsere x-Position erhöhen, ist also quasi unsere Geschwindigkeit auf der x-Achse. Sie wird später auf Tastendruck auf den Pfeil nach oben erhöht.
this.VersatzY  ist das selbe in Grün und gilt für die y-Achse.
this.Schub  ist der Wert mit dem wir später unseren sinus und unseren cosinus multiplizieren. Anhand der dabei errechneten Ergebnisse und anhand von this.VersatzX und this.VersatzY bestimmen wir die Bewegung auf der x- und der y- Achse.
maxGeschwindigkeit gibt die Höchstgeschwindigkeit unseres Raumschiffes vor
verzoegerung ist der Wert der unser Raumschiff verlangsamt.

So, um eine flüssige Bewegung zu erzielen haben wir ja zu Beginn unsere Framerate auf 25 Bilder gesetzt. Man sagt, das das Auge zwischen 20 und 25 Bildern pro Sekunde keine Einzelbilder mehr erkennt sondern diese in eine flüssige Bewegung umsetzt. So erstellen wir also jetzt eine onEnterFrame Prozedur in unserem Konstruktor Raumschiff in die wir alles eintragen was jeden Frame passieren soll, also das Lenken, das Bewegen, das Verzögern und das Steuern. Schreiben wir also nach dem attachen unseres Raumschiffes (this.Clip = anzeige.attachMovie…) folgende Codezeilen:

this.Clip.onEnterFrame = function() {
        this.bewegen();
        this.lenken();
};
In diesem onEnterFrame rufen wir jeden Frame  zwei Methoden auf, welche wir gleich schreiben werden. Dieses onEnterFrame findet in this.clip statt. Das hat den Vorteil, das wir nachher kein onEnterFrame löschen müssen sondern nur noch den entsprechenden Clip löschen und das onEnterFrame löscht sich automatisch mit. Der Vorteil dieser Variante wird später im Konstruktor ‚Asteroid’ deutlich.Wichtig ist, das alle Methoden, die wir jetzt schreiben werden vor dem attachen unseres Raumschiffes stehen.
Ach ja, der Einfachheit halber: Alles was wir von nun an schreiben, schreiben wir im Konstruktor Raumschiff und vor dem attachen des Raumschiffes. Sollten wir eine Zeile außerhalb dieses Konstruktors brauchen werde ich extra darauf hinweisen.

Schritt 6 Erste Flugversuche:

Beginnen wir nun mit der Methode this.lenken(). Dies ist unsere ’Steuerfunktion’, welche überprüft ob ein Steuerbutton gedrückt wird und, wenn ja, den entsprechenden Wert verändert.
Tragen wir also folgenden Code ein:

this.lenken = function() {
    if (Key.isDown(Key.LEFT)) {
            this.Richtung = (this.Richtung-10);
    }
    if (Key.isDown(Key.RIGHT)) {
            this.Richtung = (this.Richtung+10);
    }
    if (Key.isDown(Key.UP)) {

            this.beschleuningen();
    }
};

Wie bereits erklärt wird this.lenken also jeden onEnterFrame aufgerufen. Es wird jetzt also jeden Frame geprüft, ist der Pfeil Links, Hoch oder rechts gedrückt. Die Pfeile nach Links und nach rechts bestimmen den Winkel unseres Raumschiffes von der y Achse aus. Links reduziert diesen Winkel um 10° und rechts erhöht in um 10°. Der Pfeil nach oben ruft die Methode this.beschleunigen() auf, welche unsere Geschwindigkeit und unsere Positionierung festlegen wird.
Schreiben wir also schnell die Methode und kommen dann zu den Erklärungen:

this.beschleuningen = function() {
                        var Bogen = this.Richtung*Math.PI/180;
                        var SchubX = this.Schub*Math.sin(Bogen);
                        var SchubY = this.Schub*-Math.cos(Bogen);
                        var neuVersatzX = this.VersatzX+SchubX;
                        var neuVersatzY = this.VersatzY+SchubY;
                        var neuGeschwindigkeit = Math.sqrt(neuVersatzX*neuVersatzX+neuVersatzY*neuVersatzY);
                        if (neuGeschwindigkeit<maxGeschwindigkeit) {
                                   this.VersatzX = neuVersatzX;
                                   this.VersatzY = neuVersatzY;
                        }
            };


Jetzt kommt leider ein bisschen Mathe. Wir haben nämlich ein Problem. Wir haben einen Winkel, und eine Strecke (unsere Richtung und unseren Schub). Aus diesen beiden Variablen müssen wir einen Versatz auf der X und auf der Y-Achse ermitteln. Gott sei Dank haben uns so ein paar alte Griechen vor einiger Zeit die Hauptdenkarbeit abgenommen und wir müssen uns das Zeug jetzt nur noch richtig hinwursteln.
Also, die Stichworte sind Einheitskreis, Sinus und Cosinus. Erinnert Ihr Euch, Mathe, 6. oder 7. Klasse?
Was wir machen ist praktisch folgendes. Anhand unseres Winkels errechnen wir einen Punkt im Einheitskreis. Dann ermitteln wir die Position X und die Position Y dieses Punktes. Diese X- und Y- Positionen geben an um wie viel wir unser Objekt um X und Y verschieben müssen.
Alles in allem sieht das dann eben aus wie die ersten drei Zeilen unserer Methode.
Die vars var neuVersatzX und var neuVersatzY sind Hilfsvariablen anhand derer wir jetzt unsere neue Geschwindigkeit berechnen, Die Variable neuGeschwindigkeit benutzen wir nur dazu um Sie mit unserer maxGeschwindigkeit abzugleichen und, wenn neuGeschwindigkeit kleiner ist als maxGeschwindigkeit, ersetzen wir this.VersatzX durch neuVersatzX und thisVersatzY durch neuVersatzY .


Bilder

Jetzt haben wir also durch einige mathematischen Wirren mehrere Variablen definiert, beim testen unseres Flash-Films fällt aber auf, das sich trotz all der Anstrengungen noch nichts bewegt. Kommen wir also zu der im onEnterFrame aufgerufenen Methode this.bewegen().

Schritt 7 Und sie bewegt sich doch:

In this.bewegen() erhalten plötzlich alle bisher definierten Variablen einen Sinn. Die Methode schreibt sich wie folgt (wie immer im Konstruktor Raumschiff, vor dem Attachen):

this.bewegen = function() {
            this._x += this.VersatzX;
            this._y += this.VersatzY;
            this._rotation = Math.round(this.Richtung);
};

Vor der Beschreibung ein kleines Erfolgserlebniss. Wenn wir jetzt nämlich Strg&Enter (Film testen) drücken sehen wir, das sich unser Raumschiff schon bewegen lässt.

Die bisherige Datei als Download

 


 

Was ist jetzt passiert? Mit this._x += this.VersatzX; versetzen wir die Position unseres Raumschiffes um die eben aktualisierte Variable this.VersatzX;. Das selbe machen wir in der folgenden Zeile mit der y-Achse und this.VerstatzY.  Zudem gibt this._rotation die Drehung unserer Raumschiffinstanz an.

Was jetzt noch auffält ist, das das Raumschiff wenn man nicht aufpasst schnell über den Rand unseres Universums und dann auch über den Rand unseres Dokumentes rausfliegt. Um das zu verhindern müssen wir die Methode this.bewegen ein klein wenig erweitern. Herauskommen soll dabei, das ,wenn das Raumschiff den oberen Rand erreicht, es am unteren wieder auftaucht. Selbiges gilt beim rechten Rand, dann soll es links wieder erscheinen und so weiter und sofort. Wie das genau von statten gehen soll erfahrt ihr im nächsten Schritt.


Der gesamte Code sieht bisher so aus:

stop();
var Objektliste:Array = new Array();
var InstanzNr:Number = 0;
var HalbeBreite:Number = anzeige._width/2;
var HalbeHoehe:Number = anzeige._height/2;
Raumschiff = function (listposition) {
    this.Schicht = listposition;
    this.Richtung = 0;
    this.VersatzX = 0;
    this.VersatzY = 0;
    this.Schub = 1;
    maxGeschwindigkeit = 14;
    verzoegerung = 0.98;
    this.lenken = function() {
        if (Key.isDown(Key.LEFT)) {
            this.Richtung = (this.Richtung-10);
        }
        if (Key.isDown(Key.RIGHT)) {
            this.Richtung = (this.Richtung+10);
        }
        if (Key.isDown(Key.UP)) {
            this.beschleuningen();
        }
    };
    this.beschleuningen = function() {
        var Bogen = this.Richtung*Math.PI/180;
        var SchubX = this.Schub*Math.sin(Bogen);
        var SchubY = this.Schub*-Math.cos(Bogen);
        var neuVersatzX = this.VersatzX+SchubX;
        var neuVersatzY = this.VersatzY+SchubY;
        var neuGeschwindigkeit = Math.sqrt(neuVersatzX*neuVersatzX+neuVersatzY*neuVersatzY);
        if (neuGeschwindigkeit<maxGeschwindigkeit) {
            this.VersatzX = neuVersatzX;
            this.VersatzY = neuVersatzY;
        }
    };
    this.bewegen = function() {
        this._x += this.VersatzX;
        this._y += this.VersatzY;
        this._rotation = Math.round(this.Richtung);
    };
    this.Clip = anzeige.attachMovie('Raumschiff', 'Raumschiff'+this.Schicht, this.Schicht, this);
    this.Clip.onEnterFrame = function() {
        this.bewegen();
        this.lenken();
    };
};
Objektliste[0] = new Raumschiff(InstanzNr++);

Schritt 6 Auch das Universum hat Grenzen:

Erweitern wir als wie gesagt die Methode this.bewegen um die folgenden Zeilen:

if (this._x+this.VersatzX<-HalbeBreite) {
    this._x = HalbeBreite;
}
if (this._x+this.VersatzX>HalbeBreite) {
    this._x = -HalbeBreite;
}
if (this._y+this.VersatzY<-anzeige._height/2) {
    this._y = anzeige._height/2;
}
if (this._y+this.VersatzY>anzeige._height/2) {
    this._y = -anzeige._height/2;
}

HalbeBreite ist die halbe Breite unserer Instanz anzeige, also unseres Universums. HalbeHoehe die Hälfte der Höhe. Da sich der 0 Punkt unserer Anzeige ja in diesem Fall genau in der Mitte befindet, befindet sich der rechte Rand der Anzeige auf – HalbeBreite .Wir prüfen also in mehreren ifs ob sich das Raumschiff, nach dem wir VersatzX und VersatzY aufrechnen, auf einer X- Position befindet die kleiner als -HalbeBreite oder höher als HalbeBreite ist. Oder ob es sich auf einer Y- Position befindet, die niedriger als -HalbeHoehe oder höher als HalbeHoehe ist. Sollte eine dieser Bedingungen zutreffen, so wird das Raumschiff auf die Gegenüberliegende Seite des Anzeigebereichs versetzt.
Wenn Ihr Strg& Enter drückt wisst Ihr was ich meine.


Et voila, unser Raumschiff fliegt und kennt seine Grenzen. Außerdem haben wir einen guten Teil diese Tuts geschafft. Ich würde sagen es wird jetzt ist erstmal Zeit für eine Kaffeepause.
Für alle diejenigen, die in den letzten Schritten Probleme hatten hänge ich im folgenden noch mal eine Datei an, die sich auf dem jetztigen Stand des Tutorials befindet. Ihr könnt diese gerne saugen und damit von jetzt an wieder mit weitermachen.

Die bisherige Datei als Download

Schritt 7 Kaffeepause:

Schritt 8 ein bisschen was fürs Auge:



Jetzt haben wir uns die letzte Zeit so mit Code rumgeschlagen, ich denke es wird mal wieder Zeit für ein bisschen gestalterische Arbeit. Zunächst braucht jedes richtige Raumschiff einen Antrieb. Begeben wir uns also in den MC ‚Raumschiff’ und erstellen dort eine neue Ebene. Diese Ebene nennen wir ‚Antrieb’ und ziehen sie unter unsere Ebene in der das Raumschiff liegt. Btw. Wenn Ihr die Ebenen in denen Ihr nicht arbeitet sperrt erspart Ihr Euch hin und wieder ne Menge Stress.

In unserer Ebene ‚Antrieb’ erstellen wir unterhalb der ‚Düsen’ unseres Raumschiffes zwei Feuerscheine. Am Besten erreicht Ihr das durch zwei Formen, die Ihr mit einem Verlauf füllt. Bei mir sieht das in etwa so aus.:

Bilder

Jetzt markieren wir die beiden Formen und machen Sie via F8 zu einem Symbol. Dies nennen wir ‚Triebwerk’, geben ihm die Eigenschaft Movieclip und bestätigen mit Ok. Der Instanz von ‚Triebwerk’ im MC ‚Raumschiff’ geben wir den Instanznamen ‚antrieb’. Jetzt klicken wir doppelt auf diese Instanz auf der Bühne um eben in den MC ‚Triebwerk’ zu gelangen, wir aber den Hintergrund und unser Raumschiff noch erkennen können. Im Mc ‚Triebwerk’ erstellen wir eine neue Ebene und nennen diese ‚Script’. Die Ebene in der unser Feuerschein liegt nennen wir ‚Feuer’. Jetzt erstellen wir in der Ebene Feuer einen neuen Keyframe bei Frame 5. Im ersten Frame der Ebene ‚Feuer’ verkleinern wir die beiden Formen so, das Sie mit der oberen Kante unter dem Antrieb des Raumschiffs liegen, aber ganz klein sind.

Jetzt klicken wir in einen Frame zwischen unseren beiden Keyframes und wählen im Eigenschafteninspektor unter ‚Tween’ ‚Form’ aus. Achtung, bitte seid vorsichtig, das Ihr nicht zufällig auf  ‚Bewegung’ einstellt, hierbei wird nämlich aus unserer Form ein weiterer MC und das wollen wir nicht, außerdem ist ein Formtween, wie der Name schon sagt nur mit Formen, nicht aber mit MCs möglich.

So, jetzt klicken wir auf den ersten Keyframe in der Ebene ‚Feuer’, halten die linke Maustaste gedrückt, drücken jetzt zusätzlich ALT und ziehen diesen Keyframe auf Frame Nummer 10. Neben unserem Mauszeiger sollte solange ALT gedrückt wird ein Pluszeichen zu sehen sein. Das bedeutet wir kopieren unseren ‚gedragten’ Frame an die Stelle an der wir die Maus loslassen. Also, über Frame Nummer 10 lassen wir die Maustaste los. Jetzt haben wir in der Ebene ‚Feuer’ 3 Keyframes. Im ersten Keyframe ist unser Feuer klein, im 2ten Keyframe (Framenummer 5) ist unser Feuer normal groß und im dritten Keyframe (Bild 10) ist es wieder klein. Jetzt klicken wir wieder in einen Frame zwischen dem 2ten und dem dritten Keyframe (zwischen Bild 5 und 10) und wählen wieder im Eigenschafteninspektor unter ‚Tween’ ‚Form’ aus. Wenn Ihr den Timeslider jetzt hin und her zieht, dann sollte sich das ‚Feuer’ vergrößern und verkleinern. 

Bilder

Begeben wir uns also in die Ebene ‚Script’ im MC ‚Triebwerk’. Hier benötigen wir im ersten  und im sechsten  Frame je ein stop(); (Frame anklicken, F9 drücken, stop() eintragen). So, jetzt schieben wir den ersten Frame der Ebene ‚Feuer’ auf Frame Nummer 2, so das in Frame Nummer eins ein leerer Keyframe liegt. Den Keyframe an Frame 5 schieben wir auf Frame 6. In der Ebene ‚Script’ setzten wir je einen Keyframe in Bild Nr. 2 und in Bild Nummer 7. Dem Key im zweiten Frame geben wir die Bildbezeichnung ‚auf’ und dem auf Bild Nummer 7 geben wir die Bezeichnung ‚zu’.

Das ganze sollte jetzt in etwa so aussehen:

Bilder


Schritt 9 Gas geben:

Jetzt brauchen wir noch eine Steuerfunktion für unser Triebwerk.

Begeben wir uns also wieder auf die Hauptzeitleiste und dort wieder in den Frame ‚Script’ in dem wir unsere Aktionen eintragen. Frame markieren, F9 drücken und das Actionsfenster öffnet sich.

Eigentlich ist die Hauptarbeit für unsere Antriebssteuerung ja schon getan. Wir prüfen zumindest schon mal ab ob der User ‚Gas’ gibt. Erinnert Ihr Euch? Das war das mit den ganzen if() in der Methode this.lenken, im Konstruktor ‚Raumschiff’.
Dort steht im Moment noch if (Key.isDown(Key.UP)) {this.beschleuningen();}. Dieses if erweitern wir jetzt einfach (nach this.beschleunigen, vor der }) um folgende Zeile:

this.antrieb.gotoAndPlay('auf');

Wenn wir den Film jetzt testen sehen wir, das, wenn wir Gas geben, der Antrieb auch schön anfängt zu leuchten. Jetzt müssen wir nur noch etwas schrauben damit er auch wieder aufhört, wenn man die Taste ‚UP’ loslässt.
Am bequemsten sollte sich das über ein ‚else’ nach unserem if() erreichen lassen. Also, wenn die Taste ‚UP’ nicht gedrückt ist, dann soll der Antrieb nicht leuchten.
Im Grunde könnte die entsprechende Bedingung wie folgt aussehn:

else {
    this.antrieb.gotoAndPlay('zu');
}

Vom Prinzip her ist das auch richtig, wenn wir aber unseren Film testen fällt auf, das der Antrieb sich dauernd auf der Position ‚zu’ befindet, aber leider nicht zugeht. Außerdem ist der Antrieb, solange wir auf ‚UP’ bleiben, nur auf der Position ‚auf’ und springt dann direkt auf die Position ‚zu’ sobald wir ‚UP’ loslassen.
Das liegt daran, das wir die Überprüfung ob ‚UP’ gedrückt ist ja jeden Frame aufs neue durchführen, er also jedes onEnterFrame merkt: Aha, ‚Up’ ist nicht gedrückt, also springe ich im Film Antrieb auf ‚zu’. Oder eben, ‚UP’ ist gedrückt, da spring ich mal ganz brav auf ‚auf’. Wie könnten wir jetzt also erreichen das er das nur einmal, nach loslassen oder bei drücken der Taste ‚UP’ tut? Am Besten wird hier wohl sein, wir schaffen uns eine Hilfsvariable (nennen wir sie ‚antriebspruef’). Diese setzen wir bei Druck auf ‚UP’ auf true, prüfen in dem else ob sie wirklich true ist, lassen den Antrieb auf ‚zu’ springen und setzen dann direkt die Hilfsvariable auf False.
Alles in allem stell ich mir das in etwa so vor:

if (Key.isDown(Key.UP)) {
    this.beschleuningen();
    if (!antriebspruef) {
        this.antrieb.gotoAndPlay('auf');
        antriebspruef = true;
    }
} else {
    if (antriebspruef) {
        this.antrieb.gotoAndPlay('zu');
        antriebspruef = false;
    }
}

Prinzip verstanden? Beim ersten Durchlauf der onEnterFrame ist antriebspruef noch nicht bekannt, also sagt Flash dem MC antrieb’ er solle doch bitte auf ‚auf’ springen, setzt aber gleichzeitig die Hilfsvariable auf true. Bleibt die Taste ‚UP’ gedrückt, so durchläuft er das nächste onEnterFrame, merkt das antriebspruef schon auf true ist und ignoriert also die Anweisungen in unserem if(!antriebspruef)-Block. Das selbe geht in dem else von Statten, nur das er hier prüft ob antriebspruef true ist und es dann auf false setzt Damit hätten wir nun also unserem Raumschiff ein Triebwerk verpasst.

So, jetzt gibt es im Weltraum zwar keine Reibung und keinen Wiederstand. Ich aber fände es trotzdem schön, das, wenn unser Raumschiff keine Schub bekommt es langsamer wird.
Wir haben ja schon zu Anfang die Variable this.verzoegerung festgelegt. Wir werden jetzt also wenn die ‚Up’ Taste nicht gedrückt ist die Variable mit unserer Geschwindigkeit multiplizieren. Da this.verzoegerung kleiner als 1 ist verringern wir durch die Multiplikation unsere Geschwindigkeit.

Tragen wir also noch in unser else folgende Zeilen hinzu:

this.VersatzX = this.VersatzX*this.verzoegerung;
this.VersatzY = this.VersatzY*this.verzoegerung;

Die Variablen this.VersatzX und this.VersatzY die wir zur Berechnung unseres Versatzes nutzen werden also reduziert und ds Raumschiff wird langsamer.

Schritt 10 Geil, Ballern:

Nachdem jetzt unser Raumschiff fliegt, wir es steuern können und wir einen fetzigen Antrieb dran geschraubt haben, wird es langsam Zeit, das wir uns bewaffnen. Schließlich will man ja nicht ganz so doof dastehen wenn dann mal die Vogonen vorbeischauen.
Bauen wir doch für den Anfang mal einen Laser ein. So ein Laser an sich ist schon ein schlagendes Argument und macht auch wirklich was her. Doch wie kriegen wir den jetzt an unser Raumschiff?
Begeben wir uns in unseren MC ‚Raumschiff’. Hier sperren wir die beiden Ebenen ‚Raumschiff’ und ‚Abtrieb’, erstellen eine neue Ebene und nennen diese ‚Laser’.
In dieser Ebene zeichnen wir eine senkrechte, rote Line an der Spitze unseres Raumschiffs. Diese Linie sollte so liegen, das ihr Mittelpunkt ziemlich genau an der äußersten Kante unseres Raumschiffs liegt. Die Länge der Linie ist erstmal egal, um die werden wir uns gleich kümmern. Bei mir sieht das jetzt so aus:


Bilder

Diese Linie verwandeln wir in einen MC (markieren, F8 drücken), nennen diesen ‚Laser’ und geben der Instanz den Instanznamen ‚laser’.
Mit einem Doppelklick auf die Instanz auf der Bühne gelangen wir in den MC ‚Laser’. Jetzt verschieben wir den ersten Frame eins nach Links (also in den zweiten Frame) und nennen die Ebene ‚Laser’. Außerdem erstellen wir eine neue Ebene, nennen sie ‚Script’ und schreiben in den ersten Frame ein stop();.
Dann begeben wir uns in den zweiten Frame der Ebene ‚Laser’. Wir markieren unsere Linie und konvertieren sie in eine Form. Modifizieren -> Form -> Linien in Füllungen konvertieren. Wir haben jetzt zwar immer noch eine Rote Linie, diese verhält sich aber nicht mehr wie eine Linie sondern wie eine Form. Wenn wir sie jetzt gleich in einen MC verwandeln und diesen dann skallieren wird klar wo einer der Unterschiede liegt. Markieren wir also unsere Linie, drücken F8 und nennen den MC ‚ Laserhittest’. Was es mit der Endung ‚hittest’ auf sich hat dazu später mehr, wenden wir uns erst einmal der Animation unseres Lasers zu. Wir geben der Instanz von ‚ Laserhittest’ im Mc ‚Laser’ noch den Instanznamen ‚laserhittest’ und skallieren sie wie folgt: Höhe 5px, X:0 Y :-2.5.
Jetzt erstellen wir einen neuen Keyframe in Frame 5. Hier geben wir der ‚laserhittest’ Instanz eine Höhe von 300px, und eine Y-Position von -300px. Hätten wir die Linie vorhin nicht in eine Füllung konvertiert, so würde uns als Bemaßung zwar eine Breite von 0px angegeben, die Linie im MC ‚Laserhittest’ hätte sich aber relativ zu ihrer Länge auch in der Breite verändert und wir hätten bei 300px Höhe nicht nur einen langen- sondern auch einen verdammt breiten Laser. Nun klicken wir noch mit der rechten Maustaste in einen Frame zwischen den beiden Keyframes und wählen ‚Bewegungs- Tween erstellen’. Eigentlich ist damit unser Laser fertig, wir müssen nur noch einen Taste fürs ‚feuern’ einstellen. Das machen wir genau dort wo auch alle unseren Tasten festgelegt sind, also in der Methode this.lenken() in unserem Haptcode.
Begeben wir uns also wieder auf unsere Hauptzeitleiste in unseren Script. Hier erweitern wir die Methode this.lenken(), im Konstruktor ‚Raumschiff’ um folgende Zeilen:

if (Key.isDown(Key.SPACE)) {
    this.laser.play();
}

Wie Ihr seht wird wieder via if abgefragt ob die Taste Space gedrückt wird und sollte das der Fall sein wird der Laser abgespielt. Damit hätten wir unser Raumschiff fertig zum Einsatz, fehlen nur noch unsere Gegner.
Zur Kontrolle hier aber noch einmal ein File, der sich auf dem momentanen Stand der Dinge befindet.

Die bisherige Datei als Download


Schritt 11 Gegner, keine Opfer:

Dann wollen wir doch mal ein paar Asteroiden ins Spiel bringen. Ihr erinnert Euch noch wie wir ganz zu Anfang den Konstruktor ‚Raumschiff’ erstellt haben  und Ihn einfach dadurch das wir ihn an ein Array angehängt haben auf die Bühne gezaubert haben? Genau so verfahren wir jetzt auch mit unseren Asteroiden. Wir bilden den Konstruktor, attachen in ihm den Asteroiden und steuern den Asteroiden aus dem Konstruktor heraus. Dann stecken wir den Konstruktor in unser Array ‚ Objektliste’ und schon sollten wir einen Asteroiden auf der Bühne haben. Da sich die Vorgehensweise nur ganz wenig von der des Raumschiffs unterscheidet und wir das ja wirklich schon gut durchgekaut haben, werde ich den folgenden Code nicht ganz so intensiv behandeln und erst wieder bei den Methoden des Konstruktors ausführlich beschreiben.

Schreiben wir also, diesmal außerhalb des Konstruktors Raumschiff(!!), folgenden Code:

Asteroid = function (PlatzNr, Ord, px, py) {
    this.Schicht = PlatzNr;
    this.Ordnung = Ord;
    this.Spin = (Math.random()*20)-10;
    this.Richtung = 0;
    this._x = px;
    this._y = py;
    this.VersatzX = Math.random()*10-5;
    this.VersatzY = Math.random()*10-5;
    this._rotation = 0;
    this._x = Math.round(this._x);
    this._y = Math.round(this._y);
    this.bewegen = function() {
        if (this._x+this.VersatzX<-HalbeBreite) {
            this._x = HalbeBreite;
        }
        if (this._x+this.VersatzX>HalbeBreite) {
            this._x = -HalbeBreite;
        }
        if (this._y+this.VersatzY<-HalbeHoehe) {
            this._y = HalbeHoehe;
        }
        if (this._y+this.VersatzY>HalbeHoehe) {
            this._y = -HalbeHoehe;
        }
        this._X += this.VersatzX;
        this._y += this.VersatzY;
        this.Richtung = Math.round(this.Richtung+this.Spin)%360;
        this._rotation = Math.round(this.Richtung);
    };
    this.Clip = anzeige.attachMovie('Asteroid', 'Asteroid'+this.Schicht, this.Schicht, this);
    this.Clip._width = this.Clip._width/this.Ordnung;
    this.Clip._height = this.Clip._height/this.Ordnung;
    this.Clip.onEnterFrame = function() {
        this.bewegen();
    };
};

Wie Ihr seht ist das im Prinzip genau der selbe Stiefel wie der Konstruktor Raumschiff. Wir übergeben zwar ein paar Parameter mehr und deklarieren zu Beginn ein paar Variablen mehr. Aber wir haben wieder unser onEnterFrame in dem wir die Methoden aufrufen in denen wir die Aktionen des Asteroiden steuern. Fangen wir oben an:
Asteroid = function (PlatzNr, Ord, px, py) { Während wir im Konstruktor Raumschiff nur einen Parameter empfangen, empfangen wir hier gleich 4.
PlatzNr wandeln wir in der zweiten Zeile um in this.Schicht. this.Schicht ist die Tiefe in die der MC ‚Asteroid’ attacht wird. Ord wird in this.Ordnung umgewandelt. Diese Variable brauchen wir später. Anhand ihrer werden wir den Asteroiden skallieren. Dazu später mehr. Die Variablen px und py verwenden wir um unser Raumschiff zu positionieren: this._x = px; und this._y = py; 
In den Zeilen this.VersatzX = Math.random()*10-5; und this.VersatzY = Math.random()*10-5; geben wir unserem VersatzX und VersatzY einen zufälligen Wert zwischen -5 und 5. Vorhin in ‚Raumschiff’ waren diese Variablen durch das Userverhalten definiert. Unserem Asteroiden geben wir aber die Möglichkeit so schnell wie er halt Bock hat und wohin er eben will zu fliegen. Es folgt wieder die Funktion this.bewegen(); in der wir unseren Asteroiden auf die gegenüberliegende Seite setzen, wenn er über den Rand der Anzeige hinaus will. Dann attachen wir unsere Instanz des Asteroiden auf die Bühne.
Mit this.Clip._width = this.Clip._width/this.Ordnung; und  this.Clip._height = this.Clip._height/this.Ordnung; skallieren wir unseren Asteroiden in dem wir seine vorgegebene Höhe und Breite durch this.Ordnung teilen. Dazu später mehr.
Danach folgt unser onEnterFrame in dem wir bisher die Methode this.bewegen() aufrufen. Jetzt müssen wir nur noch unseren Asteroiden an das Array ‚Objektliste’ anhängen um ihn auf die Bühne zu bringen. Schreiben wir also unter die Zeile Objektliste[0] = new Raumschiff(InstanzNr++); :

Objektliste[1] = new Asteroid(InstanzNr++, 1, 100, 100);

Ach nehmen wir doch besser gleich zwei Asteroiden:

Objektliste[2] = new Asteroid(InstanzNr++, 1, 200, 200);

Wir testen den Film und siehe da, zwei Asteroiden kreuzen unsere Wege.
Dann fangen wir mal an etwas kaputt zu machen.


Die bisherige Datei als Download


Schritt 12 Treffer!:

Dann wollen wir doch mal auf Asteroidenjagd gehen. Wir werden jetzt im Asteroiden eine neue Methode schreiben. Diese rufen wir im onEnterFrame auf. In der Methode überprüfen wir ob der Asteroid den MC ‚laserhittest’ im Laser unseres Raumschiffes berührt.
Schreiben wir erst den Aufruf ins onEnterFrame in Konstruktor ‚Asteroid’:

this.getroffen();

und schreiben die Methode außerhalb des onEnterFrame im Konstruktor Asteroid, vor dem attachen:

this.getroffen = function() {
    if (this.hitTest(anzeige.Raumschiff0.laser.laserhittest)) {
        this.zerstoeren();
    }
};

Wie Ihr seht wird in der Zeile if (this.hitTest(anzeige.Raumschiff0.laser.laserhittest)) { abgefragt, ob der entsprechende Asteroid (this) den laserhittest im Laser unseres Raumschiffes berührt (hitTest). Sollte das der Fall sein so wird this.zerstoeren() aufgerufen. Und this.zerstoeren() werden wir jetzt gleich schreiben. Zunächst aber noch eine kleine Anmerkung zu dem Hittest. Diese Variante die ich hier genommen habe ist äußerst ungenau, da sie auf den Rahmen des Objektes reagiert. So wird bei einem Kreis nicht der Kreis als reaktive Fläche erkannt sondern sein kompletter Bereich (also der Kasten der zu sehen ist wenn man einen MC markiert).  Es gäbe jetzt die Möglichkeit mehrere MCs als Hittestbereich anzulegen und diese Abzufragen. Oder aber man verwendet die Methode

this.hitTest(objekt._x, objekt._y, true). Damit wird zwar in etwa die Form erkannt, im anderen MC wird aber nur der 0-Punkt als reaktive Fläche genommen, heißt es würde nur ein true zurückgegeben, wenn wir den Asteroiden genau in der Mitte treffen. Ab Flash 8 wird noch eine Bitmapklasse angeboten die einen Hittest ermöglicht. Dies zu erklären würde aber hier den Rahmen sprengen, bitte habt dafür Verständniss.

Schreiben wir aber jetzt unsere Methode this.zerstoeren(). Tragen wir also im Konstruktor Asteroid folgenden Code ein:

this.zerstoeren = function() {
    if (Ord<4) {
        Objektliste[Objektliste.length] = new Asteroid(InstanzNr++, Ord*2, this._x, this._y);
        Objektliste[Objektliste.length] = new Asteroid(InstanzNr++, Ord*2, this._x, this._y);
    }
    Objektliste.splice(this, 1);
    removeMovieClip(this);
};

Mit if (Ord<4) { gewährleisten wir, das jeder Asteroid nur 2 mal zersplittern kann. Würden wir das nicht abfragen hätten wir spätestens nach dem dritten oder vierten zersplittern mikroskopisch kleine Asteroiden. Ord war die Ordnungsnummer die wir als Parameter beim Aufruf des Konstruktors Asteroid als 1 übergeben und anhand derer wir den Asteroiden skallieren (siehe oben this.Clip._width = this.Clip._width/this.Ordnung;). Mit Objektliste[Objektliste.length] = new Asteroid(InstanzNr++, Ord*2, this._x, this._y); hängen wir an unsere Objektliste einen neuen Asteroiden an, übergeben als Parameter die Momentane Ord mal 2 (beim ersten mal 1) und übergeben außerdem die momentane Position des gerade zerstörten Asteroiden. Da ein Asteroid in zwei Teile zersplittert führen wir diesen Aufruf eben zwei mal durch.
Außerhalb unseres if() entfernen wir zuerst unseren grossen Asteroiden aus unserem Objektarray Objektliste.splice(this, 1); und löschen den Movieclip von der Bühne removeMovieClip(this);
Wenn wir den Film jetzt testen sehen wir, das unser Asteroid, sobald wir ihn treffen, sich in 2 Teile zerlegt. Die wieder eine eigene Flugbahn einschlagen, eine eigene Rotation haben und bei einem Treffer nochmals zersplittern.
So, jetzt sollen sich die armen Asteroiden auch noch wehren können. Wir wollen also, das unser Raumschiff schaden nimmt, wenn ein Asteroid es berührt.

Schritt 13 eine Pause vom Code:

Begeben wir uns zunächst in den MC ‚Raumschiff’. Wir markieren unser Raumschiff im MC ‚raumschiff’ und nehmen es mit Strg&C in den Zwischenspeicher. Jetzt erstellen wir eine neue Ebene, nennen diese ‚Hittest’ und fügen unser Raumschiff mit Strg&Shift&V an der selben Position ein. Die Instanz nennen wir ‚hittest’. Ihr werdet Euch sicher fragen was uns das bringt das wir das Raumschiff jetzt zwei mal auf der Bühne haben, einmal instanziert und einmal nicht. Ganz einfach, wenn ein Asteroid unser Raumschiff berührt, oder gar durch es hindurchfliegt, so kann es passieren, das beim nächsten onEnterFrame der Asteroid das Raumschiff immer noch berührt, und somit durch eine Kollision 2 Leben verloren gehen. Bestimmt habt ihr auch schon einmal gesehen wie in einem Spiel eine Figur, nachdem Sie getroffen wurde, eine kurze Zeit lang blinkt und über diese Zeit nicht verwundbar ist. So etwas wollen wir uns jetzt bauen.
Erstellen wir uns also zunächst eine neue Ebene, im MC Raumschiff, die wir ‚Script’ nennen.
In diese Ebene schreiben wir in den ersten Frame ein stop(). Jetzt legen wir in den Ebenen ‚Hittest’, Laser und ‚Antrieb’ jeweils in den zweiten Frame je einen leeren Keyframe (F7). In der Ebene ‚Raumschiff’ erstellen wir in Frame 6 und Frame 10 je einen leeren Keyframe.
Das sollte in etwa so aussehn:

Bilder


Jetzt markieren wir in der Ebene Raumschiff alle Frames, ziehen sie mit gedrückter Alt- Taste nach rechts und legen Sie rechts bündig an die bereits existierenden Frames.

Bilder

Jetzt haben wir also in der Ebene ‚Raumschiff’ 20 Bilder. Diese Markieren wir wieder alle und ziehen sie wieder mit gedrückter Alt- Taste nach rechts und legen sie wieder neben die anderen Frames. Womit wir 40 Bilder in der Ebene ‚Raumschiff’ hätten. Wenn wir jetzt Enter drücken sehen wir das unser Raumschiff 4 mal blinkt.
Wenn jetzt also unser Raumschiff mit einem Asteroiden kollidiert sagen wir einfach dem MC Raumschiff er solle abspielen. Da der Hittest aber nur im ersten Frame existiert wird unsere Hittest Abfrage in der Zeit in der das Raumschiff blinkt, kein true zurückgeben und es wird auch  kein Leben abgezogen.
Jetzt erstellen wir noch in der Ebene ‚Script’ im MC ‚Raumschiff’ einen Keyframe in Bild 40 und schreiben dort hinein:

gotoAndStop(1);

Schritt 14 auch hier kein Code:

Jetzt braucht so ein Raumschiff natürlich noch einen Schutzschild. Den wollen wir uns jetzt bauen. Erstellen wir also wieder im MC ‚Raumschiff’ eine neue Ebene und nennen sie ‚Schild’. In dieser Ebene erstellen wir einen Keyframe in Bild 41. Zudem nehmen wir wieder den ersten Frame der Ebene ‚Raumschiff’ und draggen ihn wieder mit gedrückter Alt-Taste in Bild 41.
In der Ebene ‚Schild’ malen wir jetzt eine Kreisform über unser Raumschiff. Ich habe bei diesem Kreis einen Radialen Verlauf verwendet. Beiden Farben dieses Verlaufs habe ich einen Alphawert von ca 70% gegeben, damit unser Raumschiff darunter noch sichbar ist. Ausserdem hat der Kreis keine Umrandung.
Wenn Ihr wollt könnt Ihr natürlich diesen Kreis noch in einen MC umwandeln und den Schild dann in diesem MC animieren.
Jetzt erstellen wir noch einen Keyframe in der Ebene ‚Script’, wieder in Bild 41, tragen dort ein stop() ein und benennen diesen Frame als ‚schild’

Bilder


Da man in den meisten Arcadegames ja eine bestimmte Anzahl an Leben hat wollen wir das später auch noch in unseren Code mit einbaun. Wir erstellen jetzt nur schonmal die Grafiken, die wir brauchen, wenn unser Raumschiff kein Leben mehr übrig hat und explodiert.
Erstellen wir also wieder im MC ‚Raumschiff’ eine neue Ebene und nennen sie ‚Explosion’.
In dieser Ebene erstellen wir einen Keyframe in Bild 42. Ausserdem erstellen wir auch in der Ebene Script einen Keyframe in Bild 42 und geben diesem Frame die Bildbezeichnung ‚explosion’. Jetzt benötigen wir die Grafik eines Feuerballs. Ihr könnt Euch diesen Feuerball entweder in Flash malen, oder ihn saugen und in einem Grafikprogramm freistellen.
Ziehen wir also unsere Grafik ‚feuer’ in die Ebene ‚Explosion’ ins Bild 42. Der Feuerball sollte in etwa so groß sein wie unser Raumschiff und auch mit seinem Schwerpunkt auf 0*0 Pixel ausgerichtet sein. Jetzt Markieren wir die Frames 43 bis 50 in der Ebene ‚Explosion’ und fügen hier Keyframes ein (F6). In jedem dieser Keyframes rotiert Ihr den Feuerball in eine Beliebige Richtung und vergrössert oder verkleinert ihn ein bisschen. Mit einem Druck auf Enter könnt Ihr testen ob die Explosion gut (einem Arcadegame entsprechend) aussieht.
In der Ebene Script erstellen wir einen neuen Keyframe bei Bild 50 und tragen hier folgendes ein:

removeMovieClip(this);

Damit löschen wir, nach ablauf unserer Explosion den kompletten MC ‚Raumschiff’ von unserer ‚anzeige’. Somit müssen wir in unserem ‚Hauptcode’ nicht abfragen, ob der MC schon die Explosion abgespielt hat.

 


Schritt 15 Kaffepause:


Jetzt haben wir unser Tutorial fast überstanden und wollen uns doch vor dem Endspurt glatt noch ein Tässchen Kaffee gönnen.:-)

Die bisherige Datei als Download


Schritt 16 Eisberg backboard voraus:

Dann wollen wir doch die eben erstellten Grafiken und Effekte mal im Spiel unterbringen.
Begeben wir uns also wieder in die Hauptzeitleiste in unsere Aktionen und erweitern zunächst unseren Konstruktor ‚Asteroid’.
Schreiben wir in die Methode this.getroffen() folgende Zeilen:

if (this.hitTest(anzeige.Raumschiff0.hittest)) {
    anzeige.Raumschiff0.play();
}

Sobald also ein Asteroid den Raumschiffhittest berührt wir der MC ‚Raumschiff’ abgespielt. Wir sehen also unser Raumschiff blinken, an Frame 20 wird der MC wieder in Frame 1 gesetzt und das Raumschiff hört auf zu blinken. In der eben geschriebenen if()- Schleife werden wir gleich (im Schritt ‚Statistiken’) auch ein Leben abziehen oder, wenn keine Leben mehr vorhanden sind, den MC ‚Raumschiff’ auf den Frame  ‚explosion’ setzen.
Zunächst wenden wir uns aber noch unserem Schild zu.
Da wir ja nicht wollen, das der User dauernd mit hochgefahrenen Schilden unterwegs ist, erstellen wir uns noch eine Variable, die die Dauer des aktivierten Schildes bestimmt. Schreiben wir also in eine der ersten Zeilen unseres Codes:

var Schilddauer:Number = 3000;
var Maxschild:Number = 3000;

Die Zahl 3000 gibt die Zeit in Millisekunden an. Also kann unser Raumschiff den Schild 3 Sekunden lang aktiv lassen.
Als Erstes brauchen wir eine Taste auf die unser Schild aktiv wird. Da sie noch nicht belegt ist nehmen wir die Taste mit dem Pfeil nach unten. Wir haben ja im Konstruktor ‚Raumschiff’ schon eine Methode die unsere Tasten überwacht, erweitern wir also die Methode ‚this.lenken‚ im Konstruktor ‚Raumschiff’ um folgende Zeilen:

if (Key.isDown(Key.DOWN)) {
    if (Schilddauer>20) {
        this.schildfunktion();
    }
}

Hier überprüfen wir, ob unsere Variable ‚Schilddauer’ höher als 20 ist. ‚Schilddauer’ wird später onEnterFrame erhöht und in ‚schildfunktion’ nach Ablauf von ‚Schilddauer’, auf 0 gesetzt. Somit erreichen wir, das der User eben nicht dauernd die Schildfunktion nutzen kann und, wenn er sie öfter nutzt die Zeit, die der Schild aktiv ist, dementsprechend kürzer ist.
Die eben aufgerufene Methode ‚this.schildfunktion();’ schreiben wir wieder im ‚Raumschiff’ Konstruktor:

this.schildfunktion = function() {
    this.gotoAndStop('schild');
    function schildrunter() {
        anzeige.Raumschiff0.gotoAndStop(1);
        clearInterval(schildinterval);
        Schilddauer = 0;
    }
    var schildinterval:Number = setInterval(schildrunter, Schilddauer);
};

In der Methode ‚this.schildfunktion’ schicken wir also unser Raumschiff in den Frame ‚schild’. Hier kann das Raumschiff nicht schiessen, da im Frame ‚schild’ keine Instanz namens Laser existiert. Ausserdem kann unser Raumschiff nicht getroffen werden, da auch keine Instanz namens hittest existiert. Damit erklären sich die eben vorgenommenen Schritte mit den leeren Keyframes in den entsprechenden Ebenen im MC ‚Raumschiff’. Weiterhin starten wir in der Methode ‚this.schildfunktion’ noch ein Interval (var schildintervall), welches nach Ablauf von ‚Schilddauer’ die Methode ‚schildrunter’ aufruft. In ‚schildrunter’ wird der MC ‚Raumschiff’ wieder in den ersten Frame gesetzt, wo Laser, Hittest und Antrieb wieder vorhanden sind, demnach also auch angesprochen werden können. Wir löschen noch das intervall ‚schildinterval’ und setzen ‚Schilddauer’ auf 0.
Eigentlich haben wir jetzt unser Spiel so gut wie fertig. Wir müssen nur noch die Leben einbaun, die Level bestimmen, ein Punktesystem bauen und einen Game Over Screen erstellen. Fangen wir also an mit den Statistiken an:

Schritt 17 Statistiken:

Zunächst ändern wir die Hintergrundfarbe unseres Flashfilms auf Schwarz um ein schöneres Gesamtbild zu erhalten.

Dann erstellen wir einen neuen Frame in der Hauptzeitleiste, nennen ihn ‚stats’ und erstellen links oberhalb der Anzeige 3 dynamische Textfelder. Dem obersten geben wir den var-namen ‚Leben’, das in der Mitte nennen wir ‚Level’ und das untere nennen wir ‚Punkte’. Die Textfelder sollten zweizeilig sein, die Schriftfarbe und der Font sind egal (natürlich kein Schwarz). Ich habe die Textausrichtung zentriert gewählt. Zudem sollte ‚Auswählbar’ deaktiviert sein.

Bilder

Wenn Ihr Fonts verwenden wollt, die nicht zu den Standardfonts zählen, Ihr die Textfelder maskieren wollt oder Ihr diese Spiel nachher in einen anderen Flashfilm einladen wollt, denkt bitte daran die Zeichen einzubetten (Textfeld markieren und unten im Eigenschafteninspektor auf ‚Einbetten’ klicken, dann den entspr. Zeichensatz auswählen). Ausserdem solltet Ihr nicht vergessen den verwendeten Font in Eure Bibliothek zu packen.
Schreiben wir also zunächst noch ein paar Variablen an den Anfang unseres Codes:

var AnzahlLeben:Number = 3;
var AnzahlPunkte:Number = 0;
var AnzahlLevel:Number = 1;
var Laserpower:Number = 100;
var LaserMaxpower:Number = 100;

AnzahlLeben, AnzahlPunkte und AnzahlLevel dürften klar sein, zu Laserpower komme ich gleich.
Jetzt erstellen wir noch eine neue Methode, die wir statistiken() nennen. Schreiben wir also am besten vor dem Aufruf unserer Konstruktoren aber ausserhalb der Konstruktoren:

function statistiken() {
    this.onEnterFrame = function() {
        Leben = 'Leben:'+newline+AnzahlLeben;
        Level = 'Level:'+newline+AnzahlLevel;
        Punkte = 'Punkte:'+newline+AnzahlPunkte;
        if (Laserpower<LaserMaxpower) {
            Laserpower++;
        }
        if (Schilddauer<Maxschild) {
            Schilddauer += 3;
        }
    };
}

Diese Methode führt wieder onEnterFrame folgende Schritte aus:
- Die Textfelder Leben, Level und Punkte werden mit Ihren Werten und Ihrer Bezeichnung gefüttert.
- Solange Laserpower niedriger ist als der Maximalwert ‚LaserMaxpower’ wird auf ‚Laserpower’ eins aufaddiert
- Selbiges bei Schild, nur das hier jedesmal eine 3 ist.

Unter der Methode rufen wir sie am besten auch gleich auf, schreiben wir also nach function statistiken (){...}:

statistiken();

Jetzt müssen wir noch die Punkte verteilen. Ich denke 10 Punkte pro Treffer sind für den Anfang Ok. Wir werden jedes neue Level mehr Asteroiden hinzukommen lassen, also sollte es auch für einen Treffer in einem höheren Level mehr Punkte geben. Multiplizieren wir doch einfach die Levelvariable mit unseren 10 Punkten. Nur wo sollte das am Besten geschehn?
Na, ganz klar, die Punkte verteilen wir in der Methode this.zerstoeren(), im Konstruktor ‚Asteroid’. Ich habe das so geschrieben (außerhalb der if- Schleife):

AnzahlPunkte += 10*AnzahlLevel;

Wenn wir den Film jetzt testen, bemerken wir, das ein Treffer tatsächlich auch Punkte gibt. Jetzt müssen wir noch die Leben abziehn, wenn unser Raumschiff getroffen wurde. Schreiben wir das am Besten in der Methode ‚this.getroffen’. Die gesamte Methode sieht bei mir dann so aus:


this.getroffen = function() {
    if (this.hitTest(anzeige.Raumschiff0.laser.laserhittest)) {
        this.zerstoeren();
    }
    if (this.hitTest(anzeige.Raumschiff0.hittest)) {
        AnzahlLeben--;
        if (AnzahlLeben>0) {
            anzeige.Raumschiff0.play();
        } else {
            anzeige.Raumschiff0.gotoAndPlay('explosion');
            gameover();
        }
    }
};


Wie Ihr seht ziehen wir in der zweiten if- Schleife von Anzahl Leben ein Leben ab AnzahlLeben--;. Dann Fragen wir in einer weiteren if- Schleife ab, ob wir noch mehr als 0 Leben haben. Wenn ja, dann fängt das Raumschiff an zu blinken anzeige.Raumschiff0.play();

Wenn wir aber das letzte Leben verloren haben, dann wird das Raumschiff zu Frame ‚explosion’ geschickt, spielt diese ab und löscht sich am Ende der Explosion dann von selbst. (haben wir vorhin im MC ‚Raumschiff’ geschrieben, erinnert Ihr Euch? removeMovieClip(this);) Danach rufen wir noch die Methode gameover() auf, die wir später schreiben werden.

Die bisherige Datei als Download
Schritt 18 Laser und Schilde:

Zunächst kümmern wir uns noch um die Schild- und die Laserenergie. Erstellen wir auf der Hauptzeitleiste eine neue Ebene und nennen sie ‚Skalen’. In dieser Ebene ziehen wir rechts von der Anzeige zwei Rechtecke auf. Sie sollten 15px breit sein und 200px hoch. Ich habe ihnen einen blau- weiß - blauen, linearen Farbverlauf gegeben. Die Umrandung 1 Punkt stark und leicht grau gefärbt. Ausserdem habe ich die Balken leicht in der Höhe versetzt.


Bilder


Jetzt markieren wir die Füllung (nicht den Rand dazu!) des linken Rechteckes und machen Sie zu einem Movieclip.Diesen nennen wir ‚Skala’. Mit einem doppelklick gelangen wir in den MC ‚Skala’ und geben der Füllung eine Position von y -100;
Wieder zurück auf der Hauptzeitleiste müssen wir natürlich unsere Instanz wieder in den linken Rahmen einpassen, sie sitzt jetzt zu hoch. Dieser Instanz geben wir den Instanznamen ‚laserpwr’.
Aus dem rechten, unteren Rechteck entfernen wir die Füllung und ziehen uns stattdessen unseren MC ‚Skala’ auf die Bühne. Dieser Instanz geben wir den Namen ‚schildpwr’ und passen sie im unteren rechten Rahmen ein.
Unter die zwei Balken setzen wir noch je ein statisches Textfeld. In das linke schreiben wir ‚Laser’, in das rechte ‚Schild’.
Jetzt begeben wir uns wieder in den Code. Hier schreiben wir in die Methode statistiken() folgende Zeilen:

schildpwr._height = 200/Maxschild*Schilddauer;
laserpwr._height = 200/LaserMaxpower*Laserpower;


Solange also Laserpower > 10 ist kann der User schiessen und von Laserpower wird 5 abgezogen.

Fast fertig.

Jetzt müssen wir noch die Level aufbaun und einen Game Over Screen erstellen. Fangen wir mit den Leveln an.

Schritt 20 Der Levelaufbau:

Genaugenommen baun wir ja schon ein Level auf, nämlich das Erste. Alle weiteren Level können wir eigentlich generieren indem wir den vorhandenen Code ein klein bisschen Umbaun.
Zunächst machen wir uns an die Zeilen Objektliste[1] = new Asteroid(InstanzNr++, 1, 100, 100); und Objektliste[2] = new Asteroid(InstanzNr++, 1, 200, 200);.
Diese ersetzen wir durch folgenden Code:

var positionen:Array = new Array(-200, -150, 150, 200);
levelaufbau = function () {
    anzeige.Raumschiff0._x = 0;
    anzeige.Raumschiff0._y = 0;
    for (i=0; i<=AnzahlLevel; i++) {
        Objektliste[Objektliste.length] = new Asteroid(InstanzNr++, 1, positionen[Math.round(Math.random()*positionen.length)], positionen[Math.round(Math.random()*positionen.length)]);
    }
};
levelaufbau();

Das Array ‚ positionen’ kann der Ordnung halber am Anfang des Codes erstellt werden, wo die Methode Levelaufbau steht ist eigenltich egal, nur darf sie nicht in einem unserer beiden Konstruktoren liegen. Wichtig ist nur, das der Aufruf levelaufbau(); nach der Zeile Objektliste[0] = new Raumschiff(InstanzNr++); steht.
Der Reihe nach: Das Array beinhaltet Positionsangaben an denen sowohl x als auch y ein Asteroid bei Neustart des Levels entstehen darf. Da wir in der Methode ‚levelaufbau’ unser Raumschiff _x =0 und _y=0 setzen, verhindern wir, das Bei Levelwechsel ein Asteroid direkt auf unserem Raumschiff entsteht und wir dadurch ein Leben verlieren.
In der for-Schleife in der Methode hängen wir, solange i<= der Anzahl Level ist, einen  Raumschiffkonstruktor in unser Array ‚Objektliste’. Diesem Konsturktor übergeben wir neben der Instanznummer+1 seine Ordnungszahl und je eine, zufällig aus dem Array ausgewählte x und y Position. Jetzt müssen wir nur noch, wenn alle Asteroiden zerstört sind, die Levelzahl eins erhöhen und die Methode ‚Levelaufbau’ erneut Aufrufen um jedes Level einen Asteroiden mehr zu erhalten.

Schreiben wir also unsere Methode this.zerstoeren wie folgt um:

 

this.zerstoeren = function() {
    if (Ord<4) {
        Objektliste[Objektliste.length] = new Asteroid(InstanzNr++, Ord*2, this._x, this._y);
        Objektliste[Objektliste.length] = new Asteroid(InstanzNr++, Ord*2, this._x, this._y);
    }
    if (Objektliste.length<=2) {
        AnzahlLevel++;
        AnzahlLeben++;
        levelaufbau();
    }
    AnzahlPunkte += 10*AnzahlLevel;
    Objektliste.splice(this, 1);
    removeMovieClip(this);
};

Wir überprüfen also mit jedem this.zerstoeren ob keinAsteroid mehr in der Objektliste liegt if (Objektliste.length<=2) {. Ist das der Fall erhöhen wir Leben und Level je um eins und rufen die gerade geschriebene Methoden ‚levelaufbau’ auf.
Damit hätten wir nur noch unseren GameOverScreen zu erstellen.

Schritt 21 Game Over:

Vorhin, in der Methode ‚this.getroffen’ haben wir ja schon die Methode ‚gameover’ aufgerufen. In dieser Methode erstellen wir unseren game Over Screen.
Meiner ist recht einfach gehalten, Ihr könnt Euch natürlich austoben wie Ihr wollt.
Erstellen wir erst mit Strg&F8 einen neuen MC. Diesen nennen wir gameoverbttn und aktivieren die Option ‚Export für Actionscript’, der Bezeichner trägt sich wieder automatisch ein. In diesem MC erstellen wir ein Rechteck mit 120*40px Grösse. Der Schwerpunkt des Rechtecks sollte wieder bei 0*0px liegen, die farbe sollte weiss sein und 65% Alphawert haben.
Wir erstellen eine neue Ebene im MC ‚ gameoverbttn’ und setzen hier ein statisches Textfeld hin. Darein schreiben wir in blauer schrift ‚Nochmal’.
Jetzt begeben wir uns wieder auf die Hauptzeitleiste und wieder in unseren Code.
Hier schreiben wir ganz zum Schluss unsere Methode gameover():

gameover = function () {
    bttn = anzeige.attachMovie('gameoverbttn', 'gameoverbttn', anzeige.getNextHighestDepth(), this);
    bttn.onRelease = function() {
        Objektliste = new Array();
        InstanzNr = 0;
        Schilddauer = 3000;
        Maxschild = 3000;
        AnzahlLeben = 3;
        AnzahlPunkte = 0;
        AnzahlLevel = 1;
        Laserpower = 100;
        LaserMaxpower = 100;
        statistiken();
        Objektliste[0] = new Raumschiff(InstanzNr++);
        levelaufbau();
        removeMovieClip(bttn);
    };
};

In der Methode ‚gameover’ attachen wir also unseren MC ‚ gameoverbttn’ in unsere Instanz ‚anzeige’ und weisen ihm zu, was er onRelease ausführen soll.

Der Button setzt onRelease sämtliche relevanten Werte wieder auf Ihre Ausgangswerte, ruft den Konstrucktor ‚raumschiff’ ins Array und beginnt damit und durch den Aufruf von levelaufbau() das Spiel von neuem. Dann löscht er sich selbst von der Bühne.

Wenn wir jetzt unseren Film testen sollte eigentlich alles funktionieren. Das einzige was noch auffällt ist, das die Objekte und der Laser über die ‚anzeige’ hinausragen. Deswegen erstellen wir noch eine neue Ebene auf der Hauptzeitleiste. In dieser ebene Zeichnen wir ein rechteck, was die selbe Grösse und die selbe Position wie unsere Anzeige hat. Dann verwandeln wir diese Ebene in eine Maske und lassen damit unsere Ebene ‚Anzeige’ maskieren.

Herzlichen Glückwunsch, damit ist unser Tutorial fertig!

Die fertige Datei als Download


Schritt 22 Ein paar Worte noch:

So, das war ein ganz schönes Stück Arbeit. Ich hoffe es hat Euch ein bisschen Spass gemacht und Ihr habt ein bisschen was gelernt. Wenn Ihr Euch die Ausmasse des Tutorials anschaut, werdet Ihr hoffentlich verstehen, das ich nicht auf alles bis ins FF eingehn konnte. Ich hoffe die meisten Sachen sind dennoch gut rübergekommen und ich habe ein paar Fragen mehr beantwortet als aufgeworfen.

Solltet Ihr aber dennoch Fragen zu diesem Tutorial haben oder einfach nicht weiter kommen, dann bin ich natürlich gerne bereit Euch zu helfen. Bitte stellt Eure Fragen aber am besten im Forum und nicht hier oder via PM. Schliesslich sollen ja alle was davon haben.

Mal schaun was ich als nächstes Tut zusammenschraub. In der Überlegung sind Pong, ein Forum in Flash, Flash-HTML und CSS, Flash und simmuliertes 3D oder eine kleine Rennspielengine. Genau weiss ich das jetzt noch nicht, kommt auch ein bisschen auf meine Zeit an. Vielleicht habt Ihr ja noch Ideen oder Wünsche.

 

Sodenne, bis zum nächsten mal,

 

LG B2B


DVD-Werbung
Kommentare
Achtung: Du kannst den Inhalt erst nach dem Login kommentieren.
Portrait von Susan99
  • 22.05.2012 - 20:52

Eine gute Anleitung, verständlich erklärt. Vielen Dank!

Portrait von dastan
  • 26.04.2011 - 13:59

Super Tutorial gibt es vllt noch mehr solche Tutorials :)

Portrait von dastan
  • 26.04.2011 - 14:00

Wäre echt cool wenns mehrere geben würde...

Portrait von Dineria
  • 28.03.2011 - 20:16

Hi! Finde das Tut echt cool, allerdings habe ich ein Problem beim Nachbauen: Vor Schritt 5 bekomme ich immer folgende Fehlermeldungen, obwohl ich alles richtig gemacht haben dürfte... Voran könnte das liegen...? Danke schön mal! :-)

1067: Implicit coercion of a value of type Function to an unrelated type Class.
1188: Illegal assignment to class Raumschiff.
1136: Incorrect number of arguments. Expected 0.

Portrait von Dineria
  • 31.03.2011 - 14:05

Okay, mir wurde im Forum geholfen: Es lag daran, dass ich es mit ActionScript 3 probiert habe, das Tut aber noch unter AS2 läuft... ;-)

Portrait von juriwolf
  • 15.09.2010 - 18:07

supper, das tutorial gefällt mir sehr gut.
nachdem ich schon 2 etwas einfacher spiele mit flash und actionscript gemacht habe werde ich mich mal mit hilfe dieses tutorials an etwas größeres wagen :)

Portrait von sailsour
  • 24.04.2010 - 20:59

Sehr gute Grafik auch die Steuerung ist echt gut. Danke und weiter so.

Portrait von moiko
  • 23.01.2010 - 22:18

super tut,
ich stehe bei 2780 punkte... kann mich wer überbieten?!

Portrait von dafdrax
  • 07.01.2010 - 13:43

Sehr geniales Game und Tutorial für Fortgeschrittene User und eine sehr schöne Beschäftigung für Feiertage! Merci

Alternative Portrait

-versteckt-(Autor hat Seite verlassen)

  • 02.12.2009 - 15:17

cool, endlich mal einen einblick über sone spielentwicklung

Portrait von Litti
  • 30.10.2009 - 19:32

schöne Grafik, alles prima gemacht

Portrait von pyromenniels05
  • 15.08.2009 - 00:46

Sehr umfanreiches Tutorials! Gefällt mir, mit viel Liebe zum Detail.

Portrait von Panade
  • 22.06.2009 - 18:59

ich versuche seit gestern mich mit flash anzufreunden und findet das tutorial bisher echt genjal. nur ich muss unbedingt loswerden was ich gerade zum antrieb gefumelt habe.

der step beschreibt wie man das mit formen macht... aber wer gerne was lernen willt macht ja eh nich was der lehrer sagt hehe...
also habe da ich ein unkonventionelles raumschiff gebaut habe auch ein png als motion genommen. mit der auf funktion bei frame 1 beginnend und mit einem stop() beim ersten frame funktioniert das auch super.

aber sonst zu dem tut I LOVE IT 5 sterne

Portrait von SaLue85
  • 15.06.2009 - 14:12

Danke für das Tutorial! Hat gut geklappt..

Alternative Portrait

-versteckt-(Autor hat Seite verlassen)

  • 11.06.2009 - 15:32

super beschrieben, danke.

Portrait von Posaidon
  • 30.05.2009 - 10:54

Super Tutorial, klasse beschrieben!!

Wäre toll, wenn du mal für ein Fighting Game ein tut schreiben würdest.
Ich bin gerade dabei, komme aber bei Combos nicht weiter, da wäre es schon sehr hilfreich!!

Portrait von FlashSoft
  • 17.04.2009 - 22:24

Super Tutorial, wollte schon langemal so etwas machen. Hoffe du machst weitere Tutorials.

Alternative Portrait

-versteckt-(Autor hat Seite verlassen)

  • 27.03.2009 - 11:41

kann jemand es vieleicht zum download bereitstellen???

Alternative Portrait

-versteckt-(Autor hat Seite verlassen)

  • 22.06.2008 - 13:59

Super Tut habe es sogar einigermaßen hinbekommen^^

Alternative Portrait

-versteckt-(Autor hat Seite verlassen)

  • 19.04.2008 - 23:48

Wow super tutorial! hab ich sofort ausprobiert und ist sogar was dabei rausgekommen :-) Auch wenn mein Raumschiff bei weiter nicht so stylisch ist wie deins, hab meins schnell mit ein paar Linien und Dreiecken erstellt! Nunja das Ergebnis lässt sich sehn, vielen vielen Dank!

x
×
×