En esta serie de tutoriales, vamos a crear un juego similar al popular Pokemon GO. En primer lugar, vamos a crear un estado Phaser para atrapar Pokémon. A continuación, vamos a añadir un estado mundial, donde el jugador puede navegar con el fin de encontrar Pokemon. También vamos a añadir características del juego Pokemon GO tales como: diferentes Pokémon, diferentes pokeballs, pokestops para conseguir pokeballs. Al final vamos a guardar el reproductor Pokedex en una base de datos en línea.

En este primer tutorial que cubrirá el siguiente contenido:


  • Crear un estado de captura donde el jugador puede atrapar Pokemon
  • Uso de motor de física Phaser P2 para lanzar pokeballs y la captura de Pokemon
  • Creación de cuadros de mensaje que interactúan con el jugador para llamar a los métodos del estado del juego
  • La creación de un estado mundial, que lee un mapa de baldosa con la corriente Pokemon

    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
    • Creación de mapas con 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.

      archivos de código fuente

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

      archivo de nivel y el juego establece

      En este tutorial vamos a utilizar archivos JSON como la de abajo con el fin de activos de carga, crear grupos y casas prefabricadas en nuestro juego.
      { «Activos»: { «background_image»: { «type»: «imagen», «fuente»: «assets / images / background.png»}, «message_box_image»: { «type»: «imagen», «fuente» : «assets / images / message_box.png»}, «pokeball_image»: { «type»: «imagen», «fuente»: «assets / images / pokeball.png»}, «pokemon_spritesheet»: { «type»: » spritesheet » «fuente»: «assets / images / pokemon.png», «frame_width»: 98, «frame_height»: 85}}, «grupos»: [ «aislado», «pokemon», «PokéBalls»,» HUD «] » collision_groups»: [ «pokemons», «Pokébolas»], «prefabricados»: { «fondo»: { «type»: «fondo», «posición»: {» x «: 0 » y»: 0}, «propiedades»: { «textura»: «background_image», «grupo»: «fondo»}}, «pokeball»: { «type»: «pokeball», «posición»: { «x»: 0,5, «y»: 0,8}, «propiedades»: { «textura»: «pokeball_image», «grupo»: «pokeballs», «ancla»: { «x»: 0,5, «y»: 0,5}, «pokeball_speed»: 300, «catching_rate»: 0.3}}, «pokemon»: { «type»: «pokemon», «posición»: { «x»: 0,5, «y»: 0,6}, «propiedades»: { «textura»: «pokemon_spritesheet», «grupo»: «pokemon», «Ancla»: { «x»: 0,5, «y»: 0,5}, «marco»: 1, «fleeing_rate»: 1,0}}}} 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950 { «activos»: { «background_image»: { «type»:» imagen», «fuente»: «assets / images / background.png»}, «message_box_image»: { «type»: «imagen», «fuente»: «assets / images / message_box.png»}, «pokeball_image»: { «type»: «imagen», «fuente»: «assets / images / pokeball.png»}, «pokemon_spritesheet»: { «type»: «spritesheet», «fuente»: «assets / images / pokemon.png» , «frame_width»: 98, «frame_height»: 85}}, «grupos»: [ «de fondo», «pokemons», «Pokébolas», «HUD»] «collision_groups»: [ «pokemons», «pokeballs»] , «prefabricados»: { «fondo»: { «type»: «fondo», «posición»: { «x»: 0 «y»: 0}, «propiedades»: { «textura»: «background_image», «grupo»: «fondo»}}, «pokeball»: { «type»: «pokeball», «posición»: { «x»: 0,5, «y»: 0,8}, «propiedades»: { «textura»: «pokeball_image», «grupo»: «pokeballs», «ancla»: { «x»: 0,5, «y»: 0,5}, «pokeball_speed»: 300, «catching_rate»: 0.3}}, «pokemon»: {» type «:» pokemon » «posición»: { «x»: 0,5, «y»: 0,6},» pro piedades «: {» textura «:» pokemon_spritesheet», «grupo»: «pokemons», «de anclaje»: { «x»: 0,5, «y»: 0,5}, «marco»: 1, «fleeing_rate»: 1,0} }}}

      La Phaser afirma que vamos a utilizar son:


      • BootState: responsable de cargar el archivo de nivel
      • LoadingState: responsable de cargar todos los activos de nivel
      • CatchState: representa la pantalla donde el jugador puede coger un Pokemon
      • WorldState: representa el mundo en el que el jugador puede navegar con el fin de encontrar Pokemon. En este primer tutorial WorldState sólo le muestre la corriente de Pokemon para la captura.

        BootState y LoadingState son los más simples, y sus códigos se muestran a continuación. Como se mencionó anteriormente, BootState simplemente carga un archivo de nivel, y enviar su contenido como un parámetro para LoadingState.
        var Pokemon = Pokemon || {}; Pokemon.BootState = function () { «utilizar estricta»; Phaser.State.call (this);}; Pokemon.BootState.prototype = Object.create (Phaser.State.prototype); Pokemon.BootState.prototype.constructor = Pokemon.BootState; Pokemon.BootState.prototype.init = function ( level_file, next_state) { «utilizar estricta»; this.level_file = level_file; this.next_state = next_state;}; Pokemon.BootState.prototype.preload = function () { «utilizar estricta»; // cargar el this.load.text archivo de nivel ( «level1», this.level_file);}; Pokemon.BootState.prototype.create = function () { «utilizar estricta»; level_text var, level_data; // analizar el archivo de nivel que un objeto JSON y enviar sus datos a LoadingState level_text = this.game.cache.getText ( «Nivel 1»); level_data = JSON.parse (level_text); this.game.state.start ( «LoadingState», verdadero, falso, level_data, this.next_state);}; 123456789101112131415161718192021222324252627282930varPokemon = Pokemon || {}; Pokemon.BootState = function () { «utilizar estricta»; Phaser.State. llamada (esto);}; Pokemon.BootState.prototype = Object.create (Phaser.State.prototype); Pokemon.BootState.prototype.constructor = Pokemon.BootState; Pokemon.BootState.prototype.init = function (level_file, next_state) { «utilizar estricta»; this.level_file = level_file; this.next_state = next_state;}; Pokemon.BootState.prototype.preload = function () { «utilizar estricta»; // cargar el filethis.load.text nivel ( «level1 «, this.level_file);}; Pokemon.BootState.prototype.create = function () { «utilizar estricta»; varlevel_text, level_data; // analizar el archivo de nivel como un objeto JSON y enviar sus datos a LoadingStatelevel_text = this.game .cache.getText ( «level1»); level_data = JSON.parse (level_text); this.game.state.start ( «LoadingState», verdadero, falso, level_data, this.next_state);};

        LoadingState, por A su vez, itera a través de todos los activos en los datos de nivel de lo ading el activo correcto para cada uno. Tenga en cuenta que usamos una propiedad denominada tipo con el fin de identificar el elemento correcto de la carga, y una clave de activos para guardarlo.
        var Pokemon = Pokemon || {}; Pokemon.LoadingState = function () { «utilizar estricta»; Phaser.State.call (this);}; Pokemon.LoadingState.prototype = Object.create (Phaser.State.prototype); Pokemon.LoadingState.prototype.constructor = Pokemon.LoadingState; Pokemon.LoadingState.prototype.init = function ( level_data, next_state) { «utilizar estricta»; this.level_data = level_data; this.next_state = next_state;}; Pokemon.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; }}}}; Pokemon.LoadingState.prototype.create = function () { «utilizar estricta»; this.game.state.start (this.next_state, verdadero, falso, this.level_data);}; 123456789101112131415161718192021222324252627282930313233343536373839404142varPokemon = Pokemon || {}; Pokemon.LoadingState = function () { «utilizar estricta»; Phaser.State.call ( este);}; Pokemon.LoadingState.prototype = Object.create (Phaser.State.prototype); Pokemon.LoadingState.prototype.constructor = Pokemon.LoadingState; Pokemon.LoadingState.prototype.init = function (level_data, next_state) {» utilizar estricta «; this.level_data = level_data; this.next_state = next_state;}; Pokemon.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); break; caso» tilemap «: This.load.tilemap (asset_key, asset.source, null, Phaser.Tilemap.TILED_JSON); break;}}}}; Pokemon.LoadingState.prototype.create = function () {» utilizar estricta «; this.game .state.start (this.next_state, verdadero, falso, this.level_data);};

        código CatchState se muestra a continuación. En primer lugar, en el método “init” que necesitamos para iniciar el motor de física. Tenga en cuenta que en esta serie tutorial vamos a utilizar P2 Física con el fin de tener formas redondeadas de colisión.

        El método “crear” de CatchState es responsable de la creación de grupos, grupos de choque (para el motor de física) y las casas prefabricadas. Grupos y grupos de colisión pueden ser fácilmente creados por iteración a través de sus respectivas matrices y la creación de ellos en Phaser o P2. Con el fin de crear las casas prefabricadas que vamos a iterar a través de todas las casas prefabricadas que se describen en el archivo JSON y llamar a un método “create_prefab”.
        var Pokemon = Pokemon || {}; Pokemon.CatchState = function () { «utilizar estricta»; Phaser.State.call (this); this.prefab_classes = { «fondo»: Pokemon.Prefab.prototype.constructor, «Pokeball»: Pokemon.Pokeball.prototype.constructor, «pokemon»: Pokemon.Pokemon.prototype.constructor};}; Pokemon.CatchState.prototype = Object.create (Phaser.State.prototype); Pokemon.CatchState.prototype.constructor = Pokemon.CatchState; Pokemon.CatchState.prototype.init = function (level_data) { «utilizar estricta»; this.level_data = level_data; this.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL; this.scale.pageAlignHorizontally = true; this.scale.pageAlignVertically = true; // iniciar la física del sistema this.game.physics.startSystem (Phaser.Physics.P2JS); this.game.physics.arcade.gravity.y = 0;}; Pokemon.CatchState.prototype.create = function () { «utilizar estricta»; GROUP_NAME var, prefab_name; // crear grupos this.groups = {}; this.level_data.groups.forEach (function (GROUP_NAME) {this.groups [GROUP_NAME] = this.game.add.group ();}, this); this.collision_groups = {}; this.level_data.collision_groups.forEach (función (collision_group_name) {this.collision_groups [collision_group_name] = this.game.physics.p2.createCollisionGroup ();}, this); // crear prefabricadas this.prefabs = {}; para (prefab_name en this.level_data.prefabs) {if (this.level_data.prefabs.hasOwnProperty (prefab_name)) {// crear prefabricada this.create_prefab (prefab_name, this.level_data.prefabs [prefab_name]); }}}; Pokemon.CatchState.prototype.create_prefab = function (prefab_name, prefab_data) { «utilizar estricta»; prefab_position var, prefabricada; // crear el objeto de acuerdo con su tipo si (this.prefab_classes.hasOwnProperty (prefab_data.type)) {if (prefab_data.position.x> 0 && prefab_data.position.x <= 1) {// posición como porcentaje prefab_position = new Phaser.Point (prefab_data.position.x * this.game.world.width, prefab_data.position.y * this.game.world.height); } Else {// posición como absoluta número prefab_position = prefab_data.position; } = prefabricadas nuevas this.prefab_classes [prefab_data.type] (Esto, prefab_name, prefab_position, prefab_data.properties); } Devolver prefabricada;}; Pokemon.CatchState.prototype.return_to_world = function () { "utilizar estricta"; this.game.state.start ( "BootState", verdadero, falso, "activos / niveles / world_level.json", "WorldState");}; 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576varPokemon = Pokemon || {}; Pokemon.CatchState = function () {" utilizar estricta "; Phaser.State.call (this); this.prefab_classes = {" fondo ": Pokemon.Prefab.prototype.constructor," pokeball ": Pokemon.Pokeball.prototype.constructor," pokemon ": Pokemon.Pokemon. prototype.constructor};}; Pokemon.CatchState.prototype = Object.create (Phaser.State.prototype); Pokemon.CatchState.prototype.constructor = Pokemon.CatchState; Pokemon.CatchState.prototype.init = function (level_data) {" utilizar estricta "; this.level_data = level_data; this.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL; this.scale.pageAlignHorizontally = true; this.scale.pageAlignVertically = true; // iniciar systemthis.game.physics.startSystem la física ( Phaser.Physics.P2JS); this.game.physics.arcade.gravity.y = 0;}; Pokemon.CatchState.prototype.create = fu ncio () { "uso estricto"; vargroup_name, prefab_name; // crear groupsthis.groups = {}; this.level_data.groups.forEach (function (GROUP_NAME) {this.groups [GROUP_NAME] = this.game.add.group ();}, this); this.collision_groups = {}; this.level_data.collision_groups.forEach (function (collision_group_name) {this.collision_groups [collision_group_name] = this.game.physics.p2.createCollisionGroup ();}, este ); // crear prefabsthis.prefabs = {}; para (inthis.level_data.prefabs prefab_name) {if (this.level_data.prefabs.hasOwnProperty (prefab_name)) {// crear prefabthis.create_prefab (prefab_name, this.level_data.prefabs [prefab_name]);}}}; Pokemon.CatchState.prototype.create_prefab = function (prefab_name, prefab_data) { "utilizar estricta"; varprefab_position, prefabricada; // crear el objeto de acuerdo con su typeif (this.prefab_classes.hasOwnProperty (prefab_data. tipo)) {if (prefab_data.position.x> 0 && prefab_data.position.x <= 1) {// posición como porcentaje prefab_position = new Phaser.Point (prefab_data.position.x * this.game.world.width, prefab_data .posición .y * this.game.world.height);} else {// posición como numberprefab_position absoluta = prefab_data.position;} prefabricada = newthis.prefab_classes [prefab_data.type] (esto, prefab_name, prefab_position, prefab_data.properties);} returnprefab;}; Pokemon.CatchState.prototype.return_to_world = function () { "utilizar estricta"; this.game.state.start ( "BootState", verdadero, falso, "activos / niveles / world_level.json", "WorldState" );};

        los “create_prefab” método comienza por el cálculo de la posición prefabricada. Esto puede ser una posición absoluta o porcentaje. Si la posición se define como el número entre cero y uno (por ejemplo: 0,5), su posición se calcula como un porcentaje de las dimensiones mundo. De lo contrario, será simplemente la posición definida en el archivo JSON. Después de definir la posición prefabricada, lo creamos llamando al constructor apropiado con cualquier propiedad personalizada declarados en el archivo JSON nivel. Tenga en cuenta que lo hacemos por el ahorro de los constructores prefabricadas en una propiedad “prefab_classes”, indexada por el tipo prefabricada. Esto es posible porque todas las casas prefabricadas tienen el mismo constructor, se define en una clase genérica prefabricada (mostrado a continuación), que todas las casas prefabricadas debe extenderse.
        var Pokemon = Pokemon || {}; Pokemon.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; si (properties.anchor) {this.anchor.setTo (properties.anchor.x, properties.anchor.y); } This.game_state.prefabs [nombre] = esta;}; Pokemon.Prefab.prototype = Object.create (Phaser.Sprite.prototype); Pokemon.Prefab.prototype.constructor = Pokemon.Prefab; 123456789101112131415161718192021varPokemon = Pokemon || {} ; Pokemon.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; si (properties.anchor) {this.anchor.setTo (properties.anchor. x, properties.anchor.y);} this.game_state.prefabs [nombre] = esta;}; Pokemon.Prefab.prototype = Object.create (Phaser.Sprite.prototype); Pokemon.Prefab.prototype.constructor = Pokemon. prefabricada;

        Ahora vamos a crear nuestro último estado para este tutorial: WorldState. Este cargas de estado un mapa de baldosa como el que se muestra a continuación. Dado que el objetivo de este tutorial no es de baldosa, usted es libre de utilizar el mismo mapa que aparece en el código fuente, o crear su propio mapa. Lo único que hay que tener cuidado es que los objetos en el mapa deben tener al menos su grupo y textura definida en sus propiedades.

        mapa

        Además del mapa de baldosa, WorldState también va a utilizar un archivo de nivel JSON para cargar los activos, el mapa y crear los grupos, como el que se muestra a continuación:
        { «activos»: { «map_tileset»: { «type»: «imagen», «fuente»: «assets / images / open_tileset.png»}, «pokemon_spritesheet»: { «type»: «spritesheet», «fuente» : «assets / images / pokemon.png», «frame_width»: 98, «frame_height»: 85}, «world_tilemap»: { «type»: «tilemap», «fuente»: «activos / mapas / world.json» }}, «grupos»: [ «desoves»], «mapa»: { «clave»: «world_tilemap», «baldosas»: [ «map_tileset»]}} 123456789101112131415 { «activos»: { «map_tileset»: {» type «:» imagen » «fuente»: «assets / images / open_tileset.png»}, «pokemon_spritesheet»: { «type»: «spritesheet», «fuente»: «assets / images / pokemon.png»,» frame_width «: 98,» frame_height «: 85},» world_tilemap «: {» type «:» tilemap», «fuente»: «activos / Mapas / world.json»}}, «grupos»: [ «desoves»] «mapa»: { «clave»: «world_tilemap», «baldosas»: [ «map_tileset»]}}

        Este es el código para WorldState. De manera similar a CatchState se inicia el motor de física P2 en el método “init”. Sin embargo, también tiene que crear el tilemap, utilizando los datos proporcionados por el archivo de nivel JSON. Luego, en el método de “crear” crea las capas de mapas, grupos de juego y casas prefabricadas. Las capas de mapa y los grupos se crean de manera similar a lo que hemos hecho en CatchState, pero con el fin de crear casas prefabricadas que tenemos que iterar a través de las capas de objetos en el mapa de baldosa y llamar a un método “create_object” para cada objeto.
        var Pokemon = Pokemon || {}; Pokemon.WorldState = function () { «utilizar estricta»; Phaser.State.call (this); this.prefab_classes = { «pokemon_spawn»: Pokemon.PokemonSpawn.prototype.constructor};}; Pokemon.WorldState.prototype = Object.create (Phaser.State.prototype); Pokemon.WorldState.prototype.constructor = Pokemon.WorldState; Pokemon .WorldState.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; // iniciar la física del sistema this.game.physics.startSystem (Phaser.Physics.P2JS); 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);}; Pokemon.WorldState.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);}, 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); }}}; Pokemon.WorldState.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;}; 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576varPokemon = Pokemon || {}; Pokemon.WorldState = function () { «utilizar estricta»; Phaser.State.call (this); this.prefab_classes = {» pokemon_spawn «: Pokemon.PokemonSpawn.prototype.constructor};}; Pokemon.WorldState.prototype = Object.create (Phaser.State.prototype); Pokemon.WorldState.prototype.constructor = Pokemon.WorldState; Pokemon.WorldState.prototype.init = function (level_data) { «use strict»; vartileset_index; this.level_data = level_data; this.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL; this.scale.pageAlignHorizontally = true; this.scale.pageAlignVertically = true; // inicio la física systemthis.game.physics.startSystem (Phaser.Physics.P2JS); this.game.physics.arcade.gravity.y = 0; // crear el mapa y conjunto tilesetthis.map = this.game.add.tilemap (level_data. map.key); tileset_index = 0; this.map.tilesets.forEach (función (conjunto de baldosas) {this.map.addTilesetImage (tilese t.name, level_data.map.tilesets [tileset_index]); tileset_index + = 1;}, this);}; Pokemon.WorldState.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);}, this); // cambio de tamaño el mundo sea el tamaño de las layerthis.layers actuales [this.map.layer.name] .resizeWorld (); // crear groupsthis.groups = {}; this.level_data.groups.forEach (function (GROUP_NAME) {este .Grupos [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);}}}; Pokemon.WorldState.prototype.create_object = función (objeto) { «utilizar estricta»; varobject_y, la posición, prefabricada; // coordenadas azulejos comienza en la parte inferior izquierda = cornerobject_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 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;};

        las “create_object” método se inicia mediante el cálculo de la posición prefabricada porque queremos que el punto de anclaje los sprites sean sus centros, mientras baldosa utilizan como la esquina inferior izquierda del objeto. A continuación, creamos una instancia de la correcta prefabricada mediante la propiedad “prefab_classes” exactamente de la misma manera que hicimos en CatchState.

        A estas alturas, puede intentar iniciar tanto CatchState y WorldState para ver si se están creando correctamente las casas prefabricadas. Con el fin de hacer eso hay que añadir todas las casas prefabricadas en la propiedad “prefab_classes”, incluso si no están haciendo nada. Debería ver las pantallas siguientes:

        mundo atrapar

        PokemonSpawn prefabricada

        Vamos a empezar por crear la PokemonSpawn prefabricada, que mostrará un Pokémon en el mundo, y permitir al jugador para atraparla. Este prefabricada será utilizado en WorldState, así que asegúrese de cambiar el código para comenzar con WorldState con el fin de probarlo.

        El código para PokemonSpawn se muestra a continuación. En el constructor es necesario establecer adecuadamente el punto de anclaje y la escala. A continuación, hacemos posible que la entrada de la misma, así como añadir un evento onInputDown. Este evento se llama al método “try_catching”, que se limitará a iniciar CatchState.
        var Pokemon = Pokemon || {}; Pokemon.PokemonSpawn = function (game_state, nombre, posición, propiedades) { «utilizar estricta»; Pokemon.Prefab.call (esto, game_state, nombre, posición, propiedades); this.anchor.setTo (0,5); this.scale.setTo (0,5); // evento de entrada añadir a intentar la captura de este Pokémon this.inputEnabled = true; this.events.onInputDown.add (this.try_catching, este);}; Pokemon.PokemonSpawn.prototype = Object.create (Pokemon.Prefab.prototype); Pokemon.PokemonSpawn.prototype.constructor = Pokemon.PokemonSpawn; Pokemon.PokemonSpawn. prototype.try_catching = function () { «utilizar estricta»; // iniciar CatchState this.game_state.game.state.start ( «BootState», verdadero, falso, «activos / niveles / catch_level.json», «CatchState»);}; 12345678910111213141516171819202122varPokemon = Pokemon || {}; Pokemon.PokemonSpawn = función (game_state, nombre, posición, propiedades) { «uso estricto»; Pokemon.Prefab.call (esto, game_state, nombre, posición, propiedades); this.anchor.setTo (0,5); this.scale.setTo (0,5 ); // evento de entrada añadir a tratar de atrapar este Pokemonthis.inputEnabled = true; this.events.onInputDown.add (this.try_catching, this);}; Pokemon.PokemonSpawn.prototype = Object.create (Pokemon.Prefab.prototype) ; Pokemon.PokemonSpawn.prototype.constructor = Pokemon.PokemonSpawn; Pokemon.PokemonSpawn.prototype.try_catching = function () { «use strict»; // iniciar CatchStatethis.game_state.game.state.start ( «BootState», verdadero, falso «activos / niveles / catch_level.json», «CatchState»);};.

        Por ahora, puede intente hacer clic en el Pokemon en WorldState y comprobar si se inicia correctamente CatchState

        Pokemon y Pokeball prefabricados

        Ahora vamos a crear las casas prefabricadas para los Pokemon y la Pokeball, puesto que estas dos casas prefabricadas trabajarán juntos con el fin de permitir al jugador para atrapar Pokémon.

        En primer lugar, vamos a crear el constructor de Pokemon de la siguiente manera. El constructor simplemente guardar el tipo que huye de Pokemon es propiedades (definidos en el archivo JSON), y comenzará su cuerpo físico. Para el cuerpo físico tenemos que definirlo como algo estático, ya que no queremos que se mueva, a definir su cuerpo colisión como un círculo, establecer su grupo de colisión y decirle al motor que colisiona con grupos que (el grupo pokeballs, en nuestra caso).
        var Pokemon = Pokemon || {}; Pokemon.Pokemon = function (game_state, nombre, posición, propiedades) { «utilizar estricta»; Pokemon.Prefab.call (esto, game_state, nombre, posición, propiedades); this.BODY_RADIUS = 30; this.fleeing_rate = properties.fleeing_rate; // initialize Pokemon física this.game_state.game.physics.p2.enable cuerpo (this); = This.body.static verdaderos; this.body.setCircle (this.BODY_RADIUS); this.body.setCollisionGroup (this.game_state.collision_groups.pokemons); this.body.collides ([this.game_state.collision_groups.pokeballs]);}; Pokemon.Pokemon.prototype = Object.create (Pokemon.Prefab.prototype); Pokemon.Pokemon.prototype.constructor = Pokemon.Pokemon; 1234567891011121314151617181920varPokemon = Pokemon || {}; Pokemon.Pokemon = función (game_state, nombre, posición, propiedades) { «uso estricto»; Pokemon.Prefab.call (esto, game_state, nombre, posición, propiedades); this.BODY_RADIUS = 30; este .fleeing_rate = properties.fleeing_rate; // initialize Pokemon bodythis.game_state.game.physics.p2.enable física (this); this.body.static = true; this.body.setCircle (this.BODY_RADIUS); this.body. setCollisionGroup (this.game_state.collision_groups.pokemons); this.body.collides ([this.game_state.collision_groups.pokeballs]);}; Pokemon.Pokemon.prototype = Object.create (Pokemon.Prefab.prototype); Pokemon.Pokemon .prototype.constructor = Pokemon.Pokemon;

        Ahora que tenemos nuestro Collidable Pokemon, vamos a ir a la casa prefabricada Pokeball. En el constructor (que se muestra a continuación) que necesitamos para salvar algunas de las propiedades que se utilizarán más adelante y crear eventos de entrada. Vamos a utilizar dos eventos de entrada:


        1. cuando el jugador hace clic en la Pokeball que comenzarán arrastrándolo
        2. cuando el jugador lanza la Pokeball debe tirar

          var Pokemon = Pokemon || {}; Pokemon.Pokeball = function (game_state, nombre, posición, propiedades) { «utilizar estricta»; rotate_tween var; Pokemon.Prefab.call (esto, game_state, nombre, posición, propiedades); this.TWEEN_DURATION = 0,5; this.THROW_THRESHOLD = 50; this.pokeball_speed = properties.pokeball_speed; this.catching_rate = properties.catching_rate; this.dragging = false; this.initial_position = {x: this.x, Y: this.y}; // eventos de entrada complemento para arrastrar y tirar la Pokeball this.inputEnabled = true; this.events.onInputDown.add (this.drag, este); this.events.onInputUp.add (this.throw, this);}; Pokemon.Pokeball.prototype = Object.create (Pokemon.Prefab.prototype); Pokemon.Pokeball.prototype.constructor = Pokemon.Pokeball; 12345678910111213141516171819202122232425varPokemon = Pokemon | | {}; Pokemon.Pokeball = function (game_state, nombre, posición, propiedades) { «utilizar estricta»; varrotate_tween; Pokemon.Prefab.call (esto, game_state, nombre, posición, propiedades); this.TWEEN_DURATION = 0,5; esta .THROW_THRESHOLD = 50; this.pokeball_speed = properties.pokeball_speed; this.catching_rate = properties.catching_rate; this.dragging = false; this.initial_position = {x: this.x, Y: this.y}; // eventos de entrada add para arrastrar y tirar el pokeballthis.inputEnabled = true; this.events.onInputDown.add (this.drag, este); this.events.onInputUp.add (this.throw, este);}; Pokemon.Pokeball.prototype = Object .Create (Pokemon.Prefab.prototype); Pokemon.Pokeball.prototype.constructor = Pokemon.Pokeball;

          por lo tanto, vamos a poner en práctica los métodos de esos dos eventos de entrada. En primer lugar, el método de “arrastrar” simplemente establecer el “arrastre” a true. Entonces, tenemos que cambiar el método de “actualización” para cambiar la posición Pokeball a ser el mismo que el puntero activo si está siendo arrastrado.
          Pokemon.Pokeball.prototype.drag = function () { «utilizar estricta»; this.dragging = true;}; Pokemon.Pokeball.prototype.update = function () { «utilizar estricta»; // si el pokeball está siendo arrastrado, actualizar su posición para seguir el puntero activo si (this.dragging) {this.x = this.game_state.game.input.activePointer.x; this.y = this.game_state.game.input.activePointer.y; }}; 12345678910111213Pokemon.Pokeball.prototype.drag = function () { «utilizar estricta»; this.dragging = true;}; Pokemon.Pokeball.prototype.update = function () { «utilizar estricta»; // si el pokeball está siendo arrastrado, actualizar su posición de seguir la pointerif activa (this.dragging) {this.x = this.game_state.game.input.activePointer.x; this.y = this.game_state.game.input.activePointer.y; }};

          el método “tirar”, por su parte, se iniciará mediante el establecimiento de la “arrastrando” propiedad en false. A continuación, se calcula la distancia que la pokeball fue arrastrado, a partir de su distancia a la posición inicial. Si se arrastró por encima de un umbral predefinido, entonces deberíamos tirar la pokeball inicializando su cuerpo físico y el cambio de su velocidad en ambas direcciones x e y.
          Pokemon.Pokeball.prototype.throw = function () { «utilizar estricta»; distance_to_initial_position var; // parada draggin la this.dragging pokeball = false; // tirar la pokeball si la distancia a la posición inicial está por encima del umbral distance_to_initial_position = new Phaser.Point (this.x – this.initial_position.x, this.y – this.initial_position.y); si (distance_to_initial_position.getMagnitude ()> this.THROW_THRESHOLD) {distance_to_initial_position.normalize (); // inicializar el this.init_body cuerpo físico pokeball (); this.body.velocity.x = -distance_to_initial_position.x * this.pokeball_speed; this.body.velocity.y = -distance_to_initial_position.y * this.pokeball_speed; } Else {this.reset (this.initial_position.x, this.initial_position.y); }}; 12345678910111213141516171819Pokemon.Pokeball.prototype.throw = function () { «utilizar estricta»; vardistance_to_initial_position; // parada draggin la pokeballthis.dragging = false; // tirar la pokeball si la distancia a la posición inicial está por encima del thresholddistance_to_initial_position = newPhaser.Point (this.x-this.initial_position.x, this.y-this.initial_position.y), si (distance_to_initial_position.getMagnitude ()> this.THROW_THRESHOLD) {distance_to_initial_position.normalize (); // inicializar la física pokeball bodythis.init_body (); this.body.velocity.x = -distance_to_initial_position.x * this.pokeball_speed; this.body.velocity.y = -distance_to_initial_position.y * this.pokeball_speed;} else {this.reset (this.initial_position .x, this.initial_position.y);}};

          Ahora vamos a poner en práctica el método “init_body”. El cuerpo físico Pokeball será similar a la de un Pokemon, excepto que no será estático y vamos a añadir una devolución de llamada ( “start_catching”) para cuando choca con un Pokémon.
          Pokemon.Pokeball.prototype.init_body = function () { «utilizar estricta»; this.game_state.game.physics.p2.enable (this); this.body.setCircle (this.width / 2); this.body.setCollisionGroup (this.game_state.collision_groups.pokeballs); this.body.collides ([this.game_state.collision_groups.pokemons]); // iniciar la captura de un Pokémon cuando los colisiona con pokeball que this.body.onBeginContact.add (this.start_catching, this);}; 123456789Pokemon.Pokeball.prototype.init_body = function () { «use strict»; this.game_state. game.physics.p2.enable (this); this.body.setCircle (this.width / 2); this.body.setCollisionGroup (this.game_state.collision_groups.pokeballs); this.body.collides ([this.game_state. collision_groups.pokemons]); // iniciar la captura de un Pokémon cuando los colisiona con pokeball itthis.body.onBeginContact.add (this.start_catching, this);};

          las “start_catching” método comienza por destruir el cuerpo físico, ya no lo necesitamos más y hará que los Pokémon invisibles. A continuación, se reproducirá una animación de interpolación de rotación para simular el proceso de recuperación. Cuando se realiza la animación de interpolación se llamará a un método “try_catching”, que comprobará si el Pokemon fue capturado con éxito.

          El método “try_catching” generará un número aleatorio entre 0 y 1 y compararla con la tasa de captura de pokeball. Si el número generado es menor que la tasa de captura de los Pokémon fue capturado con éxito, y tenemos que matar a la Pokeball. De lo contrario, todavía tenemos que comprobar si el Pokemon huirá. Si es así, también tenemos que matar a la Pokeball y volver a WorldState, por lo que el jugador no puede lanzar más. De lo contrario, simplemente hacemos lo visible pokemon de nuevo y restablecer el Pokeball a su posición inicial.
          Pokemon.Pokeball.prototype.start_catching = function (body_b) { «utilizar estricta»; pokemon var, pokemon_position, rotate_tween; this.body.destroy (); pokemon = body_b.sprite; = Pokemon.visible FALSE; // jugar una animación Girar para simular la rotate_tween proceso de recuperación = this.game_state.game.add.tween (this); rotate_tween.to ({ángulo: «-45»}, Phaser.Timer.SECOND * this.TWEEN_DURATION); rotate_tween.to ({ángulo: «90»}, Phaser.Timer.SECOND * this.TWEEN_DURATION * 2); rotate_tween.to ({ángulo: «-45»}, Phaser.Timer.SECOND * this.TWEEN_DURATION); rotate_tween.onComplete.add (this.try_catching.bind (esto, pokemon), este); rotate_tween.start ();}; Pokemon.Pokeball.prototype.try_catching = function (pokemon) { «utilizar estricta»; random_number var; // Comprobar si el pokemon fue capturado random_number = this.game_state.rnd.frac (); si (random_number Ahora tenemos que poner en práctica la “captura” y “huido” en los métodos la prefabricada Pokemon.

          El primer método simplemente matar a los Pokémon e imprimir un mensaje en la consola y volver a WorldState. El segundo método se iniciará mediante la generación de un número aleatorio entre 0 y 1. Si este número es inferior a la tasa que huye Pokemon, entonces exitosamente la fuga. Entonces, nos limitaremos a imprimir un mensaje en la consola si el Pokemon ha huido y volveremos es resultado en el final del procedimiento.
          Pokemon.Pokemon.prototype.catch = function () { «utilizar estricta»; // matar a los pokemon y mostrar el cuadro de mensaje de captura this.kill (); console.log ( «Gotcha!»); this.game_state.return_to_world ();}; Pokemon.Pokemon.prototype.fled = function () { «utilizar estricta»; flee_chance var, huyó; // Comprobar si el Pokemon huirá flee_chance = this.game_state.rnd.frac (); huido = flee_chance Finally, we only need to implement the “return_to_world” method in CatchState. This method will simply start WorldState with the world JSON file.

          Pokemon.CatchState.prototype.return_to_world = function () { «use strict»; this.game.state.start(«BootState», true, false, «assets/levels/world_level.json», «WorldState»);};1234Pokemon.CatchState.prototype.return_to_world=function(){«use strict»;this.game.state.start(«BootState»,true,false,»assets/levels/world_level.json»,»WorldState»);};

          By now you can already try catching a Pokemon. Try changing the catch and fleeing rates in order to test different outcomes.

          catching

          MessageBox prefab

          In the end of this tutorial we are going to show message boxes when a Pokemon is caught or when it flees. Those message boxes will have input events to call methods from the game state.

          Let’s start by creating the MessageBox prefab. This prefab will simply create a TextPrefab to show its message and add an input event. The input event will call a method from the game state defined in the “callback” property from the properties parameter.

          var Pokemon = Pokemon || {};Pokemon.MessageBox = function (game_state, name, position, properties) { «use strict»; Pokemon.Prefab.call (esto, game_state, nombre, posición, propiedades); // create TextPrefab to show the message this.message_text = new Pokemon.TextPrefab(this.game_state, this.name + «_text», Object.create(this.position), properties.text_properties); this.message_text.anchor.setTo(0.5); // add input event to call game state method this.inputEnabled = true; this.events.onInputDown.add(this.game_state[properties.callback], this.game_state);};Pokemon.MessageBox.prototype = Object.create(Pokemon.Prefab.prototype);Pokemon.MessageBox.prototype.constructor = Pokemon.MessageBox;1234567891011121314151617varPokemon=Pokemon||{};Pokemon.MessageBox=function(game_state,name,position,properties){«use strict»;Pokemon.Prefab.call(this,game_state,name,position,properties);// create TextPrefab to show the messagethis.message_text=newPokemon.TextPrefab(this.game_state,this.name+»_text»,Object.create(this.position),properties.text_properties);this.message_text.anchor.setTo(0.5);// add input event to call game state methodthis.inputEnabled=true;this.events.onInputDown.add(this.game_state[properties.callback],this.game_state);};Pokemon.MessageBox.prototype=Object.create(Pokemon.Prefab.prototype);Pokemon.MessageBox.prototype.constructor=Pokemon.MessageBox;

          Now let’s change the Pokemon prefab to show the message boxes when the Pokemon is caught or when it flee s.

          First, we are going to add a “MESSAGE_PROPERTIES” property in the Pokemon prefab constructor, which will be used to create the message boxes. Notice that the callback for the message boxes will be the “return_to_world” method in game state. Then, we can change the “catch” method to, instead of printing a message in the console, it will show a message box. Next we are going to change the “fled” method to also create a message box instead of printing a message in the console.

          var Pokemon = Pokemon || {};Pokemon.Pokemon = function (game_state, name, position, properties) { «use strict»; Pokemon.Prefab.call (esto, game_state, nombre, posición, propiedades); this.BODY_RADIUS = 30; this.MESSAGE_PROPERTIES = { texture: «message_box_image», group: «hud», anchor: {x: 0.5, y: 0.5}, callback: «return_to_world», text_properties: { text: «», group: «hud», style: { font: «32px Arial», fill: «#000» } } }; this.fleeing_rate = properties.fleeing_rate; // initialize Pokemon physical body this.game_state.game.physics.p2.enable(this); this.body.static = true; this.body.setCircle(this.BODY_RADIUS); this.body.setCollisionGroup(this.game_state.collision_groups.pokemons); this.body.collides([this.game_state.collision_groups.pokeballs]);};Pokemon.Pokemon.prototype = Object.create(Pokemon.Prefab.prototype);Pokemon.Pokemon.prototype.constructor = Pokemon.Pokemon;Pokemon.Pokemon.prototype.catch = function () { «use strict»; catch_message var; // matar a los pokemon y mostrar el cuadro de mensaje de captura this.kill (); catch_message = new Pokemon.MessageBox(this.game_state, «catch_message», {x: this.game_state.game.world.centerX, y: this.game_state.game.world.centerY}, this.MESSAGE_PROPERTIES); catch_message.message_text.text = «Gotcha!»;};Pokemon.Pokemon.prototype.fled = function () { «use strict»; var flee_chance, fled, flee_message; // check if the Pokemon will flee flee_chance = this.game_state.rnd.frac(); fled = flee_chance < this.fleeing_rate; if (fled) { // kill the Pokemon and show the fled message box this.kill(); flee_message = new Pokemon.MessageBox(this.game_state, "flee_message", {x: this.game_state.game.world.centerX, y: this.game_state.game.world.centerY}, this.MESSAGE_PROPERTIES); flee_message.message_text.text = "You lost it!"; } return fled;};12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758varPokemon=Pokemon||{};Pokemon.Pokemon=function(game_state,name,position,properties){"use strict";Pokemon.Prefab.call(this,game_state,name,position,properties);this.BODY_RADIUS=30;this.MESSAGE_PROPERTIES={texture:"message_box_image",group:"hud",anchor:{x:0.5,y:0.5},callback:"return_to_world",text_properties:{text:"",group:"hud",style:{font:"32px Arial",fill:"#000"}}};this.fleeing_rate=properties.fleeing_rate;// initialize Pokemon physical bodythis.game_state.game.physics.p2.enable(this);this.body.static=true;this.body.setCircle(this.BODY_RADIUS);this.body.setCollisionGroup(this.game_state.collision_groups.pokemons);this.body.collides([this.game_state.collision_groups.pokeballs]);};Pokemon.Pokemon.prototype=Object.create(Pokemon.Prefab.prototype);Pokemon.Pokemon.prototype.constructor=Pokemon.Pokemon;Pokemon.Pokemon.prototype.catch=function(){"use strict";varcatch_me ssage;// kill the Pokemon and show the catch message boxthis.kill();catch_message=newPokemon.MessageBox(this.game_state,"catch_message",{x:this.game_state.game.world.centerX,y:this.game_state.game.world.centerY},this.MESSAGE_PROPERTIES);catch_message.message_text.text="Gotcha!";};Pokemon.Pokemon.prototype.fled=function(){"use strict";varflee_chance,fled,flee_message;// check if the Pokemon will fleeflee_chance=this.game_state.rnd.frac();fled=flee_chanceFinally, we need to remove the calls to “return_to_world” that we added in the Pokemon and Pokeball prefabs.

          By now you can try catching a Pokemon again to see if the message boxes are being correctly displayed, as well as if the callback is being properly called.

          gotcha_messagelost_message

          And we finished the first part of this tutorial series. In the next tutorial we are going to allow the player to navigate the world in order to find Pokemon, which will be randomly spawned. We are also going to add different Pokemon, and a Pokedex menu where the player can see which Pokemon were already caught

          Mensajes relacionados

Deja una respuesta

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