En este tutorial vamos a empezar a construir un juego Bomberman. Vamos a añadir la estructura básica en este tutorial y seguir añadiendo contenidos en los siguientes tutoriales. En este tutorial, voy a cubrir el siguiente contenido:


  • Lectura de un mapa de baldosa
  • Creación de un jugador que se mueve en cuatro direcciones y bombas de caída
  • Creación de una bomba que explota cuando sus extremos animación
  • Crear epxlosions cuando explota una bomba que mata el jugador y enemigos
  • Creación de un enemigo que camina en un eje (horizontal o vertical)

    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
    • La creación de mapas usando el editor de mapas de baldosa

      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

      Los activos utilizados en este tutorial fueron creados por Cem Kalyoncu / cemkalyoncu y Matt Hackett / richtaur y puestos a disposición por “usr_share” a través de los campos comunes creativos licencia, cosa que permite el uso comercial bajo la atribución. Puede descargarlos en http://opengameart.org/content/bomb-party-the-complete-set o descargando el código fuente.

      archivos de código fuente

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

      JSON archivo de nivel

      A pesar de que nuestro mapa es creado por baldosa, todavía podemos utilizar un archivo JSON nivel para describir los bienes que necesitamos (incluyendo el archivo de mapa), los grupos de nuestro juego y las propiedades del mapa. El archivo JSON nivel que va a utilizar se muestra a continuación. Tenga en cuenta que describimos cada activo de acuerdo con su tipo, los nombres de los grupos y la clave del mapa y baldosas.
      { «activos»: { «map_tiles»: { «type»: «imagen», «fuente»: «activos / images / bomberman_spritesheet.png»}, «player_spritesheet»: { «type»: «spritesheet», «fuente» : «assets / images / player_spritesheet.png», «frame_width»: 16, «frame_height»: 16}, «bomb_spritesheet»: { «type»: «spritesheet», «fuente»: «assets / images / bomb_spritesheet.png» «frame_width»: 16, «frame_height»: 16}, «enemy_spritesheet»: { «type»: «spritesheet», «fuente»: «assets / images / enemy_spritesheet.png», «frame_width»: 16, «frame_height» : 16}, «explosion_image»: { «type»: «imagen», «fuente»: «assets / images / explosion.png»}, «level_tilemap»: { «type»: «tilemap», «fuente»: » activos / mapas / level1_map.json «}}, «grupos»: [ «explosiones», «bombas», «enemigos», «jugadores»], «mapa»: { «clave»: «level_tilemap», «baldosas»: [ «map_tiles»]}} {123456789101112131415161718192021 «activos»: { «map_tiles»: { «type»: «imagen», «fuente»: «activos / images / bomberman_spritesheet.png»}, «player_spritesheet»: { «tipo» : «spritesheet», «fuente»: «assets / images / player_spritesheet.png», «fra me_width «: 16,» frame_height «: 16},» bomb_spritesheet «: {» type «:» spritesheet», «fuente»: «assets / images / bomb_spritesheet.png», «frame_width»: 16, «frame_height»: 16 }, «enemy_spritesheet»: { «type»: «spritesheet», «fuente»: «assets / images / enemy_spritesheet.png», «frame_width»: 16, «frame_height»: 16}, «explosion_image»: { «tipo» : «imagen», «fuente»: «assets / images / explosion.png»}, «level_tilemap»: { «type»: «tilemap», «fuente»: «activos / mapas / level1_map.json»}}» grupos «: [» explosiones», «bombas», «enemigos», «jugadores»], «mapa»: { «clave»: «level_tilemap», «baldosas»: [ «map_tiles»]}}

      Creación de la mapa

      En este tutorial voy a centrarse en la construcción del juego mediante el uso de un mapa de baldosa, y no en la creación del mapa. Por lo tanto, no dude en crear su propio mapa o utilizar el proporcionado en el código fuente. Algunos detalles son importantes debido a la forma en que vamos a leer este mapa:


      1. Para cada capa Collidable, hay que añadir una propiedad de colisión que es igual a true
      2. Para cada objeto tiene que definir correctamente su tipo (que se utiliza para crear una instancia del prefabricado correcta) y agregar al menos propiedades con su textura y el grupo
      3. El mapa debe estar guardado en formato JSON

        La siguiente imagen muestra el mapa que voy a usar:

        mapa

        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, y se inicia el siguiente estado
        • baldosa Estado: carga un archivo de mapa de azulejos

          El código BootState se muestra a continuación. Sólo es responsable de cargar el archivo de nivel JSON y llamar a la LoadingState.
          var Bomberman = Bomberman || {}; Bomberman.BootState = function () { «utilizar estricta»; Phaser.State.call (this);}; Bomberman.BootState.prototype = Object.create (Phaser.State.prototype); Bomberman.BootState.prototype.constructor = Bomberman.BootState; Bomberman.BootState.prototype.init = function ( level_file, next_state) { «utilizar estricta»; this.level_file = level_file; this.next_state = next_state;}; Bomberman.BootState.prototype.preload = function () { «utilizar estricta»; this.load.text ( «level1», this.level_file);}; Bomberman.BootState.prototype.create = function () { «utilizar estricta»; level_text var, level_data; level_text = this.game.cache.getText ( «level1»); level_data = JSON.parse (level_text); this.game.state.start ( «LoadingState», verdadero, falso, level_data, this.next_state);}; 12345678910111213141516171819202122232425262728varBomberman = Bomberman || {}; Bomberman.BootState = function () { «utilizar estricta»; Phaser.State. llamada (esto);}; Bomberman.BootState.prototype = Object.create (Phaser.State.prototype); Bomberman.BootState.prototype.constructor = Bomberman.BootState; Bomberman.BootState.prototype.init = function (level_file, next_state) { «utilizar estricta»; this.level_file = level_file; this.next_state = next_state;}; Bomberman.BootState.prototype.preload = function () { «utilizar estricta»; this.load.text ( «level1», this.level_file );}; Bomberman.BootState.prototype.create = function () { «utilizar estricta»; varlevel_text, level_data; level_text = this.game.cache.getText ( «level1»); level_data = JSON.parse (level_text); esta .game.state.start ( «LoadingState», verdadero, falso, level_data, this.next_state);};

          El LoadingState es responsable de cargar todos los activos que serán utilizados en este nivel, como se muestra a continuación. Como se puede observar, el método de “precarga” iterar a través de todos los activos se define en el archivo de nivel JSON y cargarlo llamando al método correspondiente. Después de todos los activos se cargan, se llama al siguiente estado, que será TiledState.
          var Bomberman = Bomberman || {}; Bomberman.LoadingState = function () { «utilizar estricta»; Phaser.State.call (this);}; Bomberman.LoadingState.prototype = Object.create (Phaser.State.prototype); Bomberman.LoadingState.prototype.constructor = Bomberman.LoadingState; Bomberman.LoadingState.prototype.init = function ( level_data, next_state) { «utilizar estricta»; this.level_data = level_data; this.next_state = next_state;}; Bomberman.LoadingState.prototype.preload = function () { «utilizar estricta»; var activos, asset_loader, asset_key, activo; = activos this.level_data.assets; para (asset_key en activos) {// activos de carga de acuerdo con la clave activo si (assets.hasOwnProperty (asset_key)) {activos = activos [asset_key]; interruptor (asset.type) {case «imagen»: this.load.image (asset_key, asset.source); descanso; caso «spritesheet»: this.load.spritesheet (asset_key, asset.source, asset.frame_width, asset.frame_height, asset.frames, asset.margin, asset.spacing); descanso; caso «tilemap»: this.load.tilemap (asset_key, asset.source, null, Phaser.Tilemap.TILED_JSON); descanso; }}}}; Bomberman.LoadingState.prototype.create = function () { «utilizar estricta»; this.game.state.start (this.next_state, verdadero, falso, this.level_data);}; 123456789101112131415161718192021222324252627282930313233343536373839404142varBomberman = Bomberman || {}; Bomberman.LoadingState = function () { «utilizar estricta»; Phaser.State.call ( este);}; Bomberman.LoadingState.prototype = Object.create (Phaser.State.prototype); Bomberman.LoadingState.prototype.constructor = Bomberman.LoadingState; Bomberman.LoadingState.prototype.init = function (level_data, next_state) {» utilizar estricta «; this.level_data = level_data; this.next_state = next_state;}; Bomberman.LoadingState.prototype.preload = function () {» utilizar estricta «; varassets, asset_loader, asset_key, activo; activos = this.level_data.assets ; para (inassets asset_key) {// activos de carga de acuerdo con keyif activo (assets.hasOwnProperty (asset_key)) {activos = activos [asset_key]; conmutador (asset.type) {case «imagen»: this.load.image (asset_key , asset.source); break; caso «spritesheet»: this.load.spritesheet (asset_key, asset.source, asset.frame_width, asset.frame_height, asset.frames, asset.margin, asset.spacing); br EAK; caso «tilemap»: this.load.tilemap (asset_key, asset.source, null, Phaser.Tilemap.TILED_JSON); break;}}}}; Bomberman.LoadingState.prototype.create = function () { «utilizar estricta «; this.game.state.start (this.next_state, verdadero, falso, this.level_data);};

          lectura el mapa de baldosa

          Vamos a leer el mapa de baldosa en el TiledState, la cual se muestra el código fuente a continuación. En primer lugar, en el método init añadimos el tilemap utilizando el activo se describe en el archivo JSON. Entonces, cada imagen juego de fichas se describe en el archivo JSON para, el estado lo añade al mapa. En nuestro juego, vamos a utilizar una sola imagen juego de fichas.
          var Bomberman = Bomberman || {}; Bomberman.TiledState = function () { «utilizar estricta»; Phaser.State.call (this); this.prefab_classes = { «jugador»: Bomberman.Player.prototype.constructor, «enemigo»: Bomberman.Enemy.prototype.constructor};}; Bomberman.TiledState.prototype = Object.create (Phaser.State.prototype); Bomberman .TiledState.prototype.constructor = Bomberman.TiledState; Bomberman.TiledState.prototype.init = function (level_data) { «utilizar estricta»; tileset_index var; this.level_data = level_data; this.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL; this.scale.pageAlignHorizontally = true; this.scale.pageAlignVertically = true; sistema de física this.game.physics.startSystem (Phaser.Physics.ARCADE) // empezar; this.game.physics.arcade.gravity.y = 0; // crear el mapa y establecer conjunto de baldosas this.map = this.game.add.tilemap (level_data.map.key); tileset_index = 0; this.map.tilesets.forEach (función (conjunto de baldosas) {this.map.addTilesetImage (tileset.name, level_data.map.tilesets [tileset_index]); tileset_index + = 1;}, this);}; Bomberman.TiledState.prototype .Create = function () { «utilizar estricta»; GROUP_NAME var, object_layer, collision_tiles; // crear capas de mapa this.layers = {}; this.map.layers.forEach (función (capa) {this.layers [layer.name] = this.map.createLayer (layer.name), si (layer.properties.collision) {// collision_tiles capa colisión = [] ; layer.data.forEach (function (data_row) {// encontrar azulejos usados ​​en la capa de data_row.forEach (function (teja) {// Comprobar si se trata de un índice de baldosas válido y no está ya en la lista si (teja. índice> 0 && collision_tiles.indexOf (tile.index) === -1) {collision_tiles.push (tile.index);}}, esto);}, this); this.map.setCollision (collision_tiles, es cierto, capa .name);}}, this); // cambiar el tamaño del mundo para ser el tamaño de las this.layers capa actuales [this.map.layer.name] .resizeWorld (); // crear grupos this.groups = {}; this.level_data.groups.forEach (function (GROUP_NAME) {this.groups [GROUP_NAME] = this.game.add.group ();}, this); this.prefabs = {}; para (object_layer en this.map.objects) {if (this.map.objects.hasOwnProperty (object_layer)) {// crear capa de objetos this.map.objects [object_layer] .forEach (this.create_object, este); }}}; Bomberman.TiledState.prototype.create_object = función (objeto) { «utilizar estricta»; var object_y, la posición, prefabricada; // azulejos coordenadas se inicia en la esquina inferior izquierda object_y = (object.gid)? object.y – (this.map.tileHeight / 2): object.y + (object.height / 2); posición = { «x»: object.x + (this.map.tileHeight / 2), «y»: object_y}; // crear el objeto de acuerdo con su tipo si (this.prefab_classes.hasOwnProperty (object.type)) {= prefabricadas nuevas this.prefab_classes [object.type] (esto, object.name, la posición, object.properties); } this.prefabs [object.name] = prefabricada;}; Bomberman.TiledState.prototype.game_over = function () { «utilizar estricta»; localStorage.clear (); this.game.state.restart (verdadero, falso, this.level_data);}; 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495varBomberman = Bomberman || {}; Bomberman.TiledState = function () { «utilizar estricta»; Phaser.State.call (this); esta .prefab_classes = { «jugador»: Bomberman.Player.prototype.constructor, «enemigo»: Bomberman.Enemy.prototype.constructor};}; Bomberman.TiledState.prototype = Object.create (Phaser.State.prototype); Bomberman. TiledState.prototype.constructor = Bomberman.TiledState; Bomberman.TiledState.prototype.init = function (level_data) { «utilizar estricta»; vartileset_index; this.level_data = level_data; this.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL; esto. scale.pageAlignHorizontally = true; this.scale.pageAlignVertically = true; // inicia la física systemthis.game.physics.startSystem (Phaser.Physics.ARCADE); this.game.physics.arcade.gravity.y = 0; // crear y conjunto del tilesetthis.map = this.game.add.tilemap (nivel _data.map.key); tileset_index = 0; this.map.tilesets.forEach (función (conjunto de baldosas) {this.map.addTilesetImage (tileset.name, level_data.map.tilesets [tileset_index]); tileset_index + = 1;}, este);}; Bomberman.TiledState.prototype.create = function () { «utilizar estricta»; vargroup_name, object_layer, collision_tiles; // crear layersthis.layers mapa = {}; this.map.layers.forEach (función (capa ) {this.layers [layer.name] = this.map.createLayer (layer.name), si (layer.properties.collision) {// layercollision_tiles colisión = []; layer.data.forEach (function (data_row) { // encontrar azulejos utilizados en la layerdata_row.forEach (function (teja) {// Comprobar si se trata de un índice de baldosas válido y no está ya en la listif (tile.index> 0 && collision_tiles.indexOf (tile.index) === -1) {collision_tiles.push (tile.index);}}, esto);}, this); this.map.setCollision (collision_tiles, cierto, layer.name);}}, this); // cambiar el tamaño del mundo siendo el tamaño de las layerthis.layers actuales [this.map.layer.name] .resizeWorld (); // crear groupsthis.groups = {}; this.level_data.groups.forEach (functio n (GROUP_NAME) {this.groups [GROUP_NAME] = this.game.add.group ();}, this); this.prefabs = {}; para (inthis.map.objects object_layer) {if (this.map. objects.hasOwnProperty (object_layer)) {// crear objectsthis.map.objects capa [object_layer] .forEach (this.create_object, este);}}}; Bomberman.TiledState.prototype.create_object = función (objeto) { «utilizar estricta «; varobject_y, la posición, prefabricada; // coordenadas azulejos comienza en el cornerobject_y inferior izquierda = (object.gid) object.y- (this.map.tileHeight / 2):? object.y + (object.height / 2); posición = { «x»: object.x + (this.map.tileHeight / 2), «y»: object_y}; // crear objeto de acuerdo con su typeif (this.prefab_classes.hasOwnProperty (object.type)) {prefabricada = newthis.prefab_classes [object.type] (esto, object.name, posición, object.properties);} this.prefabs [object.name] = prefabricada;}; Bomberman.TiledState.prototype.game_over = function () { «uso estricta «; localStorage.clear (); this.game.state.restart (verdadero, falso, this.level_data);};

          En el método de crear, creamos las capas, grupos y casas prefabricadas. En primer lugar, iterar a través de todas las capas del objeto de mapa, crear y guardar la misma. Si una capa tiene una propiedad de colisión que configurarlo como Collidable, mediante la búsqueda de todos los índices de baldosas válidos en él. Para crear los grupos, sólo iterar a través de todos los grupos en el archivo JSON, la creación de ellos.

          Para crear las casas prefabricadas, en primer lugar vamos a definir una clase genérica prefabricada, como se muestra a continuación. Se extiende Phaser.Sprite y es responsable de añadir a su propio grupo. Por lo tanto, es importante que las propiedades de parámetro contienen la información de textura y de grupo.
          var Bomberman = Bomberman || {}; Bomberman.Prefab = function (game_state, nombre, posición, propiedades) { «utilizar estricta»; Phaser.Sprite.call (esto, game_state.game, position.x, position.y, properties.texture); this.game_state = game_state; this.name = Nombre; this.game_state.groups [properties.group] .add (this); this.frame = + properties.frame; this.game_state.prefabs [nombre] = esta;}; Bomberman.Prefab.prototype = Object.create (Phaser.Sprite.prototype); Bomberman.Prefab.prototype.constructor = Bomberman.Prefab; 123456789101112131415161718varBomberman = Bomberman || {}; Bomberman.Prefab = function (game_state, nombre, posición, propiedades) { «utilizar estricta»; Phaser.Sprite.call (esto, game_state.game, position.x, position.y, properties.texture); this.game_state = game_state ; this.name = nombre; this.game_state.groups [properties.group] .add (this); this.frame = + properties.frame; this.game_state.prefabs [nombre] = esta;}; Bomberman.Prefab.prototype = Object.create (Phaser.Sprite.prototype); Bomberman.Prefab.prototype.constructor = Bomberman.Prefab;

          Finalmente, para crear las casas prefabricadas que iterar a través de los objetos en la capa de objetos. Hay tres cosas importantes a la notificación de la “create_object”: 1) baldosa de coordenadas del sistema se inicia en la esquina inferior izquierda, mientras que en Phaser que se inicia en la esquina superior izquierda. Como consecuencia, tenemos que cambiar la coordenada y en consecuencia. 2) una instancia de la prefabricada correcta mediante el acceso a un mapa “prefab_classes” con el tipo de objeto. Esto sólo es posible porque todas las casas prefabricadas tienen el mismo constructor. 3) Dado que nuestra clase genérica prefabricada requiere una textura y propiedades de grupo, estas propiedades deben estar definidas en los objetos de mapa de baldosas.

          Creación del reproductor

          Nuestro jugador prefabricada puede caminar en las cuatro direcciones y bombas de caída. En primer lugar, en el constructor que tenemos para establecer sus propiedades, tales como la velocidad de la marcha y la duración bomba, y crear las animaciones para caminar en cada dirección.

          En el método de actualización, comprobamos los cursores para el movimiento y la barra espaciadora para dejar caer una bomba. Para cada dirección, se comprueba si se ha pulsado la tecla del cursor correspondiente y no si el jugador ya está moviendo en la dirección opuesta. Si ese es el caso, establecemos su velocidad en consecuencia. Si el jugador acaba de comenzar en movimiento, comenzamos a jugar su correspondiente animación caminar. Además, dado que estamos utilizando la misma animación para ambas direcciones izquierda y derecha, tenemos que establecer la escala prefabricada correctamente.

          Al final del método de actualización, si el jugador velocidad es 0 en ambos ejes nos detenemos la animación actual y establecer el cuadro detenido de acuerdo con la propiedad con orientación de su cuerpo físico (la propiedad frente se actualiza automáticamente por el motor de física . Para obtener más información, se puede consultar la documentación).

          Para lanzar bombas, comprobamos de la barra espaciadora, y si se pulsa llamamos al método “drop_bomb”. Para mantener al jugador caiga múltiples bombas al mismo tiempo, cuando se deja caer una bomba, establecemos una variable “dropping_bomb” de verdad, y no permitimos que otra bomba se desconecte. Sólo se establece esta variable a falso de nuevo cuando se libera la tecla barra espaciadora.

          En el método “drop_bomb” vamos a utilizar un conjunto de objetos para evitar la creación de objetos innecesarios. La idea es mantener un grupo con todas las bombas de juego y, cuando necesitamos una nueva, que recibimos el primer objeto muerto de este grupo. Si no hay un objeto muerto, creamos una nueva. Si hay uno, sólo reutilizamos, evitando seguir creando nuevos objetos innecesariamente. Además, dado que este es un método que utilizaremos en diferentes lugares, lo puse en un archivo de Utilidades, que recibe como parámetro la piscina, el constructor prefabricada y sus parámetros de constructor.
          var Bomberman = Bomberman || {}; Bomberman.Player = function (game_state, nombre, posición, propiedades) { «utilizar estricta»; Bomberman.Prefab.call (esto, game_state, nombre, posición, propiedades); this.anchor.setTo (0,5); this.walking_speed = + properties.walking_speed; this.bomb_duration = + properties.bomb_duration; this.dropping_bomb = false; this.animations.add ( «walking_down», [1, 2, 3], 10, true); this.animations.add ( «walking_left», [4, 5, 6, 7], 10, true); this.animations.add ( «walking_right», [4, 5, 6, 7], 10, true); this.animations.add ( «walking_up», [0, 8, 9], 10, true); this.stopped_frames = [1, 4, 4, 0, 1]; this.game_state.game.physics.arcade.enable (this); this.body.setSize (14, 12, 0, 4); this.cursors = this.game_state.game.input.keyboard.createCursorKeys ();}; Bomberman.Player.prototype = Object.create (Bomberman.Prefab.prototype); Bomberman.Player.prototype.constructor = Bomberman.Player; Bomberman .Player.prototype.update = function () { «utilizar estricta»; this.game_state.game.physics.arcade.collide (esto, this.game_state.layers.collision); this.game_state.game.physics.arcade.collide (Esto, this.game_state.groups.bombs); this.game_state.game.physics.arcade.overlap (esto, this.game_state.groups.explosions, this.kill, null, este); this.game_state.game.physics.arcade.overlap (esto, this.game_state.groups.enemies, this.kill, null, este); si (this.cursors.left.isDown && this.body.velocity.x <= 0) {// mover hacia la izquierda this.body.velocity.x = -this.walking_speed; si (this.body.velocity.y === 0) {// cambiar la escala, ya que sólo tenemos una animación para izquierda y derecha this.scale.setTo direcciones (-1, 1); this.animations.play ( "walking_left"); }} Else if (this.cursors.right.isDown && this.body.velocity.x> = 0) {// movimiento correcto this.body.velocity.x = + this.walking_speed; si (this.body.velocity.y === 0) {// cambiar la escala, ya que sólo tenemos una animación para la izquierda y la derecha this.scale.setTo direcciones (1, 1); this.animations.play ( «walking_right»); }} Else {this.body.velocity.x = 0; } If (this.cursors.up.isDown && this.body.velocity.y <= 0) {// sube this.body.velocity.y = -this.walking_speed; si (this.body.velocity.x === 0) {this.animations.play ( "walking_up"); }} Else if (this.cursors.down.isDown && this.body.velocity.y> = 0) {// baja this.body.velocity.y = + this.walking_speed; si (this.body.velocity.x === 0) {this.animations.play ( «walking_down»); }} Else {this.body.velocity.y = 0; } If (this.body.velocity.x === === 0 && this.body.velocity.y 0) {// parada actual this.animations.stop animación (); this.frame = this.stopped_frames [this.body.facing]; } If {this.drop_bomb () (this.dropping_bomb && this.game_state.input.keyboard.isDown (Phaser.Keyboard.SPACEBAR)!); this.dropping_bomb = true; } If (! This.dropping_bomb && this.game_state.input.keyboard.isDown (Phaser.Keyboard.SPACEBAR)) {this.dropping_bomb = false; }}; Bomberman.Player.prototype.drop_bomb = function () { «utilizar estricta»; var bomba, bomb_name, bomb_position, bomb_properties; // obtener la primera bomba muerto de la piscina bomb_name = this.name + «_bomb_» + this.game_state.groups.bombs.countLiving (); bomb_position = new Phaser.Point (this.x, this.y); bomb_properties = { «textura»: «bomb_spritesheet», «grupo»: «bombas», bomb_radius: 3}; bombardear = Bomberman.create_prefab_from_pool (this.game_state.groups.bombs, Bomberman.Bomb.prototype.constructor, this.game_state, bomb_name, bomb_position, bomb_properties);}; 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596varBomberman = Bomberman || {}; Bomberman.Player = function (game_state , nombre, posición, propiedades) { «uso estricto»; Bomberman.Prefab.call (esto, game_state, nombre, posición, propiedades); this.anchor.setTo (0,5); this.walking_speed = + properties.walking_speed; esto. bomb_duration = + properties.bomb_duration; this.dropping_bomb = false; this.animations.add ( «walking_down», [1,2,3], 10, true); this.animations.add ( «walking_left», [4,5 , 6,7], 10, true); this.animations.add ( «walking_right», [4,5,6,7], 10, true); this.animations.add ( «walking_up», [0,8 , 9], 10, true); this.stopped_frames = [1,4,4,0,1]; this.game_state.game.physics.arcade.enable (this); this.body.setSize (14,12, 0,4); this.cursors = this.ga me_state.game.input.keyboard.createCursorKeys ();}; Bomberman.Player.prototype = Object.create (Bomberman.Prefab.prototype); Bomberman.Player.prototype.constructor = Bomberman.Player; Bomberman.Player.prototype.update = function () { «utilizar estricta»; this.game_state.game.physics.arcade.collide (esto, this.game_state.layers.collision); this.game_state.game.physics.arcade.collide (esto, this.game_state .groups.bombs); this.game_state.game.physics.arcade.overlap (esto, this.game_state.groups.explosions, this.kill, null, este); this.game_state.game.physics.arcade.overlap (esto , this.game_state.groups.enemies, this.kill, null, esta), si (this.cursors.left.isDown && this.body.velocity.x <= 0) {// mover hacia la izquierda this.body.velocity.x = -this.walking_speed; si (this.body.velocity.y === 0) {// cambiar la escala, ya que sólo tenemos una animación para directionsthis.scale.setTo izquierda y derecha (-1,1); este .animations.play ( "walking_left");}} elseif (this.cursors.right.isDown && this.body.velocity.x> = 0) {// movimiento correcto this.body.velocity.x = + this.walk ing_speed; si (this.body.velocity.y === 0) {// cambiar la escala, ya que sólo tenemos una animación para directionsthis.scale.setTo izquierda y derecha (1,1); this.animations.play ( «walking_right»);}} else {this.body.velocity.x = 0;} if (this.cursors.up.isDown && this.body.velocity.y <= 0) {// moverse hacia arriba this.body.velocity .y = -this.walking_speed; si (this.body.velocity.x === 0) {this.animations.play ( "walking_up");}} elseif (this.cursors.down.isDown && this.body.velocity .y> = 0) {// moverse hacia abajo this.body.velocity.y = + this.walking_speed; si (this.body.velocity.x === 0) {this.animations.play ( «walking_down»); }} else {this.body.velocity.y = 0;} if (this.body.velocity.x === === 0 && this.body.velocity.y 0) {// actual parada this.animations animación. stop (); this.frame = this.stopped_frames [this.body.facing];} if (! this.dropping_bomb && this.game_state.input.keyboard.isDown (Phaser.Keyboard.SPACEBAR)) {this.drop_bomb (); this.dropping_bomb = true;} if (! this.dropping_bomb && this.game_state.input.keyboard.isDown (Phaser.Keyboard.SPACEBAR)) {this.drop ping_bomb = false;}}; Bomberman.Player.prototype.drop_bomb = function () { «use strict»; varbomb, bomb_name, bomb_position, bomb_properties; // obtener la primera bomba muerto de la poolbomb_name = this.name + «_ _ bomba» + this.game_state.groups.bombs.countLiving (); bomb_position = newPhaser.Point (this.x, this.y); bomb_properties = { «textura»: «bomb_spritesheet», «grupo»: «bombas», bomb_radius: 3} ; bombas = Bomberman.create_prefab_from_pool (this.game_state.groups.bombs, Bomberman.Bomb.prototype.constructor, this.game_state, bomb_name, bomb_position, bomb_properties);};

          puede ya crear un mapa con el jugador y ver si se trata de caminar correctamente.

          jugador

          Creación de la bomba

          El prefabricada bomba comenzará con una animación explosión y cuando se realiza la animación que va a explotar. Para ello, hemos creado una propiedad radio de bomba en el constructor y crear su animación, por lo que es llamar al método de matanza cuando la animación se ha completado.

          Para crear las explosiones, tenemos que sobreescribir el método de matanza. En el nuevo método de matanza de empezar a crear una explosión en la posición bomba, y luego llamar al método “create_explosions” para crearlos en cada una de las cuatro direcciones. parámetros de este método son un índice inicial, el índice de final, el paso y el eje. Por iteración a través de esos índices, creamos nuevas explosiones en una posición dada por el índice actual y el eje. Si se encuentra una pared de azulejos durante este proceso, lo detenemos. Para ello, se utiliza el “getTileFromXY” de Phaser.Tilemap, que devuelve una ficha dada una posición en el mundo (se puede comprobar la documentación para obtener más información). Tenga en cuenta que, para permitir que los valores negativos se deben comparar los valores absolutos de “índice” y “final_index”. Además, estamos utilizando un conjunto de objetos de la explosión, ya que vamos a crear un montón de ellos.

          Hay una última cosa que tenemos que hacer en la casa prefabricada bomba. En el método de restablecimiento tenemos que reiniciar la animación explosión, de lo contrario no jugaría cuando reutilizamos un objeto de la bomba de las bombas de la piscina.
          var Bomberman = Bomberman || {}; Bomberman.Bomb = function (game_state, nombre, posición, propiedades) { «utilizar estricta»; Bomberman.Prefab.call (esto, game_state, nombre, posición, propiedades); this.anchor.setTo (0,5); this.bomb_radius = + properties.bomb_radius; this.game_state.game.physics.arcade.enable (this); = This.body.immovable verdaderos; this.exploding_animation = this.animations.add ( «explosión», [0, 2, 4], 1, false); this.exploding_animation.onComplete.add (this.kill, este); this.animations.play ( «explosión»);}; Bomberman.Bomb.prototype = Object.create (Bomberman.Prefab.prototype); Bomberman.Bomb.prototype.constructor = Bomberman.Bomb; Bomberman.Bomb.prototype.reset = función (Position_X, position_y) { «utilizar estricta»; Phaser.Sprite.prototype.reset.call (esto, Position_X, position_y); this.exploding_animation.restart ();}; Bomberman.Bomb.prototype.kill = function () { «utilizar estricta»; Phaser.Sprite.prototype.kill.call (this); var explosion_name, explosion_position, explosion_properties, explosión; explosion_name = this.name + «_explosion_» + this.game_state.groups.explosions.countLiving (); explosion_position = nuevo Phaser.Point (this.position.x, this.position.y); explosion_properties = {textura: «explosion_image», grupo: «explosiones», duración: 0,5}; // crear una explosión en la explosión posición bomba = Bomberman.create_prefab_from_pool (this.game_state.groups.explosions, Bomberman.Explosion.prototype.constructor, this.game_state, explosion_name, explosion_position, explosion_properties); // crear explosiones en cada this.create_explosions de dirección (-1, -this.bomb_radius, -1, «x»); this.create_explosions (1, this.bomb_radius, 1, «x»); this.create_explosions (-1, -this.bomb_radius, -1 «y»); this.create_explosions (1, this.bomb_radius, 1 «y»);}; Bomberman.Bomb.prototype.create_explosions = function (initial_index, final_index, paso, eje y) { «utilizar estricta»; Índice var, explosion_name, explosion_position, explosión, explosion_properties, baldosas; explosion_properties = {textura: «explosion_image», grupo: «explosiones», duración: 0,5}; para (índice = initial_index; Math.abs (índice) <= Math.abs (final_index); índice + = paso) {explosion_name = this.name + "_explosion_" + this.game_state.groups.explosions.countLiving (); // la posición es diferente accoring al eje si (eje === "x") {explosion_position = nuevo Phaser.Point (this.position.x + (índice * this.width), this.position.y); } Else {explosion_position = new Phaser.Point (this.position.x, this.position.y + (índice * this.height)); } Tile = this.game_state.map.getTileWorldXY (explosion_position.x, explosion_position.y, this.game_state.map.tileWidth, this.game_state.map.tileHeight, "colisión"); (Azulejo) si {// crear una nueva explosión en la nueva posición explosión = Bomberman.create_prefab_from_pool (this.game_state.groups.explosions, Bomberman.Explosion.prototype.constructor, this.game_state, explosion_name, explosion_position, explosion_properties); } Else {break; }}}; 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566varBomberman = Bomberman || {}; Bomberman.Bomb = function (game_state, nombre, posición, propiedades) { "utilizar estricta"; Bomberman.Prefab.call (esto, game_state, nombre, posición, propiedades); esta .anchor.setTo (0,5); this.bomb_radius = + properties.bomb_radius; this.game_state.game.physics.arcade.enable (this); this.body.immovable = true; this.exploding_animation = this.animations.add ( "explosión", [0,2,4], 1, false); this.exploding_animation.onComplete.add (this.kill, este); this.animations.play ( "explosión");}; Bomberman.Bomb.prototype = Object.create (Bomberman.Prefab.prototype); Bomberman.Bomb.prototype.constructor = Bomberman.Bomb; Bomberman.Bomb.prototype.reset = function (Position_X, position_y) { "utilizar estricta"; Phaser.Sprite.prototype. reset.call (esto, Position_X, position_y); this.exploding_animation.restart ();}; Bomberman.Bomb.prototype.kill = function () { "utilizar estricta"; Phaser.Sprite.prototype.kill.call (esto) ; varexplosion_n AME, explosion_position, explosion_properties, explosión; explosion_name = this.name + "_ explosión _" + this.game_state.groups.explosions.countLiving (); explosion_position = newPhaser.Point (this.position.x, this.position.y); explosion_properties = {textura: "explosion_image", grupo: "explosiones", duración: 0,5}; // crear una explosión en el positionexplosion bomba = Bomberman.create_prefab_from_pool (this.game_state.groups.explosions, Bomberman.Explosion.prototype.constructor, esto. game_state, explosion_name, explosion_position, explosion_properties); // crear explosiones en cada directionthis.create_explosions (-1, -this.bomb_radius, -1, "x"); this.create_explosions (1, this.bomb_radius, + 1, "x "); this.create_explosions (-1, -this.bomb_radius, -1," Y "); this.create_explosions (1, this.bomb_radius, + 1," Y ");}; Bomberman.Bomb.prototype.create_explosions = function (initial_index, final_index, paso, eje y) { "utilizar estricta"; varindex, explosion_name, explosion_position, explosión, explosion_properties, baldosas; explosion_properties = {textura: "explosion_image", gr OUP: "explosiones", duración: 0,5}; for (index = initial_index; Math.abs (índice) <= Math.abs (final_index); índice + = paso) {explosion_name = this.name + "_ explosión _" + this.game_state. groups.explosions.countLiving (); // la posición es diferente accoring a la axisif (eje === "x") {explosion_position = newPhaser.Point (this.position.x + (índice * this.width), this.position .y);} else {explosion_position = newPhaser.Point (this.position.x, this.position.y + (índice * this.height));} tile = this.game_state.map.getTileWorldXY (explosion_position.x, explosion_position. Y, this.game_state.map.tileWidth, this.game_state.map.tileHeight, "colisión"); if (teja) {// crear una nueva explosión en el nuevo positionexplosion = Bomberman.create_prefab_from_pool (this.game_state.groups. explosiones, Bomberman.Explosion.prototype.constructor, this.game_state, explosion_name, explosion_position, explosion_properties);} else {break;}}};

          puede que ya intentar colocar bombas para ver si su trabajo. Puesto que todavía no creamos la explosión prefabricada sin embargo, sólo puede comentar esta parte del código o crear una casa prefabricada simulado por ahora.

          bomba

          Creación de explosiones

          El prefabricada Explosión tendrá una duración, que definirá el tiempo que va a durar hasta que desaparezca. Esta propiedad se establece en el constructor, y se utiliza cuando se crea un temporizador que llama al método de matar cuando esté terminado. Por lo tanto, cuando el número de segundos definido por las que transcurre la propiedad de duración, la explosión prefabricada se mató.

          Tenga en cuenta que tenemos que establecer la propiedad “autoDestroy” de “kill_timer” (en “this.game_state.time.create”) a falso, por lo que no será destruida cuando su finalice el evento. Luego, en el “reset” método añadimos otro evento de matar, por lo que seguirá trabajando cuando una explosión se reutiliza de la piscina.
          var Bomberman = Bomberman || {}; Bomberman.Explosion = function (game_state, nombre, posición, propiedades) { «utilizar estricta»; Bomberman.Prefab.call (esto, game_state, nombre, posición, propiedades); this.anchor.setTo (0,5); this.duration = + properties.duration; this.game_state.game.physics.arcade.enable (this); = This.body.immovable verdaderos; // crear el temporizador de matar con autoDestroy es igual a falsa this.kill_timer = this.game_state.time.create (false); this.kill_timer.add (Phaser.Timer.SECOND * this.duration, this.kill, este); this.kill_timer.start ();}; Bomberman.Explosion.prototype = Object.create (Bomberman.Prefab.prototype); Bomberman.Explosion.prototype.constructor = Bomberman.Explosion; Bomberman.Explosion.prototype.reset = function (Position_X , position_y) { «utilizar estricta»; Phaser.Sprite.prototype.reset.call (esto, Position_X, position_y); // añadir otro evento matanza this.kill_timer.add (Phaser.Timer.SECOND * this.duration, this.kill, this);}; 12345678910111213141516171819202122232425262728varBomberman = Bomberman || {}; Bomberman.Explosion = function (game_state, nombre, cargo , propiedades) { «uso estricto»; Bomberman.Prefab.call (esto, game_state, nombre, posición, propiedades); this.anchor.setTo (0,5); this.duration = + properties.duration; this.game_state.game. physics.arcade.enable (este); this.body.immovable = true; // crear el temporizador de matar con autoDestroy es igual falsethis.kill_timer = this.game_state.time.create (falso); this.kill_timer.add (Phaser.Timer .SECOND * this.duration, this.kill, este); this.kill_timer.start ();}; Bomberman.Explosion.prototype = Object.create (Bomberman.Prefab.prototype); Bomberman.Explosion.prototype.constructor = Bomberman .Explosion; Bomberman.Explosion.prototype.reset = function (Position_X, position_y) { «utilizar estricta»; Phaser.Sprite.prototype.reset.call (esto, Position_X, position_y); // añadir otro eventthis.kill_timer.add kill (* Phaser.Timer.SECOND esto. duration,this.kill,this);};

          Now you can try playing again to see if the explosions are being created and killed properly.

          explosion

          Creating the enemy

          Our enemy will keep walking in a single axis (horizontal or vertical) and will switch direction when it reaches a maximum walked distance or it collides with something, like a wall or a bomb. To do this, we start by setting its walking speed, walking distance, direction and axis in the constructor. We also creates the enemy animations and start its velocity in the initial direction.

          In the update method we manage the animations according to its velocity in each direction, in a similar way we did with the player. However, since it will always walk in a single direction at once, we don’t have to check if it isn’t already walking in another direction.

          After starting or stopping animations, we check if it has reached its maximum distance, by subtracting the current position by the position in the beginning of the movement. If this value is greater or equal than the maximum distance to walk, we have to switch its direction. The “switch_direction” method only reverts the velocity and saves the new initial position.

          var Bomberman = Bomberman || {};Bomberman.Enemy = function (game_state, name, position, properties) { «use strict»; Bomberman.Prefab.call(this, game_state, name, position, properties); this.anchor.setTo (0,5); this.walking_speed = + properties.walking_speed; this.walking_distance = + properties.walking_distance; this.direction = +properties.direction; this.axis = properties.axis; this.previous_position = (this.axis === «x») ? this.x : this.y; this.animations.add(«walking_down», [1, 2, 3], 10, true); this.animations.add(«walking_left», [4, 5, 6, 7], 10, true); this.animations.add(«walking_right», [4, 5, 6, 7], 10, true); this.animations.add(«walking_up», [0, 8, 9], 10, true); this.stopped_frames = [1, 4, 4, 0, 1]; this.game_state.game.physics.arcade.enable (this); if (this.axis === «x») { this.body.velocity.x = this.direction * this.walking_speed; } else { this.body.velocity.y = this.direction * this.walking_speed; }};Bomberman.Enemy.prototype = Object.create(Bomberman.Prefab.prototype);Bomberman.Enemy.prototype.constructor = Bomberman.Enemy;Bomberman.Enemy.prototype.update = function () { «use strict»; var new_position; this.game_state.game.physics.arcade.collide(this, this.game_state.layers.collision, this.switch_direction, null, this); this.game_state.game.physics.arcade.overlap(this, this.game_state.groups.bombs, this.switch_direction, null, this); this.game_state.game.physics.arcade.overlap(this, this.game_state.groups.explosions, this.kill, null, this); if (this.body.velocity.x < 0) { // walking left this.scale.setTo(-1, 1); this.animations.play("walking_left"); } else if (this.body.velocity.x > 0) { // walking right this.scale.setTo(1, 1); this.animations.play(«walking_right»); } if (this.body.velocity.y < 0) { // walking up this.animations.play("walking_up"); } else if (this.body.velocity.y > 0) { // walking down this.animations.play(«walking_down»); } If (this.body.velocity.x === === 0 && this.body.velocity.y 0) {// parada actual this.animations.stop animación (); this.frame = this.stopped_frames [this.body.facing]; } new_position = (this.axis === «x») ? this.x : this.y; if (Math.abs(new_position – this.previous_position) >= this.walking_distance) { this.switch_direction(); }};Bomberman.Enemy.prototype.switch_direction = function () { «use strict»; if (this.axis === «x») { this.previous_position = this.x; this.body.velocity.x *= -1; } else { this.previous_position = this.y; this.body.velocity.y *= -1; }};1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980varBomberman=Bomberman||{};Bomberman.Enemy=function(game_state,name,position,properties){«use strict»;Bomberman.Prefab.call(this,game_state,name,position,properties);this.anchor.setTo(0.5);this.walking_speed=+properties.walking_speed;this.walking_distance=+properties.walking_distance;this.direction=+properties.direction;this.axis=properties.axis;this.previous_position=(this.axis===»x»)?this.x:this.y;this.animations.add(«walking_down»,[1,2,3],10,true);this.animations.add(«walking_left»,[4,5,6,7],10,true);this.animations.add(«walking_right»,[4,5,6,7],10,true);this.animations.add(«walking_up»,[0,8,9],10,true);this.stopped_frames=[1,4,4,0,1];this.game_state.game.physics.arcade.enable(this);if(this.axis===»x»){this.body.velocity.x=this.direction*this.walking_speed;}else{this.body.velocity.y=this.direction*this.walking_speed;}};Bomberman.En emy.prototype=Object.create(Bomberman.Prefab.prototype);Bomberman.Enemy.prototype.constructor=Bomberman.Enemy;Bomberman.Enemy.prototype.update=function(){«use strict»;varnew_position;this.game_state.game.physics.arcade.collide(this,this.game_state.layers.collision,this.switch_direction,null,this);this.game_state.game.physics.arcade.overlap(this,this.game_state.groups.bombs,this.switch_direction,null,this);this.game_state.game.physics.arcade.overlap(this,this.game_state.groups.explosions,this.kill,null,this);if(this.body.velocity.x<0){// walking leftthis.scale.setTo(-1,1);this.animations.play("walking_left");}elseif(this.body.velocity.x>0){// walking rightthis.scale.setTo(1,1);this.animations.play(«walking_right»);}if(this.body.velocity.y<0){// walking upthis.animations.play("walking_up");}elseif(this.body.velocity.y>0){// walking downthis.animations.play(«walking_down»);}if(this.body.velocity.x===0&& this.body.velocity.y === 0) { // stop current animation this.animations.stop();this.fr ame=this.stopped_frames[this.body.facing];}new_position=(this.axis===»x»)?this.x:this.y;if(Math.abs(new_position-this.previous_position)>=this.walking_distance){this.switch_direction();}};Bomberman.Enemy.prototype.switch_direction=function(){«use strict»;if(this.axis===»x»){this.previous_position=this.x;this.body.velocity.x*=-1;}else{this.previous_position=this.y;this.body.velocity.y*=-1;}};

          You can already try playing with the enemy prefab, to see if it’s working. Don’t forget to properly add the collisions in the prefabs update method.

          enemy

          Acabado del juego

          And now our game is complete! In the next tutorials we will add some content to it.

          Mensajes relacionados
          The Complete Mobile Game Development Course – Platinum Edition

Deja una respuesta

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