Forward Kinematics (FK) es un algoritmo de posicionamiento. No es tan complicado como parece si lo asocia a una secuencia de acciones desde el punto de vista del operador de una excavadora. Comenzando con el nodo más cercano a él, el operador configura la orientación de cada nodo con la esperanza de que la primicia llegue a la ubicación deseada. A menudo, se hacen varios intentos antes de alcanzar el éxito. FK es un algoritmo para realizar dicha tarea. En este tutorial, intentaremos la implementación de FK y la aplicaremos en una excavadora desde una vista lateral 2D. Habiendo entendido este algoritmo, uno puede adaptarlo fácilmente a un entorno 3D. Disfrutar!
Este tutorial asumirá la siguiente secuencia:
En primer lugar, debemos entender el concepto de una cadena. Una cadena abstrae el orden jerárquico de los nodos. Hay un nodo raíz, el orden más alto de la cadena, donde se unen todos los demás nodos. El nodo que se conecta a la raíz es el niño de primer nivel. El nodo que se conecta al niño de primer nivel es el niño de segundo nivel.
La relación jerárquica se simplifica a continuación:
raíz> nodo1> nodo2> nodo3> nodo4> nodo5?
La animación flash anterior muestra las relaciones padre (superior en jerarquía) a hijo (inferior en jerarquía), donde cada flecha apunta a un nodo secundario.
Cada uno de estos nodos está conectado a los adyacentes por una restricción. Voy a referir estas restricciones como "flechas". Las flechas son vectores. Tienen una longitud (mejor conocida como magnitud) y un ángulo que describe su orientación. En este tutorial, estas flechas apuntan desde el nodo principal al nodo secundario. Por ejemplo, node1 se une a root por arrow1. Arrow1 está apuntando desde la raíz a node1.
Las flechas también siguen un orden jerárquico porque intentan unirse a una cadena jerárquica de nodos. Esta relación jerárquica se simplifica de la siguiente manera:
flecha1> flecha2> flecha3> flecha4> flecha5?
Entonces, ¿dónde está arrow0? Bueno, la raíz es la más alta en la jerarquía. Ninguna flecha lo apunta, así que efectivamente no hay flecha0.
Ajustar la rotación de las flechas es lo más importante en el algoritmo FK. Aquí, rotaremos una flecha en ángulo delta. Si rotamos arrow1, la posición del nodo1 se actualizará. Pero eso no es todo.
En el algoritmo FK, la cinemática atraviesa de mayor a menor jerarquía. Supongamos que nuestra cadena tiene 6 nodos, unidos por 5 flechas. Si la rotación delta se aplica a la flecha 1, entonces la flecha 2 a la flecha 5 también debe girarse con el ángulo delta. He puesto en negrita las flechas que se ven afectadas por el cambio..
flecha1 > arrow2 > flecha3 > flecha4 > arrow5
Si la rotación delta se aplica en arrow3, solo se verán afectadas arrow4 y arrow5.
arrow1>arrow2> flecha3 > flecha4 > arrow5
Para cada flecha afectada, la posición de su nodo asociado también se verá afectada. Así que node4 y node5 actualizarán sus posiciones..
En el SWF anterior, haga clic en las flechas para ver la cinemática ondulada en los nodos (flechas más oscuras).
Lauch FlashDevelop y comienza un nuevo proyecto. Agregue un "MileStone1.as" a su proyecto.
Ahora a implementar nuestra primera cadena FK. Primero, necesitamos agregar los dos sprites al escenario como variables de clase. El nodo raíz es un círculo azul y el primer nodo es un círculo púrpura.
rootNode = new Sprite (); rootNode.graphics.beginFill (0x4499FF); rootNode.graphics.drawCircle (0, 0, 20); rootNode.graphics.endFill (); addChild (rootNode); node1 = nuevo Sprite (); node1.graphics.beginFill (0x772255); node1.graphics.drawCircle (0, 0, 20); node1.graphics.endFill (); addChild (node1);
nodo1
se une a rootNode a través de vec1
, que es una instancia de la clase Vector2D (clase de escritura personalizada). Es una variable de clase. Lo iniciamos y fijamos su magnitud en 60..
vec1 = nuevo Vector2D (0, 0); vec1.setMagnitud (60);
Antes de comenzar a asignar oyentes para agregar interactividad a nuestro pequeño programa, debemos establecer la posición inicial de los nodos. Primero el rootnode
, que es bastante obvio. El siguiente es nodo1
(resaltado) que depende de rootnode
posición de.
// configurando los nodos rootNode.x = 150; rootNode.y = 150; node1.x = rootNode.x + vec1.x; node1.y = rootNode.y + vec1.y;
Casi allí. Añadimos un oyente al evento de teclado. Al pulsar una tecla arbitraria, vec1
gira y cambia aún más la orientación de nodo1
con respecto a rootnode
.
stage.addEventListener (KeyboardEvent.KEY_DOWN, mover); movimiento de función privada (e: KeyboardEvent): void vec1 = vec1.rotate (Math2.radianOf (10)); node1.x = rootNode.x + vec1.x; node1.y = rootNode.y + vec1.y;
A continuación se completa MileStone1. Simple a la derecha?
Haga clic en el SWF, luego presione cualquier tecla (repetidamente) para ver el efecto.
Ahora que tenemos la configuración básica, empujemos esto un poco más. Nosotros agregaremos nodo2
(también púrpura) a la cadena existente. nodo2
está unido a nodo1
vía vec2
, que se le da una magnitud de 60
// un segundo nodo secundario2 = nuevo Sprite (); node2.graphics.beginFill (0x772255); node2.graphics.drawCircle (0, 0, 20); node2.graphics.endFill (); addChild (node2); vec2 = nuevo Vector2D (0, 0); vec2.setMagnitud (60);
Inicializamos la posición de nodo2
En relación a nodo1
utilizando vec2
como restricción utilizando el siguiente código. Recuerde incluir también la misma pieza de código en el oyente del teclado (línea 64 de MileStone2).
node2.x = node1.x + vec2.x; node2.y = node1.y + vec2.y;
Aquí está el MileStone2 completado:
De nuevo, usa el teclado para ver el efecto..
Hmm Algo está mal con esta implementación FK. Mira, la cinemática no se desplaza por la cadena. Recuerde el Paso 4: Rotación delta; la cinemática debe ondularse desde el nivel actual de jerarquía hasta el final. He resaltado las líneas de código que hacen esto. Para corregir el error lógico, simplemente pegue la línea 65 en MileStone2. He suministrado MileStone3 en caso de que tenga dificultades..
movimiento de función privada (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;
A continuación, vamos a añadir flexibilidad a nuestro control. Actualmente controlamos el posicionamiento de nodo1
y nodo2.
Permite controlar el posicionamiento de nodo2
solamente.
movimiento de función privada (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;
Use las teclas Av Pág y Av Pág para mover los diferentes nodos..
Sí, la rotación sigue siendo de una manera: en sentido contrario a las agujas del reloj. El propósito de ejecutar los Pasos 5 a 13 es construir una comprensión sólida del algoritmo FK. Ahora que está construido, vamos a llevar esto a otro nivel: diseñar una clase FKChain que permita una implementación fácil de FK.
FKChain fue diseñado para implementar fácilmente FK. He diseñado la clase con las siguientes variables y funciones. Te hare pasar por ellos.
Variables | Propósito | Tipo de datos |
nodos | Para sujetar nodos de cadena FK. | Vector gama de Sprites |
flechas | Mantener flechas conectando nodos. | Vector gama de Vector2D |
Límites más bajos | Para mantener el límite inferior del ángulo permitido | Vector gama de Número |
Límites superiores | Para mantener el límite superior del ángulo permitido | Vector gama de Número |
selectIndex | Para mantener los datos del nodo seleccionado actual | Entero |
La asociación de nodos a flechas junto con otras restricciones se muestra en el siguiente diagrama.
Tenga en cuenta la asociación de nodos
a flechas
, Límites más bajos
y Límites superiores
. El ángulo marcado en rojo está restringido de acuerdo con la fórmula en la imagen de arriba.
Note también que mencioné en el Paso 3 que no hay flecha [0]
. Sin embargo, si tuviéramos que implementar límites, necesitaremos flecha [0]
ser un vector horizontal donde el ángulo de flecha [1]
Se mide desde y se evalúa por las restricciones..
Ahora que comprende los tornillos y tuercas de la clase FKChain, pasamos a definir las funciones de FKChain.
Funciones | Tipo de entrada / datos | Propósito |
FKChain () | nodo raíz / Duende | Inicia las variables de clase. Establece el nodo raíz en la cadena FK a lo largo con restricciones relevantes. Conjuntos nodo seleccionado al nodo raíz. |
appendNode () | siguiente nodo hijo / Duende | Agregue el nuevo nodo a la cadena junto con las restricciones relevantes. Conjuntos actual seleccionado Conjuntos nodo seleccionado a nuevo nodo. |
removeNode () | nodo para eliminar / Duende | Elimine el nodo de entrada de la cadena junto con las restricciones relevantes. |
selectedNode () | nodo para manipular / Duende | Establecer el nodo seleccionado actual para realizar manipulaciones como ajustar Su flecha (magnitud y ángulo) y sus limitaciones en el ángulo de flecha.. |
updateLimits () | límites inferiores, superiores / Número | Establece nuevas limitaciones (límite superior e inferior) en la flecha ángulo del nodo seleccionado. |
alterMagnitud () | magnitud/ Número | Establece nueva magnitud en la flecha del nodo seleccionado.. |
alterAngle () | ángulo para ajustar a / Número | Ingresa el ángulo delta a la flecha del nodo seleccionado. |
posición de ajuste() | (ninguna) | Rizar la cinemática desde la jerarquía del nodo seleccionado hasta el final de la cadena. |
También introduje algunos captadores para facilitar el desarrollo. Se utilizan al desplazarse por nodos..
Propiedad | Propósito |
nodo actual | Devuelve el nodo seleccionado actual. |
niño | Devuelve el hijo del nodo seleccionado. |
padre | Devuelve el padre del nodo seleccionado. |
Ahora que tenemos una visión general de FKChain, echemos un vistazo a su aplicación y funcionamiento interno. En tu proyecto, crea una clase. TestChain
. Vamos a recurrir a un método de dibujo para dibujar todos los requeridos Sprites
en nuestro escenario Hay cinco sprites y un corchete para indicar el nodo seleccionado actual.
función pública draw (): void b0 = new Sprite (); b0.graphics.beginFill (0); b0.graphics.drawCircle (0, 0, 15); b0.graphics.endFill (); addChild (b0); b1 = nuevo Sprite (); b1.graphics.beginFill (0); b1.graphics.drawRect (-80, -10, 80, 20); b1.graphics.endFill (); addChild (b1); b2 = nuevo Sprite (); b2.graphics.beginFill (0); b2.graphics.drawRect (-40, -10, 40, 20); b2.graphics.endFill (); addChild (b2); b3 = nuevo Sprite (); b3.graphics.beginFill (0); b3.graphics.drawRect (-40, -10, 40, 20); b3.graphics.endFill (); addChild (b3); b4 = nuevo Sprite (); b4.graphics.beginFill (0); b4.graphics.drawRect (-40, -10, 40, 20); b4.graphics.endFill (); addChild (b4); objetivo = nuevo 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);
función pública initChain (): void c = new FKChain (b0); c.appendNode (b1); c.alterMagnitud (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); // actualizar la posición de todos los nodos b0.x = 250; b0.y = 300; c.selectNode (b1); c.setPosition (); // Coloque el destino en el nodo raíz inicialmente target.x = c.currentNode.x; target.y = c.currentNode.y;
Primero, debemos crear una instancia de la clase FKChain llamando a su constructor. Suministre un nodo raíz en el constructor. Un examen adicional de la función del constructor muestra dos operaciones principales de la función. Primero está la instanciación de nodos
, flechas
, Límites superiores
y Límites más bajos
. Los datos se suministran en estas variables a partir de entonces.
Tenga en cuenta que el nodo raíz tiene una flecha asociada. Yo no mostré explícitamente que flechas
siempre son un miembro menos de nodos
. Sin embargo, acéptelo por ahora como explico sobre su uso en secciones posteriores. Las otras líneas resaltadas son solo rellenos para garantizar un direccionamiento fácil en las restricciones. Finalmente configurando el nodo actualmente seleccionado a raíz
para una mayor manipulación.
función pública FKChain (node0: Sprite) // instancia las variables nodes = new Vector.; flechas = nuevo vector. ; upperLimits = nuevo vector. ; Límite inferior = nuevo vector. ; // introducir el nodo raíz nodes.push (node0); arrows.push (nuevo Vector2D (1, 0)); lowerLimits.push (0); upperLimits.push (0); selectNode (node0);
Después de la iniciación, podemos comenzar a agregar nodos a la instancia de FKChain. La creación de la flecha se abstrae de los usuarios. He resaltado la magnitud inicial y la limitación en el ángulo de curvatura (hasta dentro de -90). < angle < 90). These constraints are easily customised.
función pública appendNode (nodo: Sprite): void nodes.push (nodo); var newArrow: Vector2D = nuevo Vector2D (0, 0); newArrow.setMagnitude (60); arrows.push (newArrow); lowerLimits.push (Math2.radianOf (-90)); upperLimits.push (Math2.radianOf (90)); selectNode (nodo);
// actualizar la posición de todos los nodos b0.x = 250; b0.y = 300; c.selectNode (b0); c.setPosition (); // Coloque el destino en el nodo raíz inicialmente target.x = c.currentNode.x; target.y = c.currentNode.y;
Ahora la posición del nodo raíz está en la esquina superior izquierda del escenario. Vamos a mover la ubicación de b1
cerca del centro. Luego, debemos reposicionar los otros nodos en la cadena y establecer el soporte de destino en el nodo seleccionado actualmente. Examinemos más a fondo posición de ajuste
:
función pública setPosition (): void var index: int = Math.max (1, selectedIndex); para (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());
Esta función intenta reposicionar y reorientar todos los nodos a partir del nodo seleccionado actualmente. He establecido un límite en el índice (resaltado) porque, lógicamente, al realizar un reposicionamiento relativo, el nodo raíz no se ve afectado por ningún padre. El nodo más alto en la jerarquía para realizar el reposicionamiento relativo es b1
. No importa si escribes c.selectNode (b0)
o c.selectNode (b1)
antes de c.setPosition ()
A pesar de que afectará a la posición inicial del corchete trágico.?
función pública TestChain () this.draw (); this.initChain (); stage.addEventListener (KeyboardEvent.KEY_DOWN, keyDown);
Ahora es el momento de animar la cadena. Asignaremos un oyente al evento de teclado..
función privada keyDown (e: KeyboardEvent): void // desplazarse por la selección del nodo if (e.keyCode == Keyboard.SPACE) if (c.currentNode == b4) c.selectNode (b1); else c.selectNode (c.child); else else if (e.keyCode == Keyboard.UP) c.alterAngle (Math2.radianOf (-1 * step)); c.setPosition (); else if (e.keyCode == Keyboard.DOWN) c.alterAngle (Math2.radianOf (paso)); c.setPosition (); target.x = c.currentNode.x; target.y = c.currentNode.y;
Al presionar la tecla de espacio, el corchete de destino se desplazará por todos los nodos, excepto el nodo raíz, b0
. Presionando la tecla de flecha hacia arriba dará un ángulo delta negativo, -1 * paso
; mientras que la tecla de flecha hacia abajo dará un ángulo delta positivo, paso
.
Aquí hay una muestra de TestChain..
Usa la barra espaciadora y las teclas de flecha arriba y abajo para controlarla. Observe cómo las restricciones afectan la distancia a la que cada nodo puede "doblarse".
Nosotros usamos alterAngle ()
en el oyente. Ahora vamos a analizar el funcionamiento interno de la misma..
función pública alterAngle (ang: Number): void var index: int = Math.max (1, selectedIndex); // desviación calculada entre la flecha anterior y la flecha actual desviación var: Número = flechas [índice - 1] .angleBetween (flechas [índice]); var future: Número = desviación + ang; // asegura ang dentro de límites definidos if (future> upperLimits [index]) ang = upperLimits [index] - desviación; else if (future < lowerLimits[index]) ang = lowerLimits[index] - deviation; //update relevant arrows for (var i:int = selectedIndex; i < arrows.length; i++) arrows[i] = arrows[i].rotate(ang);
Se calcula la desviación de la flecha del nodo actual de la de su padre, este es su ángulo actual. El ángulo de entrada se agrega al ángulo actual para formar un ángulo futuro. Todo está bien y este valor debe salir. Sin embargo, queremos implementar un límite mínimo y máximo para que el ángulo futuro se verifique con estos valores y se ajuste en consecuencia. Después de eso, generamos el valor para actualizar todas las flechas relevantes..
Puede notar que la animación es entrecortada. Presionas la tecla, y la empuja un poco. Podemos mejorar esto un poco al acelerar y desacelerar la velocidad angular. Pero requerirá un cambio de cableado de los controladores de eventos. Tenga en cuenta que el dibujar()
y initChain ()
Las funciones se llevan adelante de los pasos anteriores..
función pública TestChain2 () this.draw (); this.initChain (); stage.addEventListener (KeyboardEvent.KEY_DOWN, keyDown); stage.addEventListener (KeyboardEvent.KEY_UP, keyUp); stage.addEventListener (Event.ENTER_FRAME, animate);
Al presionar las teclas direccionales, las banderas se activarán. cierto
. Al soltar estas teclas, se activarán sus banderas asociadas. falso
. Estas banderas serán capturadas y evaluadas para futuras operaciones por un onEnterFrame
controlador de eventos.
función privada keyDown (e: KeyboardEvent): void // desplazarse por la selección de nodo if (e.keyCode == Keyboard.SPACE) if (c.currentNode == b4) c.selectNode (b0); else c.selectNode (c.child); else 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; tecla de función privada Up (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;
A continuación se presentan las variables utilizadas para animar cinemáticas:
privado var angVelo: Número = 0; // velocidad angular actual privada var maxVelo: Number = 5; // estableciendo un límite en la velocidad angular private var angAcc: Number = 0.2; // paso incremental en la velocidad angular privada var angDec: Número = 0.8; // multiplicador de decaimiento en velocidad angular variable var step: Number = 5; // pasos direccionales al mover toda la cadena
Al capturar banderas de eventos de teclado, podemos manipular aún más la cinemática de la cadena.
función privada animate (e: Event): void // mover toda la cadena if (c.currentNode == b0) if (upFlag) b0.y - = step else if (downFlag) b0.y + = paso if (leftFlag) b0.x - = paso else if (rightFlag) b0.x + = paso // ajuste del ángulo else if (upFlag) angVelo - = angAcc; // ajuste del límite en la velocidad angular angVelo = Math.max (-1 * maxVelo, angVelo); else if (downFlag) angVelo + = angAcc; // establecer el límite en la velocidad angular angVelo = Math.min (maxVelo, angVelo); else // desacelerar cuando se sueltan las teclas angVelo * = angDec // establecer el valor en la flecha del nodo seleccionado. c.alterAngle (Math2.radianOf (angVelo)); // actualizar posición c.setPosition (); target.x = c.currentNode.x; target.y = c.currentNode.y;
Tenga en cuenta que hay un manejo ligeramente diferente del nodo raíz. A medida que se selecciona, moveremos toda la cadena hacia arriba, hacia abajo, hacia la izquierda o hacia la derecha. Mientras se seleccionan otros niños, bombeamos a velocidad angular., angVelo
, Arriba o abajo dentro de la velocidad mínima y máxima. Si se sueltan las teclas (por lo tanto, todas las banderas se giran falso
), la velocidad actual decelera. Para aclarar más este fragmento, lea mi publicación sobre cinemática lineal para tener una idea del código anterior..
A continuación se muestra un ejemplo del trabajo terminado:
Nuevamente, use la barra espaciadora y las teclas de flecha arriba y abajo; esta vez, note cuán suave es el movimiento.
Ahora que el trabajo de base para el código base está hecho, nos centraremos en los trabajos cosméticos en nuestro proyecto. No soy un artista muy bueno, así que ten cuidado con mi dibujo de excavadora.
Los gráficos que dibujé se convierten en MovieClips. Una cosa a tener en cuenta es que el punto de registro de los gráficos se debe colocar hacia el final del segmento para los brazos y la cuchara. He resaltado los puntos de registro con un círculo rojo para todos mis activos en las capturas de pantalla a continuación.
He nombrado estos MovieClip arriba Raíz
, Brazo1
, Brazo2
, y Cuchara
respectivamente
Otro detalle es que debe presionar Ctrl + L para abrir el panel de la biblioteca y exportar estos activos para ActionScript. Haga clic con el botón derecho, seleccione Vinculación y complete los detalles como se muestra en las imágenes a continuación..
Una vez que se hayan completado todos los recursos gráficos, publíquelos en formato SWC para importarlos correctamente a FlashDevelop. Estoy usando Flash CS3. Presione Ctrl + Shift + F12 para abrir la Configuración de publicación. Seleccione la pestaña Flash y active Exportar SWC. Luego pulsa Publicar.
Copie el nuevo archivo (.swc) en la carpeta lib de su proyecto.
Ahora que lo tiene dentro de su proyecto, todavía necesita incluirlo en la biblioteca. Haga clic derecho en su archivo .swc y seleccione "Agregar a la biblioteca".
Expanda la lista como se muestra en la imagen a continuación para verificar los nombres de las variables. He usado los siguientes nombres Brazo1
, Brazo2
, Raíz
y Cuchara
. Estos son los nombres de clase asociados con esos gráficos. Los usaremos más tarde..
Finalmente llegamos a la última etapa de este tutorial. Reemplazaremos las existentes. dibujar()
método con este nuevo, drawAssets ()
.
función privada drawAssets (): void rootNode = new Root (); arm1 = new Arm1 (); arm2 = nuevo arm2 (); scoop = nueva Scoop (); addChild (arm1); addChild (rootNode); addChild (scoop); addChild (arm2); objetivo = nuevo 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);
Ahora mismo, si inicia la aplicación, puede ver un grupo de dibujos en la esquina superior izquierda, o todo el brazo y el cuerpo de la excavadora alineados de manera divertida. Ajuste las restricciones de magnitud y las limitaciones angulares en las uniones adecuadamente. He incluido el mio como abajo.
función privada initChain (): void c = new FKChain (rootNode); c.appendNode (arm1); c.alterMagnitud (260); c.updateLimits (Math2.radianOf (-45), Math2.radianOf (45)); c.appendNode (arm2); c.alterMagnitud (100); c.updateLimits (Math2.radianOf (0), Math2.radianOf (90)); c.appendNode (scoop); c.alterMagnitud (60); c.updateLimits (Math2.radianOf (45), Math2.radianOf (135)); // actualizar la posición de todos los nodos rootNode.x = 250; rootNode.y = 300; c.selectNode (rootNode); c.setPosition (); // Coloque el destino en el nodo raíz inicialmente target.x = c.currentNode.x; target.y = c.currentNode.y;
Más ajustes al control del teclado del nodo raíz, he eliminado el movimiento vertical de toda la cadena para que la excavadora (raíz) solo se mueva de manera horizontal. El fragmento de abajo se coloca en el Evento.ENTER_FRAME
entrenador de animales
if (c.currentNode == rootNode) if (leftFlag) rootNode.x - = step else if (rightFlag) rootNode.x + = step
Cada ajuste único a la base del código se realiza. Por supuesto, puedes personalizarlo como quieras. Por ahora, desplácese por los nodos utilizando la tecla Espacio. Para cada nodo, juegue con las teclas direccionales para ver cómo la excavadora se mueve hacia arriba y hacia abajo.
Eso es todo por esta vez. Espero que el archivo de clase que he reunido te ayude a facilitar tu cinemática avanzada en algún lugar de tu simulación y juegos. Gracias por leer y dejar algunos comentarios si encuentra una falla en algo.