Zweimal im Monat besuchen wir einige der Lieblingsbeiträge unserer Leser aus der gesamten Geschichte von Activetuts +. Dieses Tutorial wurde erstmals im März 2010 veröffentlicht.
In diesem Lernprogramm erstellen wir eine benutzerdefinierte Klasse, die ein Bild in tausend Teile zerlegt und einen Wind simuliert, der sie wegbläst. Ich habe dieses Projekt ausschließlich mit AS3 und FlashDevelop erstellt - Flash ist nicht erforderlich!
Werfen wir einen Blick auf das Endergebnis, auf das wir hinarbeiten werden. Klicken Sie auf eine beliebige Stelle in der SWF-Datei:
FlashDevelop ist ein kostenloser Code-Editor für Flash und Flex. Sie können es verwenden, um Ihre Klassendateien zu bearbeiten, wenn Sie mit Flash-Software arbeiten, oder Sie können ein AS3-Projekt erstellen, für das überhaupt kein Flash erforderlich ist. Genau das machen wir in diesem Tutorial.
Laden Sie also FlashDevelop herunter und installieren Sie es. Leider läuft FlashDevelop nur unter Windows. Zu den Mac-Alternativen gehören FDT und Flex Builder. Beide sind jedoch nicht kostenlos. Sie können Flash selbst verwenden, und ich erkläre, wie das geht, während wir weitergehen.
Öffnen Sie FlashDevelop und klicken Sie auf Projekt> Neues Projekt?
Wählen Sie Actionscript 3> AS3-Projekt. Um den Namen des Projekts einzugeben, geben Sie "WindEffect" ein. Klicken Sie für den Speicherort auf und navigieren Sie zu dem Ordner, in dem Sie ihn speichern möchten. Lassen Sie das Kontrollkästchen "Verzeichnis für Projekt erstellen" aktiviert, und klicken Sie auf "OK".
Wenn Sie Flash CS3 / CS4 verwenden möchten, erstellen Sie eine neue Flash-Datei und legen Sie die Breite und Höhe der Bühne auf 550x250px fest. Setzen Sie die Hintergrundfarbe auf Schwarz. Nennen Sie es "windEffect.fla" und speichern Sie es an einem beliebigen Ort.
Öffnen Sie für FlashDevelop das Projektverzeichnis und kopieren oder ziehen Sie die Datei windEffect.jpg aus dem Quelldownload (oben auf der Seite verlinkt) in den Ordner \ bin \.
Kopieren oder ziehen Sie für Flash die Datei windEffect.jpg aus dem Quelldownload in den Ordner, in dem sich windEffect.fla befindet.
Wir werden TweenLite von Greensock für das Tweening verwenden. Sie können die neueste Version der Komponente hier herunterladen. Ich habe es auch in den Quellendownload aufgenommen.
Gehen Sie für FlashDevelop vor und kopieren oder ziehen Sie greensock.swc aus dem Quelldownload in den Ordner \ lib \ für dieses Projekt.
Klicken Sie in FlashDevelop auf Ansicht> Projektmanager
Klicken Sie in FlashDevelop immer noch auf das "+" - Zeichen links vom lib-Ordner, um ihn zu erweitern. Klicken Sie mit der rechten Maustaste auf greensock.swc und wählen Sie Zur Bibliothek hinzufügen aus.
Kopieren Sie für Flash den Ordner \ com \ aus dem Quelldownload in den gleichen Ordner wie Ihre windEffect.fla-Datei.
Öffnen Sie für FlashDevelop erneut den Projektmanager (siehe Schritt 4), erweitern Sie den Ordner \ src \, und doppelklicken Sie auf Main.as. Fügen Sie unterhalb der Importe und oberhalb der Klassendefinition das folgende Metadaten-Tag hinzu, um die Stage-Eigenschaften einzurichten:
[SWF (Breite = 550, Höhe = 250, FrameRate = 30, Hintergrundfarbe = 0)]
Fügen Sie in der Methode init () nach dem Kommentar "Einstiegspunkt" den folgenden Code hinzu:
stage.scaleMode = StageScaleMode.NO_SCALE; // Dehne den Bühnenvariereffekt nicht: WindEffect = new WindEffect ('windEffect.jpg'); // Wir werden bald die WindEffect-Klasse erstellen addChild (effect);
Das war es für die Hauptdokumentklasse.
Erstellen Sie für Flash eine neue Main.as-Klasse in demselben Ordner wie Ihr Projekt. Stellen Sie sicher, dass sich die Main.as-Klasse im selben Ordner befindet wie der fla. & com Ordner. Fügen Sie die folgenden Zeilen hinzu:
package import flash.display.Sprite; import flash.display.StageScaleMode; import flash.events.Event; public class Main erweitert Sprite public function Main (): void if (stage) init (); else addEventListener (Event.ADDED_TO_STAGE, init); private Funktion init (e: Event = null): void removeEventListener (Event.ADDED_TO_STAGE, init); stage.scaleMode = StageScaleMode.NO_SCALE; // Dehne den Bühnenvariereffekt nicht: WindEffect = new WindEffect ('windEffect.jpg'); // Wir werden bald die WindEffect-Klasse erstellen addChild (effect);
Öffnen Sie Flash und weisen Sie "Main" als Dokumentklasse zu.
(Sie sind sich nicht sicher, worum es sich handelt? Lesen Sie diese kurze Einführung in die Verwendung einer Dokumentenklasse.)
Wenn Sie versuchen, dies jetzt auszuführen, wird eine Fehlermeldung angezeigt, da wir die WindEffect-Klasse noch nicht erstellt haben. Stellen Sie einfach sicher, dass Sie die Datei speichern und für den Moment belassen.
Klicken Sie für FlashDevelop auf Ansicht> Projektmanager, klicken Sie mit der rechten Maustaste auf den Ordner \ src \ und wählen Sie Hinzufügen> Neue Klasse.
Benennen Sie die Klasse WindEffect, klicken Sie auf die Durchsuchen-Schaltfläche für die Basisklasse und geben Sie flash.display.Sprite ein. Klicken Sie auf OK, um den Vorgang abzuschließen.
Fügen Sie alle erforderlichen Importe in die Paketklammern direkt unter 'import flash.display.Sprite;' ein. und vor der Klassendefinition. Klicken Sie auf Speichern.
import com.greensock.easing.Strong; import com.greensock.TweenLite; import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.Loader; import flash.events.Event; import flash.events.MouseEvent; import flash.geom.Point; import flash.geom.Rectangle; import flash.net.URLRequest;
Erstellen Sie für Flash eine neue ActionScript-Datei, nennen Sie sie "WindEffect.as" und speichern Sie sie in demselben Verzeichnis, in dem Sie bereits gearbeitet haben. Es sollte direkt neben dem Fla sein. Datei, COM-Ordner und Main.as.
Fügen Sie den folgenden Code hinzu:
Paket Import com.greensock.easing.Strong; import com.greensock.TweenLite; import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.Loader; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import flash.geom.Point; import flash.geom.Rectangle; import flash.net.URLRequest; public class WindEffect erweitert Sprite public function WindEffect ()
Fügen Sie eine private Variable mit dem Namen "_pictureArray" hinzu. Dies ist die einzige Variable, die wir in dieser Klasse haben werden. Sein Hauptzweck besteht darin, Verweise auf all die kleinen Sprites zu halten, die die kleinen Teile des Bildes enthalten, sobald es aufgelöst wurde.
Fügen Sie die folgende Codezeile in die Klammern ein
der Klasse:
public class WindEffect erweitert Sprite // Hier werden alle Teile des Bildes untergebracht, die wir animieren werden. private var _pictureArray: Array;
Fügen Sie nach der _pictureArray-Deklaration die folgenden Zeilen ein:
public class WindEffect erweitert Sprite // Hier werden alle Teile des Bildes untergebracht, die wir animieren werden. private var _pictureArray: Array; public function WindEffect ($ url: String) // Wir rufen einfach das load-Bild im Konstruktor auf. loadPicture ($ url);
Innerhalb der loadPicture () -Methode, die von der Konstruktormethode aufgerufen wird, instantiieren wir einen Loader, um windEffect.jpg zu laden. Wir fügen auch einen COMPLETE-Ereignis-Listener hinzu, auf den Sie warten möchten, wenn der Ladevorgang abgeschlossen ist.
Fügen Sie nach der WindEffect () - Methode die folgenden Codezeilen hinzu. (Beachten Sie, dass der Parameter "$ url" der Pfad zu dem Bild ist, das von Main.as geladen wird.)
private Funktion loadPicture ($ url: String): void // Wir erstellen einen Loader mit Listenern, um das von uns verwendete Quellbild zu laden. // und dann laden wir das Bild. var loader: Loader = neuer Loader; loader.contentLoaderInfo.addEventListener (Event.COMPLETE, onLoadComplete); // Wenn es geladen ist, rufen Sie die onLoadComplete () -Funktion auf. loader.load (new URLRequest ($ url));
Nachdem das Bild ordnungsgemäß importiert wurde, wird diese Methode aufgerufen. Fügen Sie nach der loadPicture () -Methode die folgenden Codezeilen hinzu und speichern Sie die Datei.
private Funktion onLoadComplete (e: Event): void // zum Testen addChild (e.target.content);
Fahren Sie fort und drücken Sie auf Ihrer Tastatur STRG + Eingabetaste. Es sollte funktionieren und das Bild sollte sich in der linken oberen Ecke der Bühne befinden.
Nachdem wir überprüft haben, dass das Laden korrekt ist, entfernen Sie die addChild-Methode und ersetzen Sie sie durch folgenden Code:
createEffect (e.target.content);
Ihre WindEffect-Klasse sollte ungefähr so aussehen:
Paket Import com.greensock.easing.Strong; import com.greensock.TweenLite; import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.Loader; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import flash.geom.Point; import flash.geom.Rectangle; import flash.net.URLRequest; [SWF (width = 550, height = 250, frameRate = 30, backgroundColor = 0)] Öffentliche Klasse WindEffect erweitert Sprite private var _pictureArray: Array; öffentliche Funktion WindEffect ($ url: String) loadPicture ($ url);
private Funktion loadPicture ($ url: String): void var loader: Loader = neuer Loader; loader.contentLoaderInfo.addEventListener (Event.COMPLETE, onLoadComplete); loader.load (neue URLRequest ($ url)); private Funktion onLoadComplete (e: Event): void createEffect (e.target.content);
Die createEffect () - Methode nimmt den image-Parameter, der im Wesentlichen eine Bitmap ist, auf 1250 Teile auf.
Zuerst berechnen wir die x- und y-Position, um das Bild auf der Bühne zu zentrieren. Wir speichern sie in lokalen Variablen namens centerWidth und centerHeight.
Da die Größe des Bildes, das wir verwenden, 300 x 100 beträgt, habe ich mich entschieden, das Bild 50 Mal horizontal und 25 Mal vertikal zu teilen. Diese Werte ergaben ein ziemlich gutes Ergebnis bei optimaler Leistung. Wir speichern sie in lokalen Variablen, die ich "numberOfColumns" und "numberOfRows" genannt habe.
Wir speichern das Ergebnis der Unterteilung der Bildbreite durch numberOfColumns in "sizeWidth" und das Ergebnis der Unterteilung der Bildhöhe durch numberOfRows in "sizeHeight".
Die Variable "numberOfBoxes" enthält numberOfColumns, multipliziert mit numberOfRows.
Als Nächstes instanziieren wir _pictureArray, damit wir anfangen können, kleine Sprites darin zu platzieren. Fügen Sie nach der onLoadComplete () - Methode die folgenden Codezeilen hinzu:
private Funktion createEffect ($ bitmap: Bitmap): void // zentriert das Bild horizontal. var centerWidth: Number = (stage.stageWidth - $ bitmap.width) * .5; // zentriere das Bild vertikal. var centerHeight: Number = (stage.stageHeight - $ bitmap.height) * .5; var numberOfColumns: uint = 50; var numberOfRows: uint = 25; var sizeWidth: uint = $ bitmap.width / numberOfColumns; var sizeHeight: uint = $ bitmap.height / numberOfRows; var numberOfBoxes: uint = numberOfColumns * numberOfRows; _pictureArray = [];
Nach der Instantiierung von _pictureArray fügen wir zwei Loops hinzu, eine in die andere. Die erste Schleife bewegt sich an der x-Position und durchläuft alle Spalten, während sich die zweite Schleife an der y-Position bewegt und alle Zeilen durchläuft.
Fügen Sie die folgenden Codezeilen direkt nach der Instantiierung von _pictureArray in die createEffect () - Methode ein, und speichern Sie die Datei:
für (var i: uint = 0; i < numberOfColumns; i++) //these loops are what splits the image into 1250 pieces. for (var j:uint = 0; j < numberOfRows; j++) //let's see what it does. trace ('i:' + i, 'j:' + j);
Testen Sie den Film, indem Sie STRG + Eingabetaste drücken.
Wie Sie sehen können, für jeden ich Es gibt eine vollständige Schleife von j. Dies wird "Verschachtelungsschleifen" genannt. Das bedeutet, dass ich Die X-Achse bleibt dabei auf einem Wert, während die zweite Schleife für die Y-Achse wiederholt wird.
Einfach gesagt, beginnen wir mit x = 0, y = 0; dann ist die nächste Iteration x = 0, y = 1; dann x = 0, y = 2 und so weiter.
Wenn y das Ende erreicht, erhöht sich die erste Schleife um 1 und durchläuft dann erneut die zweite Schleife: x = 1, y = 0; x = 1, y = 1, x = 1, y = 2 usw. Dies wird fortgesetzt, bis die 1. Schleife abgeschlossen ist.
Sie werden sehen, was dies bewirkt, wenn wir es in den nächsten Zeilen auf einige Bitmap-Manipulationen anwenden.
Entfernen Sie innerhalb der zweiten Schleife die Trace-Funktion, die wir zum Testen verwendet haben. Bei jeder Schleife müssen wir ein kleines Bild mit der Breite von "sizeWidth" und der Höhe von "sizeHeight" erstellen.
Dieses kleine Bild macht eine Momentaufnahme eines kleinen Teils des Bildes, angefangen von der oberen linken Ecke bis nach rechts unten. Bei "tempBitmapData" zeichnen wir den kleinen Teil des Bildes. "SourceRect" ist das Rechteck, mit dem festgelegt wird, welcher Teil des Bildes kopiert wird.
Fügen Sie die folgenden Zeilen in die 2. Schleife ein und speichern Sie die Datei:
// 1 temporäre Bitmapdata var tempBitmapData: BitmapData = neue BitmapData (sizeWidth, sizeHeight); // 1 temporäres Rechteck (x, y, width, height) // Wir übergeben i * sizeWidth für den x-Parameter & i * sizeHeight für den y-Parameter // und sizeWidth & sizeHeight für die Parameter width und height. var sourceRect: Rechteck = neues Rechteck (i * sizeWidth, j * sizeHeight, sizeWidth, sizeHeight); trace (sourceRect); // zum Testen
Testen Sie den Film. Jetzt wird ein Rechteck erstellt, das bei jeder Iteration seine x- und y-Position einstellt.
Wie Sie sehen, zeigt das erste Beispiel x = 0, y = 0 und das nächste ist x = 0, y = 4. Dies ist, was wir für die Grenzen der Momentaufnahme des Quellbildes verwenden. Entfernen Sie die Testfunktion, wenn Sie bereit sind, fortzufahren.
Wir verwenden dann die BitmapData.copyPixels () -Methode, um einen kleinen Ausschnitt des Bildes basierend auf dem sourceRect zu kopieren. Die Parameter für diese Methode sind das zu kopierende Bitmap-Bild, der zu kopierende Rechteckbereich und der Zielpunkt, an den die Kopie kopiert werden soll.
Fügen Sie die folgende Codezeile unterhalb der sourceRect-Deklaration hinzu.
tempBitmapData.copyPixels ($ bitmap.bitmapData, sourceRect, neuer Punkt);
Dann erstellen wir eine temporäre Bitmap für die gerade kopierten BitmapData und eine temporäre Sprite für die Bitmap.
Dann schieben wir eine Referenz jedes Sprites auf _pictureArray, um später darauf zugreifen zu können. Danach fügen wir der Bühne das Sprite mit der gleichen Koordinate hinzu, von der wir es kopiert haben, und erstellt so das ursprüngliche Bild neu.
Das Bild wird dann um centerWidth und centerHeight versetzt, um es auf der Bühne richtig zu zentrieren.
Fügen Sie die folgenden Codezeilen hinzu und speichern Sie die Datei erneut:
// Wir erstellen dann eine temporäre Bitmap, um die gerade kopierten Bitmap-Daten aufzunehmen. var tempBitmap: Bitmap = neue Bitmap (tempBitmapData); // und 1 temporäres Sprite, um die Bitmap aufzunehmen, um Interaktivität zu ermöglichen. var tempSprite: Sprite = neues Sprite; // Wir fügen einfach jede Box in ihr eigenes Sprite ein, um Interaktivität zu ermöglichen, da Bitmaps an sich nicht interaktiv sind. tempSprite.addChild (tempBitmap); // Jedes Sprite wird dem _pictureArray-Array für den späteren Zugriff hinzugefügt. _pictureArray.push (tempSprite); // positioniere dann jeden von ihnen auf der Bühne. // Wir addieren die Mittenbreite und die Mittenhöhe, damit das Bild auf der Bühne zentriert wird. tempSprite.x = i * sizeWidth + centerWidth; tempSprite.y = j * sizeHeight + centerHeight; addChild (tempSprite);
Testen Sie es erneut. Sie sollten das Bild auf der Bühne richtig angelegt sehen. Es sieht nicht einmal so aus, als wäre es in 1250 Teile aufgeteilt worden.
Fügen Sie unmittelbar nach der schließenden Klammer der zweiten Schleife die folgende Codezeile hinzu, bevor wir die Methode schließen:
stage.addEventListener (MouseEvent.CLICK, blowWind);
Wir fügen der Bühne einen Ereignis-Listener hinzu, um nach einem MouseEvent.CLICK zu hören. Dadurch wird die Animation durch Ausführen der Funktion blowWind () ausgelöst, die im nächsten Schritt erstellt wird.
Ihre WindEffect-Klasse sollte ungefähr so aussehen:
Paket Import com.greensock.easing.Strong; import com.greensock.TweenLite; import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.Loader; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import flash.geom.Point; import flash.geom.Rectangle; import flash.net.URLRequest; public class WindEffect erweitert Sprite private var _pictureArray: Array; öffentliche Funktion WindEffect ($ url: String) loadPicture ($ url); private Funktion loadPicture ($ url: String): void var loader: Loader = neuer Loader; loader.contentLoaderInfo.addEventListener (Event.COMPLETE, onLoadComplete); loader.load (neue URLRequest ($ url)); private Funktion onLoadComplete (e: Event): void createEffect (e.target.content); private Funktion createEffect ($ bitmap: Bitmap): void var centerWidth: Number = (stage.stageWidth - $ bitmap.width) * .5; var centerHeight: Number = (stage.stageHeight - $ bitmap.height) * .5; var numberOfColumns: uint = 50; var numberOfRows: uint = 25; var sizeWidth: uint = $ bitmap.width / numberOfColumns; var sizeHeight: uint = $ bitmap.height / numberOfRows; var numberOfBoxes: uint = numberOfColumns * numberOfRows; _pictureArray = []; für (var i: uint = 0; i < numberOfColumns; i++) for (var j:uint = 0; j < numberOfRows; j++) var tempBitmapData:BitmapData = new BitmapData (sizeWidth, sizeHeight); var sourceRect:Rectangle = new Rectangle (i * sizeWidth, j * sizeHeight, sizeWidth, sizeHeight); tempBitmapData.copyPixels ($bitmap.bitmapData, sourceRect, new Point); var tempBitmap:Bitmap = new Bitmap (tempBitmapData); var tempSprite:Sprite = new Sprite; tempSprite.addChild (tempBitmap); _pictureArray.push (tempSprite); tempSprite.x = i * sizeWidth + centerWidth; tempSprite.y = j * sizeHeight + centerHeight; addChild (tempSprite); stage.addEventListener (MouseEvent.CLICK, blowWind);
Beginnen Sie mit dem Entfernen des MouseEvent.CLICK-Ereignis-Listeners, da er nur einmal ausgeführt werden muss. Fügen Sie nach der createEffect () - Methode die folgenden Codezeilen hinzu:
private Funktion blowWind (e: MouseEvent): void stage.removeEventListener (MouseEvent.CLICK, blowWind);
Wir müssen alle Sprites durchgehen, die wir _pictureArray zugewiesen haben, und sie einzeln animieren.
TweenLite wird angewendet, um alle Teile nach rechts zu animieren, als ob der Wind auf sie weht.
Die Parameter sind: das Ziel für das Tween, die Dauer des Tween, ein variables Objekt, das alle Eigenschaften sowie die Werte enthält, auf die das Tween angewendet werden soll.
Zum Beispiel: TweenLite.to (Ziel, Dauer, x: 100, y: 100, Rotation: 30, Leichtigkeit: Strong.easeIn, onComplete: trace, onCompleteParams: ['hello']).
Die letzten beiden Parameter des obigen Beispiels werden verwendet, wenn das Tween beendet ist. Der Parameter onComplete ruft die Trace-Funktion auf, und der Parameter OnCompleteParams sendet ein Array mit der Zeichenfolge 'Hello' an die Trace-Funktion.
Fügen Sie die folgenden Codezeilen direkt nach dem Remove Event Listener hinzu:
für (var i: uint = 0; i < _pictureArray.length; i++) TweenLite.to ( _pictureArray[i], getRandomInRange (.25, 2, false), x: stage.stageWidth + 100, y:_pictureArray[i].y + getRandomInRange (-100, 100, false),// rotation: getRandomInRange (-90, 90), ease:Strong.easeIn, onComplete:removeSprite, onCompleteParams:[_pictureArray[i]] );
Wenn wir in der tatsächlichen Implementierung TweenLite innerhalb der Schleife aufrufen, weisen wir das Ziel als _pictureArray [aktuelle Iteration] zu..
Für die Dauer weisen wir einen Wert für die Tween-Länge einer zufälligen Zeit zwischen 0,25 Sekunden und 2 Sekunden zu.
Das variable Objekt enthält 5 Eigenschaften:
Diese Methode wird von TweenLite aufgerufen, wenn die Animation für ein bestimmtes Tween beendet ist. Wir entfernen einfach das Sprite aus der Anzeigeliste, so dass kein Durcheinander entsteht. Fügen Sie nach der blowWind () -Methode die folgenden Codezeilen hinzu:
private Funktion removeSprite ($ sprite: Sprite): void removeChild ($ sprite);
Ich bin sicher, dass Sie mit diesem vertraut sind (falls nicht, hat Carlos Yanez einen Quick Tip zum Thema geschrieben.) Meine Version hat die Möglichkeit, entweder ganze Zahlen (int, uint) oder Floats (Brüche) zurückzugeben..
Fügen Sie die folgenden Codezeilen hinzu. Wenn Sie FlashDevelop verwenden, können Sie es als benutzerdefiniertes Snippet speichern, sodass es problemlos zu jeder Klasse / jedem Projekt hinzugefügt werden kann. Ich habe es als öffentliche statische Methode für volle Zugänglichkeit deklariert.
public static function getRandomInRange ($ min: Number, $ max: Number, $ abgerundet: Boolean = true): Number if ($ abgerundet) gibt Math.round (Math.random () * ($ max - $ min) + $ zurück Mindest); sonst Rückgabe Math.random () * ($ max - $ min) + $ min;
Das ist es! Führen Sie den Film aus. Wenn etwas nicht stimmt, überprüfen Sie Ihren Code mit der WindEffect-Klasse, die ich im Quelldownload enthalten habe.
Der Schlüssel zum Erstellen cooler Effekte ist das Erlernen und Beherrschen von Tweening-Klassen wie TweenLite. Bitte zögern Sie nicht, eine Notiz für Anmerkungen, Bedenken oder Vorschläge zu hinterlassen. Danke fürs Lesen!