En la Parte 1 de la Fruit Ninja tutorial empezamos a crear un juego Fruit Ninja. En nuestro juego ya tenemos frutas y bombas, que podemos cortar. Si se corta una fruta, a aumentar su puntuación, que se muestra en la pantalla. De lo contrario, si se corta una bomba, se pierde. En este tutorial vamos a los contenidos de nuestro juego siguiente, por lo que es más divertido jugar:


  • jugador vive, por lo que el jugador tiene un número de bombas que puede cortar antes de perder
  • Un juego sobre la pantalla, que mostrará la puntuación actual y la puntuación más alta hasta el momento (se guardará la puntuación más alta)
  • Los efectos de partículas cuando el jugador de corte algo, por lo que es visiblemente más atractiva
  • Una fruta especial, que se detiene cuando la corte por primera vez, que le permite hacer más recortes en una fila

    Para leer este tutorial, es importante que usted está familiarizado con los conceptos siguientes:


    • Javascript y conceptos orientados a objetos.
    • conceptos básicos Phaser, tales como: estados, sprites, los grupos y la física de arcade

      Tabla de contenidos

      Aprender Phaser mediante la construcción de 15 juegos

      Si usted quiere dominar Phaser y aprender cómo publicar juegos Phaser como juegos nativas para iOS y Android se sienten libres para comprobar Zenva En línea En este supuesto The Complete el juego para móvil Curso de Desarrollo – Construir 15 juegos.

      Activos de derechos de autor

      El activo bomba usada en este tutorial fue hecho por Alucard bajo Creative Commons License (http://opengameart.org/content/bomb-2d), que permite el uso comercial con atribución.

      archivos de código fuente

      Puede descargar los archivos de código fuente tutorial aquí.

      Juego Unidos

      utilizará los siguientes estados para ejecutar nuestro juego:


      • Estado de arranque: Carga un archivo JSON con la información de nivel y comienza la carga del Estado
      • Cargando Estado: carga todos los recursos del juego, e inicia el Nivel Estado
      • Nivel Estado: crea los grupos de juego y casas prefabricadas

        El código para BootState y carga es exactamente el mismo desde el último tutorial, así que voy a omitirlos.

        Sin embargo, el LevelState, tiene algunos cambios que eran necesarios para permitir que el nuevo contenido. Por lo tanto, voy a mostrar esos cambios cuando sean necesarios.

        jugador vive

        Para hacer funcionar el juego con la vida de jugador, que se cree primero una Vidas prefabricadas como se muestra a continuación. La vida prefabricada tendrá la textura de vida activo, pero será invisible. De esta manera, podemos utilizarlo para crear nuevos sprites con la misma textura. Esto se hace en el constructor, en el que iterar a través de cada vida y crear un nuevo sprite Phaser. La posición de este nuevo sprite está dada por la Lives posición prefabricada más una separación, mientras que la textura es la misma que Lives prefabricadas. Todos esos sprites se almacenan en una matriz, por lo que podemos manipularlos más adelante en el método de “matriz”.
        var Fruit Ninja = Fruit Ninja || {}; FruitNinja.Lives = función (game_state, nombre, posición, propiedades) { «utilizar estricta»; live_index var, la vida; FruitNinja.Prefab.call (esto, game_state, nombre, posición, propiedades); = This.visible FALSE; this.lives = properties.lives; this.lives_sprites = []; // crear un sprite para cada vida por (live_index = 0; live_index el método de “matriz” se llamará cuando el pl Ayer corta una bomba. Se disminuirá el número de vidas, matar a la última vida en la matriz de vidas y comprobar el jugador restante número de vidas. Si no hay más vidas, se acabó el juego.

        Por último, tenemos que cambiar el método de “corte” en el prefabricada bomba llamar a este nuevo método “die” (recordemos que se llama “game_over” antes).
        FruitNinja.Bomb.prototype.cut = function () { «utilizar estricta»; FruitNinja.Cuttable.prototype.cut.call (this); // si una bomba es de corte, el jugador pierde una vida this.game_state.prefabs.lives.die (); this.kill ();}; 1234567FruitNinja.Bomb.prototype.cut = function () { «use strict»; FruitNinja.Cuttable.prototype.cut.call (this); // si una bomba es de corte, el jugador pierde una lifethis.game_state.prefabs.lives.die (); this.kill ();};.

        puede que ya trata de jugar con las vidas jugador y ver si está funcionando

        vidas

        Juego sobre la pantalla

        Ahora que ya tenemos vidas jugador, sería interesante mostrar un juego sobre la pantalla cuando el jugador pierde en realidad, en lugar de reiniciar el juego. Para hacerlo más sencillo, nuestro juego sobre la pantalla será sólo un panel que se proyectará sobre el juego, con un juego sobre el mensaje, la puntuación actual y la puntuación más alta hasta el momento. Vamos a crear un GameOverPanel prefabricada para que, como se muestra a continuación. En primer lugar, vamos a bajar el alfa de nuestro panel, por lo que el jugador puede ver el juego detrás de él. A continuación, se iniciará una animación de interpolación para mostrarlo. La idea es que el panel vendrá de la parte inferior de la pantalla y, cuando llega a la cima, se mostrará el juego sobre el mensaje, una llamada al método “show_game_over”.
        var Fruit Ninja = Fruit Ninja || {}; FruitNinja.GameOverPanel = function (game_state, nombre, posición, propiedades) { «utilizar estricta»; movement_animation var; FruitNinja.Prefab.call (esto, game_state, nombre, posición, propiedades); this.text_style = properties.text_style; this.alpha = 0,5; // crear una animación de interpolación para mostrar el juego sobre el panel movement_animation = this.game_state.game.add.tween (this); movement_animation.to ({y: 0}, properties.animation_time); movement_animation.onComplete.add (this.show_game_over, este); movement_animation.start ();}; FruitNinja.GameOverPanel.prototype = Object.create (FruitNinja.Prefab.prototype); FruitNinja.GameOverPanel.prototype.constructor = FruitNinja.GameOverPanel; FruitNinja.GameOverPanel.prototype.show_game_over = function () { » utilizar estricta «; var game_over_text, current_score_text, highest_score_text; // juego AÑADIR sobre game_over_text text = this.game_state.game.add.text (this.game_state.game.world.width / 2, this.game_state.game.world.height * 0.4, «Game Over», this.text_style .juego terminado); game_over_text.anchor.setTo (0,5); this.game_state.groups.hud.add (game_over_text); // añadir texto current_score_text puntuación actual = this.game_state.game.add.text (this.game_state.game.world.width / 2, this.game_state.game.world.height * 0.5, «Puntuación:» + this.game_state .score, this.text_style.current_score); current_score_text.anchor.setTo (0,5); this.game_state.groups.hud.add (current_score_text); // añadir más alta highest_score_text texto puntuación = this.game_state.game.add.text (this.game_state.game.world.width / 2, this.game_state.game.world.height * 0.6 «la puntuación más alta:» + localStorage. highest_score, this.text_style.highest_score); highest_score_text.anchor.setTo (0,5); this.game_state.groups.hud.add (highest_score_text); // añadir evento a nivel de reinicio this.inputEnabled = true; this.events.onInputDown.add (this.game_state.restart_level, this.game_state);}; 123456789101112131415161718192021222324252627282930313233343536373839404142varFruitNinja = Fruit Ninja || {}; FruitNinja.GameOverPanel = function (game_state, nombre, posición, propiedades) { «utilizar estricta»; varmovement_animation ; FruitNinja.Prefab.call (esto, game_state, nombre, posición, propiedades); this.text_style = properties.text_style; this.alpha = 0,5; // crear una animación de interpolación para mostrar el juego sobre panelmovement_animation = this.game_state.game .add.tween (this); movement_animation.to ({y: 0}, properties.animation_time); movement_animation.onComplete.add (this.show_game_over, este); movement_animation.start ();}; FruitNinja.GameOverPanel.prototype = Object.create (FruitNinja.Prefab.prototype); FruitNinja.GameOverPanel.prototype.constructor = FruitNinja.GameOverPanel; FruitNinja.GameOverPanel.prototype.show_game_over = function () { «use strict»; vargame_over_text, current_score_text, highest_score_text; // Añadir juego sobre textgame_over_text = this.game_state.game.ad D.TEXT (this.game_state.game.world.width / 2, this.game_state.game.world.height * 0.4, «juego sobre», this.text_style.game_over); game_over_text.anchor.setTo (0,5); esta .game_state.groups.hud.add (game_over_text); // añadir textcurrent_score_text puntuación actual = this.game_state.game.add.text (this.game_state.game.world.width / 2, this.game_state.game.world.height * 0.5, «Puntuación:» + this.game_state.score, this.text_style.current_score); current_score_text.anchor.setTo (0,5); this.game_state.groups.hud.add (current_score_text); // añadir puntuación más alta texthighest_score_text = this.game_state.game.add.text (this.game_state.game.world.width / 2, this.game_state.game.world.height * 0.6, «puntuación más alta:» + localStorage.highest_score, this.text_style.highest_score) ; highest_score_text.anchor.setTo (0,5); this.game_state.groups.hud.add (highest_score_text); // evento añadir a reinicio levelthis.inputEnabled = true; this.events.onInputDown.add (this.game_state.restart_level, este .game_state);};

        El método “show_game_over” añadirá tres textos Phaser en t que la pantalla de la siguiente información: 1) Juego encima mensaje; 2) puntuación actual; 3) mayor puntuación. Tenga en cuenta que cada texto tiene su propio estilo, que todos se pasaron en el constructor a través del parámetro de propiedades. Además, la posición se calcula utilizando el ancho mundo del juego y la altura, por lo que debe trabajar con diferentes tamaños de pantalla. Por último, “show_game_over” agregará un evento de entrada para reiniciar el juego cuando el jugador toca la pantalla.

        Todavía tenemos para crear esta GameOverPanel en el LevelState, y vamos a hacer que en el “game_over_method”. En primer lugar, vamos a actualizar la puntuación más alta. Para guardar los datos de su juego, puede utilizar el navegador localStorage. Los datos guardados de esta manera se mantendrá incluso cuando se vuelve a cargar el navegador (para más información: http://www.w3schools.com/html/html5_webstorage.asp). Así, en primer lugar vamos a comprobar si nuestra puntuación es superior a “localStorage.highest_score” (o si no hay una puntuación más alta aún) y si es así, actualizarlo.
        FruitNinja.LevelState.prototype.game_over = function () { «uso estricto»; var game_over_panel, game_over_position, game_over_bitmap, panel_text_style; // si la puntuación actual es superior a la puntuación más alta, que se actualizará si {localStorage.highest_score = this.score (localStorage.highest_score || this.score> localStorage.highest_score!); } // crear un mapa de bits no mostrar el juego sobre game_over_position del panel = new Phaser.Point (0, this.game.world.height); game_over_bitmap = this.add.bitmapData (this.game.world.width, this.game.world.height); game_over_bitmap.ctx.fillStyle = «# 000»; game_over_bitmap.ctx.fillRect (0, 0, this.game.world.width, this.game.world.height); panel_text_style = {game_over: {font: «32px Arial», relleno: «#FFF»}, current_score: {font: «20px Arial», relleno: «#FFF»}, highest_score: {font: «18px Arial», relleno : «#FFF»}}; // crear el juego sobre el panel game_over_panel = new FruitNinja.GameOverPanel (esto «game_over_panel», game_over_position, {textura: game_over_bitmap, grupo: «HUD», text_style: panel_text_style, animation_time: 500}); this.groups.hud.add (game_over_panel);}; 1234567891011121314151617181920FruitNinja.LevelState.prototype.game_over = function () { «use strict»; vargame_over_panel, game_over_position, game_over_bitmap, panel_text_style; // si la puntuación actual es superior a la puntuación más alta, actualizar ITIF {localStorage.highest_score = this.score;} (localStorage.highest_score || this.score> localStorage.highest_score!) // crear un mapa de bits no mostrar el juego sobre panelgame_over_position = newPhaser.Point (0, this.game.world. altura); game_over_bitmap = this.add.bitmapData (this.game.world.width, this.game.world.height); game_over_bitmap.ctx.fillStyle = «# 000»; game_over_bitmap.ctx.fillRect (0,0, este .game.world.width, this.game.world.height); panel_text_style = {game_over: {font: «32px Arial», relleno: «# FFF»}, current_score: {font: «20px Arial», relleno:» #FFF «}, highest_score: {font:» 18px Arial», relleno: «# FFF»}}; // crear el juego más panelgame_over_panel = newFruitNinja.GameOverPanel (esto «game_over_panel», game_over_position, {textura: game_over_bitmap, grupo : «HUD», text_styl e: panel_text_style, animation_time: 500}); this.groups.hud.add (game_over_panel);};

        A continuación, tenemos que crear GameOverPanel. La textura de este elemento sprite será un mapa de bits Phaser, que es un objeto Phaser con un lienzo HTML, por lo que se puede utilizar como un lienzo (para más información, consulte la documentación). Nuestra mapa de bits será del tamaño del mundo, y que cambia de color como lo haríamos con un lienzo HTML. Por último, nos fijamos el estilo de texto para cada uno de los textos GameOverPanel, y creamos.

        Ya se puede intentar jugar con el juego sobre la pantalla para ver si funciona. Intenta marcar más que antes y ver si la puntuación más alta se actualiza correctamente, incluso si vuelve a cargar el navegador.

        game_over

        Adición de un efecto de partículas

        Lo siguiente que vamos a añadir a nuestro juego es puramente visual, pero verá que añade mucho al juego. En la actualidad, cuando cortamos una fruta o una bomba, simplemente desaparece, que es un poco extraño desde el punto de vista del jugador. Ahora vamos a añadir un efecto de partículas, que funcionará como una retroalimentación visual para el jugador, así que entiende automáticamente que en realidad corte algo.

        Esto se hará cambiar el método de “corte” en Cuttable. Empezamos a crear un emisor Phaser en la posición prefabricada y establecer el activo partículas (notará he añadido un nuevo activo llamado “particle_image” en el archivo JSON nivel). A continuación tenemos que establecer el mínimo de partículas y la velocidad máxima en ambas direcciones, así como la gravedad que actúa sobre ellos. Por último, empezamos el emisor, diciéndole cuánto tiempo debe emitir y el número de partículas (para más información acerca de la clase de emisor, compruebe la documentación Phaser).
        FruitNinja.Cuttable.prototype.cut = function () { «utilizar estricta»; emisor var; // crear emisor en posición prefabricada emisor = this.game_state.game.add.emitter (this.x, this.y); emitter.makeParticles ( «particle_image»); // partículas de ajuste de la velocidad emitter.minParticleSpeed.setTo (-200, -200); emitter.maxParticleSpeed.setTo (200, 200); emitter.gravity = 0; // iniciar emisor emitter.start (verdadero, 700, null, 1000);}; 12345678910111213FruitNinja.Cuttable.prototype.cut = function () { «use strict»; varemitter; // crear emisor en prefabricada positionemitter = this.game_state. game.add.emitter (this.x, this.y); emitter.makeParticles ( «particle_image»); // set partículas speedemitter.minParticleSpeed.setTo (-200, -200); emitter.maxParticleSpeed.setTo (200,200); emitter.gravity = 0; // iniciar emitteremitter.start (true, 700, null, 1000);};

        Todos los valores I utilizan como parámetros para los métodos de emisor (tales como la velocidad, el número de partículas) se decidió experimentalmente por prueba y error. Esto se hace generalmente cuando tenemos que decidir los parámetros en un juego, lo que debe tratar algunos valores y ver cuáles se adapte a su mejor juego.

        A estas alturas, ya se puede intentar cortar algunas frutas y bombas y ver las partículas de efecto visual.

        fruta especial

        Lo último que vamos a añadir es una fruta especial. Cuando el jugador esta fruta cortada, se detendrá durante algún tiempo, por lo que el jugador puede seguir cortando y aumentar la puntuación. Para hacer eso, vamos a crear una casa prefabricada SpecialFruit como se muestra a continuación. En el constructor vamos a crear un contador de tiempo de matar, que no se inicia hasta que se corta la fruta. Luego, en el método de “corte”, aumentamos la puntuación de jugador y comprobar si el temporizador matanza no se está ejecutando. Si ese es el caso, este fue el primer corte, por lo que debemos dejar la fruta (que se realiza mediante el establecimiento de body.allowGravity a falso y haciendo que la velocidad en ambas direcciones 0) e iniciar el temporizador matanza. La próxima vez que el fruto es cortado, el temporizador de matanza ya estará en marcha, por lo que sólo aumentará la puntuación del jugador.
        var Fruit Ninja = Fruit Ninja || {}; FruitNinja.SpecialFruit = function (game_state, nombre, posición, propiedades) { «utilizar estricta»; frame_index var; FruitNinja.Cuttable.call (esto, game_state, nombre, posición, propiedades); this.body.setSize (20, 20); // crear un temporizador con autoDestroy = falso, por lo que no se mató this.kill_timer = this.game_state.game.time.create (falso);}; FruitNinja.SpecialFruit.prototype = Object.create (FruitNinja.Cuttable. prototipo); FruitNinja.SpecialFruit.prototype.constructor = FruitNinja.SpecialFruit; FruitNinja.SpecialFruit.prototype.kill = function () { «utilizar estricta»; Phaser.Sprite.prototype.kill.call (this); // preparar la fruta para que pueda ser reutilizado this.body.allowGravity = true; this.kill_timer.stop ();}; FruitNinja.SpecialFruit.prototype.cut = function () { «utilizar estricta»; FruitNinja.Cuttable.prototype.cut.call (this); // si un fruto, es cortado, incremento puntuación this.game_state.score + = 1; // si es el primer corte, se detiene la fruta e iniciar el temporizador para matarlo si {this.body.allowGravity = false (this.kill_timer.running!); this.body.velocity.y = 0; this.body.velocity.x = 0; this.kill_timer.add (Phaser.Timer.SECOND * 3, this.kill, este); this.kill_timer.start (); }}; 1234567891011121314151617181920212223242526272829303132333435363738varFruitNinja = Fruit Ninja || {}; FruitNinja.SpecialFruit = function (game_state, nombre, posición, propiedades) { «utilizar estricta»; varframe_index; FruitNinja.Cuttable.call (esto, game_state, nombre, posición, propiedades); this.body.setSize (20,20); // crear un temporizador con autoDestroy = falso, por lo que no será killedthis.kill_timer = this.game_state.game.time.create (falso);}; FruitNinja.SpecialFruit. prototipo = Object.create (FruitNinja.Cuttable.prototype); FruitNinja.SpecialFruit.prototype.constructor = FruitNinja.SpecialFruit; FruitNinja.SpecialFruit.prototype.kill = function () { «uso estricto»; Phaser.Sprite.prototype.kill. llamada (this); // preparar la fruta así que puede ser reusedthis.body.allowGravity = true; this.kill_timer.stop ();}; FruitNinja.SpecialFruit.prototype.cut = function () { «utilizar estricta»; Fruit Ninja .Cuttable.prototype.cut.call (this); // si un fruto, es cortado, incremento scorethis.game_state.score + = 1; // si es el primer corte, se detiene la fruta e iniciar el temporizador para matar ITIF (! This.kill_timer.running) {this.body.allowGravity = false; this.body.velocity.y = 0; this.body.velocity.x = 0; this.kill_timer.add (Phaser.Timer.SECOND * 3 , this.kill, this); this.kill_timer.start ();}};

        Hay cosas importantes para notificación aquí, sin embargo. Cuando la fruta se mató, esperamos que el objeto a ser reutilizado para la próxima fruta, porque estamos manteniéndola en un charco de objetos y no queremos crear un nuevo objeto. Para permitir esto, tenemos que volver body.allowGravity conjunto en true y detener el temporizador en el método de “matar”, por lo que todavía va a trabajar cuando se reutiliza. Además, cuando creamos el temporizador en el constructor, hemos creado la falsa parámetro autoDestroy, de lo contrario el temporizador sería destruida cuando no había más eventos.

        Ahora que tenemos nuestro prefabricada especial de frutas, tenemos que crear un desovador por ello. Por eso, vamos a crear un SpecialFruitSpawner que sobrescribirá el método “create_object” para devolver un SpecialFruit. Para el activo que acabo de utilizar una fruta diferente de nuestra frutos spritesheet. Aviso cómo era fácil de añadir un nuevo tipo de fruta ya que tenemos nuestras casas prefabricadas genéricos Cuttable y reproductores. Si quisiéramos añadir otro tipo de fruta (o bomba), podríamos seguir el mismo proceso, overwritting sólo los métodos que son diferentes de las clases originales Cuttable y reproductores. Esto hace que sea mucho más fácil de agregar contenido a nuestro juego.
        var Fruit Ninja = Fruit Ninja || {}; FruitNinja.SpecialFruitSpawner = function (game_state, nombre, posición, propiedades) { «utilizar estricta»; FruitNinja.Spawner.call (esto, game_state, nombre, posición, propiedades); this.frames = properties.frames;}; FruitNinja.SpecialFruitSpawner.prototype = Object.create (FruitNinja.Spawner.prototype); FruitNinja.SpecialFruitSpawner.prototype.constructor = FruitNinja.SpecialFruitSpawner; FruitNinja.SpecialFruitSpawner.prototype.create_object = función (nombre , posición, velocidad) { «utilizar estricta»; // volver nueva fruta con retorno marco aleatorio nuevo FruitNinja.SpecialFruit (this.game_state, nombre, posición, {textura: «fruits_spritesheet», grupo: «special_fruits», marco: 15, velocidad: velocidad});}; 1234567891011121314151617varFruitNinja = Fruit Ninja || {}; FruitNinja.SpecialFruitSpawner = function (game_state, nombre, posición, propiedades) { «utilizar estricta»; FruitNinja.Spawner.call (esto, game_state, nombre, posición, propiedades); this.frames = properties.frames; }; FruitNinja.SpecialFruitSpawner.prototype = Object.create (FruitNinja.Spawner.prototype); FruitNinja.SpecialFruitSpawner.prototype.constructor = FruitNinja.SpecialFruitSpawner; FruitNinja.SpecialFruitSpawner.prototype.create_object = función (nombre, posición, velocidad) { «uso estricta «; // devolver nueva fruta con al azar framereturnnewFruitNinja.SpecialFruit (this.game_state, nombre, posición, {textura:» fruits_spritesheet», grupo: «special_fruits», marco: 15, velocidad: velocidad});};

        Por último, nuestro juego se hace y se puede intentar cortar algunas frutas especiales para vencer a su puntuación más alta.

        special_fruit

        Acabado del juego

        Con esto, terminamos nuestro juego. En el siguiente tutorial vamos a añadir una pantalla de título y un nuevo modo de juego!

        Mensajes relacionados
        El juego completo curso de desarrollo móvil - Platinum Edition

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *