Forward Kinematics (FK) ist ein Positionierungsalgorithmus. Es ist nicht so kompliziert, wie es sich anhört, wenn Sie es aus der Sicht eines Baggerführers mit einer Folge von Aktionen verknüpfen. Beginnend mit dem nächstgelegenen Knoten konfiguriert der Bediener die Ausrichtung jedes Knotens in der Hoffnung, dass der Löffel die vorgesehene Position erreicht. Oft werden mehrere Versuche unternommen, um Erfolg zu haben. FK ist ein Algorithmus, um eine solche Aufgabe auszuführen. In diesem Lernprogramm versuchen wir, die Implementierung von FK zu versuchen und von einer 2D-Seitenansicht auf einen Bagger anzuwenden. Wenn Sie diesen Algorithmus verstanden haben, können Sie ihn leicht an eine 3D-Umgebung anpassen. Genießen!
Dieses Tutorial setzt die folgende Reihenfolge voraus:
Zunächst müssen wir das Konzept einer Kette verstehen. Eine Kette abstrahiert die hierarchische Reihenfolge der Knoten. Es gibt einen Wurzelknoten, die höchste Ordnung der Kette, mit dem alle anderen Knoten verbunden sind. Der Knoten, der mit dem Stamm verbunden ist, ist das untergeordnete Element der ersten Ebene. Der Knoten, der eine Verbindung mit dem ersten untergeordneten Element herstellt, ist das untergeordnete zweite Element.
Die hierarchische Beziehung wird im Folgenden vereinfacht:
root> node1> node2> node3> node4> node5?
Die Flash-Animation oben zeigt die Beziehungen zwischen Eltern (in Hierarchie höher) und untergeordnet (in Hierarchie niedriger), wobei jeder Pfeil auf einen Kindknoten zeigt.
Jeder dieser Knoten ist durch eine Einschränkung mit benachbarten Knoten verbunden. Ich werde diese Einschränkungen als "Pfeile" bezeichnen. Pfeil sind Vektoren. Sie haben eine Länge (besser bekannt als Betrag) und einen Winkel, der ihre Ausrichtung beschreibt. In diesem Lernprogramm zeigen diese Pfeile vom übergeordneten Knoten zum untergeordneten Knoten. Beispielsweise wird Knoten1 durch Pfeil1 mit Root verbunden. Pfeil1 zeigt vom Stamm zum Knoten1.
Pfeile folgen ebenfalls einer hierarchischen Reihenfolge, da sie versuchen, eine hierarchische Kette von Knoten zu verbinden. Diese hierarchische Beziehung wird wie folgt vereinfacht:
pfeil1> pfeil2> pfeil3> pfeil4> pfeil5?
Also wo ist arrow0? Nun, root ist das höchste in der Hierarchie. Kein Pfeil zeigt darauf, also gibt es praktisch keinen Pfeil0.
Das Einstellen der Pfeilrotation ist das Wichtigste im FK-Algorithmus. Hier drehen wir einen Pfeil um den Delta-Winkel. Wenn wir Pfeil1 drehen, wird die Position von Knoten1 aktualisiert. Aber das ist nicht alles.
Im FK-Algorithmus wird die Kinematik in der Hierarchie vom höchsten zum niedrigsten durchlaufen. Nehmen wir an, unsere Kette hat 6 Knoten, die durch 5 Pfeile verbunden sind. Wenn Delta-Drehung auf Pfeil1 angewendet wird, müssen auch Pfeil2 bis Pfeil5 um den Delta-Winkel gedreht werden. Ich habe die Pfeile markiert, die von der Änderung betroffen sind.
pfeil1 > pfeil2 > pfeil3 > Pfeil4 > Pfeil5
Wenn Delta-Drehung auf Pfeil3 angewendet wird, sind nur Pfeil4 und Pfeil5 betroffen.
arrow1>pfeil2> pfeil3 > Pfeil4 > Pfeil5
Für jeden betroffenen Pfeil ist auch die Position des zugehörigen Knotens betroffen. Knoten 4 und Knoten 5 aktualisieren ihre Positionen.
Klicken Sie in der obigen SWF-Datei auf die Pfeile, um zu sehen, wie die Kinematik die Knoten durchläuft (dunklere Pfeile)..
Starten Sie FlashDevelop und starten Sie ein neues Projekt. Fügen Sie Ihrem Projekt eine "MileStone1.as" hinzu.
Jetzt implementieren wir unsere erste FK-Kette. Zuerst müssen wir die beiden Sprites als Klassenvariablen auf der Bühne hinzufügen. Der Wurzelknoten ist ein blauer Kreis und der erste Knoten ist ein violetter Kreis.
rootNode = new Sprite (); rootNode.graphics.beginFill (0x4499FF); rootNode.graphics.drawCircle (0, 0, 20); rootNode.graphics.endFill (); addChild (rootNode); node1 = neues Sprite (); node1.graphics.beginFill (0x772255); node1.graphics.drawCircle (0, 0, 20); node1.graphics.endFill (); addChild (node1);
node1
wird mit rootNode über verbunden vec1
, Dies ist eine Instanz der Vector2D-Klasse (benutzerdefinierte Klasse). Es ist eine Klassenvariable. Wir initiieren es und setzen seine Stärke auf 60.
vec1 = neuer Vector2D (0, 0); vec1.setMagnitude (60);
Bevor wir Listener zuweisen, um unserem kleinen Programm Interaktivität hinzuzufügen, müssen wir die Anfangsposition der Knoten festlegen. Zuerst die Wurzelknoten
, das ist ziemlich offensichtlich. Der nächste ist node1
(hervorgehoben) was davon abhängt Wurzelknoten
Position.
// Setzen der Knoten rootNode.x = 150; rootNode.y = 150; node1.x = rootNode.x + vec1.x; node1.y = rootNode.y + vec1.y;
Fast dort. Wir fügen dem Tastaturereignis einen Listener hinzu. Beim Drücken einer beliebigen Taste, vec1
dreht sich und ändert weiter die Ausrichtung von node1
in Gedenken an Wurzelknoten
.
stage.addEventListener (KeyboardEvent.KEY_DOWN, verschieben); private Funktion move (e: KeyboardEvent): void vec1 = vec1.rotate (Math2.radianOf (10)); node1.x = rootNode.x + vec1.x; node1.y = rootNode.y + vec1.y;
Unten ist MileStone1 abgeschlossen. Einfach, richtig?
Klicken Sie auf die SWF-Datei und drücken Sie eine beliebige Taste (wiederholt), um den Effekt anzuzeigen.
Nachdem wir nun die Grundeinstellungen vorgenommen haben, wollen wir dies etwas weiter vorantreiben. Wir werden hinzufügen node2
(auch lila) zur bestehenden Kette. node2
ist mit verbunden node1
über vec2
, das ist eine Stärke von 60 gegeben
// ein zweites Kind node2 = new Sprite (); node2.graphics.beginFill (0x772255); node2.graphics.drawCircle (0, 0, 20); node2.graphics.endFill (); addChild (node2); vec2 = neuer Vector2D (0, 0); vec2.setMagnitude (60);
Wir initialisieren die Position von node2
im Verhältnis zu node1
mit vec2
als Einschränkung mit dem folgenden Code. Denken Sie daran, den gleichen Code auch in den Tastaturlistener aufzunehmen (Zeile 64 von MileStone2)..
node2.x = node1.x + vec2.x; node2.y = node1.y + vec2.y;
Hier ist der MileStone2 abgeschlossen:
Verwenden Sie wieder die Tastatur, um den Effekt zu sehen.
Hmm? Mit dieser FK-Implementierung stimmt etwas nicht. Sehen Sie, die Kinematik läuft nicht die Kette hinunter. Erinnern Sie sich an Schritt 4: Delta-Rotation; Die Kinematik muss sich von der aktuellen Hierarchieebene bis zum Ende bewegen. Ich habe die Codezeilen hervorgehoben, die dies tun. Um den logischen Fehler zu beheben, fügen Sie einfach die Zeile 65 in MileStone2 ein. Ich habe MileStone3 für den Fall geliefert, dass Sie Schwierigkeiten haben.
private function move (e: KeyboardEvent): void vec1 = vec1.rotate (Math2.radianOf (10)); node1.x = rootNode.x + vec1.x; node1.y = rootNode.y + vec1.y; vec2 = vec2.rotate (Math2.radianOf (10)); node2.x = node1.x + vec2.x; node2.y = node1.y + vec2.y;
Als Nächstes können wir unserer Kontrolle mehr Flexibilität verleihen. Derzeit kontrollieren wir die Positionierung von node1
und node2.
Erlaubt die Kontrolle über die Positionierung von node2
nur.
private Funktion move (e: KeyboardEvent): void if (e.keyCode == Keyboard.PAGE_UP) vec1 = vec1.rotate (Math2.radianOf (10)); node1.x = rootNode.x + vec1.x; node1.y = rootNode.y + vec1.y; vec2 = vec2.rotate (Math2.radianOf (10)); node2.x = node1.x + vec2.x; node2.y = node1.y + vec2.y; else if (e.keyCode == Keyboard.PAGE_DOWN) vec2 = vec2.rotate (Math2.radianOf (10)); node2.x = node1.x + vec2.x; node2.y = node1.y + vec2.y;
Verwenden Sie die Tasten Bild ab und Bild hoch, um die verschiedenen Knoten zu verschieben.
Ja, die Drehung ist immer noch eine Richtung - gegen den Uhrzeigersinn. Das Durchlaufen der Schritte 5 bis 13 dient dazu, ein solides Verständnis des FK-Algorithmus zu entwickeln. Nun, da es fertig ist, wollen wir dies auf eine andere Ebene bringen: Die Entwicklung einer FKChain-Klasse, die eine einfache Implementierung von FK ermöglicht.
FKChain wurde zur einfachen Implementierung von FK entwickelt. Ich habe die Klasse mit den folgenden Variablen und Funktionen entworfen. Ich werde dich durch sie führen.
Variablen | Zweck | Datentyp |
Knoten | Knoten der FK-Kette halten | Vektor Anordnung von Sprites |
Pfeile | Pfeile halten, die Knoten verbinden | Vektor Anordnung von Vector2D |
lowerLimits | Untere Grenze des zulässigen Winkels halten | Vektor Anordnung von Nummer |
upperLimits | Obergrenze des zulässigen Winkels halten | Vektor Anordnung von Nummer |
selectedIndex | Daten des aktuell ausgewählten Knotens halten | Ganze Zahl |
Die Zuordnung von Knoten zu Pfeilen zusammen mit anderen Abhängigkeiten wird im folgenden Diagramm dargestellt.
Beachten Sie die Zuordnung von Knoten
zu Pfeile
, lowerLimits
und upperLimits
. Der rot markierte Winkel ist gemäß der oben stehenden Formel eingeschränkt.
Beachten Sie auch, dass ich in Schritt 3 erwähnt habe, dass es keine gibt Pfeil [0]
. Wenn wir jedoch Grenzen umsetzen sollten, werden wir es brauchen Pfeil [0]
ein horizontaler Vektor sein, bei dem der Winkel von Pfeil [1]
wird anhand der Randbedingungen gemessen und bewertet.
Nachdem Sie nun die Schrauben und Muttern der FKChain-Klasse verstanden haben, definieren wir die Funktionen von FKChain.
Funktionen | Eingabe / Datentyp | Zweck |
FKChain () | Wurzelknoten/ Sprite | Initiiert Klassenvariablen. Setzt den Wurzelknoten entlang der FK-Kette mit relevanten Einschränkungen. Sets selectedNode zum Wurzelknoten. |
appendNode () | nächster Kindknoten / Sprite | Neuen Knoten zusammen mit relevanten Einschränkungen an die Kette anhängen. Sets aktuell ausgewählt. Sets selectedNode zum neuen Knoten. |
removeNode () | zu entfernender Knoten / Sprite | Entfernen Sie den Eingabeknoten zusammen mit den relevanten Einschränkungen aus der Kette. |
selectedNode () | Knoten zu manipulieren / Sprite | Legen Sie den aktuell ausgewählten Knoten fest, um Anpassungen wie das Anpassen durchzuführen sein Pfeil (Betrag und Winkel) und Einschränkungen des Pfeilwinkels. |
updateLimits () | untere, obere Grenzen / Nummer | Legt neue Begrenzungen (obere und untere Grenze) für die Pfeile fest Winkel des ausgewählten Knotens. |
alterMagnitude () | Größe/ Nummer | Legt den neuen Betrag für den Pfeil des ausgewählten Knotens fest. |
alterAngle () | Winkel zum Anpassen an / Nummer | Eingabe des Delta-Winkels zum Pfeil des ausgewählten Knotens. |
Position setzen() | (keiner) | Ruckeln Sie die Kinematik von der Hierarchie des ausgewählten Knotens bis zum Ende Kette. |
Ich habe auch einige Getter vorgestellt, um die Entwicklung zu erleichtern. Sie werden beim Scrollen durch Knoten verwendet.
Eigentum | Zweck |
currentNode | Gibt den aktuell ausgewählten Knoten zurück. |
Kind | Gibt das untergeordnete Element des ausgewählten Knotens zurück. |
Elternteil | Gibt den übergeordneten Knoten des ausgewählten Knotens zurück. |
Nun haben wir einen Überblick über FKChain, werfen wir einen Blick auf die Anwendung und die internen Abläufe. Erstellen Sie in Ihrem Projekt eine Klasse TestChain
. Wir werden eine Draw-Methode aufrufen, um alle erforderlichen Elemente zu zeichnen Sprites
auf unserer bühne. Es gibt insgesamt fünf Sprites und eine Klammer, um den aktuell ausgewählten Knoten anzuzeigen.
öffentliche Funktion draw (): void b0 = new Sprite (); b0.graphics.beginFill (0); b0.graphics.drawCircle (0, 0, 15); b0.graphics.endFill (); addChild (b0); b1 = neues Sprite (); b1.graphics.beginFill (0); b1.graphics.drawRect (-80, -10, 80, 20); b1.graphics.endFill (); addChild (b1); b2 = neues Sprite (); b2.graphics.beginFill (0); b2.graphics.drawRect (-40, -10, 40, 20); b2.graphics.endFill (); addChild (b2); b3 = neues Sprite (); b3.graphics.beginFill (0); b3.graphics.drawRect (-40, -10, 40, 20); b3.graphics.endFill (); addChild (b3); b4 = neues Sprite (); b4.graphics.beginFill (0); b4.graphics.drawRect (-40, -10, 40, 20); b4.graphics.endFill (); addChild (b4); target = new Sprite (); target.graphics.lineStyle (3, 0xFF0000); target.graphics.moveTo (-15, -10); target.graphics.lineTo (-15, -15); target.graphics.lineTo (-10, -15); target.graphics.moveTo (15, -10); target.graphics.lineTo (15, -15); target.graphics.lineTo (10, -15); target.graphics.moveTo (15, 10); target.graphics.lineTo (15, 15); target.graphics.lineTo (10, 15); target.graphics.moveTo (-15, 10); target.graphics.lineTo (-15, 15); target.graphics.lineTo (-10, 15); addChild (Ziel);
öffentliche Funktion initChain (): void c = new FKChain (b0); c.appendNode (b1); c.alterMagnitude (120); c.updateLimits (Math2.radianOf (-90), Math2.radianOf (45)); c.appendNode (b2); c.updateLimits (Math2.radianOf (-45), Math2.radianOf (90)); c.appendNode (b3); c.updateLimits (Math2.radianOf (0), Math2.radianOf (90)); c.appendNode (b4); // Aktualisiere die Position aller Knoten b0.x = 250; b0.y = 300; c.selectNode (b1); c.setPosition (); // Ziel zunächst auf den Wurzelknoten setzen target.x = c.currentNode.x; target.y = c.currentnode.y;
Zuerst müssen wir die FKChain-Klasse durch Aufruf ihres Konstruktors instanziieren. Geben Sie dem Konstruktor einen Stammknoten an. Eine weitere Untersuchung der Konstruktorfunktion zeigt zwei Hauptoperationen der Funktion. Erstens ist die Instanziierung von Knoten
, Pfeile
, upperLimits
und lowerLimits
. Daten werden danach in diese Variablen eingespeist.
Beachten Sie, dass dem Wurzelknoten ein Pfeil zugeordnet ist. Das habe ich nicht explizit gezeigt Pfeile
sind immer ein Mitglied weniger als Knoten
. Akzeptieren Sie es jedoch vorerst, da ich ihn in späteren Abschnitten erläutere. Die anderen hervorgehobenen Zeilen sind Füllungen, um eine einfache Adressierung von Einschränkungen zu gewährleisten. Zum Schluss setzen Sie den aktuell ausgewählten Knoten auf Wurzel
zur weiteren Manipulation.
public function FKChain (node0: Sprite) // instanziieren Sie Variablen Knoten = neuer Vektor.; Pfeile = neuer Vektor. ; upperLimits = neuer Vektor. ; lowerLimits = neuer Vektor. ; // Wurzelknoten einführen node.push (node0); pfeile.push (neuer Vector2D (1, 0)); lowerLimits.push (0); upperLimits.push (0); selectNode (knoten0);
Nach der Initiierung können wir anfangen, Knoten an die Instanz von FKChain anzuhängen. Die Erstellung des Pfeils wird von den Benutzern abstrahiert. Ich habe die anfängliche Größe und Begrenzung des Biegungswinkels hervorgehoben (bis -90 < angle < 90). These constraints are easily customised.
öffentliche Funktion appendNode (node: Sprite): void node.push (node); var newArrow: Vector2D = new Vector2D (0, 0); newArrow.setMagnitude (60); pfeile.push (newArrow); lowerLimits.push (Math2.radianOf (-90)); upperLimits.push (Math2.radianOf (90)); selectNode (Knoten);
// Aktualisiere die Position aller Knoten b0.x = 250; b0.y = 300; c.selectNode (b0); c.setPosition (); // Ziel zunächst auf den Wurzelknoten setzen target.x = c.currentNode.x; target.y = c.currentnode.y;
Jetzt befindet sich die Position des Wurzelknotens in der linken oberen Ecke der Bühne. Wir werden den Standort von verschieben b1
nah am zentrum. Dann müssen wir die anderen Knoten in der Kette neu positionieren und die Zielklammer auf den aktuell ausgewählten Knoten setzen. Lassen Sie uns weiter untersuchen Position setzen
:
öffentliche Funktion setPosition (): void var index: int = Math.max (1, selectedIndex); für (var i: int = index; i < nodes.length; i++) //set position nodes[i].x = arrows[i].x + nodes[i - 1].x; nodes[i].y = arrows[i].y + nodes[i - 1].y; //set orientation nodes[i].rotation = Math2.degreeOf(arrows[i].getAngle());
Diese Funktion versucht, alle Knoten ab dem aktuell ausgewählten Knoten neu zu positionieren und neu auszurichten. Ich habe eine Obergrenze für den Index festgelegt (hervorgehoben), da der Wurzelknoten logisch nicht von einem übergeordneten Element beeinflusst wird, da wir die relative Neupositionierung durchführen. Der Knoten mit der höchsten relativen Neupositionierung in der Hierarchie ist b1
. Es ist egal, ob Sie schreiben c.selectNode (b0)
oder c.selectNode (b1)
Vor c.setPosition ()
es wird jedoch die Ausgangsposition der Tragetierungsklammer beeinflussen?
öffentliche Funktion TestChain () this.draw (); this.initChain (); stage.addEventListener (KeyboardEvent.KEY_DOWN, keyDown);
Jetzt ist es Zeit, die Kette zu animieren. Wir werden dem Tastaturereignis einen Listener zuordnen.
private function keyDown (e: KeyboardEvent): void // Durch die Knotenauswahl scrollen if (e.keyCode == Keyboard.SPACE) if (c.currentCode == b4) c.selectNode (b1); else c.selectNode (c.child); else if (e.keyCode == Keyboard.UP) c.alterAngle (Math2.radianOf (-1 * Schritt)); c.setPosition (); else if (e.keyCode == Keyboard.DOWN) c.alterAngle (Math2.radianOf (Schritt)); c.setPosition (); target.x = c.currentnode.x; target.y = c.currentnode.y;
Beim Drücken der Leertaste blättert die Zielklammer durch alle Knoten außer dem Wurzelknoten, b0
. Durch Drücken der Aufwärtspfeiltaste wird ein negativer Delta-Winkel angezeigt, -1 * Schritt
; während die Pfeiltaste nach unten einen positiven Delta-Winkel ergibt, Schritt
.
Hier ist ein Beispiel von TestChain.
Verwenden Sie die Leertaste und die Aufwärts- und Abwärtspfeiltasten, um sie zu steuern. Beachten Sie, wie sich die Einschränkungen darauf auswirken, wie weit sich jeder Knoten "verbiegen" kann..
Wir verwendeten alterAngle ()
im Zuhörer Lassen Sie uns nun die internen Arbeitsabläufe analysieren.
public function alterAngle (ang: Number): void var index: int = Math.max (1, selectedIndex); // berechne Abweichung zwischen vorherigem Pfeil und aktuellem Pfeil var Abweichung: Zahl = Pfeile [Index - 1] .angleBetween (Pfeile [Index]); var future: Anzahl = Abweichung + Ang; // Ang innerhalb festgelegter Grenzen sicherstellen, wenn (future> upperLimits [Index]) ang = upperLimits [Index] - Abweichung; else if (zukünftig < lowerLimits[index]) ang = lowerLimits[index] - deviation; //update relevant arrows for (var i:int = selectedIndex; i < arrows.length; i++) arrows[i] = arrows[i].rotate(ang);
Die Abweichung des Pfeils des aktuellen Knotens vom Pfeil des aktuellen Knotens wird berechnet, dies ist der aktuelle Winkel. Der Eingabewinkel wird zum aktuellen Winkel hinzugefügt, um den zukünftigen Winkel zu bilden. Alles ist gut und dieser Wert sollte ausgegeben werden. Wir möchten jedoch eine minimale und eine maximale Grenze implementieren, damit der zukünftige Winkel mit diesen Werten verglichen und entsprechend angepasst wird. Danach geben wir den Wert aus, um alle relevanten Pfeile zu aktualisieren.
Möglicherweise stellen Sie fest, dass die Animation abgehackt ist. Sie drücken die Taste und es bewegt sich ein wenig. Wir können dies etwas verbessern, indem wir die Winkelgeschwindigkeit beschleunigen und verlangsamen. Es ist jedoch eine Neuverkabelung der Ereignishandler erforderlich. Notiere dass der zeichnen()
und initChain ()
Funktionen werden aus vorherigen Schritten übernommen.
öffentliche Funktion TestChain2 () this.draw (); this.initChain (); stage.addEventListener (KeyboardEvent.KEY_DOWN, keyDown); stage.addEventListener (KeyboardEvent.KEY_UP, keyUp); stage.addEventListener (Event.ENTER_FRAME, animate);
Durch Drücken der Richtungstasten werden die Flaggen umgeschaltet wahr
. Beim Loslassen dieser Tasten werden die zugehörigen Flags umgeschaltet falsch
. Diese Flags werden erfasst und für weitere Operationen von einem ausgewertet onEnterFrame
Eventhandler.
private function keyDown (e: KeyboardEvent): void // durch die Auswahl des Knotens scrollen if (e.keyCode == Keyboard.SPACE) if (c.current_node == b4) c.selectNode (b0); else c.selectNode (c.child); else if (e.keyCode == Keyboard.UP) upFlag = true; else if (e.keyCode == Keyboard.DOWN) downFlag = true; else if (e.keyCode == Keyboard.LEFT) leftFlag = true; else if (e.keyCode == Keyboard.RIGHT) rightFlag = true; private function keyUp (e: KeyboardEvent): void if (e.keyCode == Keyboard.UP) upFlag = false; else if (e.keyCode == Keyboard.DOWN) downFlag = false; else if (e.keyCode == Keyboard.LEFT) leftFlag = false; else if (e.keyCode == Keyboard.RIGHT) rightFlag = false;
Nachfolgend sind die Variablen aufgeführt, die zur Animation von Kinematiken verwendet werden:
private var angVelo: Anzahl = 0; // aktuelle Winkelgeschwindigkeit private var maxVelo: Number = 5; // Festlegen einer Obergrenze für die Winkelgeschwindigkeit private var angAcc: Number = 0.2; // inkrementeller Schritt auf Winkelgeschwindigkeit private var angDec: Number = 0.8; // Decay-Multiplikator für die Winkelgeschwindigkeit private var step: Number = 5; // Richtungsschritte beim Verschieben der gesamten Kette
Durch das Aufnehmen von Flags vom Tastaturereignis können wir die Kinematik der Kette weiter manipulieren.
private Funktion animate (e: Event): void // Verschieben der gesamten Kette if (c.currentCode == b0) if (upFlag) b0.y - = Schritt else if (downFlag) b0.y + = step if (leftFlag) b0.x - = step else if (rightFlag) b0.x + = step // Anpassen des Winkels else if (upFlag) angVelo - = angAcc; // Festlegen der Begrenzung der Winkelgeschwindigkeit angVelo = Math.max (-1 * maxVelo, angVelo); else if (downFlag) angVelo + = angAcc; // Festlegen der Obergrenze für die Winkelgeschwindigkeit angVelo = Math.min (maxVelo, AngVelo); else // verlangsamen, wenn Tasten losgelassen werden angVelo * = angDec // // Wert auf den Pfeil des ausgewählten Knotens setzen. c.alterAngle (Math2.radianOf (angVelo)); // Position aktualisieren c.setPosition (); target.x = c.currentnode.x; target.y = c.currentnode.y;
Beachten Sie, dass die Handhabung des Wurzelknotens etwas anders ist. Bei der Auswahl bewegen wir die gesamte Kette nach oben, unten, links oder rechts. Während andere Kinder ausgewählt werden, pumpen wir in die Winkelgeschwindigkeit, angVelo
, innerhalb der minimalen und maximalen Geschwindigkeit nach oben oder unten. Wenn die Tasten losgelassen werden, werden alle Flags gesetzt falsch
), die aktuelle Geschwindigkeit verlangsamt sich. Um dieses Snippet weiter zu verdeutlichen, lesen Sie meinen Beitrag zur linearen Kinematik, um eine Vorstellung von dem obigen Code zu erhalten.
Ein Beispiel für die fertige Arbeit ist unten gezeigt:
Verwenden Sie wieder die Leertaste und die Pfeiltasten nach oben und nach unten. Beachten Sie diesmal, wie glatt die Bewegung ist.
Nachdem nun die Grundlagen für die Code-Basis geschaffen sind, werden wir uns bei unserem Projekt auf kosmetische Arbeiten konzentrieren. Ich bin kein sehr guter Künstler, also ertrage meine Baggerzeichnung.
Die Grafiken, die ich gezeichnet habe, werden in MovieClips konvertiert. Dabei ist zu beachten, dass der Registrierungspunkt für Grafiken am Ende des Segments für Arme und Löffel positioniert werden muss. Ich habe die Registrierungspunkte für alle meine Assets in den folgenden Screenshots mit einem roten Kreis markiert.
Ich habe diesen MovieClip oben genannt Wurzel
, Arm1
, Arm2
, und Scoop
beziehungsweise
Ein weiteres Detail ist, dass Sie die Tastenkombination Strg + L drücken müssen, um das Bibliotheksfenster zu öffnen und diese Assets für Actionscript zu exportieren. Klicken Sie mit der rechten Maustaste, wählen Sie Verknüpfung aus und geben Sie die Details wie in den folgenden Bildern gezeigt ein.
Wenn Sie alle grafischen Elemente erstellt haben, veröffentlichen Sie sie im SWC-Format, um sie ordnungsgemäß in FlashDevelop importieren zu können. Ich verwende Flash CS3. Drücken Sie Strg + Umschalt + F12, um die Veröffentlichungseinstellungen aufzurufen. Wählen Sie die Registerkarte Flash und aktivieren Sie den Export SWC. Klicken Sie dann auf Veröffentlichen.
Kopieren Sie die neue Datei (.swc) in den lib-Ordner Ihres Projekts.
Jetzt, da Sie es in Ihrem Projekt haben, müssen Sie es noch in die Bibliothek aufnehmen. Klicken Sie mit der rechten Maustaste auf die .swc-Datei und wählen Sie "Zur Bibliothek hinzufügen"..
Erweitern Sie die Liste wie in der Abbildung unten gezeigt, um die Namen der Variablen zu überprüfen. Ich habe die folgenden Namen verwendet Arm1
, Arm2
, Wurzel
und Scoop
. Dies sind die Klassennamen, die diesen Grafiken zugeordnet sind. Wir werden sie später verwenden.
Schließlich kommen wir zur letzten Etappe dieses Tutorials. Wir werden das Bestehende ersetzen zeichnen()
Methode mit dieser neuen, drawAssets ()
.
private Funktion drawAssets (): void rootNode = new Root (); arm1 = neuer Arm1 (); arm2 = neuer Arm2 (); Scoop = neuer Scoop (); addChild (arm1); addChild (rootNode); addChild (Schaufel); addChild (arm2); target = new Sprite (); target.graphics.lineStyle (3, 0xFF0000); target.graphics.moveTo (-15, -10); target.graphics.lineTo (-15, -15); target.graphics.lineTo (-10, -15); target.graphics.moveTo (15, -10); target.graphics.lineTo (15, -15); target.graphics.lineTo (10, -15); target.graphics.moveTo (15, 10); target.graphics.lineTo (15, 15); target.graphics.lineTo (10, 15); target.graphics.moveTo (-15, 10); target.graphics.lineTo (-15, 15); target.graphics.lineTo (-10, 15); addChild (Ziel);
Wenn Sie jetzt Ihre Anwendung starten, sehen Sie möglicherweise eine Gruppe von Zeichnungen in der oberen linken Ecke oder den gesamten Baggerarm und -körper auf lustige Weise. Passen Sie die Größenbeschränkungen und die Winkelbegrenzungen für Verbindungen entsprechend an. Ich habe meine als unten aufgeführt.
private Funktion initChain (): void c = new FKChain (rootNode); c.appendNode (arm1); c.alterMagnitude (260); c.updateLimits (Math2.radianOf (-45), Math2.radianOf (45)); c.appendNode (arm2); c.alterMagnitude (100); c.updateLimits (Math2.radianOf (0), Math2.radianOf (90)); c.appendNode (Scoop); c.alterMagnitude (60); c.updateLimits (Math2.radianOf (45), Math2.radianOf (135)); // Aktualisiere die Position aller Knoten rootNode.x = 250; rootNode.y = 300; c.selectNode (rootNode); c.setPosition (); // Ziel zunächst auf den Wurzelknoten setzen target.x = c.currentNode.x; target.y = c.currentnode.y;
Weitere Anpassungen an der Tastatursteuerung des Wurzelknotens, ich habe die vertikale Bewegung der gesamten Kette eliminiert, so dass sich der Bagger (Wurzel) nur horizontal bewegt. Der Ausschnitt unten wird in der Event.ENTER_FRAME
Handler
if (c.currentNode == rootNode) if (leftFlag) rootNode.x - = step else if (rightFlag) rootNode.x + = step
Jede einzelne Anpassung der Codebasis wird durchgeführt. Natürlich können