In dem vorherigen Tutorial haben wir die Grundlagen der Kollisionserkennung auf Pixelebene durchlaufen. In diesem Lernprogramm werden wir die Verwendung von Matrizen untersuchen, um den Interessenbereich besser zu definieren - sehr nützlich für Grafiken, die gedreht, übersetzt oder verzerrt wurden.
Dies ist das letzte Stück, das wir versuchen werden zu programmieren. Klicken Sie auf den Ball und Haken, um die interaktive Demo zu starten.
Beachten Sie, dass wir trotz der rotierenden Kokosnussbaumgrafik und der anderweitigen Transformation immer noch eine pixelgenaue Kollisionserkennung haben.
zeichnen
FunktionUm eine Kollisionserkennung auf Pixelebene durchzuführen, muss die Grafik in a konvertiert werden BitmapData
Objekt. Wir haben dies im vorherigen Tutorial anhand der Analogie eines Röntgenbildes betrachtet. In diesem Tutorial erkläre ich diesen "Röntgen" -Prozess.
Nehmen wir an, wir haben ein Stück einer Grafik (Diagramm 1) und wollten es in eine gießen BitmapData
Objekt; Wir müssen die Dimensionen der festlegen BitmapData
Objekt zuerst (Diagramm 2). In diesem Fall ist es ganz einfach, weil die Grafik ist Breite
und Höhe
Eigenschaften bieten dies. Dann rufen wir die an zeichnen()
Methode; Pixel, die mindestens zur Hälfte von der Grafik besetzt sind, werden theoretisch aufgefüllt (Diagramm 3). Dieses Pixelarray wird mit einem anderen Pixelarray einer anderen Grafik verglichen, um eine Kollision zwischen den beiden zu überprüfen (Diagramm 4)..
In Flash IDE werden verschiedene Koordinatenräume verwendet (Abbildungen 1 und 2 oben). Ich bin mir sicher, dass jeder Leser das erlebt hätte - siehe mein Tutorial über affine Räume für einen detaillierteren Blick.
In der Flash-IDE zeichnen wir ein Bild und verwandeln es in ein Symbol des Typs Filmausschnitt
. Wenn wir doppelt auf das Symbol klicken Filmausschnitt
, wir kommen zu einem anderen Koordinatenraum (Diagramm 3). Von hier aus können wir auf das Bühnenetikett klicken, um den lokalen Koordinatenraum dieser Grafik zu verlassen und den Koordinatenraum der Bühne zu erreichen. Dann können wir damit beginnen, die Instanz von zu transformieren Filmausschnitt
auf der Bühne (Diagramm 4). In der Tat können wir mehrere Instanzen des erstellen Filmausschnitt
, Jeder von ihnen hat unterschiedliche Transformationen.
In der Bibliothek bleibt die Originalgrafik trotz aller auf der Bühne vorgenommenen Verbesserungen unverändert. Dies ist sinnvoll, denn wenn wir eine neue Kopie von a erstellen Filmausschnitt
Auf der Bühne entsprechen sie immer dem Original in der Bibliothek. Nun stellt sich die Frage: "Wie erfasst Flash all die Transformation, die wir auf den Bühnenkopien vorgenommen haben?" Nun, jeder benutzt das MovieClip.transform.matrix
Eigenschaft zum Erfassen aller Transformationen (Übersetzung, Rotation, Neigung usw.).
Kommen wir jetzt zu dem Punkt zurück, an dem wir aufgehört haben. Es ist wichtig, dass wir dies verstehen, weil die zeichnen()
Methode von BitmapData
bezieht sich nicht auf die grafische Instanz auf der Bühne, wenn ein "Röntgenbild" ausgeführt wird, sondern auf die unveränderte Grafikquelle in der Bibliothek.
Das BitmapData
Das erste Pixel des Objekts richtet sich nach dem Registrierungspunkt (dem roten Punkt) von Filmausschnitt
im lokalen Koordinatenraum (siehe Diagramm 3 in Schritt 1), erfasst dann die Grafik in Pixelform mit den von uns angegebenen Abmessungen.
Wenn es darum geht hitTest
überprüft, dass ActionScript dieses erste Pixel (das obere linke Pixel) des BitmapData
Objekt mit dem Registrierungspunkt der grafischen Instanz auf der Bühne. Damit sind alle Pixel im BitmapData
Das Objekt wird auf der Bühne auf den Koordinatenraum abgebildet und erhält seine individuellen Koordinaten. Überprüfungen können später durchgeführt werden, indem diese Koordinaten zwischen zwei Bitmaps verglichen werden, um festzustellen, ob sich Pixel überlappen.
Hinweis: Diese Erklärung nimmt das an Filmausschnitt
oder Sprite
Instanz wird der Anzeigeliste der Bühne hinzugefügt. In ActionScript können wir tatsächlich der Dokumentklasse selbst Anzeigeobjekte hinzufügen, da diese erweitert wird Filmausschnitt
oder Sprite
.
Wenn also die interessierende Grafik auf der Bühne gedreht wird, wie funktionieren wir? zeichnen()
?
Aus dem obigen Diagramm können wir diese Probleme klar erkennen.
Diagramm | Problem | Beschreibung |
1 | Dimension von BitmapData Objekt | Da sich die Objektorientierung geändert hat, ist die erforderliche Dimension von BitmapData Besetzung kann nicht mehr bequem aus dem übernommen werden Breite und Höhe Eigenschaften der grafischen Instanz. |
2 | Orientierung der Grafikquelle | Die Instanz der Grafik auf der Bühne ist gedreht, die in der Bibliothek jedoch nicht. Wir müssen eine Momentaufnahme der transformierten Grafikquelle aus der Bibliothek erstellen. |
3 | Koordinate des oberen linken Pixels (Startpixel) von BitmapData Objekt | Wir können das nicht ausrichten BitmapData Das erste Pixel des Objekts mit dem Registrierungspunkt der Grafikinstanz. Das wird falsch sein. |
Um diese Probleme zu lösen, definieren wir zuerst ein Rechteck, das die gedrehte Grafikinstanz auf der Bühne eng begrenzt. ActionScript-Bestimmungen hierfür durch die getBounds ()
Funktion. Dies löst unser erstes Problem. Beachten Sie das Bild unten. Beachten Sie, dass es einen Unterschied zwischen dem Registrierungspunkt der grafischen Instanz und dem des Rechtecks gibt.
Ich habe die Flash-Präsentation unten eingefügt, um die rechteckige Begrenzungsbox (rote Box) und die lokale Begrenzungsbox (Black Box) anzuzeigen.
Als Nächstes bringen wir eine Momentaufnahme der transforrmed-Grafikquelle in dieses Rechteck auf der Bühne. Beachten Sie das Bild unten.
Wir beginnen damit, dass der Registrierungspunkt der Grafikquelle mit dem des rechteckigen Bereichs (Diagramm 1) ausgerichtet ist. Dann drehen wir uns (Diagramm 2) und verschieben es (Diagramm 3), bevor wir die "Röntgenaufnahme" des Bildes auf die Kamera machen BitmapData
Objekt (Diagramm 4).
Wir können dies manuell tun oder eine Kopie der grafischen Instanz erstellen transform.matrix
Eigentum. Wenn Sie den zweiten Ansatz verwenden, sollten Sie darauf achten, dass Sie den transform.matrix
Übersetzung property - andernfalls werden die Registrierungspunkte nicht wie in Diagramm 1 gezeigt ausgerichtet. In beiden Fällen müssen wir den x- und y-Abstand zum Offset berechnen.
Nach dieser ausführlichen Erklärung hoffe ich, dass es einfacher ist, den Code zu verstehen. Ich habe die wichtigen Zeilen hervorgehoben und Kommentare hinzugefügt:
Private Var Coconut: CTree, hk: Haken; private var bdat1: BitmapData, bdat2: BitmapData; private var t1: TextField; privater Var-Winkel: Anzahl = 45 private Var-KokosnussBox: Rechteck; öffentliche Funktion Matrix_Bitmap4 () coconut = new CTree (); addChild (Kokosnuss); coconut.rotation = Winkel; coconut.x = stage.stageWidth * 0,3; coconut.y = stage.stageHeight * 0,2; coconutBox = coconut.getBounds (this); // Rechteckige Box in Schritt 2 erhalten var coconut_newX: Number = coconut.x - coconutBox.x // Offset x in Schritt 3 erhalten var coconut_newY: Number = coconut.y - coconutBox.y // Offset y in Schritt 3 erhalten : Matrix = neue Matrix (); m.rotate (Winkel / 180 * Math.PI); // Grafik in Schritt 3 drehen // var m: Matrix = coconut.transform.matrix // empfohlen, wenn viele Transformationen stattgefunden haben. //m.tx = 0; m.ty = 0; // In diesem Fall erledigt er dieselbe Arbeit wie die vorherige Zeile. m.translate (coconut_newX, coconut_newY); // Implementiere den Offset bdat1 = new BitmapData (coconutBox.width, coconutBox.width, true, 0x00000000); bdat1.draw (Kokosnuss, m);
Vergessen Sie auch nicht, die Position des ersten Pixels (oben links) in zu ändern BitmapData
Objekt zu dem der rechteckigen Box
private Funktionsprüfung (e: Event): void var closeEnough: Boolean = coconut.hitTestObject (hk) if (closeEnough) // var point1: Punkt = neuer Punkt (coconut.x, coconut.y); // jetzt, da wir eine andere Box mit unterschiedlichen Positionen zum Startpixel haben, // sollten wir auf coconutBox als Startpunkt verweisen var point1: Point = new Point (coconutBox.x, coconutBox.y); var point2: Punkt = neuer Punkt (hk.x, hk.y); if (bdat1.hitTest (point1, 1, bdat2, point2, 1)) t1.text = "Mindestens ein Pixel ist kollidiert" else t1.text = "Keine Kollision"
Und hier ist ein Beispiel für die Arbeit.
Wenn die interessierende Form, in diesem Fall der Kokosnussbaum, sich ständig wandelt (rotiert, skaliert, verkleinert, verzerrt usw.), dann wird die BitmapData
Das Objekt muss für jeden Frame aktualisiert werden. Dies erfordert einige Verarbeitungsschritte. Beachten Sie auch, dass ich mich für den in Schritt 4 genannten alternativen Ansatz entschieden habe. Hier ist das Skript zum Aktualisieren der Röntgenkopie der Grafik für jeden Frame:
private Funktion updateBmp (): void coconutBox = coconut.getBounds (this); // Rechteckige Box in Schritt 2 erhalten var coconut_newX: Number = coconut.x - coconutBox.x // Offset x in Schritt 3 erhalten var coconut_newY: Number = coconut.y - coconutBox.y // Offset y in Schritt 3 erhalten // var m: Matrix = neue Matrix (); //m.rotate(angle / 180 * Math.PI); // Grafik in Schritt 3 drehen var m: Matrix = coconut.transform.matrix // empfohlen, wenn viele Transformationen stattfanden, m.tx = 0; m.ty = 0; // In diesem Fall erledigt er dieselbe Arbeit wie die vorherige Zeile. m.translate (coconut_newX, coconut_newY); // Implementiere den Offset bdat1 = new BitmapData (coconutBox.width, coconutBox.width, true, 0x00000000); b = neue Bitmap (bdat1); addChild (b); b.x = stage.stageWidth * 0,3; b.y = stage.stageHeight * 0,2; bdat1.draw (Kokosnuss, m);
Die folgende Funktion wird für jeden Frame ausgeführt:
private Funktionsprüfung (e: Event): void coconut.rotation + = angle; // dynamische Änderungen zur Laufzeit coconut.scaleX + = 0.01 var closeEnough: Boolean = coconut.hitTestObject (hk) if (closeEnough) updateBmp (); var point1: Point = neuer Punkt (coconutBox.x, coconutBox.y); var point2: Punkt = neuer Punkt (hk.x, hk.y); if (bdat1.hitTest (point1, 1, bdat2, point2, 1)) t1.text = "Mindestens ein Pixel ist kollidiert" else t1.text = "Keine Kollision" bdat1.dispose ();
Und das ist die Ausgabe. Ziehen Sie den Haken, um die Animation zu sehen.
Ich verstehe, dass dieses Tutorial nicht zu schnell gelesen werden kann, aber es ist wichtig, dass Sie ein klares Verständnis davon bekommen, was passiert. Ich hoffe, das war hilfreich und wenn Sie mehr an der 2x2-Matrix interessiert sind, besuchen Sie meinen Artikel zu diesem Thema. Vielen Dank.