Zweimal im Monat besuchen wir einige der Lieblingsbeiträge unserer Leser aus Activetuts + history. Das im April erstmals veröffentlichte Retro-Active-Tutorial ist ein Leitfaden für euklidische Vektoren: Was sind sie, warum verwenden Sie sie und wie werden sie in Flash mit AS3 implementiert?.
Euklidische Vektoren sind Objekte in der Geometrie mit bestimmten Eigenschaften, die für die Entwicklung von Spielen sehr nützlich sind. Sie können als Punkte gesehen werden, aber sie haben auch eine Größe und eine Richtung. Sie werden als Pfeile dargestellt, die vom Anfangspunkt zum Endpunkt gehen, und so zeichnen wir sie in diesem Artikel.
Euklidische Vektoren werden in der Mathematik und Physik häufig für viele Dinge verwendet: Sie können Geschwindigkeit, Beschleunigung und Kräfte in der Physik darstellen oder helfen, viele wichtige Theoreme in der Mathematik zu beweisen. In diesem Lernprogramm erfahren Sie mehr über euklidische Vektoren und erstellen eine Klasse, die Sie in Ihren eigenen Flash-Projekten verwenden können.
Bitte beachten Sie, dass sich euklidische Vektoren von der Vector-Klasse von ActionScript und auch von der Vektorzeichnung unterscheiden.
Vektoren können in der Flash-Umgebung verwendet werden, um komplexe Aufgaben zu erledigen, die andernfalls sehr aufwendig wären, wenn sie ohne sie erledigt würden. In diesem Artikel erfahren Sie, wie Sie sie in Flash verwenden können, und Sie lernen viele coole Tricks mit Vektoren.
Bevor wir in Vektoren springen, wollen wir das Koordinatensystem von Flash einführen. Sie kennen wahrscheinlich das kartesische Koordinatensystem (auch wenn Sie es nicht anhand des Namens kennen):
Das System von Flash ist sehr ähnlich. Der einzige Unterschied ist, dass die Y-Achse auf dem Kopf steht:
Wenn wir mit Vektoren in Flash arbeiten, müssen wir uns daran erinnern. Eine gute Nachricht: Dieses andere System macht keinen großen Unterschied. Das Arbeiten mit Vektoren wird im Grunde so sein wie das Arbeiten mit Vektoren im kartesischen System.
In diesem Tutorial definieren und arbeiten wir mit den Anfangspunkten aller Vektoren als Registrierungspunkt der Stufe, genau wie sie in der Mathematik häufig verwendet werden. Ein Vektor wird dann wie ein gemeinsamer Punkt definiert, er hat jedoch Größen- und Winkeleigenschaften. Schauen Sie sich einige Beispielvektoren an, die auf der Bühne definiert wurden:
Wie Sie sehen, wird ein Vektor durch einen Pfeil dargestellt, und jeder Vektor hat eine bestimmte Länge (oder Größe) und zeigt entlang einer bestimmten Winkel. Das Ende jedes Vektors befindet sich am Registrierungspunkt (0, 0)
.
Für dieses Lernprogramm erstellen wir eine einfache EuclideanVector-Klasse. Verwenden Sie die Point-Klasse, um die Koordinaten des Vektors zu speichern. Erstellen Sie jetzt die grundlegende Vektorklasse:
Paket import flash.geom.Point; öffentliche Klasse EuclideanVector public var position: Point; public var magnitude: Anzahl; public var angle: Anzahl; öffentliche Funktion EuclideanVector (endPoint: Point) position = endPoint;
Während dieses Tutorials werden wir über das sprechen Sinn und das Richtung eines Vektors. Beachten Sie, dass die Richtung nur eine Linie definiert, die den Vektor "enthält". Der Sinn ist, was definiert, wie der Vektor entlang dieser Linie zeigt.
In diesem Tutorial verwenden wir den Ausdruck "Inverse eines Vektors". Die Inverse eines Vektors ist ein anderer Vektor mit der gleichen Größe und Richtung, jedoch einem entgegengesetzten Sinn. Dies übersetzt sich in einen Vektor mit dem entgegengesetzten Signal der ersten Vektorkoordinaten. Ein Vektor mit einem Endpunkt von (x, y) hätte also einen inversen Vektor mit einem Endpunkt von (-x, -y)..
Fügen wir unserer EuclideanVector-Klasse eine Funktion hinzu, um den inversen Vektor zurückzugeben:
public function inverse (): EuclideanVector return new EuclideanVector (neuer Punkt (-position.x, -position.y));
Nun, da wir gelernt haben, wie man einen Vektor definiert, lernen wir nun, wie man zwei Vektoren hinzufügt: Es ist so einfach, ihre Koordinaten separat hinzuzufügen. Schau dir dieses Bild an:
Wenn Sie im Bild feststellen, ist das Ergebnis der Addition zweier Vektoren ein anderer Vektor, und Sie können sehen, dass seine Koordinaten die Summe der Koordinaten der beiden anderen Vektoren sind. Im Code würde es so aussehen:
öffentliche Funktionssumme (otherVector: EuclideanVector): EuclideanVector position.x + = otherVector.position.x; position.y + = otherVector.position.y; kehre das zurück;
Also können wir das sagen:
vecR == vec1.sum (vec2);
Die Subtraktion funktioniert fast genauso wie die Addition. Stattdessen fügen wir die Addition hinzu invers des zweiten Vektors zum ersten Vektor.
Es ist bereits bekannt, wie zwei Vektoren summiert werden, daher ist hier der Code für die Subtraktion:
öffentliche Funktion subtrahieren (otherVector: EuclideanVector): EuclideanVector position.x - = otherVector.position.x; position.y - = otherVector.position.y; kehre das zurück;
Dieser Code ist äußerst nützlich, um einen Vektor zu erhalten, der vom Punkt eines Vektors zum Punkt eines anderen führt. Schauen Sie sich noch einmal das Bild an und Sie werden sehen, dass dies wahr ist. In den späteren Beispielen wird es häufig verwendet.
Die Multiplikation zwischen einem Vektor und einer Zahl (reguläre Zahlen werden in der Vektormathematik als "Skalare" bezeichnet) führt zu einem Vektor, dessen Größe mit dieser Zahl multipliziert wurde, aber immer noch in dieselbe Richtung zeigt. es ist "gestreckt", wenn der Skalar größer als 1 ist, und wird gestaucht, wenn der Skalar zwischen 0 und 1 liegt. Der Sinn des neuen Vektors ist derselbe wie der ursprüngliche Vektor, wenn der Skalar positiv ist, oder das Gegenteil, falls negativ. Grundsätzlich "skaliert" diese Zahl den Vektor. Sehen Sie das Bild an:
Im Code multiplizieren wir nur die Koordinaten eines Vektors mit der Zahl, wodurch der Vektor skaliert wird:
öffentliche Funktion multiplizieren (Nummer: Nummer): EuclideanVector position.x * = number; position.y * = Nummer; kehre das zurück;
Um die Größe eines Vektors zu erhalten, verwenden wir den Satz des Pythagoras. Wenn Sie vergessen haben, was es ist, hier eine kurze Auffrischung:
(Mehr Infos hier.)
Der Code ist sehr einfach:
public function magnitude (): Number return Math.sqrt ((position.x * position.x) + (position.y * position.y));
Sie sollten auch die Zeile entfernen public var magnitude: Anzahl
, da wir dies von nun an verwenden werden.
Die Größe eines Vektors ist immer positiv, da er die Quadratwurzel der Summe zweier positiver Zahlen ist.
Der Winkel eines Vektors ist der Winkel zwischen der x-Achse und der Richtungslinie des Vektors. Der Winkel wird gemessen von der x-Achse und gegen den Uhrzeigersinn bis zur Richtungslinie im kartesischen System gemessen:
Da jedoch die y-Achse im Flash-Koordinatensystem auf dem Kopf steht, wird dieser Winkel im Uhrzeigersinn gemessen:
Dies kann leicht mit dem folgenden Code berechnet werden. Der Winkel wird im Bogenmaß zwischen 0 und 2pi zurückgegeben. Wenn Sie nicht wissen, was Radiant ist oder wie man sie verwendet, hilft Ihnen dieses Tutorial von Michael James Williams sehr.
public function angle (): Number var angle: Number = Math.atan2 (position.y, position.x); wenn (Winkel < 0) angle += Math.PI * 2; return angle;
Das Punktprodukt zwischen zwei Vektoren ist eine Zahl, die anscheinend keine Bedeutung hat, sie hat jedoch zwei nützliche Zwecke. Sehen wir uns zunächst an, wie das Dot-Produkt berechnet werden kann:
Es kann aber auch durch die Koordinaten jedes Vektors erhalten werden:
Das Punktprodukt kann uns viel über den Winkel zwischen den Vektoren sagen: Wenn es positiv ist, reicht der Winkel von 0 bis 90 Grad. Bei einem negativen Wert liegt der Winkel zwischen 90 und 180 Grad. Wenn es Null ist, beträgt der Winkel 90 Grad. Dies geschieht, weil in der ersten Formel nur der Cosinus dafür verantwortlich ist, dem Punktprodukt ein "Signal" zu geben: Die Größen sind immer positiv. Wir wissen jedoch, dass ein positiver Kosinus bedeutet, dass der Winkel zwischen 0 und 90 Grad liegt, usw. für negativen Kosinus und Null.
Das Punktprodukt kann auch verwendet werden, um die Länge eines Vektors in Richtung des anderen Vektors darzustellen. Betrachten Sie es als Projektion. Dies erweist sich als äußerst nützlich in Sachen wie dem Separation of Axis Theorem (SAT) und seiner Implementierung in AS3 für die Kollisionserkennung und -reaktion in Spielen.
Hier ist der praktische Code, um das Punktprodukt zwischen zwei Vektoren zu erhalten:
öffentlicher Funktionspunkt (otherVector: EuclideanVector): Number return (position.x * otherVector.position.x) + (position.y * otherVector.position.y);
Der Winkel zwischen den Vektoren, wie in Schritt 9 zu sehen, kann durch das Punktprodukt gegeben werden. So berechnen Sie es:
public function angleBetween (otherVector: EuclideanVector): Number return Math.acos (Punkt (otherVector) / (Magnitude () * otherVector.magnitude ()));
Es gibt auch eine andere Methode zur Berechnung des Winkels, die Ergebnisse zwischen -pi und pi ergibt und immer den Winkel berechnet, der vom ersten Vektor zum zweiten Vektor geht. Dies ist nützlich, wenn Sie die Rotation eines Anzeigeobjekts (von -180 bis 180) einfach integrieren möchten..
Die Methode funktioniert, indem der Winkel für beide Vektoren ermittelt wird, dann die Winkel subtrahiert und das Ergebnis bearbeitet wird.
Der Code:
öffentliche Funktion rangedAngleBetween (otherVector: EuclideanVector): Number var firstAngle: Number; var secondAngle: Number; Var Winkel: Anzahl; firstAngle = Math.atan2 (otherVector.position.y, otherVector.position.x); secondAngle = Math.atan2 (position.y, position.x); Winkel = secondAngle - firstAngle; while (Winkel> Math.PI) Winkel - = Math.PI * 2; während (Winkel < -Math.PI) angle += Math.PI * 2; return angle;
Beachten Sie, dass dieser Winkel positiv ist, wenn secondAngle ist höher als firstAngle, Daher beeinflusst die Reihenfolge, in der Sie den Entfernungswinkel erhalten, das Ergebnis!
Normalisieren eines Vektors bedeutet, dass seine Größe gleich 1 wird, während die Richtung und der Sinn des Vektors erhalten bleiben. Dazu multiplizieren wir den Vektor mit 1 / Betrag
. Auf diese Weise wird seine Größe auf 1 verringert oder erhöht.
public function normalize (): EuclideanVector var m: Number = Magnitude (); position.x / = m; position.y / = m; kehre das zurück;
Das normal Ein Vektor ist ein weiterer Vektor, der einen Winkel von 90 Grad zum ersten Winkel bildet. Es kann nach folgenden Formeln berechnet werden:
Die Formeln beruhen auf der Tatsache, dass, da die Normale immer senkrecht zu einem Vektor steht, wir nur die Reihenfolge der X- und Y-Koordinaten ändern und eine von ihnen invertieren müssen, um eine Normalen zu erhalten. Das folgende Bild zeigt den Vorgang:
Im Bild, Vec ist der ursprüngliche Vektor, Vec2 ist der Vektor mit Vechat Koordinaten getauscht, und Vec3 ist ein Vektor mit Vec2negative y-Koordinate. Ang und Ang2 sind variabel, aber der Winkel dazwischen Vec und Vec3 ist immer 90 Grad.
Und der Code ist einfach
public function normalRight (): EuclideanVector return new EuclideanVector (neuer Punkt (-position.y, position.x)); public function normalLeft (): EuclideanVector return new EuclideanVector (neuer Punkt (position.y, -position.x));
Um einen Vektor zu drehen, nehmen wir an, dass die Position (0, 0) (Anfangspunkt) der Drehpunkt ist. Der gedrehte Punkt ergibt sich aus der Formel:
Diese Formel erhält man durch Anwenden einer Rotationsmatrix auf diesen Vektor. Wir würden den Rahmen dieses Tutorials sprengen, wenn wir uns mit der Matrix und deren Funktionsweise beschäftigen würden. Ich werde die Formel hier einfach belassen.
Der Code ist so ziemlich derselbe:
öffentliche Funktion drehen (angleInRadians: Number): EuclideanVector var newPosX: Number = (position.x * Math.cos (angleInRadians)) - (position.y * Math.sin (angleInRadians)); var newPosY: Number = (position.x * Math.sin (angleInRadians)) + (position.y * Math.cos (angleInRadians)); position.x = newPosX; position.y = newPosY; kehre das zurück;
Dies ist das Ende unserer grundlegenden Vektoroperationen. Was Sie als Nächstes sehen werden, ist die Verwendung dieser Klasse, um interessante Dinge zu tun. Hier ist unsere Klasse bisher:
Paket import flash.geom.Point; öffentliche Klasse EuclideanVector public var position: Point; public var angle: Anzahl; öffentliche Funktion EuclideanVector (endPoint: Point) position = endPoint; public function inverse (): EuclideanVector return new EuclideanVector (neuer Punkt (-position.x, -position.y)); public function sum (otherVector: EuclideanVector): EuclideanVector position.x + = otherVector.position.x; position.y + = otherVector.position.y; kehre das zurück; public function subtract (otherVector: EuclideanVector): EuclideanVector position.x - = otherVector.position.x; position.y - = otherVector.position.y; kehre das zurück; public function multiply (number: Number): EuclideanVector position.x * = number; position.y * = Nummer; kehre das zurück; public function magnitude (): Number return Math.sqrt ((position.x * position.x) + (position.y * position.y)); public function angle (): Number var angle: Number = Math.atan2 (position.y, position.x); wenn (Winkel < 0) angle += Math.PI * 2; return angle; public function dot(otherVector:EuclideanVector):Number return (position.x * otherVector.position.x) + (position.y * otherVector.position.y); public function angleBetween(otherVector:EuclideanVector):Number return Math.acos(dot(otherVector) / (magnitude() * otherVector.magnitude())); public function rangedAngleBetween(otherVector:EuclideanVector):Number var firstAngle:Number; var secondAngle:Number; var angle:Number; firstAngle = Math.atan2(otherVector.position.y, otherVector.position.x); secondAngle = Math.atan2(position.y, position.x); angle = secondAngle - firstAngle; while (angle > Math.PI) Winkel - = Math.PI * 2; während (Winkel < -Math.PI) angle += Math.PI * 2; return angle; public function normalize():EuclideanVector position.x /= magnitude(); position.y /= magnitude(); return this; public function normalRight():EuclideanVector return new EuclideanVector(new Point(-position.y, position.x)); public function normalLeft():EuclideanVector return new EuclideanVector(new Point(position.y, -position.x)); public function rotate(angleInRadians:Number):EuclideanVector var newPosX:Number = (position.x * Math.cos(angleInRadians)) - (position.y * Math.sin(angleInRadians)); var newPosY:Number = (position.x * Math.sin(angleInRadians)) + (position.y * Math.cos(angleInRadians)); position.x = newPosX; position.y = newPosY; return this;
Die Aktion beginnt hier. Die Feststellung, ob ein Punkt innerhalb eines Polygons liegt oder nicht, ist ein sehr interessantes Thema, und es gibt viele Methoden, um dies zu erreichen. In diesem Artikel werde ich die drei Methoden vorstellen, die im Allgemeinen verwendet werden:
Alle diese Algorithmen basieren auf der Tatsache, dass Sie die Koordinaten der Ecken (Ecken) kennen, die das Polygon definieren.
Dieser Algorithmus kann für jede Form verwendet werden. Das lesen Sie: jede Form hat Löcher oder nicht, sei es konvex oder nicht. Es basiert auf der Tatsache, dass jeder Strahl, der von einem Punkt aus, den Sie nach Unendlich auschecken möchten, geworfen wird, eine gerade Anzahl von Kanten kreuzt, wenn sich der Punkt außerhalb der Form befindet, oder eine ungerade Anzahl von Kanten, wenn sich der Punkt innerhalb der Form befindet. Dies kann durch den Jordan-Kurventheorem bewiesen werden, der impliziert, dass Sie eine Grenze zwischen einer Region und einer anderen Region überschreiten müssen, wenn Sie von einer Region zur anderen wechseln möchten. In unserem Fall sind unsere Regionen "innerhalb der Form" und "außerhalb der Form"..
Der Code für diesen Algorithmus lautet wie folgt:
öffentliche Funktion isPointInsideShape1 (Punkt: EuclideanVector, ShapeVertices: Vector.): Boolean var numberOfSides: int = shapeVertices.length; var i: int = 0; var j: int = numberOfSides - 1; var oddNodes: Boolean = false; während ich < numberOfSides) if ((shapeVertices[i].position.y < point.position.y && shapeVertices[j].position.y >= Punkt.Position.y) || (shapeVertices [j] .position.y < point.position.y && shapeVertices[i].position.y >= point.position.y)) if (shapeVertices [i] .position.x + (((point.position.y - shapeVertices [i] .position.y) / (shapeVertices [j] .position.y - shapeVertices [i] .position.y)) * (shapeVertices [j] .position.x - shapeVertices [i] .position.x)) < point.position.x) oddNodes = !oddNodes; j = i; i++; return oddNodes;
Es wird wiederkommen falsch
wenn sich der Punkt nicht innerhalb der Form befindet, oder wahr
Wenn sich der Punkt innerhalb der Form befindet.
Das Wicklungsnummernalgorithmus Verwenden Sie die Summe aller Winkel zwischen dem zu prüfenden Punkt und jedem Punktepaar, das das Polygon definiert. Wenn die Summe nahe bei 2 pi liegt, befindet sich der überprüfte Punkt innerhalb des Vektors. Wenn es nahe bei 0 liegt, ist der Punkt außerhalb.
öffentliche Funktion isPointInsideShape2 (Punkt: EuclideanVector, ShapeVertices: Vector.): Boolean var numberOfSides: int = shapeVertices.length; var i: int = 0; Var Winkel: Anzahl = 0; var rawAngle: Number = 0; var firstVector: EuclideanVector; var secondVector: EuclideanVector; während ich < numberOfSides) firstVector = new EuclideanVector(new Point(shapeVertices[i].position.x - point.position.x, shapeVertices[i].position.y - point.position.y)); secondVector = new EuclideanVector(new Point(shapeVertices[(i + 1) % numberOfSides].position.x - point.position.x, shapeVertices[(i + 1) % numberOfSides].position.y - point.position.y)); angle += secondVector.rangedAngleBetween(firstVector); i++; if(Math.abs(angle) < Math.PI) return false; else return true;
Der Code verwendet den Entfernungswinkel zwischen Vektoren und gibt Raum für Ungenauigkeiten: Beachten Sie, wie wir die Ergebnisse der Summe aller Winkel prüfen. Wir prüfen nicht, ob der Winkel genau Null oder 2pi ist. Stattdessen prüfen wir, ob es weniger als pi und einen höheren Medianwert als pi ist.
Das konkaver Polygonalgorithmus stützt sich auf die Tatsache, dass sich bei einem konkaven Polygon ein Punkt immer links von den Kanten befindet (wenn wir sie im Gegenuhrzeigersinn durchlaufen) oder rechts von den Kanten (wenn wir durchlaufen) sie im Uhrzeigersinn).
Stellen Sie sich vor, Sie stehen in einem Raum, der wie das Bild oben geformt ist, und gehen um die Ränder herum, während Ihre linke Hand an der Wand entlangführt. An dem Punkt entlang der Wand, an dem Sie dem Punkt am nächsten sind, an dem Sie interessiert sind. Wenn er sich zu Ihrer Rechten befindet, muss er sich innerhalb des Raums befinden. Wenn es zu Ihrer Linken ist, muss es draußen sein.
Das Problem besteht darin, zu bestimmen, ob sich ein Punkt links oder rechts von einer Kante befindet (was im Wesentlichen ein Vektor ist). Dies geschieht durch die folgende Formel:
Diese Formel gibt für Punkte rechts von der Kante eine Zahl unter 0 und für links davon Punkte größer als 0 zurück. Wenn die Zahl gleich 0 ist, liegt der Punkt auf der Kante und wird innerhalb der Form betrachtet. Der Code lautet wie folgt:
öffentliche Funktion isPointInsideShape3 (Punkt: EuclideanVector, ShapeVertices: Vector.): Boolean var numberOfSides: int = shapeVertices.length; var i: int = 0; var firstEdgePoint: EuclideanVector; var secondEdgePoint: EuclideanVector; var leftOrRightSide: Boolean; während ich < numberOfSides) firstEdgePoint = shapeVertices[i]; secondEdgePoint = shapeVertices[(i + 1) % numberOfSides]; if(i == 0) // Determining if the point is to the left or to the right of first edge // true for left, false for right leftOrRightSide = ((point.position.y - firstEdgePoint.position.y) * (secondEdgePoint.position.x - firstEdgePoint.position.x)) - ((point.position.x - firstEdgePoint.position.x) * (secondEdgePoint.position.y - firstEdgePoint.position.y)) > 0; else // Jetzt müssen alle Kanten auf derselben Seite sein, wenn (leftOrRightSide && ((point.position.y - firstEdgePoint.position.y) * (secondEdgePoint.position.x - firstEdgePoint.position.x)) - (( point.position.x - firstEdgePoint.position.x) * (secondEdgePoint.position.y - firstEdgePoint.position)) < 0) // Not all edges are on the same side! return false; else if(!leftOrRightSide && ((point.position.y - firstEdgePoint.position.y) * (secondEdgePoint.position.x - firstEdgePoint.position.x)) - ((point.position.x - firstEdgePoint.position.x) * (secondEdgePoint.position.y - firstEdgePoint.position.y)) > 0) // Nicht alle Kanten liegen auf derselben Seite! falsch zurückgeben; i ++; // Wir haben alle Scheitelpunkte durchlaufen und haben nicht erkannt, dass verschiedene Seiten wahr sind;
Dieser Code funktioniert unabhängig davon, ob Sie die Scheitelpunkte der Form im oder gegen den Uhrzeigersinn definiert haben.
Ray Casting ist eine Technik, die häufig zur Kollisionserkennung und zum Rendern verwendet wird. Sie besteht aus einem Strahl, der von einem Punkt zu einem anderen (oder nach unendlich) geworfen wird. Dieser Strahl besteht aus Punkten oder Vektoren und stoppt im Allgemeinen, wenn er auf ein Objekt oder den Bildschirmrand trifft. Ähnlich wie bei den Point-in-Shape-Algorithmen gibt es viele Möglichkeiten, Strahlen zu werfen, und wir werden zwei davon in diesem Beitrag sehen:
In den nächsten beiden Schritten werden beide Methoden untersucht. Danach werden wir sehen, wie unser Strahl angehalten wird, wenn er auf ein Objekt trifft. Dies ist sehr nützlich, wenn Sie eine Kollision mit sich schnell bewegenden Objekten erkennen müssen.
Dieser Algorithmus wird in der Computergrafik sehr häufig verwendet und hängt von der Konvention ab, dass die Linie immer nach rechts und nach unten gerichtet erstellt wird. (Wenn eine Linie nach oben und links erstellt werden muss, wird alles später invertiert.) Gehen wir in den Code:
Öffentliche Funktion createLineBresenham (startVector: EuclideanVector, endVector: EuclideanVector): Vektor.var points: Vektor. = neuer Vektor. (); var steil: Boolean = Math.abs (endVector.position.y - startVector.position.y)> Math.abs (endVector.position.x - startVector.position.x); var swapped: Boolean = false; if (steil) startVector = neuer EuclideanVector (neuer Punkt (startVector.position.y, startVector.position.x)); endVector = neuer EuclideanVector (neuer Punkt (endVector.position.y, endVector.position.x)); // Die Linie geht nach unten, wenn (startVector.position.x> endVector.position.x) var temporär: Number = startVector.position.x; startVector.position.x = endVector.position.x; endVector.position.x = temporär; temporär = startVector.position.y; startVector.position.y = endVector.position.y endVector.position.y = temporär; vertauscht = wahr; var deltaX: Number = endVector.position.x - startVector.position.x; var deltaY: Number = Math.abs (endVector.position.y - startVector.position.y); Var-Fehler: Anzahl = DeltaX / 2; var currentY: Number = startVector.position.y; var step: int; if (startVector.position.y < endVector.position.y) step = 1; else step = -1; var iterator:int = startVector.position.x; while (iterator < endVector.position.x) if (steep) points.push(new EuclideanVector(new Point(currentY, iterator))); else points.push(new EuclideanVector(new Point(iterator, currentY))); error -= deltaY; if (error < 0) currentY += step; error += deltaX; iterator++; if (swapped) points.reverse(); return points;
Der Code erzeugt einen AS3-Vektor von euklidischen Vektoren, der die Linie bilden wird. Mit diesem Vector können wir später auf Kollisionen prüfen.
Eine Implementierung der Digitaler Differenzialanalysator wird verwendet, um Variablen zwischen zwei Punkten zu interpolieren. Im Gegensatz zum Bresenham-Algorithmus erstellt diese Methode der Einfachheit halber nur Vektoren an ganzzahligen Positionen. Hier ist der Code:
öffentliche Funktion createLineDDA (startVector: EuclideanVector, endVector: EuclideanVector): Vektor.var points: Vektor. = neuer Vektor. (); var dx: Anzahl; var dy: Anzahl; var _x: Number = startPoint.position.x; var _y: Number = startPoint.position.y; var m: Anzahl; var i: int; dx = endPoint.position.x - startPoint.position.x; dy = endPoint.position.y - startPoint.position.y; if (Math.abs (dx)> = Math.abs (dy)) m = Math.abs (dx); sonst m = Math.abs (dy); points.push (neuer EuclideanVector (neuer Punkt (int (_x), int (_y)))); i = 1; während ich <= m) _x += dx / m; _y += dy / m; points.push(new EuclideanVector(new Point(int(_x), int(_y)))); i++; return points;
Dieser Code gibt auch einen AS3-Vektor von euklidischen Vektoren zurück.
Die Kollisionsprüfung über Strahlen ist sehr einfach. Da ein Strahl aus vielen Vektoren besteht, prüfen wir auf Kollisionen zwischen jedem Vektor und einer Form, bis einer erkannt wird oder das Ende des Strahls erreicht wird. Im folgenden Code, shapeToCheck
wird eine Form sein, genau wie die, die wir in den Schritten 13-16 verwendet haben. Hier ist der Code:
öffentliche Funktion checkRayCollision (ray: Vector., Form: Vektor. ): Boolean var rayLength: int = ray.length; var i: int = 0; während ich < rayLength) if(isPointInsideShape1(ray[i], shape)) return true; i++; return false;
Sie können jede Punkt-Innenform-Funktion verwenden, mit der Sie sich wohl fühlen, aber achten Sie auf die Einschränkungen der letzten!
Sie können dieses Wissen jetzt überall einsetzen! Dies ist oft nützlich und erspart Ihnen zusätzliche Berechnungen, wenn Sie komplexere Aufgaben in Flash ausführen möchten.