¿Alguna vez has querido crear un juego de plataformas, pero no te gusta escribir todo el código desde cero? Citrus Engine no elimina el código por completo, pero lo hace mucho más simple, con muchas funciones útiles de juego 2D integradas. En este tutorial, lo usaremos para construir un juego de plataforma simple.
En este tutorial usaremos un popular motor de juegos Flash, llamado Citrus, y una serie de clases de ActionScript para crear un juego de plataformas..
Abre Flash y crea un documento de 420x280px. Establecer la velocidad de fotogramas a 30 fps.
Usaremos estos grandes gráficos de píxeles de Guillaume Moreau. Puedes descargarlos desde opengameart.org.
Para el fondo, cambie el color del escenario a # 99D9EA, o use la herramienta Rectángulo (R) para dibujar un rectángulo de ese color.
Se mostrará una alerta cuando el jugador complete el nivel o muera; se mostrará un juego sobre el mensaje y la puntuación. Utilizar el Herramienta rectangular para crearlo y establecer su nombre de instancia en AlertView. marca el Exportar para ActionScript caja y darle el mismo nombre de clase.
Hay muchos otros objetos en el juego (por ejemplo: una pantalla de título, los distintos símbolos para cada sprite, el terreno). En lugar de explicar cómo crearlos aquí, le sugiero que descargue los archivos de origen y observe qué objetos hay en la Biblioteca de la FLA. Puedes usar los mismos símbolos en tu propio juego o crear otros nuevos!
Usaremos una fuente de mapa de bits en el juego; Como vamos a utilizar la fuente dinámicamente, necesitaremos incrustarla en la aplicación. Estoy usando las fuentes 04b11 y Arcade Classic.
Seleccione un campo de texto dinámico con la fuente de su preferencia y haga clic en Empotrar… botón en el Panel de propiedades.
Seleccione / agregue todos los caracteres necesarios y haga clic en DE ACUERDO.
Usaremos efectos de sonido para mejorar la sensación del juego. Los sonidos utilizados en este ejemplo se generaron utilizando as3sfxr y se incluyen en los archivos de origen.
Usaremos un motor de interpolación diferente del predeterminado incluido en Flash. Esto aumentará el rendimiento y será más fácil de usar..
Puedes descargar TweenNano desde su sitio web oficial..
Usaremos el Motor Citrus para potenciar nuestro juego..
¿Qué es el motor cítrico? Aprenda más de su sitio web:
The Citrus Engine es un motor de juegos Flash escalable de nivel profesional creado para juegos de calidad industrial. Se basa en las prácticas modernas de programación de Flash, lo que le permite centrarse en hacer que su juego sea increíble. Viene incorporado con un kit de inicio para "juegos de plataformas", que puede usar para hacer juegos de desplazamiento lateral en 2D increíbles..
Vaya a la página de descarga y obtenga los archivos necesarios. Abre Preferencias de Flash, selecciona ActionScript De la lista de la izquierda y haga clic en Configuraciones de ActionScript 3.0 ... , a continuación, agregue la ruta a las fuentes como se muestra en la imagen de arriba.
Haremos que nuestra aplicación sea interactiva utilizando una clase externa. Añada su nombre (Principal
) al Clase campo en el Publicar sección de la Propiedades Panel para asociar la FLA con la clase de documento principal..
Cree una nueva clase de ActionScript 3.0 (Cmd + N) y guárdela como Main.as en la carpeta de tu clase.
Crea tu estructura de clase básica para comenzar a escribir tu código.
package public class Main public function Main (): void // código de constructor
Main.as
los Principal
La clase preparará el Motor Citrus para manejar el primer nivel..
package import com.citrusengine.core.CitrusEngine; La clase final pública Principal extiende CitrusEngine función final pública Principal (): void super (); estado = nuevo nivel ();
Esta clase extiende la clase CitrusEngine y establece el "estado" del juego en Nivel, que es el nombre de la clase que contendrá todo el comportamiento de nuestro juego.
Nivel.as
La clase estatal es una de las clases principales de Citrus Engine, y debes extender esta clase para crear la lógica del juego de tus niveles o estados. En este ejemplo el Nivel clase se extiende Estado para crear el primer nivel del juego.
Cree una nueva clase de ActionScript 3.0 (Cmd + N) y guárdela como Nivel.as en la carpeta de tu clase.
Estas son las clases que necesitaremos importar para nuestra Nivel
clase para trabajar los importar
La directiva hace que las clases y los paquetes definidos externamente estén disponibles para su código..
importar flash.display.MovieClip; importar flash.display.Sprite; import flash.events.MouseEvent; import com.citrusengine.core.CitrusEngine; importar com.citrusengine.core.State; import com.citrusengine.physics.Box2D; import com.citrusengine.objects.platformer. *; import com.citrusengine.objects. *; import com.citrusengine.math.MathVector; import flash.events.Event; import flash.geom.Rectangle; importar flash.ui.Keyboard; import flash.events.KeyboardEvent; importar flash.text.TextField; importar flash.text.TextFormat; import com.greensock.TweenNano; import com.greensock.easing.Expo; importar flash.net.navigateToURL; importar flash.net.URLRequest; importar flash.filters.GlowFilter; importar flash.filters.BitmapFilter;
Estas son las variables que usaremos; Lea los comentarios en el código para saber más sobre ellos. (Algunos de sus nombres se explican por sí mismos, por lo que no hay comentarios).
private var levelView: LevelView = new LevelView (); // sprite de la biblioteca private var hero: Hero; corazones privados var: vector.= nuevo vector. (); private var tf: TextFormat = new TextFormat ('ArcadeClassic', 17, 0xFFFFFF, null, null, null, null, null, 'right'); private var scoreTF: TextField = new TextField (); private var gemSnd: GemSnd = new GemSnd (); // Snd = Sonido privado var goalSnd: GoalSnd = new GoalSnd (); private var hitSnd: HitSnd = new HitSnd (); private var jumpSnd: JumpSnd = new JumpSnd (); private var loseSnd: LoseSnd = new LoseSnd (); private var baddySnd: BaddySnd = new BaddySnd ();
El constructor es una función que se ejecuta cuando un objeto se crea a partir de una clase, este código es el primero en ejecutarse cuando se crea una instancia de un objeto, se carga una vez que el juego comienza si parte de la clase de documento.
Se llama a las funciones necesarias para iniciar el juego. Comprueba esas funciones en los siguientes pasos..
Función final pública Nivel (): nula // Código
Comenzaremos haciendo una pausa en el juego; esto evitará que el motor agregue los gráficos mientras el sprite de vista de nivel está en el escenario.
Función final pública Nivel (): void super (); // código de configuración predeterminado CitrusEngine.getInstance (). playing = false; // realmente pausa el juego
Esto agregará el sprite de Vista de Nivel al escenario, así como un detector de ratón para eliminarlo.
anular la función pública initialize (): void / * Level Start View * / addChild (levelView); levelView.addEventListener (MouseEvent.MOUSE_UP, startLevel);
La siguiente función se ejecuta cuando se hace clic en la Vista de nivel, y manejará la lógica para iniciar el juego.
función final privada startLevel (e: MouseEvent): void
Este código destruye la instancia de Level View.
levelView.removeEventListener (MouseEvent.MOUSE_UP, startLevel); removeChild (levelView); levelView = nulo;
Ahora desatamos el juego e iniciamos el nivel..
super.initialize (); CitrusEngine.getInstance (). Playing = true;
El siguiente código inicia el motor Box2D que maneja la física de Citrus Engine.
var box2D: Box2D = nuevo Box2D ('Box2d'); añadir (box2D); //box2D.visible = true; // descomentar para ver los gráficos de depuración de Box2D
Estas líneas crearán todo el nivel, lea el código para comprender el sistema de creación de instancias de Citrus Engine (¡que es realmente fácil!).
(Todos ver
Las propiedades son los nombres de clase de los símbolos de la biblioteca FLA: Bg
, TerrainPart1
, WaterX3
, etc.)
var leftWall: Platform = new Platform ('LeftWall', width: 1, height: 280, x: 0, y: 110); agregar (leftWall); var rightWall: Platform = new Platform ('RightWall', width: 1, height: 280, x: 726, y: 100); añadir (rightWall); var bg: CitrusSprite = nuevo CitrusSprite ('Bg', vista: Bg, x: 0, y: 20); añadir (bg); var terrain1: Platform = new Platform ('Terrain1', width: 422, height: 32, x: 211, y: 264, view: TerrainPart1); añadir (terreno1); var oneWay1: Platform = new Platform ('OneWay1', width: 92, height: 32, x: 184, y: 232, oneWay: true, view: OneWay1); agregar (oneWay1); var gema: Moneda = moneda nueva ('Gema', ancho: 11, altura: 10, x: 186, y: 136, vista: gema); añadir (gema); var agua: Sensor = nuevo Sensor ('Agua', ancho: 92, altura: 32, x: 468, y: 264, vista: WaterX3); añadir (agua); var terrain2: Platform = new Platform ('Terrain2', width: 214, height: 32, x: 621, y: 264, view: TerrainPart2); añadir (terreno2); var baddy: Baddy = new Baddy ('Baddy', x: 300, y: 200, leftBound: 250, rightBound: 350, view: Enemy); añadir (baddy); var movingPlatform: MovingPlatform = new MovingPlatform ('MP', width: 32, height: 8, x: 436, y: 232, startX: 436, startY: 232, endX: 500, endY: 232, view: PlatformClip, speed : 0.9); añadir (movingPlatform); var oneWay2: Platform = new Platform ('OneWay2', width: 127, height: 32, x: 663, y: 232, oneWay: true, view: OneWay2); agregar (oneWay2); var oneWay3: Platform = new Platform ('OneWay3', width: 64, height: 32, x: 695, y: 200, oneWay: true, view: OneWay3); agregar (oneWay3); var puerta: Sensor = nuevo Sensor ('Puerta', ancho: 20, altura: 28, x: 695, y: 202, vista: Puerta); añadir (puerta); hero = new Hero ('Hero', x: 30, y: 234, ancho: 19, altura: 26, vista: HeroClip, salto Altura: 9, maxVelocity: 2, hurtVelocityX: 2); añadir (héroe);
Como puede ver, en cada caso, crea una instancia del tipo de objeto que desea y utiliza los parámetros para especificar su posición, tamaño, gráfico o aspecto (esta es la ver parámetro) y otros elementos útiles. Luego lo agregamos a la etapa Citrus usando el añadir()
método.
Paremos aquí para hacer una prueba rápida y asegurarnos de que nuestro código de juego funciona:
Recuerde que los hitos están incluidos en los archivos de origen, por lo que si por alguna razón su archivo no imita este, mire la fuente para ver qué puede estar causando eso. (Y tenga en cuenta que algunas líneas se deben comentar, ya que algunas funciones aún no se han creado).
Citrus Engine usa señales para manejar la interacción de tipo de evento. Puedes aprender más sobre las señales en este tutorial de Activetuts +.
gem.onBeginContact.addOnce (función (e: *) gemSnd.play (); scoreTF.text = String (int (scoreTF.text) + 50);); door.onBeginContact.addOnce (levelComplete); hero.onTakeDamage.add (hurtHero); hero.onGiveDamage.addOnce (killBaddy); hero.onJump.add (function () jumpSnd.play ()); hero.onGiveDamage.addOnce (function () baddySnd.play ());
Nuestro Hero MovieClip se reproducirá de forma predeterminada a menos que lo impidamos. Este código se encarga de eso, y también aprenderá cómo acceder al MovieClip que sirve como arte para su objeto Citrus.
this.view.getArt (hero) .content.stop (); //State(Level).SpriteView.SpriteArt.MovieClip.stop gameListeners (); addIndicators ();
Este código agrega a los oyentes EnterFrame y al teclado que se utilizarán en nuestro juego. Puedes leer acerca de las funciones de controlador correspondientes en los siguientes pasos.
función final privada gameListeners (action: String = 'add'): void if (action == 'add') stage.addEventListener (Event.ENTER_FRAME, gameLogic); stage.addEventListener (KeyboardEvent.KEY_DOWN, animateWalk); stage.addEventListener (KeyboardEvent.KEY_UP, stopWalk); else stage.removeEventListener (Event.ENTER_FRAME, gameLogic); stage.removeEventListener (KeyboardEvent.KEY_DOWN, animateWalk); stage.removeEventListener (KeyboardEvent.KEY_UP, stopWalk);
Los corazones representarán la salud de nuestro héroe. El siguiente código agrega tres corazones al escenario y los almacena en un Vector para usarlos más adelante fuera de esta función.
función final privada addIndicators (): void / * Hearts * / for (var i: int = 0; i < 3; i++) var heart:Heart = new Heart(); heart.y = 5; heart.x = 5 + (i * heart.width); addChild(heart); hearts.push(heart);
El ScoreFieldField es creado por este código. Usamos filtros para agregar el trazo negro alrededor de las letras..
/ * Puntuación * / puntuaciónTF.x = 320; scoreTF.defaultTextFormat = tf; scoreTF.text = '0'; filtro var: BitmapFilter = nuevo GlowFilter (0, 1, 2, 2); var filter2: BitmapFilter = nuevo GlowFilter (0, 1, 1, 1); scoreTF.filters = [filter, filter2]; addChild (scoreTF);
Aquí configuramos la cámara, que seguirá a nuestro héroe si su posición está más allá del centro X del escenario..
función final privada gameLogic (e: Event): void / * Handle Camera * / if (hero.x> = stage.stageWidth * 0.5) view.setupCamera (hero, new MathVector (stage.stageWidth * 0.5, 234), nuevo Rectángulo (0, 0, 726, 228), nulo);
Este código verifica si nuestro héroe ha caído al agua, y si es así, reproduce el sonido de pérdida y emite una alerta.
/ * Comprueba si el héroe cayó * / if (hero.y> stage.stageHeight) loseSnd.play (); alerta ('perder');
Nuestra animación de caminar héroe comienza cuando se presionan las teclas de flecha izquierda o derecha.
función final privada animateWalk (e: KeyboardEvent): void if (e.keyCode == 37 || e.keyCode == 39) this.view.getArt (hero) .content.play ();
Cuando se sueltan las teclas se detiene la animación..
función final privada stopWalk (e: KeyboardEvent): void if (e.keyCode == 37 || e.keyCode == 39) this.view.getArt (hero) .content.gotoAndStop (1);
Paremos aquí para hacer otra prueba y comprobar que nuestro código de juego funciona:
Recuerde nuevamente que algunas líneas se han comentado ya que no todas las funciones se han creado aún..
Recuerde que los hitos están incluidos en los archivos de origen, por lo que si por alguna razón su archivo no imita este, mire el origen para ver qué podría estar causando que.
El héroe debería recibir daño si el enemigo lo toca; Las siguientes líneas eliminan un corazón y reproducen el sonido herido. Se llama alerta cuando el héroe está fuera de salud..
función final privada hurtHero (): void removeChild (hearts [hearts.length-1]); corazones.splice (corazones.longitud-1, 1); hitSnd.play (); if (hearts.length <= 0) loseSnd.play(); alert('lose');
Puedes matar a un enemigo saltando sobre él. Cuando esto sucede, la puntuación aumenta..
función final privada killBaddy (): void scoreTF.text = String (int (scoreTF.text) + 100);
El nivel termina cuando el héroe llega a la puerta. Se reproducirá un sonido y se llamará una alerta; Puedes ver el código de alerta en el siguiente paso..
nivel final de función privada Completa (e: *): void goalSnd.play (); alerta();
Esta función detendrá el juego y mostrará el mensaje por encima del juego, y también agrega un detector de mouse para reiniciar el juego cuando se hace clic..
alerta de la función final privada (gameState: String = 'win'): void gameListeners ('rmv'); CitrusEngine.getInstance (). Playing = false; this.view.getArt (hero) .content.gotoAndStop (1); alerta de var: AlertView = new AlertView (); alert.x = stage.stageWidth * 0.5; alert.y = stage.stageHeight * 0.5; alert.scoreTF.text = scoreTF.text; alert.addEventListener (MouseEvent.MOUSE_UP, reinicio); if (gameState == 'lose') alert.titleTF.text = 'Level Failed!'; addChild (alerta); TweenNano.from (alerta, 0.6, scaleX: 0.2, scaleY: 0.2, facilidad: Expo.easeOut);
Este código volverá a cargar el SWF cuando se haga clic en el mensaje sobre el juego, restaurando todos los valores iniciales y volviendo a la pantalla inicial.
reinicio privado de la función final (e: MouseEvent): void navigationToURL (nueva URLRequest (stage.loaderInfo.url), '_level0');
Ahora estamos listos para hacer una prueba final de nuestro juego y comprobar que todo funciona como se espera.
Experimenta con este potente motor de juego y crea tus propios juegos.!
Espero que te haya gustado este tutorial, gracias por leer.!