Aktive Tarnung ist ein Sci-Fi-Konzept, das normalerweise in Form eines Anzugs zu sehen ist, durch den der Träger fast unsichtbar werden kann. Es ist in Filmen wie Predator und Die Another Day und Spielen wie Halo und Crysis zu sehen.
Dieses Tutorial zeigt Ihnen, wie Sie einen solchen Effekt in Flash erzielen, indem Sie einen Verschiebungsfilter mit einer Folge von Bitmaps animieren. Der Effekt ist nicht nur cool, sondern wird auch in Online-Tutorials selten gesehen.
Werfen wir einen Blick auf das Endergebnis, auf das wir hinarbeiten:
Verschiebungsabbildung ist eine Texturabbildung, mit der die Verschiebungsstärke moduliert wird. Verschiebung bedeutet, die Pixel einer Oberfläche buchstäblich aus dem Ort zu verschieben. In den meisten 3D-Anwendungen werden die Pixel entlang der Oberflächennormalen verschoben. In Adobe Flash erfolgt die Verschiebung im 2D-Raum entlang der X- und Y-Koordinaten eines Bildes.
Verschiebungsfilter in Flash werden normalerweise animiert, indem ihre Intensität dynamisch geändert wird (die Parameter scaleX und scaleY), die Position der Verschiebungsbitmap (der mapPoint-Parameter) oder die Farbkanäle geändert werden. In diesem Lernprogramm werden diese Techniken näher erläutert. Wir werden jedoch auch eine andere lernen, bei der eine Bitmap-Sequenz verwendet wird, um in jedem Frame eine neue Verschiebungskarte zu zeichnen.
Beispiel für eine Verschiebung entlang der Flächennormalen.
Beispiel für eine Verschiebungsabbildung in Flash entlang der X- und Y-Achse.
Öffnen Sie ein neues Dokument in Flash und stellen Sie die Größe auf 550x368 ein, damit sie unserem Hintergrundbild entspricht. Stellen Sie die Bildrate auf 48fps ein. Der Verschiebungsfilter läuft zwar mit 12 Bildern pro Sekunde, aber falls Sie später eine zusätzliche Animation wünschen, würde er bei 48 Bildern pro Sekunde weicher aussehen.
Klicken Sie auf Datei> Veröffentlichungseinstellungen> ActionScript 3.0-Einstellungen, und deaktivieren Sie "Bühneninstanzen automatisch deklarieren"..
Importiere rainforest.jpg auf die Bühne.
Drücken Sie Strg + K, um die Leinwandgröße auszurichten. Dies wird unser Hintergrundbild sein.
Wenn das Bild nun ausgewählt ist, drücken Sie F8, um es in ein Symbol zu konvertieren. Wählen Sie "Filmclip" im Menü "Typ".
Wenn das Eigenschaftsfenster geschlossen ist, drücken Sie Strg + F3, um es zu öffnen. Wir nennen den gerade erstellten Filmclip. Geben Sie im Feld für den Instanznamen "bkgd_mc" ein..
Drücken Sie jetzt Strg + F8, um einen neuen Movieclip zu erstellen. Wir nennen das noch nicht. Zuerst importieren wir die Bitmap-Sequenz in diesen Movieclip. Gehen Sie zu Datei> Importieren> In Bühne importieren. Wählen Sie das erste Bild der Sequenz aus, das als "pred0001.jpg" bezeichnet wird. Flash wird gefragt, ob Sie alle Bilder in dieser Sequenz importieren möchten. Klicken Sie auf Ja.
Sie werden feststellen, dass jede Bitmap entlang der Zeitleiste des Movieclips auf einem Keyframe platziert wird. Wählen Sie ab Bild 1 das Bild aus und drücken Sie F8, um es in einen Movieclip umzuwandeln. Tun Sie dies bei jedem Frame bis zum Ende der Sequenz. Tun Sie dies der Reihe nach, und stellen Sie sicher, dass Sie keine Frames überspringen, da sonst die Animation durcheinander geraten kann.
Sobald Sie fertig sind, sollte jeder Keyframe einen Movieclip enthalten, der einen Frame des Gesichts der Figur enthält. Wählen Sie erneut Bild eins aus und drücken Sie die Eingabetaste, um die Animation anzuzeigen.
Wählen Sie den Movieclip in Bild 1. Klicken Sie mit der rechten Maustaste und verteilen Sie sie auf Ebenen. Wiederholen Sie dies für alle Movieclips in allen Bildern. Wenn Sie fertig sind, können Sie die Animation nicht mehr sehen, nur das Bild auf der obersten Ebene.
Drücken Sie Strg + L, um die Bibliothek zu öffnen, und ziehen Sie "Symbol 2" auf die Bühne. In der Registerkarte "Eigenschaften" nennen Sie diese Instanz "displ_mc". Dieser Movieclip wird in unserem Verschiebungsfilter verwendet.
Wir werden den Code für unseren Verschiebungskartenfilter in eine Dokumentenklassendatei schreiben. Erstellen Sie eine neue Actionscript-Datei und nennen Sie sie "pred_as3". Fügen Sie nun diesen Code ein:
package import flash.display.MovieClip; import flash.display.BitmapData; import flash.display.IBitmapDrawable; import flash.display.BitmapDataChannel; import flash.filters.DisplacementMapFilter; import flash.filters.DisplacementMapFilterMode; import flash.geom.Point; import flash.events.Event; öffentliche Klasse pred_as3 erweitert MovieClip
Gehen Sie zurück zum Flash-Dokument und benennen Sie die Klasse pred_as3.
Wie Sie sehen, haben wir bereits alle Klassen importiert, die wir in diesem Lernprogramm benötigen. Jetzt schreiben wir die Dokumentenklasse weiter. Fügen Sie diesen Code hinzu:
private var clipcont = new Array (); // Alle animierten Bilder werden in diesem Array gespeichert. private var count: Number; // Teil der Enterframe-Schleife; Gibt an, welcher Frame der Animation als privater var-Timer angezeigt wird: uint = 0; // Legt die Geschwindigkeit der Animation fest. public var displ_mc: MovieClip; public var bkgd_mc: MovieClip;
Wir geben einige Variablen an, die später verwendet werden. Sie müssen vor dem Klassenkonstruktor deklariert werden, wenn sie von mehr als einer Funktion in der Dokumentenklasse verwendet werden sollen.
Direkt unterhalb der letzten Zeile schreiben wir die Parameter und den Konstruktor des Verschiebungskartenfilters.
private var Stärke1: int = 120; // Wert von scaleX und scaleY - setzt die Intensität des Verschiebungsfilters private var mapBitmap: BitmapData = new BitmapData (320,240); // die Größe der Verschiebungskarte in Pixeln private var mapPoint: Point = new Point (0,0) ); // die Position der Verschiebungsbitmap private var componentX = BitmapDataChannel.GREEN; // welcher Farbkanal verwendet wird; spielt keine Rolle, da es in Graustufen ist; private var-KomponenteY = BitmapDataChannel.GREEN; private var spe: int = 1; // ändert die Stärke des Verschiebungsfilters // alle Variablen werden dann auf einen neuen Filter angewendet: privater var-Filter: DisplacementMapFilter = new DisplacementMapFilter (mapBitmap, mapPoint, componentX, KomponenteY, scaleX, scaleY); private var filterList = new Array (); // ein Filterlistenarray.
Wir haben also Parameter für Stärke, Größe, Position und RBG-Kanal eingestellt. Schauen wir uns jeden dieser Parameter genauer an…
Wie bereits erwähnt, ist eine Verschiebung in Flash nur entlang der X- und Y-Achse möglich. Die Parameter, die die Verschiebungsstärke für X und Y festlegen, sind scaleX
und scaleY
beziehungsweise. In diesem Lernprogramm verwenden wir auf beiden X- und Y-Achsen die gleiche Stärke. Daher verwenden wir für beide Parameter dieselbe variable Stärke1. Unten ist ein Beispiel für die Verschiebung entlang der horizontalen Achse dargestellt, wobei scaleY auf null (linkes Bild) und die vertikale Achse mit scaleX auf null (rechts) gesetzt ist..
Beachten Sie, wie die Größe auf 320x240 eingestellt ist. Wir wissen bereits, wie groß die Bitmaps in der Animation sind, und der Konstruktor muss dieselbe Größe haben. Wenn der Wert im Konstruktor größer als der der Bitmaps ist, kommt es zu Verschiebungen in Bereichen, in denen dies nicht der Fall sein sollte. Das # 808080-Grau um den Kopf des Charakters ist eine neutrale Farbe, andererseits würde ein leerer Bereich oder eine transparente Bitmap das Hintergrundbild tatsächlich verschieben.
Beispiel für den im Konstruktor festgelegten Wert, der größer als die tatsächliche Verschiebungskarte ist: Die leeren Bereiche verschieben den Hintergrund.
Der Verschiebungsfilter verwendet nur einen der 3 RGB-Kanäle in einer Bitmap für jede Achse. Wenn Sie eine farbige Bitmap als Verschiebungskarte verwenden, führt jeder Kanal zu sehr unterschiedlichen Ergebnissen, wie im nachstehenden Beispiel gezeigt. In diesem Tutorial verwenden wir ein Bild in Graustufen, sodass der Kanal irrelevant ist. ComponentX und ComponentY sind auf Grün gesetzt, der gleiche Effekt wird jedoch mit den roten oder blauen Kanälen erzielt.
Die verschiedenen Ergebnisse werden mit dem grünen Kanal, dem roten Kanal oder dem blauen Kanal erzielt.
Der Parameter mapPoint legt die Position der Verschiebungskarte fest. Die Position ist relativ zu dem Objekt, auf das sie angewendet wird, und nicht zur Bühne. Wenn Sie die Position auf (0,0) setzen, wird die Verschiebungskarte in der oberen linken Ecke unseres Hintergrundbilds angezeigt, die nicht immer mit der oberen linken Ecke der Bühne übereinstimmt, wie unten gezeigt.
Der mapPoint -Parameter ist relativ zum Objekt, nicht zur Bühne.
Wenden wir nun den Verschiebungsfilter auf unser Hintergrundbild "displ_mc" an. Der Verschiebungsfilter wird in ein Array von Filtern verschoben, und wir tun dies innerhalb des Klassenkonstruktors. Wir fügen auch unsere beiden Hauptfilmclips mit der Addchild-Methode der Bühne hinzu. In AS3 ist der Klassenkonstruktor die erste Funktion, die in einer Dokumentklasse ausgeführt wird und automatisch aufgerufen wird. Es ist daher besser, dass alle Funktionen oder Methoden, die beim Laden ausgeführt werden müssen, aus einem Klassenkonstruktor heraus aufgerufen werden.
public function pred_as3 () addChild (displ_mc); addChild (bkgd_mc); // beide Movieclip-Instanzen zur stage filterList.push (filter) hinzufügen; // den Verschiebungs-Map-Filter zum Array hinzufügen. bkgd_mc.filters = filterList; // wendet das Filter-Array auf den Ziel-Movieclip an. storeClips ();
Die letzte Codezeile ruft eine Funktion auf, die noch nicht geschrieben wurde. Wie der Name vermuten lässt, speichert diese Funktion alle animierten Movieclips in einem Array. Also schreiben wir das jetzt.
Also haben wir einen Verschiebungs-Map-Filter erstellt und auf den Movieclip angewendet. Dem Filter wurden jedoch noch keine Bitmaps hinzugefügt. Wir machen dies in zwei Schritten: Zuerst speichern wir die Animation in einem Array, und später fügen wir diese Animation dem Filter hinzu.
private function storeClips (): void // speichert die Animation in einem Array count = displ_mc.numChildren; // die Gesamtzahl der Movieclips in displ_mc für (var i: int = 0; i < displ_mc.numChildren; i++)//finds all movieclips inside displ_mc clipcont.push(displ_mc.getChildAt(i));// frames are pushed inside the clipcont array
Diese Funktion verwendet a zum
Schleife, um alle Movieclips in displ_mc zu scannen. Wir möchten die Animationsbilder, die zuvor in diesem Tutorial in Filmclips konvertiert wurden. Erinnern Sie sich noch daran, wann ich gesagt habe, sie Frame für Frame zu konvertieren? Wir haben das getan, damit die Frames richtig sortiert werden können und später mit der getChildAt () -Methode darauf zugegriffen werden kann. Da wir keine dieser Instanzen benannt haben, sortiert Flash sie intern nach der Reihenfolge ihrer Erstellung. Wenn die Bitmaps zufällig in Movieclips konvertiert wurden, würde die Animation niemals korrekt wiedergegeben. Die Frames können nun nacheinander in das clipcont-Array verschoben werden.
Der Code sollte bisher so aussehen:
package import flash.display.MovieClip; import flash.display.BitmapData; import flash.display.IBitmapDrawable; import flash.display.BitmapDataChannel; import flash.filters.DisplacementMapFilter; import flash.filters.DisplacementMapFilterMode; import flash.geom.Point; import flash.events.Event; public class pred_as3 erweitert MovieClip private var clipcont = new Array (); // Alle animierten Bilder werden in diesem Array gespeichert. private var count: Number; // Teil der Enterframe-Schleife; teilt mit, welcher Frame der Animation als privater var-Timer angezeigt wird: uint = 0; public var displ_mc: MovieClip; public var bkgd_mc: MovieClip; private var Stärke1: int = 120; // Legt die Intensität des Verschiebungsfilters private var mapBitmap fest: BitmapData = new BitmapData (320,240); // die Größe der Verschiebungskarte in Pixeln private var mapPoint: Point = new Point (0,0); // die Position von Die Verschiebungsbitmap private var componentX = BitmapDataChannel.GREEN; // welcher Farbkanal verwendet wird; spielt keine Rolle, da es in Graustufen ist; private var-KomponenteY = BitmapDataChannel.GREEN; private var spe: int = 1; // Alle Variablen werden dann auf einen neuen privaten Filter für private Filter angewendet: DisplacementMapFilter = new DisplacementMapFilter (mapBitmap, mapPoint, componentX, KomponenteY, scaleX, scaleY); private var filterList = new Array (); // ein Filterlistenarray. // CLASS CONSTRUCTOR öffentliche Funktion pred_as3 () addChild (displ_mc); addChild (bkgd_mc); // füge beide Movieclip-Instanzen der Bühne hinzu storeClips (); filterList.push (filter); // füge den Verschiebungsfilter zum Array hinzu. bkgd_mc.filters = filterList; // wendet den Filtersatz auf den Ziel-Movieclip an. private Funktion storeClips (): void // speichert die Animation in einem Array count = displ_mc.numChildren; // die Gesamtzahl der Movieclips in displ_mc für (var i: int = 0; i < displ_mc.numChildren; i++)//finds all movieclips inside displ_mc clipcont.push(displ_mc.getChildAt(i));// frames are pushed inside the clipcont array
Jetzt, da wir die Animation fertig haben, setzen wir sie in den Verschiebungsfilter. Wir werden auf das clipcont-Array mit einer "time release" -Schleife mit der Event.ENTER_FRAME
Klasse. Alle 4 Frames wird auf eine neue Bitmap im Array zugegriffen und dann mit der draw () -Methode auf den Filter angewendet. Nachdem das letzte Bild in clipcont gezeichnet wurde, beginnt die Schleife und das erste Bild in clipcont wird gezeichnet. Es ist eine endlose Schleife.
private Funktion animate (e: Event) filter.scaleX = Stärke1; // setzt den Wert von scaleY und scaleX filter.scaleY = strength1; if (Timer> 3) // alle 4 Frames wird ein neuer Frame if (count <= 0) count = clipcont.length;// setting an infinite loop count--; timer = 0; if (clipcont[count]) filter.mapBitmap.draw(clipcont[count]);// a new frame of animation is drawn bkgd_mc.filters = filterList;//updates the filter
Kopieren Sie die obigen Zeilen in Ihre Actionscript-Datei. Lassen Sie uns dies nun ausführen, indem Sie dem Klassenkonstruktor einen Ereignis-Listener hinzufügen.
public function pred_as3 () addChild (displ_mc); addChild (bkgd_mc); // beide Movieclip-Instanzen zur stage filterList.push (filter) hinzufügen; // den Verschiebungs-Map-Filter zum Array hinzufügen. bkgd_mc.filters = filterList; // wendet den Filtersatz auf den Ziel-Movieclip an. storeClips (); addEventListener (Event.ENTER_FRAME, animate); // ruft die animierte Funktion bei enter frame auf
Aktualisieren Sie den Klassenkonstruktor mit der addEventListener
Methode. Jetzt wurde die Animationsfunktion zur Bühne hinzugefügt und für jeden Frame aufgerufen. Testen Sie den Effekt durch Drücken von Strg + Eingabetaste. Sie sollten das animierte Gesicht in der oberen linken Ecke Ihres Films sehen.
In der Ecke des Films läuft eine Animationsschleife. Lassen Sie uns die Verschiebungskarte der Maus folgen lassen. Auf diese Weise können Sie sehen, wie der aktive Tarneffekt in verschiedenen Bereichen des Hintergrunds aussieht. Fügen Sie diese Zeile in die Animationsfunktion ein:
private Funktion animate (e: Event) filter.scaleY = Stärke1; // Setzt den Wert von scaleY und scaleX filter.scaleX = strength1; Timer ++; if (Timer> 3) // alle 4 Frames wird ein neuer Frame if (count <= 0) count = clipcont.length;// setting an infinite loop count--; timer = 0; if (clipcont[count]) filter.mapBitmap.draw(clipcont[count]);// a new frame of animation is drawn filter.mapPoint = new Point(mouseX-160, mouseY-240); // displacement map follows the mouse bkgd_mc.filters = filterList;
Auf diese Weise aktualisieren wir die Position der Verschiebungskarte mit den Eigenschaften mouseX und mouseY. Drücken Sie Strg + Eingabetaste, um es zu testen. Der Kopf sollte nun der Maus folgen.
Im letzten Schritt dieses Tutorials werden wir uns ein wenig mit der Stärke unseres Filters beschäftigen, indem wir den Wert der Parameter scaleX und scaleY über einen bestimmten Zeitraum erhöhen und dann wieder auf den Anfangswert zurückgehen. Was wir damit erreichen wollen, ist, den Effekt dynamischer und sichtbarer zu machen. Während im wirklichen Leben der Sinn einer Tarnung darin bestehen sollte, die Dinge weniger sichtbar zu machen, versuchen wir hier, sie cool aussehen zu lassen. Lassen Sie uns die Animation einfrieren, damit Sie verstehen, worüber ich spreche. Ersetzen Sie in der Animationsfunktion die Linie
filter.mapBitmap.draw (clipcont [Anzahl]);
stattdessen mit dieser Zeile:
filter.mapBitmap.draw (clipcont [20]);
Anstatt die Animation zu zeichnen, empfehlen wir Flash, immer und immer wieder das gleiche Bild zu zeichnen. Drücken Sie Strg + Eingabetaste, um es zu testen.
Der Effekt wirkt völlig statisch und langweilig. Lassen Sie uns etwas Bewegung geben. Fügen Sie den folgenden Code in die Animationsfunktion ein:
private Funktion animate (e: Event) filter.scaleY = Stärke1; // aktualisiert den Wert von scaleY und scaleX filter.scaleX = strength1; Timer ++; if (Timer> 3) // alle 4 Frames wird ein neuer Frame if (count <= 0) count = clipcont.length;// setting an infinite loop count--; timer = 0; if (clipcont[count]) filter.mapBitmap.draw(clipcont[20]);// a new frame of animation is drawn filter.mapPoint = new Point(mouseX-160, mouseY-240); // displacement map follows the mouse if (filter.scaleX > 220 || filter.scaleX < 120) // filter keeps changing it's intensity, making the effect more dynamic spe *= -1; strength1 += spe; bkgd_mc.filters = filterList;
Testen Sie es jetzt mit Strg + Enter.
Sehen Sie, wie viel besser es aussieht. Ok, Sie können jetzt die Animation wiederherstellen und die geänderte Zeile korrigieren:
filter.mapBitmap.draw (clipcont [Anzahl]);
Dieser Effekt ist auch hilfreich, wenn Sie später einen statischen Körper an die Gesichtsanimation anschließen möchten. Es würde nach der Bitmap-Animation aktiver aussehen.
Die Datei kann etwas schwer sein, wenn Sie JPEG-Qualität 100 verwenden, was ich empfehle. Bei einer geringeren Qualität verliert der Effekt etwas an Charme. Wenn Sie einen kleineren Film wünschen, können Sie die Bilder in Photoshop noch stärker komprimieren. Achten Sie jedoch darauf, dass Sie das Farbschema richtig einstellen. Die Farbe um den Kopf des Charakters sollte immer # 808080 sein, sonst sehen Sie eine Box um den Kopf.
So, das ist es. Das erste Tutorial, das ich jemals geschrieben habe, es hat Spaß gemacht und ich hoffe, Sie hatten Spaß beim Lesen und nutzen es gut. Ich würde mich sehr über Ihr Feedback freuen. Danke fürs Lesen!