Estoy seguro de que Stage3D no es ajeno a la mayoría de los lectores; es la nueva API que da a los programadores de AS3 acceso a la GPU. Sin embargo, la codificación contra los códigos de operación en Stage3D puede no ser la opción preferida de todos, por lo que es una suerte que haya un atajo: Starling, una biblioteca desarrollada para resumir esta programación de bajo nivel para que sea mucho más fácil. Y junto con Starling viene su extensión de efectos de partículas. En este tutorial, veremos los sistemas de partículas de este marco y veremos sus aplicaciones aplicadas a un juego de disparos..
Omita este paso si ha estado trabajando con FlashDevelop durante algún tiempo. Para los principiantes, aquí se explica cómo instalar un paquete de biblioteca: en este caso, Starling y su extensión de partículas. Tenga en cuenta que estos dos elementos no vienen en un paquete, por lo que tendremos que descargarlos por separado..
Primero, descargue el framework Starling y su extensión de partículas desde sus repositorios. Descomprimir después de la descarga exitosa. Escanee el primer directorio descomprimido para src
Carpeta y pegue la biblioteca de Starling Framework, resaltada en la siguiente imagen, en la carpeta de origen del proyecto.
Escanee la segunda carpeta para la extensión de partículas y combínelas juntas. Puede tirar de la carpeta resaltada a continuación Estornino
carpeta. La imagen de abajo es el resultado final al que debes llegar..
Para obtener más información sobre FlashDevelop y el uso de bibliotecas externas, consulte estos tutoriales:
Si aún no te han presentado Starling y su extensión de partículas, te recomiendo una visita a los tutoriales en video de Lee Brimelow sobre Starling y efectos de partículas, y al tutorial de Matthew Chung sobre cómo manejar los estados de animación con Starling..
Vamos a simplemente pasar por lo básico en dos pasos aquí. Si ya estás familiarizado con Starling y su extensión de partículas, siéntete libre de saltar al Paso 4.
Puede ver en la segunda imagen del paso anterior (la parte inferior) que se están creando dos clases: Main.as
y Testing.as
. El primero actúa como un lanzador para este último. Entonces, la mayoría de nuestro código Starling vive en Testing.as
. He resaltado el código importante en Main.as
aquí:
función privada init (e: Event = null): void removeEventListener (Event.ADDED_TO_STAGE, init); // punto de entrada var myStarling: Starling = new Starling (Testing, stage); myStarling.simulateMultitouch = true; myStarling.start (); // iniciar Starling en el escenario // permitir que ocurran eventos con el mouse / toque en la llave giratoria de Starling // ¡y arrancar el motor!
... y Testing.as
debería verse así:
la prueba de clase pública extiende Sprite prueba de función pública () addEventListener (Event.ADDED_TO_STAGE, init); función privada init (e: Event): void removeEventListener (Event.ADDED_TO_STAGE, init); // el código va aquí. stage.color = 0; // cambiar el color del escenario a negro // Dibujar un pequeño quad en el escenario, // solo para asegurarse de que todo esté en su lugar // Note que la esquina superior izquierda del sprite está alineada con la mitad del escenario var q: Quad = new Quad (30, 30); addChild (q); q.color = 0xEEEEEE; q.x = stage.stageWidth >> 1; q.y = stage.stageHeight >> 1;
Y si todo está configurado correctamente, debe llegar al resultado como se muestra a continuación. Nada mucho, solo un sprite en el escenario..
Nota: Testing.as
está extendiendo Sprite desde Starling.display.Sprite
, no flash.display.Sprite
. Las clases tienen el mismo nombre, pero no son las mismas..
La extensión de partículas de Starling contiene tres clases importantes. Sus funcionalidades están tabuladas a continuación..
Nombre de la clase | Funcionalidad |
Partícula.as | Una sola partícula con atributos únicos.. |
ParticleSystem.as | Controla el flujo de partículas: generación, animación y reciclaje.. |
ParticleDesignerPS.as | Una extensión de ParticleSystem.as para permitir una fácil manipulación del sistema de partículas. |
Vamos a crear una instancia de ParticleDesignerPS.as
. Esto requiere ingresar los siguientes argumentos en el constructor de la clase:
No te preocupes, onebyonedesign.com te ayudará con esto. Visite la página del diseñador de partículas y ajuste todos estos valores de iniciación al contenido de su corazón. Luego exporta todos los datos a formato ZIP. Este archivo ZIP contendrá el archivo XML y la imagen del efecto de partículas que acaba de diseñar a través de su página web!
Descomprima y extraiga todo esto en su carpeta de origen en FlashDevelop. Ver los elementos resaltados en la imagen de abajo..
Genere declaraciones de importación para obtener estos dos elementos en su Pruebas
clase. También necesitarás reescribir el en eso
método en Pruebas
. Están todos abajo.
[Embed (source = "particle.pex", mimeType = "application / octet-stream")] private var InitValues: Class [Embed (source = "texture.png")] private var Sample: Class
función privada init (e: Event): void removeEventListener (Event.ADDED_TO_STAGE, init); // el código va aquí. stage.color = 0; // cambiar el color del escenario a negro var flow1: ParticleDesignerPS = new ParticleDesignerPS (XML (new InitValues ()), Texture.fromBitmap (new Sample ())); addChild (flow1); flow1.emitterX = stage.stageWidth >> 1; flow1.emitterY = stage.stageHeight >> 1; flow1.start (); Starling.juggler.add (flow1);
Aquí está el resultado al que debe llegar. Bastante simple, cierto?
Nuestro siguiente paso es permitir la interacción con el sistema de partículas (ese pequeño fuego) en tiempo de ejecución. Usaremos el ratón para controlar las propiedades del fuego. Sin embargo, antes de hacerlo, me gustaría desviarme un poco para informarles sobre el concepto de sistemas de partículas..
Las partículas son solo sprites que se emiten desde una coordenada. Después del nacimiento, se animarán en un patrón determinado. Este patrón puede ser único para cada partícula o común a todas las partículas. Pero puede estar seguro, sus propiedades físicas cambiarán con el tiempo. Por ejemplo:
Además, su vida en el escenario se determina al nacer. Si se permite que cada partícula viva para siempre en el escenario, tendremos una superpoblación y el rendimiento de la aplicación sufrirá debido a la gran cantidad de activos gráficos que manejar. En algún momento, la partícula muere, pero no se despega del escenario. En su lugar, se recicla, al reubicarse en una coordenada de nacimiento y asumir el papel de una nueva partícula. Es una nueva partícula porque se definirá un nuevo conjunto de propiedades antes de que comience la animación y continúe otro ciclo..
(Esto es agrupación de objetos, y puede ver cómo aplicarlo a sus propios proyectos que no son de Starling Flash aquí.
Bien, entonces, ¿cómo se relaciona esto con nuestro fuego? Bueno, podemos usar funciones de aceleración para animar las propiedades de este incendio a lo largo del tiempo. Dentro del marco de Starling., ParticleDesignerPS
Se posiciona al final de esta jerarquía:
ParticleDesignerPS
> Sístema de partículas
> DisplayObject
> EventDispatcher
> Objeto
Para lograr un equilibrio, solo rastrearemos las propiedades heredadas de Sístema de partículas
. Echemos un vistazo a estos el siguiente paso ...
Sístema de partículas
y ParticleDesignerPS
A continuación se presentan las propiedades de Sístema de partículas
.
Propiedad | Descripción |
capacidad | Máximo de partículas que el sistema puede transportar en cualquier momento. Aumenta en pasos de 500 una vez que el número de partículas excede su capacidad actual. Solo lectura. |
NumParticles | Número de partículas en el sistema en un momento dado. Solo lectura. |
tasa de emisión | Número de partículas generadas desde el nacimiento coordinadas por segundo. |
emitterX , emisor | Punto de control del contenedor en el que viven todas las partículas.. |
| Definición de Context3DBlendFactor para origen y destino. Destino se refiere al color de píxel del último renderizado y la fuente se refiere al nuevo color de píxel para dibujar en el destino. |
textura | Imagen actual muestreada como textura de partículas. Solo lectura. |
Esos de ParticleDesignerPS
Se tabulan en la siguiente tabla. La mayoría de estas propiedades se pueden ajustar según su estado inicial y final. Por ejemplo, todas las partículas generadas se iniciarán con un tamaño de 1.0 y terminarán en 0.1. Sin embargo, el flujo de partículas será aburrido si todas las partículas se inician y terminan en estados similares, por lo que ParticleDesignerPS
provisiones para la varianza del valor inicial, y algunas veces la varianza en el valor de terminación también.
Citando su ejemplo, si damos una variación de 0.2 en el tamaño inicial de la partícula, las partículas consecutivas nacidas o recicladas en el sistema iniciarán su tamaño en algún lugar entre 0.8 y 1.2 y terminarán en 0.1.
Propiedad | Descripción |
emitterXVariance , EmarciarVarianza | Variación de la coordenada de nacimiento.. |
tamaño de inicio , startSizeVariance | Tamaño inicial y varianza |
endSize , endSizeVariance | Tamaño y varianza de la terminación. |
emitir , emitAngleVariance | Dirección inicial y varianza de la partícula. |
velocidad , SpeedVariance | Velocidad y variación inicial de la partícula. |
gravedadX | Aceleración a lo largo del eje x en la velocidad inicial de todas las partículas |
gravedad | Aceleración a lo largo del eje y en la velocidad inicial de todas las partículas |
Aceleración tangencial , tangencialAccelerationVariation | Velocidad de rotación en la velocidad de la partícula, y varianza |
Hay dos tipos de flujo de partículas previstos en ParticleDesignerPS
: gravedad y radial. En la tabla anterior se muestran propiedades que puede modificar si está utilizando el flujo por gravedad. Para la gravedad, la coordenada de nacimiento de las partículas se encuentra en emitterX
y emisor
. Para radial, la coordenada de nacimiento de las partículas se encuentra a un punto de distancia emitterX
y emisor
, y se mueven hacia eso. La siguiente tabla muestra las propiedades del flujo radial..
Propiedad | Descripción |
maxRadius , maxRadiusVariance | Radio máximo desde el centro y varianza. |
minRadio | Radio mínimo desde el centro |
rotationPerSecond , rotationPerSecondVariance | Velocidad de rotación de la velocidad de la partícula. |
color de inicio , startColorVariance | Color inicial y varianza. |
color final , endColorVariance | Color de terminación y varianza. |
Bueno, gracias por acomodar ese pequeño desvío. Ahora para algunos ActionScript. En el en eso
Método, agregaremos un oyente en el escenario para eventos táctiles..
stage.addEventListener (TouchEvent.TOUCH, pista);
Y el oyente como abajo.
pista de función privada (e: TouchEvent): void var touch: Touch = e.getTouch (stage); // mapeando en la cuadrícula de coordenadas del escenario // cuando el usuario presiona el mouse y se mueve si (touch.phase == TouchPhase.MOVED) // calcula el ángulo para apuntar el flujo de partículas a var distX: Number = touch.globalX - flow1.emitterX; var distY: Number = touch.globalY - flow1.emitterY; var angle: Number = Math.atan2 (distY, distX); t = new Tween (flow1, 1.5, Transitions.EASE_OUT_BACK); t.animate ("emitAngle", ángulo); Starling.juggler.add (t);
Para realizar la animación, un Tween
Se define la instancia. Su manipulación es similar a la de los populares. Tween
Los motores de muchas maneras. Luego, lo agregamos al malabarista de la instancia actual de Starling. Este objeto malabarista ayudará a actualizar progresivamente el Tween
instancia en el tiempo.
El resultado está abajo. Haz clic y arrastra el ratón por el escenario..
Preparemos nuestra nave ahora y pongámosle un rastro. Los activos son de opengameart.org y los he incluido en el paquete de descarga. Revisa el sitio para ver otros juegos de arte gratis..
Empezaremos de nuevo con otra clase., TestingShip.as
. Primero, importa la imagen de la nave espacial "boss1.png".
[Embed (source = "boss1.png")] private var Ship: Class
... seguido de una pequeña configuración para inicializarlo en el en eso
método:
// configura la apariencia gráfica var shipBMP: Bitmap = new Ship () como Bitmap; // importar activo en un bmp var shipTEX: Texture = Texture.fromBitmap (shipBMP); // muestra bmp como textura a la imagen var shipIMG: Image = new Image (shipTEX); // imagen creada con textura // configuración orientación y posición del barco shipIMG.rotation - = Math.PI * 0.5; // reorientar la imagen shipIMG.x - = shipIMG.width >> 1; // porque el origen de la imagen está en la esquina superior izquierda, shipIMG.y + = shipIMG.height >> 1; // reposicionamos la imagen theShip = new Sprite (); // y ponerlo en un sprite. Ahora el punto de registro está centrado. theShip.addChild (shipIMG); // sprite colocado en el escenario addChildAt (theShip, 0); // propiedades de navegación de ship loc = new Vector2D (stage.stageWidth >> 1, stage.stageHeight >> 1); lof = nuevo Vector2D (0, 10); updateShip ();
Actualiza su posición y orientación según loc
(ubicación) y Lof
(línea de visión).
función privada updateShip (): void theShip.x = loc.x; theShip.y = loc.y; theShip.rotation = lof.getAngle ();
De nuevo, haga clic y arrastre dentro del escenario para ver el efecto:
Bien, el escape de la nave está en la parte superior de la nave en sí, y la nave espacial no responde al evento del mouse. Vamos a arreglar eso ahora. Sólo compensar el emitterX
y emisor
del flujo de partículas a cierta distancia de la nave espacial y actualizar la rotación de la nave espacial utilizando Lof
.
(Tenga en cuenta que Lof
Se actualiza en eventos del mouse. Verás el guión en el siguiente paso.
función privada updateShip (): void theShip.x = loc.x; theShip.y = loc.y; theShip.rotation = lof.getAngle (); // actualizar el desplazamiento de partículas de desplazamiento = nuevo Vector2D (60, 0); offset.setAngle (lof.getAngle ()); flow1.emitterX = loc.x - offset.x; flow1.emitterY = loc.y - offset.y;
Intentemos programar la navegación de la nave ahora, en el envío de un evento de mouse. Solo he comentado las líneas importantes:
pista de función privada (e: TouchEvent): void var touch: Touch = e.getTouch (stage); if (touch.phase == TouchPhase.MOVED) var distX: Number = touch.globalX - flow1.emitterX; var distY: Number = touch.globalY - flow1.emitterY; angle = Math.atan2 (distY, distX); t = new Tween (flow1, 1.5, Transitions.EASE_OUT_BACK); t.animate ("emitAngle", angle + Math.PI); t2 = new Tween (theShip, 1.5, Transitions.EASE_OUT); t2.moveTo (touch.globalX, touch.globalY); // mover el barco t2.onUpdate = refresh // llamar a esta función cada vez que el motor tween ejecute Starling.juggler.add (t); Starling.juggler.add (t2); // agregar al malabarista función privada refresh (): void loc.x = theShip.x; // actualizar ubicación loc.y = theShip.y; lof.setAngle (ángulo); // actualizar orientación updateShip (); // actualizar
Y aquí hay una muestra del resultado final. Arrastra el mouse por el escenario y la nave espacial irá allí..
Afinemos nuestro escape. Cuando la nave se está moviendo, el escape definitivamente soplará más fuerte, ¿verdad? Podemos intensificar el tasa de emisión
y velocidad
Al mover la nave, y bajar. tasa de emisión
cuando se detiene Aquí está el evento, resaltado:
t2 = new Tween (theShip, 1.5, Transitions.EASE_OUT); t2.moveTo (touch.globalX, touch.globalY); // mover la nave t2.onUpdate = actualizar // invocar esta función cuando el motor de interpolación ejecute t2.onStart = beginState // cuando la nave comience a moverse t2.onComplete = endState // cuando se detenga la animación de la nave
Y aquí están las llamadas a la función de esos eventos..
función privada beginState (): void flow1.emissionRate = 250 flow1.speed = 100; private function endState (): void flow1.emissionRate = 50 flow1.speed = 10;
Haga clic y arrastre de nuevo, y preste atención a la longitud del escape.
Las partículas también pueden expresar qué tan rápido se está moviendo la nave en relación con su entorno. Echa un vistazo a la salida de abajo. Haga clic y arrastre el ratón alrededor. Observe la velocidad a la que se mueven las partículas circundantes. Aumentan a medida que interactúas con la nave y se ralentiza cuando detienes la interacción. También orientan su rotación en consecuencia..
Configurar este efecto es relativamente fácil en la aplicación mostrada por onebyonedesign.com. Sin embargo, tendremos que codificar algunos ActionScript para cambiarlo en tiempo de ejecución, y esto llevará a los siguientes pasos.
El inicio de las partículas sigue un formato similar al del ejemplo anterior. Puedes elegir modificar tu efecto con la aplicación desde onebyonedesign.com e importarlo a tu escenario. Acabo de codificar directamente en ActionScript para mayor facilidad.
envr = new ParticleDesignerPS (XML (new InitValues ()), Texture.fromBitmap (new Sample ())); addChildAt (envr, 0); envr.blendFactorSource = Context3DBlendFactor.ONE envr.blendFactorDestination = Context3DBlendFactor.ONE envr.speed = 10; envr.speedVariance = 20; envr.startSize = 15; envr.startSizeVariance = 0; envr.endSize = 20; envr.endSizeVariance = 20 envr.lifespan = 5.0; envr.lifespanVariance = 4.0; envr.emissionRate = 10 envr.start (); Starling.juggler.add (envr);
También necesitaremos poner el emisor de partículas un poco más alejado del barco..
envrLoc = nuevo Vector2D (100, 0); envrLoc.setAngle (ángulo);
Y actualizar este vector en tiempo de ejecución..
// actualizar el entorno envr.gravityX = -40 * lof.x; // la partícula está acelerando en dirección opuesta envr.gravityY = -40 * lof.y; // de la línea de visión vector envr.emitterX = loc.x + envrLoc.x; envr.emitterY = loc.y + envrLoc.y;
Usted ve, el emitterXVariance
y EmarciarVarianza
Manejar los ejes por separado. Esto significa que si giramos la nave espacial, necesitamos algunos medios para determinar la longitud de la extensión a lo largo de estos dos ejes.
Ahora mira el vector para ver la línea de visión. Siempre es perpendicular a la línea de propagación (la línea oscura delgada). Podemos escalar este vector en consecuencia y mezclar su xey con los de la varianza del emisor en el punto de inicio. Revisa la demo a continuación. Haga clic y arrastre el ratón alrededor. Verás el flujo de partículas más vívidamente.
Por último, amplíe la magnitud de la dispersión y póngala un poco más adelante de la nave para que los jugadores no vean su punto de emisión..
envrLoc = nuevo Vector2D (200, 0); envrLoc.setAngle (ángulo);
// actualizar la propagación = envrLoc.clone (); spread.scale (0.5); envr.emitterXVariance = spread.y; envr.emitterYVariance = spread.x;
Finalmente a medida que la nave se acelera, vamos a aumentar la magnitud de gravedadX
y gravedad
, más el escape, en consecuencia.
if (touch.phase == TouchPhase.MOVED) var distX: Number = touch.globalX - flow1.emitterX; var distY: Number = touch.globalY - flow1.emitterY; angle = Math.atan2 (distY, distX); // animar el escape t = new Tween (flow1, 1.5, Transitions.EASE_OUT_BACK); t.animate ("emitAngle", angle + Math.PI); Starling.juggler.add (t); // controlar el flujo de escape1.speed = 350; flow1.endSize = 70; // orientar el ángulo de la nave y el paralaje lof.setAngle (ángulo); lof.setMagnitude (10); // ajustar la magnitud de la aceleración envrLoc.setAngle (ángulo); if (touch.phase == TouchPhase.ENDED) // controla el flujo de escape1.speed = 100; flow1.endSize = 10; lof.setMagnitude (5); // ajustar la magnitud de la aceleración
A medida que progreses en el juego, definitivamente recibirás golpes y sufrirás daño. Como el daño se vuelve severo, tu nave se quemará. Tal efecto se puede generar aquí; podemos hacer uso de la emisiónXVarianza
y Emisión YVarianza
Para definir el área de la quemadura. Los he resaltado en el siguiente código.
envr = new ParticleDesignerPS (XML (new InitValues ()), Texture.fromBitmap (new Sample ())); addChildAt (envr, 2); envr.blendFactorSource = Context3DBlendFactor.ONE_MINUS_SOURCE_ALPHA envr.blendFactorDestination = Context3DBlendFactor.ONE; envr.emitterXVariance = theShip.width >> 2; envr.emitterYVariance = theShip.height >> 2; envr.emitAngle = 0; envr.emitAngleVariance = Math.PI; envr.speed = 0; envr.startSize = 40; envr.startSizeVariance = 0; envr.endSize = 10; envr.endSizeVariance = 0 envr.lifespan = 5.0; envr.lifespanVariance = 3.0; envr.emissionRate = 10; envr.start (); Starling.juggler.add (envr);
La severidad del daño está indicada por el área y la intensidad de la quemadura. Aumentar y disminuir tasa de emisión
para simular esto. He agregado controles en el teclado "A" y "S" para emular esto.
función privada controlBurn (e: KeyboardEvent): void if (e.keyCode == Keyboard.A) if (envr.emissionRate < 150) envr.emissionRate += 10; if (envr.lifespan < 8) envr.lifespan += 0.5; if (e.keyCode == Keyboard.S) if(envr.emissionRate > 10) envr.emissionRate - = 10; if (envr.lifespan> 5) envr.lifespan - = 0.5;
Tenga en cuenta que si aumenta la vida útil de las partículas, el fuego parece arder más intensamente. Bueno, lleva tiempo interpolar partículas desde su tamaño inicial hasta el tamaño final, por lo que si aumenta la vida útil, es más largo pasar a la transición desde el inicio más grande al tamaño final más pequeño. A medida que más partículas grandes permanecen en el mismo lugar por más tiempo, se mezclan para dar la impresión de un fuego más intenso..
Presione la tecla "A" para ver que el fuego arda con mayor intensidad y la tecla "S" para apagarlo ligeramente. El color del escape ha sido cambiado, para diferenciarlo de la quema:
Todos los buenos juegos deben terminar en algún momento. Independientemente de quién sea eliminado, no se debe perder una buena explosión para un final. Entonces, ¿qué tal una nube de hongo nuclear? Haga clic en la demostración de abajo para ver uno.
Ahora, vamos a codificarlo.
Este flujo de partículas es un poco diferente a los que hemos visto. Anteriormente, hemos estado utilizando el flujo de partículas tipo 0 (gravedad) y este es el tipo 1 (radial). Las partículas se están moviendo hacia el medio a una velocidad constante.
Volví la varianza del ángulo de emisión al máximo para que pueda ver todas las partículas generadas formando un círculo. Luego, al animar el radio máximo y el radio mínimo, estas partículas deben vivir en el tiempo, usando una Tween
, logramos este resultado.
explosion = new ParticleDesignerPS (XML (new InitValues ()), Texture.fromBitmap (new Sample ())); addChild (explosión); explosion.emitterX = stage.stageWidth >> 1; explosion.emitterY = stage.stageHeight >> 1; explosion.emitterType = 1; explosion.emitAngle = 0; explosion.emitAngleVariance = Math.PI; explosion.maxRadius = 10; explosion.maxRadiusVariance = 0; explosion.minRadius = 0;
Aquí está el código para realizar la animación..
pista de función privada (e: TouchEvent): void var touch: Touch = e.getTouch (stage); if (touch.phase == TouchPhase.BEGAN) explosion.emitterX = touch.globalX; explosion.emitterY = touch.globalY; explosion.start (); t = new Tween (explosion, 1.0, Transitions.EASE_IN); t.animate ("maxRadius", 150); t.animate ("minRadius", 130); t.onStart = congelar t.onComplete = restablecer; Starling.juggler.add (t); función privada freeze (): void stage.removeEventListener (TouchEvent.TOUCH, track); reset de la función privada (): void stage.addEventListener (TouchEvent.TOUCH, track); explosion.stop (); explosion.maxRadius = 10; explosion.minRadius = 0;
Así que este ha sido un largo tutorial. Vamos a hacer un pequeño resumen aquí. Hemos pasado por:
Hemos cubierto un poco aquí. Sin embargo, un aspecto importante por el que no he pasado es extenderme desde Sístema de partículas
. Esto realmente te dará el poder de codificar tus propios rastros de partículas en lugar de confiar en ParticleDesignerPS
. Tendré que posponer esto a otro tutorial..
Gracias por leer y nos vemos en el siguiente tutorial. Deje comentarios sobre los errores y el uso de este motor de partículas en su proyecto si decide adoptarlo..