Snippets+AS3

toc

Snippets bedeutet so viel wie ** Code-Schnipsel **. Auf dieser Seite finden sie also Beispiel-Code für oft benötigte Funktionalitäten, den sie übernehmen und mit leichten Änderungen an ihr Projekt anpassen können. Alles was im Code grau erscheint sind übrigens Kommentare, die ihnen helfen sollen zu verstehen, was genau hier vor sich geht.

Auf Mouse-Ereignisse reagieren
code format="actionscript" //Instanzen mit den Namen einKnopf und einMC müssen gegeben sein einKnopf.addEventListener(MouseEvent.CLICK, pressHandler) function pressHandler(e:MouseEvent):void { einMC.visible = !einMC.visible; //schaltet die Sichtbarkeit von einMC an und aus (wird immer ins Gegenteil verkehrt) }

code

Drag & Drop von Instanzen
code format="actionscript" //Mit diesem Code bewirkt man, dass die Instanz einMC vom Benutzer per drag & drop beliebig verschoben werden kann einMC.addEventListener(MouseEvent.MOUSE_DOWN, dragStart); einMC.addEventListener(MouseEvent.MOUSE_UP, dragStop); function dragStart(e:Event):void { //an Ereignisse gekoppelte Funktionen brauchen einen Event-Paramete in AS3 einMC.startDrag; } function dragStop(e:Event):void { einMC.stopDrag; } code

Eine Instanz auf die Mausposition setzen
code format="actionscript" einMC.y = stage.mouseY; //die Y-Koordinate des Mauszeigers relativ zur Bühne (Pixel vom oberen Rand) einMC.x = stage.mouseX; //X-Koordinate (Pixel vom linken Rand) code

Sounds aus der Bibliothek holen und bei klick auf die Instanz //knopf_mc// abspielen
code format="actionscript" //Vorbereitung: Das Sound-Symbol in der Bibliothek ist exportierbar und hat den Klassennamen GuitarSound (Klassennamen gross schreiben!) knopf_mc.addEventListener(MouseEvent.CLICK, playSound); function playSound(e:MouseEvent):void { var gitarre_snd:GuitarSound = new GuitarSound; //Instanz von GuitarSound aus der Bibliothek holen gitarre_snd.play; //der Instanz sagen, sie soll abgespielt werden } code

Verhindern, dass ein Sound mehrfach gestartet werden kann
code format="actionscript" //Vorbereitung: Das Sound-Symbol in der Bibliothek ist exportierbar und hat den Klassennamen GuitarSound (Klassennamen gross schreiben!) var gitarre_snd:GuitarSound = new GuitarSound; //Die Instanz gitarre_snd AUSSERHALB einer Funktion deklarieren, so dass sie erhalten bleibt var gitarre_chan:SoundChannel = new SoundChannel; //Auch einen SoundChannel, der für das Abspielen verantwortlich ist, deklarieren wir schon hier knopf_mc.addEventListener(MouseEvent.CLICK, playSound); function playSound(e:MouseEvent):void { //Sound nur dann starten, wenn er noch ganz am Anfang steht, oder schon fertig gespielt hat if (gitarre_chan.position <= 0 || gitarre_chan.position >= gitarre_snd.length) { gitarre_chan = gitarre_snd.play; //bereits existierenden Sound & Channel benutzen } } code

Sound auf Knopfdruck abspielen/pausieren
code format="actionscript" //Vorbereitung: Das Sound-Symbol in der Bibliothek ist exportierbar und hat den Klassennamen GuitarSound (Klassennamen gross schreiben!) var gitarre_position:Number = 0.00; //speichern, wie lange der Sound schon gespielt hat var gitarreIsPlaying:Boolean = false; //speichern, ob der Gitarren-Sound gerade spielt oder nicht var gitarre_snd:GuitarSound = new GuitarSound; //Die Instanz gitarre_snd AUSSERHALB einer Funktion deklarieren, so dass sie erhalten bleibt var gitarre_chan:SoundChannel = new SoundChannel; //Auch einen SoundChannel, der für das Abspielen verantwortlich ist, deklarieren wir schon hier knopf_mc.addEventListener(MouseEvent.CLICK, playOrPauseSound); function playOrPauseSound(e:MouseEvent):void { //Sound nur dann starten, wenn er noch ganz am Anfang steht oder schon fertig gespielt hat if (gitarreIsPlaying) { gitarre_position = gitarre_chan.position; //Position merken gitarre_chan.stop;                      //Anhalten gitarreIsPlaying = false;                 //Sich merken, dass angehalten ist } else { gitarre_chan = gitarre_snd.play(gitarre_position); //Abspielen ab gespeicherter Position gitarreIsPlaying = true;                           //Sich merken, dass abgespielt wird } } code

Mauszeiger zu Hand ändern, wenn er sich über einem aktivierbaren MovieClip befindet
code format="actionscript" myClip_mc.buttonMode = true; myClip_mc.useHandCursor = true; code

Für alle MovieClips auf der Bühne etwas (z.B. eine Eigenschaft) ändern
code format="actionscript" for (var i:Number=0; i<numChildren; i++) { if (getChildAt(i) is MovieClip) { var myClip_mc:MovieClip = getChildAt(i) as MovieClip; //hier wird der Hand-Cursor für alle MovieClips aktiviert, es können aber auch beliebige andere Eigenschaften geändert werden myClip_mc.buttonMode = true; myClip_mc.useHandCursor = true; } } code

Code in MovieClips
In Flash kann man Code in jedes Schlüsselbild schreiben, auch innerhalb von Symbolen bzw. MovieClips. Eigentlich wollen wir das NICHT tun! Aller Code sollte in einer eigenen (sinnvoll benannten, abgeschlossenen) Ebene in der Hauptzeitleiste stehen, damit es nicht zu unerwünschten Interaktionen kommen kann. Aber von jeder Regel gibt es Ausnahmen. In den folgenden zwei Fällen brechen wir die Regel und schreiben eben doch etwas Code in die Zeitleiste innerhalb eines MovieClips - schlicht, weil die saubere Lösung zu kompliziert ist.

Ausnahme 1:
Man möchte bewirken, dass der Abspielkopf in der Zeitleiste eines MovieClips anhält, wenn er an einer bestimmten Position angekommen ist - z.B. am Ende einer Animation, sagen wir in Frame 26. Der einfache Hack: Erstellen sie eine neue Ebene innerhalb des MovieClips (z.B. "Code", gleich abschliessen), in dieser Ebene ein leeres Schlüsselbild in Frame 26, und in dieses Schlüsselbild schreiben sie den Code code format="actionscript" stop; //setzt voraus, dass dieser Code im richtigen Frame innerhalb des zu stoppenden MovieClips steht code Fertig. Vor dem stop müssen wir in diesem Fall keinen Instanznamen angeben, weil der Code ja innerhalb der Instanz des MovieClips steht und automatisch auf diesen angewendet wird. Diesen kleinen Hack benötigt man auch dann, wenn man verhindern will, dass eine Animation immer wieder geloopt wird (das ist das default-Verhalten). Falls übrigens derselbe MovieClip später erneut den Befehl **play**; erhält, dann setzt sich der Abspielkopf einfach wieder in Bewegung - also weiter in der Zeitleiste oder, wenn es nicht mehr weiter geht, zurück an den Anfang - bis er erneut über ein **stop**; stolpert. So kann man also Animationen wiederholt 1 Mal abspielen - oder mehrere Animationen hintereinander schalten.

Ausnahme 2:
Will man Animationen in verschiedenen MovieClips miteinander verketten, dann braucht es den zweiten kleinen Hack. Sagen wir, es ist schon alles so eingerichtet, dass mc1 auf Knopfdruck abspielt und am Ende der Animation auch wieder stoppt (s. Ausnahme 1). Wenn man genau jetzt, also am Ende der ersten Animation, den Abspielkopf in mc2 auf die Reise schicken möchte, dann hat man ein Problem: mc1 weiss, dass die Animation fertig ist, aber er kennt mc2 nicht. Die richtige Stelle für den Code ist also dieselbe wie für das stop; im obigen Beispiel, zusätzlich brauchte es hier noch eine Zeile, um die Animation in mc2 zu starten, und zwar diese: code format="actionscript" MovieClip(root).mc2.play; //setzt voraus, dass mc2 der Instanzname eines Movieclips in der Hauptzeitleiste ist code Der Clou hier ist die Angabe von **MovieClip(root)**, das sich auf die gemeinsame "Wurzel" der beiden Clips, also die Bühne/Hauptzeitleiste bezieht. Auf dieselbe Art und Weise kann man übrigens vorgehen, wenn man aus einem MovieClip heraus den Wert einer Variablen in der Hauptzeitleiste beeinflussen möchte.

Auf Tastatur-Eingaben reagieren
code format="actionscript" function keyPressHandler(e:KeyboardEvent):void { if (e.keyCode == Keyboard.RIGHT) { //herausfinden, ob eine bestimmte Taste gedrückt wurde trace("Pfeiltaste rechts wurde gedrückt"); }   if (e.keyCode == 32) { //viele Tasten kann man nicht über den Namen, sondern nur über eine Nummer abfragen trace("Space Taste wurde gedrückt"); }   if (e.charCode == 97) { //anstatt des keyCodes kann man auch ASCII-Code (= charCode) verwenden trace("die Taste a wurde gedrückt"); }   trace("Der keyCode der gedrückten Taste ist: " + e.keyCode) //man kann sich den keyCode auch einfach ausgeben lassen } stage.addEventListener(KeyboardEvent.KEY_DOWN,keyPressHandler); // KeyboardEvent.KEY_UP würde stattdessen auf das Loslassen der Taste reagieren code __Hinweis:__ Irgendwer (z.B. eine MovieClip-Instanz) muss auf den Tastendruck reagieren. In AS2 benutzt man dafür oft **//_root//** (=~ die Hauptzeitleiste). Das geht in AS3 nicht mehr, und im Beispiel wird darum das neue //**stage**// (= die Bühne) benutzt, um auf die Tastatureingaben zu hören. Danach unterscheidet man mit Bedingungen zwischen verschiedenen Tasten - die üblichsten haben Namen (z.B. Keyboard.UP für den Pfeil nach oben), für andere muss man die KeyCodes aus dieser Liste verwenden. In allen Versionen wäre es eigentlich sauberer, als Listener (= Abhörer) ein neues Object zu erstellen und zu benutzen, das keine anderen Aufgaben hat. Dazu müsste man nur die folgende Zeile hinzufügen: //var keyListener:Object = new Object;// und jedes Vorkommen von //stage// mit //keyListener// ersetzen. Eine ausführlichere (englische) Erklärung zur Ansteuerung des Keyboards mit AS3 findet sich hier: http://www.republicofcode.com/tutorials/flash/as3keyboard/

Fokus setzen, damit Tastendrucke registriert werden
Ein Objekt wird nur dann über einen Tastendruck benachrichtigt, wenn es Fokus hat. Für //stage// ist das meist automatisch der Fall, spätestens wenn der Benutzer einmal auf das Flash-Projekt geklickt hat. Falls es doch mal Probleme gibt, hier der Code zur Fokus-Zuweisung: code format="actionscript" stage.focus = this; //sicher stellen, dass die Bühne Fokus hat code

Eine ganze Zufallszahl generieren, die zwischen zwei anderen Zahlen liegt
code format="actionscript" var minNum:Number = 1; //Beispiel für Untergrenze, könnte eine beliebige Zahl sein var maxNum:Number = 7; //Beispiel für Obergrenze - exklusive, d.h. die höchste mögliche Zufallszahl wäre hier 6 var randomNum:Number = Math.floor(Math.random*(maxNum-minNum))+minNum; code __Hinweis__: Dieser Code ist nicht schwer zu verstehen, wenn man weiss, dass der Befehl Math.random eine zufällige Zahl zwischen 0 und (exklusive) 1 erzeugt. Dabei kommen natürlich Kommazahlen heraus, man muss also noch multiplizieren und (ab)runden, damit man am Ende einen ganzzahligen Wert erhält.

Höhe und Breite der Bühne abfragen
code format="actionscript" var breite:Number = stage.stageWidth; //abfragen und speichern trace(stage.stageHeight);             //einfach ausgeben code

Position der Maus abfragen
code format="actionscript" stage.addEventListener(MouseEvent.MOUSE_MOVE, mousePosition);

function mousePosition(event:MouseEvent) { //mouseX gibt die X-Koordinate der Maus, relativ zum linken Rand der Bühne trace("Maus X zu Stage: " + String(stage.mouseX)); trace("Maus Y zu Stage: " + String(mouseY)); //das "stage" ist optional (vgl. letzte Zeile) //man kann auch die Mausposition relativ zu einem MovieClip erfragen, hier die Instanz box_mc trace("Maus X zu box_mc: " + String(box_mc.mouseX)); box_mc_x = stage.mouseX; //natürlich kann man das Ergebnis nicht nur ausgeben. Hier wird //bspw. box_mc auf die (horizontale) Mausposition verschoben } code

Videos in Flash einbetten
Es gibt viele verschiedene Methoden um in Flash mit externen Videodateien umzugehen - das hat damit zu tun, dass (a) es viele unterschiedliche Videoformate gibt, (b) Videoformate notwendigerweise komplex sind (Ton, Bild, Qualitäten, Steuerung, ...), und (c) Videodateien dazu tendieren gross zu sein und daher viel Ladezeit in Anspruch nehmen. Eine Übersicht gibt es hier: http://help.adobe.com/de_DE/Flash/10.0_UsingFlash/WSBDABD69F-D146-4e5c-9340-BF717A10426C.html Wer lange und grosse Videos einbauen will, muss sich mit den Möglichkeiten (Streaming, Pfade, Formate, URLs, ...) intensiver auseinander setzen. Hier eine knappe Anleitung zum Umgang mit KLEINEN/KURZEN Videos (< 2 oder 3 MB): > Wählen sie „FLV in SWF einbetten und in Zeitleiste abspielen“ aus. > Klicken sie auf „Weiter“ und wählen sie im nächsten Fenster als Symboltyp "Movie Clip". Wenn sie den Rest bestätigen erscheint ein neuer MovieClip in ihrer Bibliothek (ggf. auch in der Bühne), der das importierte Video enthält (in den Frames seiner Zeitleiste). Mit diesem MovieClip können sie jetzt in der üblichen Art umgehen, z.B. mit Steuerungsbefehlen wie stop; play; gotoAndPlay; gotoAndStop; .... Für grössere Videos bietet sich die Benutzung der eingebauten FLVPlayback-Komponente an, wie man das macht wird hier erklärt:
 * 1) Das einzubauende Video muss auf ihrer Festplatte gespeichert sein, also ggf. herunterladen.
 * 2) Das Video muss im Format .flv (oder .f4v) vorliegen und sollte nach Möglichkeit schon die Grösse (in Pixel) haben, mit der sie es innerhalb von Flash verwenden wollen - also ggf. mit entsprechender Software konvertieren und verkleinern.
 * 3) Wählen sie „Datei“ > „Importieren“ > „Video importieren“, um den Videoclip in das aktuelle Flash-Dokument zu importieren.
 * 4) Wählen sie auf dem lokalen Computer den Videoclip aus, den Sie importieren möchten.
 * http://www.learning-how.to/Interaktion_und_Multimedia/Flash-Video/content-docs/01-video.php
 * http://www.republicofcode.com/tutorials/flash/as3flvplayback/

Zufällige Farbe wählen
code format="actionscript" var color:Number = Math.random*0xffffff; //0xffffff ist kurz für 16 hoch sechs (oder 2 hoch 24) code code format="actionscript" //32bit - jeder Farbkanal hat einen Wert zwischen 0 und 255 (oder 0x00 und 0xff) var alpha:Number = 255; //Transparenz, 255 bedeutet nicht transparent; dieser Kanal ist meist optional var red:Number = Math.random*255; //die Menge an Rot ist zufällig var green:Number = 0; var blue:Number = 0; var color:Number = alpha << 24 | red << 16 | green << 8 | blue; //den bitshift-Operator << muss man nicht verstehen code
 * Komplett zufällige Farbe (also eine Zahl zwischen 0 und 2 hoch 24, bzw. ~16.7 Mio)
 * Separate Farbkanäle, wenn man bspw. nur die Menge an Rot variieren will

Neuen MovieClip erstellen und ein Rechteck darauf zeichnen
code format="actionscript" var figur:MovieClip = new MovieClip; //neuen MovieClip erstellen - ggf. lieber new Shape benutzen figur.graphics.lineStyle(2, Math.random*0xffffff, 1); //Linienbreite, Farbe, Alpha (0 bis 1) figur.graphics.beginFill(Math.random*0xffffff,0.7); //Farbe, Alpha figur.graphics.drawRect(10, 10, 100, 100); //xpos, ypos, Breite, Höhe //figur.graphics.moveTo(20, 20); //figur.graphics.lineTo(40, 20); //... man kann die Linien auch einzeln zeichnen, aber drawRect ist einfacher addChild(figur); //neuen MovieClip tatsächlich einfügen, in die nächsthöchste verfügbare Tiefe (also vor alle bestehenden Objekte) //addChildTo(figur, 99); //neuen MovieClip in Tiefe 99 einfügen code Weitere gute Beispiele zum Zeichnen mit AS3 finden sich hier: http://www.on-design.de/tutor/FlsExpl/AS3/lineTo/index.htm

MovieClip-Instanzen mit Code einfügen, duplizieren und entfernen
code format="actionscript" //Aus der Bibliothek holen - der Klassenname (s. Eigenschaften) ist MyClip var clip1:myClip = new MyClip; clip1.x = 100; //ab jetzt kann ich den neuen Clip über seinen Instanznamen ansprechen/beeinflussen addChild(clip1); //erst jetzt wird der neue Clip angezeigt //addChild(clip1, 200); //die Tiefe kann optional angegeben werden, default ist getNextHighestDepth, also ganz oben drauf //bestehende Instanze duplizieren geht in AS3 nur schwer, besser neue kreieren //Instanzen entfernen geht so removeChild(getChildByName("clip1")); // oder clip1.parent.removeChild(clip1); code

Eine Instanz mit beliebiger Drehung geradeaus bewegen
code format="actionscript" function moveClip(mc:MovieClip, distance:Number):void { var rad:Number = mc.rotation * Math.PI / 180;    //Grad in Radians umwandeln mc.x = mc.x + Math.cos(rad)*distance;        //in x-Richtung verschieben mc.y = mc.y + Math.sin(rad)*distance;        //in y-Richtung verschieben } myClip.rotation = 60; //setzt die Drehung der Instanz myClip auf 60 Grad (0 Grad = rechts, dann im Uhrzeigersinn) moveClip(myClip, 77); //bewegt die Instanz myClip 77 Pixel geradeaus code

Herausfinden, ob sich zwei Instanzen überschneiden
code format="actionscript" //Methode 1; tested ob sich die umhüllenden Rechtecke der beiden Clips überlappen var overlap:Boolean = clip1.hitTestObject(clip2); //Methode 2; tested ob sich ein bestimmter Punkt im umhüllenden Rechteck von clip1 befindet var overlap:Boolean = clip1.hitTestPoint(130, 34, false); //die ersten beiden Argumente sind die x- und die y-Koordinate des Punktes, das dritte Argument (optional) gibt an, ob es um die genaue Form geht oder nicht (s. Methode 3) //Methode 3; tested ob sich ein bestimmter Punkt innerhalb der Grafik/Form von clip1 befindet var overlap:Boolean = clip1.hitTestPoint(130, 34, true);  //jetzt mit der genauen Form, nicht dem umhüllenden Rechteck //Beispiel: Hier wird Methode drei verwendet um herauszufinden, ob sich die rechte untere Ecke von clip 2 mit der Form (genau) von clip 1 überlappt var overlap:Boolean = clip1.hitTestPoint(clip2.x + clip2.width, clip2.y + clip2.height, true); code

Exakter Hittest zwischen zwei MovieClips
code format="actionscript" function objectsHit(mc1, mc2): Boolean { var mc1bounds = mc1.getBounds(this); var mc2bounds = mc2.getBounds(this); var allintersections = (mc2bounds.intersection(mc1bounds)); for (var xval: Number = allintersections.x; xval < allintersections.x + allintersections.width; xval++) { for (var yval: Number = allintersections.y; yval < allintersections.y + allintersections.height; yval++)      { if (mc2.hitTestPoint(xval, yval, true) && mc1.hitTestPoint(xval, yval, true)) { return (true); }     }   }   return (false); } code Wie der oben vorgestellten hitTestObject beantwortet diese Funktion die Frage, ob sich zwei MovieClips überlappen - allerdings bezieht sich das bei dieser Funktion nicht auf die umgebenden Rechtecke, sondern auf die tatsächliche Form der Clips (durchsichtige Pixel zählen nicht). Im folgenden Code findet sich ein Beispiel für die Verwendung dieser Funktion.

Mit einer Schleife alle Elemente in einem Array ansprechen
Häufig will man mit allen Elementen eines Arrays etwas tun, z.B. alle verschieben oder einen Hittest. Dafür schreibt man einfach eine Schleife, so dass i nacheinander die Werte für den Index (=Position im Array) jedes Elements annimmt. Auf diese Weise kann man einen Code nacheinander für alle im Array gespeicherten Elemente ausführen, einfach indem man anstatt eines Instanznamens sagt: das soundsovielte Element im Array, bzw. //ArrayName[index]//. code format="actionscript" for (var i:Number = 0; i<10; i++) {   var clip:MC = new MC; //neue Instanzen per Code erstellen clip.x = i*50; //ggf. Eigenschaften ändern myArray.push(clip); //Instanz als neues Element zum Array hinzufügen addChild(clip); //Instanz anzeigen }

addEventListener(Event.ENTER_FRAME, loop); //loop wird also immer wieder aufgerufen

function loop(e:Event):void { for (var i:Number = 0; i<myArray.length; i++){ //Schleife über alle Elemente des Arrays //Beliebiger Code, der nacheinander mit allen Elementen des Arrays ausgeführt wird myArray[i].y = myArray[i].y + 10; //mit myArray[i] komme ich an ein bestimmtes Element } } code

MovieClips löschen
Wenn man viele MovieClips per Code erzeugt, dann muss man sie ggf. auch wieder löschen, da sonst die Ausführung sehr langsam werden kann. Das Löschen erfolgt genau genommen automatisch durch einen Prozess namens "garbage collection", aber dazu muss man dafür sorgen, dass nichts mehr auf den betreffenden MovieClip verweist (auch nicht Listeners). Hier ein Beispiel: code format="actionscript" import flash.utils.Timer; import flash.events.TimerEvent; import flash.display.MovieClip;

var boxTimer:Timer = new Timer(100); //erstellt einen Timer mit einem Interval von 100 ms boxTimer.addEventListener(TimerEvent.TIMER, addBox); //und weist ihn der Methode addBox zu boxTimer.start; // startet den Timer

function addBox(e:TimerEvent):void { var mc:MovieClip = new MovieClip; //Erstellt einen leeren MovieClip mc.graphics.lineStyle(3,0xFF0000); mc.graphics.drawRect(0,0,20,15); //zeichnet eine Box darauf addChild(mc); //Fügt den Movieclip zur Bühne hinzu mc.x = Math.random*stage.stageWidth; //zufällige x-Position

//hängt einen ENTER_FRAME-Listerer an diese Box // **** ACHTUNG ******* Mehr Argumente in addEventListener ! ********   mc.addEventListener(Event.ENTER_FRAME, moveBox, false, 0, true ); // die Argumente 3 und 4 sind default (einfach so übernehmen) // das 5. sollte man auf true setzen --> macht das Entfernen leichter }

function moveBox(e:Event):void{ var thisClip:MovieClip = e.currentTarget as MovieClip; //thisClip ist jetzt das Objekt, an dem der ENTER_FRAME-Listener hängt, also eine bestimmte Box thisClip.y = thisClip.y + 5; //Box bewegen if (thisClip.y > 250){ //wenn diese Bedingung erfüllt ist, soll thisClip gelöscht werden thisClip.parent.removeChild(thisClip); //thisClip aus der DisplayListe entfernen thisClip.removeEventListener(Event.ENTER_FRAME, moveBox); //Listerner entfernen //wenn man beim Erstellen des Listeners das 5. Argument auf true gesetzt hat (s. oben), dann ist dieser Schritt hier eigentlich überflüssig thisClip = null; //sicherstellen, dass thisClip keine Referenzen mehr enthält } } code