Forward Kinematics (FK) è un algoritmo di posizionamento. Non è così complicato come sembra se lo associ a una sequenza di azioni dal punto di vista dell'operatore dell'escavatore. A partire dal nodo più vicino, l'operatore configura l'orientamento di ciascun nodo nella speranza che lo scoop raggiunga la posizione desiderata. Spesso, diversi tentativi vengono fatti prima di raggiungere il successo. FK è un algoritmo per eseguire tale compito. In questo tutorial, tenteremo di implementare FK e applicarlo su un escavatore da una vista laterale 2D. Avendo capito questo algoritmo, si può facilmente adattarlo ad un ambiente 3D. Godere!
Questo tutorial assumerà la seguente sequenza:
Prima di tutto, dobbiamo capire il concetto di una catena. Una catena astrae l'ordine gerarchico dei nodi. Esiste un nodo radice, l'ordine più alto della catena, a cui tutti gli altri nodi sono uniti. Il nodo che si connette alla radice è il primo livello figlio. Il nodo che si collega al bambino di primo livello è il bambino di secondo livello.
La relazione gerarchica è semplificata di seguito:
root> node1> node2> node3> node4> node5?
L'animazione flash sopra mostra la parent (gerarchia più alta) alle relazioni child (lower in hierarchia), dove ogni freccia punta a un nodo figlio.
Ognuno di questi nodi è collegato a quelli adiacenti da un vincolo. Definirò questi vincoli come "frecce". Arrow sono vettori. Hanno una lunghezza (meglio conosciuta come grandezza) e un angolo che ne descrive l'orientamento. In questa esercitazione, queste frecce puntano dal nodo genitore al nodo figlio. Ad esempio, node1 è unito a root da arrow1. Arrow1 sta puntando da root a node1.
Le frecce seguono anche un ordine gerarchico perché tentano di unirsi a una catena gerarchica di nodi. Questa relazione gerarchica è semplificata come di seguito:
arrow1> arrow2> arrow3> arrow4> arrow5?
Allora, dov'è la freccia0? Bene, root è il più alto nella gerarchia. Nessuna freccia indica che non c'è effettivamente una freccia0.
La regolazione della rotazione delle frecce è la cosa più importante nell'algoritmo FK. Qui, ruoteremo una freccia per angolo delta. Se ruotiamo la freccia1, la posizione di node1 si aggiornerà. Ma non è tutto.
Nell'algoritmo FK, la cinematica attraversa la gerarchia dalla più alta alla più bassa. Supponiamo che la nostra catena abbia 6 nodi, uniti da 5 frecce. Se la rotazione delta è applicata alla freccia1, quindi la freccia2 alla freccia5 devono essere ruotate anche dall'angolo delta. Ho messo in evidenza le frecce che sono influenzate dal cambiamento.
arrow1 > arrow2 > arrow3 > arrow4 > arrow5
Se viene applicata la rotazione delta sulla freccia3, vengono influenzate solo la freccia4 e la freccia5.
arrow1>arrow2> arrow3 > arrow4 > arrow5
Per ogni freccia interessata, sarà interessata anche la posizione del nodo associato. Quindi node4 e node5 aggiorneranno le loro posizioni.
Nel file SWF sopra, fare clic sulle frecce per vedere l'ondulazione cinematica sui nodi (frecce più scure).
Lauch FlashDevelop e avvia un nuovo progetto. Aggiungi un "MileStone1.as" nel tuo progetto.
Ora per implementare la nostra prima catena FK. Per prima cosa, dobbiamo aggiungere i due sprite sullo stage come variabili di classe. Il nodo radice è un cerchio blu e il primo nodo è un cerchio viola.
rootNode = new Sprite (); rootNode.graphics.beginFill (0x4499FF); rootNode.graphics.drawCircle (0, 0, 20); rootNode.graphics.endFill (); addChild (rootNode); node1 = new Sprite (); node1.graphics.beginFill (0x772255); node1.graphics.drawCircle (0, 0, 20); node1.graphics.endFill (); addChild (node1);
node1
è unito a rootNode tramite vec1
, che è un'istanza della classe Vector2D (classe scritta personalizzata). È una variabile di classe. Lo iniziamo e impostiamo la sua grandezza a 60.
vec1 = new Vector2D (0, 0); vec1.setMagnitude (60);
Prima di iniziare ad assegnare agli ascoltatori l'aggiunta di interattività al nostro piccolo programma, dobbiamo impostare la posizione iniziale dei nodi. Prima il rootNode
, che è abbastanza ovvio. Il prossimo è node1
(evidenziato) da cui dipende rootNode
La posizione di.
// impostazione dei nodi rootNode.x = 150; rootNode.y = 150; node1.x = rootNode.x + vec1.x; node1.y = rootNode.y + vec1.y;
Quasi lì. Aggiungiamo un ascoltatore all'evento tastiera. Premendo una chiave arbitraria, vec1
ruota e modifica ulteriormente l'orientamento di node1
riguardo a rootNode
.
stage.addEventListener (KeyboardEvent.KEY_DOWN, move); move della funzione privata (e: KeyboardEvent): void vec1 = vec1.rotate (Math2.radianOf (10)); node1.x = rootNode.x + vec1.x; node1.y = rootNode.y + vec1.y;
Di seguito è completato MileStone1. Semplice, giusto?
Fare clic sul file SWF, quindi premere qualsiasi tasto (ripetutamente) per vedere l'effetto.
Ora che abbiamo la configurazione di base, lasciamo andare un po 'oltre. Aggiungeremo node2
(anche viola) alla catena esistente. node2
è unito a node1
attraverso vec2
, a cui viene data una grandezza di 60
// un secondo figlio node2 = new Sprite (); node2.graphics.beginFill (0x772255); node2.graphics.drawCircle (0, 0, 20); node2.graphics.endFill (); addChild (nodo 2); vec2 = new Vector2D (0, 0); vec2.setMagnitude (60);
Inizializziamo la posizione di node2
in relazione con node1
utilizzando vec2
come un vincolo usando il seguente codice. Ricorda di includere anche lo stesso pezzo di codice nell'ascoltatore della tastiera (riga 64 di MileStone2).
node2.x = node1.x + vec2.x; node2.y = node1.y + vec2.y;
Ecco il MileStone2 completato:
Ancora una volta, usa la tastiera per vedere l'effetto.
Hmm? C'è qualcosa di sbagliato in questa implementazione FK. Vedi, la cinematica non attraversa la catena. Richiama il passaggio 4: Rotazione delta; la cinematica deve decrescere dal livello attuale della gerarchia fino alla fine. Ho evidenziato le linee di codice che fanno questo. Per correggere l'errore logico, è sufficiente incollare la riga 65 su MileStone2. Ho fornito MileStone3 in caso di difficoltà.
move della funzione privata (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;
Successivamente, aggiungiamo flessibilità al nostro controllo. Attualmente controlliamo il posizionamento di node1
e node2.
Consente il controllo sul posizionamento di node2
solo.
move della funzione privata (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;
Utilizzare i tasti Pagina giù e Pagina su per spostare i diversi nodi.
Sì, la rotazione è ancora a senso unico, in senso antiorario. Lo scopo di eseguire i passaggi da 5 a 13 è quello di costruire una solida comprensione dell'algoritmo FK. Ora che è stato creato, portiamo questo ad un altro livello: progettando una classe FKChain che permetta una facile implementazione di FK.
FKChain è stato progettato per implementare facilmente FK. Ho progettato la classe con le seguenti variabili e funzioni. Ti condurrò attraverso di loro.
variabili | Scopo | Tipo di dati |
nodi | Per contenere i nodi della catena FK | Vettore matrice di sprites |
frecce | Per contenere le frecce che collegano i nodi | Vettore matrice di Vector2D |
lowerLimits | Per mantenere il limite inferiore dell'angolo ammissibile | Vettore matrice di Numero |
upperLimits | Per mantenere il limite superiore dell'angolo ammissibile | Vettore matrice di Numero |
selectedIndex | Per contenere i dati del nodo selezionato corrente | Numero intero |
L'associazione dei nodi alle frecce insieme ad altri vincoli è rappresentata dal seguente diagramma.
Nota l'associazione di nodi
a frecce
, lowerLimits
e upperLimits
. L'angolo segnato in rosso è vincolato in base alla formula nell'immagine sopra.
Nota anche che ho menzionato nel passaggio 3 che non c'è freccia [0]
. Tuttavia, se dovessimo implementare i confini, avremo bisogno freccia [0]
essere un vettore orizzontale dove angolo di freccia [1]
viene misurato e valutato dai vincoli.
Ora che comprendi i bulloni e le noci della classe FKChain, passiamo a definire le funzioni di FKChain.
funzioni | Input / Tipo di dati | Scopo |
FKChain () | nodo principale / folletto | Inizia variabili di classe. Imposta il nodo radice nella catena FK con vincoli rilevanti. Imposta selectedNode al nodo radice. |
appendNode () | prossimo nodo figlio / folletto | Aggiungi un nuovo nodo alla catena insieme ai vincoli pertinenti. Imposta corrente selezionata. Imposta selectedNode al nuovo nodo. |
removeNode () | nodo da rimuovere / folletto | Rimuovi il nodo di input dalla catena insieme ai vincoli pertinenti. |
selectedNode () | nodo da manipolare / folletto | Imposta il nodo selezionato corrente per eseguire manipolazioni come la regolazione la sua freccia (magnitudine e angolo) e le limitazioni sull'angolo della freccia. |
updateLimits () | inferiore, limiti superiori / Numero | Imposta nuove limitazioni (limite superiore e inferiore) sulla freccia angolo del nodo selezionato. |
alterMagnitude () | grandezza/ Numero | Imposta nuova magnitudine sulla freccia del nodo selezionato. |
alterAngle () | angolo da regolare a / Numero | Inserisce l'angolo delta sulla freccia del nodo selezionato. |
setPosition () | (nessuna) | Ripple giù cinematica dalla gerarchia del nodo selezionato alla fine del catena. |
Ho anche introdotto alcuni getter per facilitare lo sviluppo. Vengono utilizzati durante lo scorrimento dei nodi.
Proprietà | Scopo |
nodoCorrente | Restituisce il nodo selezionato corrente. |
bambino | Restituisce il figlio del nodo selezionato. |
genitore | Restituisce il genitore del nodo selezionato. |
Ora abbiamo una panoramica di FKChain, diamo un'occhiata alla sua applicazione e ai suoi meccanismi interni. Nel tuo progetto, crea una classe TestChain
. Chiameremo un metodo di disegno per disegnare tutto ciò che è richiesto sprites
sul nostro palco Ci sono complessivamente cinque sprite e una parentesi per indicare il nodo selezionato corrente.
public function draw (): void b0 = new Sprite (); b0.graphics.beginFill (0); b0.graphics.drawCircle (0, 0, 15); b0.graphics.endFill (); addChild (b0); b1 = new Sprite (); b1.graphics.beginFill (0); b1.graphics.drawRect (-80, -10, 80, 20); b1.graphics.endFill (); addChild (b1); b2 = new Sprite (); b2.graphics.beginFill (0); b2.graphics.drawRect (-40, -10, 40, 20); b2.graphics.endFill (); addChild (b2); b3 = new Sprite (); b3.graphics.beginFill (0); b3.graphics.drawRect (-40, -10, 40, 20); b3.graphics.endFill (); addChild (b3); b4 = new 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 (target);
funzione pubblica 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); // aggiorna la posizione di tutti i nodi b0.x = 250; b0.y = 300; c.selectNode (b1); c.setPosition (); // Posiziona il target sul nodo root inizialmente target.x = c.currentNode.x; target.y = c.currentNode.y;
Innanzitutto, dobbiamo istanziare la classe FKChain chiamando il suo costruttore. Fornire un nodo radice nel costruttore. Un ulteriore esame della funzione di costruzione mostra due operazioni principali della funzione. Il primo è l'istanziazione di nodi
, frecce
, upperLimits
e lowerLimits
. I dati vengono forniti in queste variabili successivamente.
Si noti che il nodo radice ha una freccia associata. Non l'ho mostrato esplicitamente frecce
sono sempre un membro in meno di nodi
. Tuttavia, accettalo per ora come spiegherò sul suo utilizzo nelle sezioni successive. Le altre linee evidenziate sono solo riempitivi per garantire un facile indirizzamento sui vincoli. Infine, imposta il nodo attualmente selezionato su radice
per ulteriore manipolazione.
funzione pubblica FKChain (node0: Sprite) // istanza variabili nodi = nuovo vettore.; frecce = nuovo vettore. ; upperLimits = new Vector. ; lowerLimits = new Vector. ; // introduce il nodo root nodes.push (node0); arrows.push (new Vector2D (1, 0)); lowerLimits.push (0); upperLimits.push (0); selectNode (node0);
Dopo l'avvio, possiamo iniziare ad accodare i nodi all'istanza di FKChain. La creazione della freccia è astratta dagli utenti. Ho evidenziato la magnitudine iniziale e la limitazione dell'angolo di piega (entro -90 < angle < 90). These constraints are easily customised.
funzione pubblica appendNode (node: Sprite): void nodes.push (node); var newArrow: Vector2D = new Vector2D (0, 0); newArrow.setMagnitude (60); arrows.push (newArrow); lowerLimits.push (Math2.radianOf (-90)); upperLimits.push (Math2.radianOf (90)); selectNode (nodo);
// aggiorna la posizione di tutti i nodi b0.x = 250; b0.y = 300; c.selectNode (b0); c.setPosition (); // Posiziona il target sul nodo root inizialmente target.x = c.currentNode.x; target.y = c.currentNode.y;
Ora la posizione del nodo radice si trova nell'angolo in alto a sinistra dello stage. Sposteremo la posizione di b1
vicino al centro. Quindi dobbiamo riposizionare gli altri nodi in catena e impostare la parentesi di targeting sul nodo attualmente selezionato. Esaminiamo ulteriormente setPosition
:
funzione pubblica setPosition (): void var index: int = Math.max (1, selectedIndex); per (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());
Questa funzione tenta di riposizionare e riorientare tutti i nodi a partire dal nodo attualmente selezionato. Ho impostato un limite all'indice (evidenziato) perché logicamente, mentre eseguiamo il riposizionamento relativo, il nodo radice non è influenzato da nessun genitore. Il nodo più alto nella gerarchia per eseguire il riposizionamento relativo è b1
. Non importa se scrivi c.selectNode (B0)
o c.selectNode (b1)
prima c.setPosition ()
anche se influenzerà la posizione iniziale della parentesi di tragedia?
funzione pubblica TestChain () this.draw (); this.initChain (); stage.addEventListener (KeyboardEvent.KEY_DOWN, keyDown);
Ora è tempo di animare la catena. Assegneremo un ascoltatore all'evento tastiera.
funzione privata keyDown (e: KeyboardEvent): void // scansiona la selezione del nodo if (e.keyCode == Keyboard.SPACE) if (c.currentNode == b4) c.selectNode (b1); else c.selectNode (c.child); else if (e.keyCode == Keyboard.UP) c.alterAngle (Math2.radianOf (-1 * step)); c.setPosition (); else if (e.keyCode == Keyboard.DOWN) c.alterAngle (Math2.radianOf (step)); c.setPosition (); target.x = c.currentNode.x; target.y = c.currentNode.y;
Premendo il tasto spazio, la parentesi di mira scorrerà attraverso tutti i nodi, tranne il nodo radice, b0
. Premendo il tasto freccia Su si ottiene un angolo delta negativo, -1 * passaggio
; mentre il tasto freccia giù darà un angolo delta positivo, passo
.
Ecco un esempio di TestChain.
Usa la barra spaziatrice e le frecce Su e Giù per controllarlo. Nota come i vincoli influenzano quanto lontano ogni nodo può "piegarsi".
Abbiamo usato alterAngle ()
nell'ascoltatore. Ora lascia sezionare il funzionamento interno di esso.
funzione pubblica alterAngle (ang: Number): void var index: int = Math.max (1, selectedIndex); // calc deviation tra la freccia precedente e la freccia corrente deviazione var: Number = arrows [index - 1] .angleBetween (arrows [index]); var future: Number = deviation + ang; // assicura ang entro limiti definiti se (future> upperLimits [index]) ang = upperLimits [index] - deviation; altro se (futuro < lowerLimits[index]) ang = lowerLimits[index] - deviation; //update relevant arrows for (var i:int = selectedIndex; i < arrows.length; i++) arrows[i] = arrows[i].rotate(ang);
Viene calcolata la deviazione della freccia del nodo corrente da quella del suo genitore, questo è il suo angolo corrente. L'angolo di input viene aggiunto all'angolo corrente per formare l'angolo futuro. Tutto va bene e questo valore dovrebbe essere prodotto. Tuttavia, vogliamo implementare un limite minimo e massimo in modo che l'angolo futuro venga controllato rispetto a questi valori e adeguato di conseguenza. Successivamente, emettiamo il valore per aggiornare tutte le frecce pertinenti.
Potresti notare che l'animazione è irregolare. Si preme il tasto, e si spinge un po '. Possiamo migliorare un po 'mettendo in accelerazione e decelerazione della velocità angolare. Ma richiederà qualche ricablaggio di gestori di eventi. Si noti che il disegnare()
e initChain ()
le funzioni sono riportate dai passi precedenti.
funzione pubblica TestChain2 () this.draw (); this.initChain (); stage.addEventListener (KeyboardEvent.KEY_DOWN, keyDown); stage.addEventListener (KeyboardEvent.KEY_UP, keyUp); stage.addEventListener (Event.ENTER_FRAME, animato);
Premendo i tasti direzionali, le bandierine verranno alternate vero
. Rilasciando queste chiavi, i loro flag associati verranno alternati falso
. Questi flag verranno catturati e valutati per ulteriori operazioni da parte di un onEnterFrame
gestore di eventi.
funzione privata keyDown (e: KeyboardEvent): void // scansiona la selezione del nodo if (e.keyCode == Keyboard.SPACE) if (c.currentNode == 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;
Di seguito sono riportate le variabili utilizzate per l'animazione della cinematica:
private var angVelo: Number = 0; // current angular velocity private var maxVelo: Number = 5; // impostazione di un limite su velocità angolare private var angAcc: Number = 0.2; // incremento incrementale su velocità angolare private var angDec: Number = 0.8; // decay moltiplicatore su velocity angolare var var privato: Number = 5; // passi direzionali quando si sposta l'intera catena
Catturando le bandiere dall'evento tastiera, possiamo ulteriormente manipolare la cinematica della catena.
funzione privata animate (e: Event): void // sposta l'intera catena if (c.currentNode == b0) if (upFlag) b0.y - = step else if (downFlag) b0.y + = passaggio if (leftFlag) b0.x - = step else if (rightFlag) b0.x + = step // regolazione dell'angolo else if (upFlag) angVelo - = angAcc; // impostazione limite su velocità angolare angVelo = Math.max (-1 * maxVelo, angVelo); else if (downFlag) angVelo + = angAcc; // impostazione limite su velocità angolare angVelo = Math.min (maxVelo, angVelo); else // decelera quando vengono rilasciate le chiavi angVelo * = angDec // imposta il valore sulla freccia del nodo selezionato. c.alterAngle (Math2.radianOf (angVelo)); // aggiorna la posizione c.setPosition (); target.x = c.currentNode.x; target.y = c.currentNode.y;
Si noti che esiste una gestione leggermente diversa del nodo radice. Mentre viene selezionato, sposteremo l'intera catena su, giù, a sinistra oa destra. Mentre altri bambini vengono selezionati, noi pompiamo in velocità angolare, angVelo
, su o giù all'interno della velocità minima e massima. Se le chiavi vengono rilasciate (quindi, tutte le bandiere vengono girate falso
), la velocità attuale decelera. Per chiarire ulteriormente questo frammento sopra, leggi il mio post sulla cinematica lineare per avere un'idea del codice sopra.
Di seguito è riportato un esempio del lavoro finito:
Ancora una volta, usa la barra spaziatrice e i tasti freccia su e giù; questa volta, nota quanto è scorrevole il movimento.
Ora che il lavoro di base per la base di codice è terminato, ci concentreremo sui lavori di cosmesi sul nostro progetto. Non sono un artista molto bravo, quindi sopporto il disegno del mio escavatore.
La grafica che ho disegnato viene convertita in MovieClip. Una cosa da tenere a mente è che il punto di registrazione della grafica deve essere posizionato verso la fine del segmento per le braccia e lo scoop. Ho evidenziato i punti di registrazione con un cerchio rosso per tutte le mie risorse negli screenshot qui sotto.
Ho chiamato questi MovieClip sopra Radice
, ARM1
, ARM2
, e Notizia in anticipo
rispettivamente
Un altro dettaglio è che è necessario premere Ctrl + L per aprire il pannello della libreria ed esportare queste risorse per Actionscript. Fare clic con il tasto destro del mouse, selezionare Concatenamento e inserire i dettagli come mostrato nelle immagini sottostanti.
Una volta completate tutte le risorse grafiche, pubblicarle in formato SWC per essere importate correttamente in FlashDevelop. Sto usando Flash CS3. Premi Ctrl + Maiusc + F12 per visualizzare le impostazioni di pubblicazione. Seleziona la scheda Flash e attiva Esporta SWC. Quindi premi Pubblica.
Copia il nuovo file (.swc) nella cartella lib del tuo progetto.
Ora che lo hai nel tuo progetto, devi comunque includere nella libreria. Fai clic con il tasto destro sul tuo file .swc e seleziona "Aggiungi alla libreria".
Espandi l'elenco come mostrato nell'immagine sottostante per verificare i nomi delle variabili. Ho usato i seguenti nomi ARM1
, ARM2
, Radice
e Notizia in anticipo
. Questi sono i nomi di classe associati a tali grafici. Li useremo più tardi.
Finalmente arriviamo all'ultima tappa di questo tutorial. Sostituiremo l'esistente disegnare()
metodo con questo nuovo, drawAssets ()
.
funzione privata drawAssets (): void rootNode = new Root (); arm1 = new Arm1 (); arm2 = new Arm2 (); scoop = new Scoop (); addChild (ARM1); addChild (rootNode); addChild (paletta); 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 (target);
In questo momento, se apri la tua applicazione, potresti vedere un gruppo di disegni nell'angolo in alto a sinistra o l'intero braccio e il corpo dell'escavatore allineati in modo divertente. Regolare opportunamente i vincoli di ampiezza e le limitazioni angolari sui join. Ho incluso il mio come di seguito.
funzione privata 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 (paletta); c.alterMagnitude (60); c.updateLimits (Math2.radianOf (45), Math2.radianOf (135)); // aggiorna la posizione di tutti i nodi rootNode.x = 250; rootNode.y = 300; c.selectNode (rootNode); c.setPosition (); // Posiziona il target sul nodo root inizialmente target.x = c.currentNode.x; target.y = c.currentNode.y;
Ulteriori modifiche al controllo da tastiera del nodo radice, ho eliminato il movimento verticale dell'intera catena in modo che l'escavatore (radice) si muova solo in modo orizzontale. Il frammento di seguito è inserito nel Event.ENTER_FRAME
gestore
if (c.currentNode == rootNode) if (leftFlag) rootNode.x - = step else if (rightFlag) rootNode.x + = step
Ogni singolo adeguamento alla base del codice è fatto. Certo, puoi personalizzarlo come vuoi. Per ora, scorri i nodi usando il tasto Spazio. Per ogni nodo, gioca con i tasti direzionali per vedere l'escavatore che si muove su e giù.
Questo è tutto per questa volta. Spero che il file di classe che ho messo insieme aiuti ad alleggerire la cinematica diretta da qualche parte nella simulazione e nei giochi. Grazie per aver letto e lasciato alcuni commenti se hai trovato un difetto in qualcosa.