Representar la animación en términos de vectores es intuitivo, pero entender las matemáticas vectoriales es un dolor. En este tutorial, espero aliviar ese dolor y proporcionar una solución a los problemas de animación utilizando una clase escrita Vector2D personalizada. Veremos algunos conceptos fundamentales de la cinemática lineal en el enfoque euleriano: desplazamiento, velocidad y aceleración. Entonces, vamos a construir una aplicación sencilla con él..
Echemos un vistazo al resultado final en el que trabajaremos. Haga clic en el panel de Flash a continuación y controle la punta de flecha presionando las cuatro teclas direccionales.
Todas las cantidades vectoriales tienen dos componentes: magnitud y dirección.
Un cambio en cantidades vectoriales se refiere a uno de estos casos:
El desplazamiento, la velocidad y la aceleración son cantidades vectoriales. Sus definiciones son las siguientes:
La siguiente animación muestra el desplazamiento, tal como lo implementaremos en Flash más adelante..
La velocidad se ilustra en la siguiente animación. La velocidad de la nota es constante, lo que significa que la aceleración está ausente en este escenario. Si la velocidad es cero, el desplazamiento permanecerá constante a lo largo de.
La aceleración se ilustra en la siguiente animación. Nota: la cinemática implica. constante aceleración. Si la aceleración cambia con el tiempo, cae bajo el tema de dinámica. La dinámica es el estudio de las fuerzas que causan que la aceleración varíe con el tiempo. Una de esas fuerzas es la gravedad, y he escrito un post animando que.
Ahora que ha adquirido una breve comprensión de las cantidades de cinemática lineal y puede relacionarlos con vectores, podemos comenzar a construir nuestra clase de proyectiles. Nos gustaría que el proyectil sea capaz de capturar todas estas cantidades: desplazamiento, velocidad y aceleración, para que pueda ser manipulado en cada cuadro..
A continuación se muestran los datos que registraremos en nuestra clase de proyectiles:
privada var desplazar: Vector2D; var velo privado: Vector2D; var privado: Vector2D;
Al iniciar esta clase de proyectil, inicializaremos las variables mencionadas y dibujaremos su representación gráfica..
función pública Projectile () // draw graphics this.draw (); // init todas las cantidades vectoriales desplazan = nuevo Vector2D (this.x, this.y); velo = nuevo Vector2D (0, 0); acc = nuevo Vector2D (0, 0); función protegida draw (): void // dibujando la punta de flecha var height: Number = 30; ancho var: Número = 60; graphics.beginFill (0x0000FF); graphics.moveTo (0, 0); graphics.lineTo (ancho / -3, altura / -2); graphics.lineTo (ancho / 2, 0); graphics.lineTo (ancho / -3, altura / 2); graphics.lineTo (0, 0); graphics.endFill ();
Los siguientes son los accesores de nuestras variables privadas. - desplazar
, velo
, acc
- en la clase de proyectil.
función pública setDisp (mag: Número, ángulo: Número): void displace.redefine (mag, angle); función pública getDisp (): Vector2D return desplazar; función pública setVelo (mag: Number, angle: Number): void velo.redefine (mag, angle); función pública getVelo (): Vector2D return velo; función pública setAcc (mag: Number, angle: Number): void acc.redefine (mag, angle); función pública getAcc (): Vector2D return acc
Al actualizar cada fotograma, necesitamos actualizar la velocidad (utilizando la aceleración) y actualizar el desplazamiento (utilizando dicha velocidad). Esto se puede lograr utilizando las siguientes funciones. Para una explicación detallada sobre la adición de Vector, visite este gran post de Daniel Sidhon.
public function applyVelo (): void this.displace = this.displace.add (velo); public function applyAcc (): void this.velo = this.velo.add (acc); // actualizar la posición del sprite por desplazamiento. función pública animate (): void this.x = this.displace.x; this.y = this.displace.y;
También necesitaremos actualizar la orientación del Sprite. Esto se puede lograr a través de la rotación
propiedad de Sprite.
función pública orientar (): void this.rotation = Math2.degreeOf (velo.getAngle ());
También he implementado un Matemáticas2
clase estática, en la que he escrito una función para convertir fácilmente hacia adelante y hacia atrás desde las unidades de grados y radianes del ángulo.
función estática pública radianOf (deg: Number): Number return deg / 180 * Math.PI; grado de función estática públicaOf (rad: Número): Número return rad / Math.PI * 180;
Ahora que hemos establecido nuestra clase de Proyectil y Matemáticas2, podemos comenzar a codificar nuestra clase Principal. También necesitaremos una clase Vector2D aunque no se incluye una explicación completa debido al artículo mencionado anteriormente sobre Vectores por Daniel Sidhon. Asumo que los lectores entienden la clase Vector2D después de leerla. Sin embargo, si se necesitan aclaraciones, indíqueme sus consultas.
En primer lugar, necesitamos conocer las variables privadas de esta clase..
var var privado: proyectil; // keypress flags private var UP: Boolean = false; var privado ABAJO: Booleano = falso; var privado IZQUIERDA: Booleano = falso; var privado DERECHA: Booleano = falso;
Tras la inicialización de Main, función en eso
se pondrá en marcha. Esta función creará un nuevo proyectil y establecerá su velocidad inicial. Luego, se asignarán oyentes a los eventos..
función privada init (e: Event = null): void removeEventListener (Event.ADDED_TO_STAGE, init); // punto de entrada b1 = nuevo proyectil (); stage.addChild (b1); // ajuste de la velocidad inicial b1.setVelo (5, Math2.radianOf (30)); // configurando escuchas de eventos b1.addEventListener (Event.ENTER_FRAME, proj_enterFrame); stage.addEventListener (KeyboardEvent.KEY_DOWN, handle_keyDown); stage.addEventListener (KeyboardEvent.KEY_UP, handle_keyUp);
He definido el control del usuario como pulsaciones de las teclas de flecha Arriba, Izquierda, Abajo e Izquierda. Al presionar y soltar esas teclas, las variables de marca de Main (Paso 11) se volverán verdaderas y falsas. Sobre la base de estas banderas, las cantidades de vectores se manipularán en cada fotograma. Tenga en cuenta que también he dividido los controles en manipuladores de eje horizontal y vertical.
función privada handle_keyDown (e: KeyboardEvent): void if (e.keyCode == Keyboard.UP) UP = true; else if (e.keyCode == Keyboard.DOWN) DOWN = true; if (e.keyCode == Keyboard.LEFT) LEFT = true; else if ((e.keyCode == Keyboard.RIGHT) RIGHT = true; private function handle_keyUp (e: KeyboardEvent): void if (e.keyCode == Keyboard.UP) UP = false; else if (e.keyCode == Keyboard.DOWN) DOWN = falso; if (e.keyCode == Keyboard.LEFT) LEFT = false; else if ((e.keyCode == Keyboard.RIGHT) RIGHT = false;
Al actualizar cada cuadro se ejecutará el siguiente código. Es largo, pero no te preocupes; solo sigue leyendo.
función privada proj_enterFrame (e: Evento): void // define acceleration var accMag: Number = 0.1; if (UP) b1.setAcc (accMag, Math2.radianOf (-90)); b1.applyAcc (); else if (DOWN) b1.setAcc (accMag, Math2.radianOf (90)); b1.applyAcc (); if (IZQUIERDA) b1.setAcc (accMag, Math2.radianOf (180)); b1.applyAcc (); else if (RIGHT) b1.setAcc (accMag, Math2.radianOf (0)); b1.applyAcc (); // desacelerar cuando se presiona nothng para simular la fricción. if (ARRIBA + ABAJO + IZQUIERDA + DERECHA == 0) var currentVeloMag: Number = b1.getVelo (). getMagnitude (); var currentVeloAng: Number = b1.getVelo (). getAngle (); if (currentVeloMag> 1) b1.setAcc (accMag * -1, currentVeloAng); b1.applyAcc (); b1.applyVelo (); // restringiendo el sprite a los bordes de la etapa b1.getDisp (). x = Math2.implementBound (0, stage.stageWidth, b1.getDisp (). x); b1.getDisp (). y = Math2.implementBound (0, stage.stageHeight, b1.getDisp (). y); b1.animate (); b1.orient ();
La actualización de la moción se debe hacer en el siguiente orden:
He resaltado los códigos para facilitar la identificación de estos pasos..
función privada proj_enterFrame (e: Evento): void // define acceleration var accMag: Number = 0.1; if (UP) b1.setAcc (accMag, Math2.radianOf (-90)); b1.applyAcc (); else if (DOWN) b1.setAcc (accMag, Math2.radianOf (90)); b1.applyAcc (); if (IZQUIERDA) b1.setAcc (accMag, Math2.radianOf (180)); b1.applyAcc (); else if (RIGHT) b1.setAcc (accMag, Math2.radianOf (0)); b1.applyAcc (); // desacelerar ya que no se presiona nada para simular la fricción. if (ARRIBA + ABAJO + IZQUIERDA + DERECHA == 0) var currentVeloMag: Number = b1.getVelo (). getMagnitude (); var currentVeloAng: Number = b1.getVelo (). getAngle (); if (currentVeloMag> 1) b1.setAcc (accMag * -1, currentVeloAng); b1.applyAcc (); b1.applyVelo (); // restringiendo el sprite a los bordes del escenario b1.getDisp (). x = Math2.implementBound (0, stage.stageWidth, b1.getDisp (). x); b1.getDisp (). y = Math2.implementBound (0, stage.stageHeight, b1.getDisp (). y); b1.animate (); b1.orient ();
Puede encontrar que hay otras funciones entre estos códigos resaltados. ¿Qué son? Una es aplicar otro vector para ralentizar nuestro proyectil, ya que el usuario no presiona ninguna tecla. Esto se aplica antes de añadir velocidad a nuestro desplazamiento..
// desacelerar a medida que se pulsa nothng para simular la fricción. if (ARRIBA + ABAJO + IZQUIERDA + DERECHA == 0) var currentVeloMag: Number = b1.getVelo (). getMagnitude (); var currentVeloAng: Number = b1.getVelo (). getAngle (); if (currentVeloMag> 1) b1.setAcc (accMag * -1, currentVeloAng); b1.applyAcc ();
El siguiente es restringir nuestro proyectil para que permanezca siempre en el escenario, de lo contrario saldrá de la pantalla. Otra vez, implementarBound
es una función que he incluido en la clase estática Math2. Dado un límite superior, un límite inferior y un valor aleatorio, implementarBound
devolverá un valor que está dentro de los límites.
Después de aplicar estas restricciones a nuestro desplazamiento (y solo después de eso), actualizamos la posición del Sprite con este valor de desplazamiento.
// restringiendo el sprite a los bordes del escenario b1.getDisp (). x = Math2.implementBound (0, stage.stageWidth, b1.getDisp (). x); b1.getDisp (). y = Math2.implementBound (0, stage.stageHeight, b1.getDisp (). y);
Antes de dejar este sprite tal como está, deberíamos orientarlo de modo que siempre apunte a la posición que está encabezando usando la función orientar
.
Ahora todo está listo para ir. A medida que inicie esta pieza presionando Ctrl + Intro, verá una flecha que disminuye gradualmente a medida que avanza en diagonal hacia abajo en la pantalla. Presione las cuatro teclas de dirección para mover la flecha. No te preocupes por perder tu flecha; se mantendrá dentro de su vista.
Este artículo debería familiarizarte con el uso de vectores para animar el movimiento. Una vez que haya entendido la cinemática, continúe leyendo mi publicación sobre dinámica. Déjame saber como va. Terima Kasih.