En el último tutorial añadió una WorldState donde el jugador puede navegar y ligado con el BattleState creada en el primer tutorial. Ahora, vamos a mejorar nuestra BattleState, para incluir lo siguiente:


  • recompensa Batalla incluida la experiencia y los elementos
  • Sistema de nivel A en base a una tabla de experiencia
  • La posibilidad de utilizar elementos durante la batalla
  • Magic ataques junto con los ataques físicos actuales

    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.

      Activos de derechos de autor

      Los monstruos activos utilizados en este tutorial están disponibles en http://opengameart.org/content/2d-rpg-enemy-set y fueron creadas por los siguientes artistas: Brett Steele (Safir-Kreuz), Joe Raucci (Sylon ), Vicki Beinhart (Namakoro), Tyler Olsen (raíces). Los activos caracteres están disponibles en http://opengameart.org/content/24×32-characters-with-faces-big-pack y fueron creadas por Svetlana Kushnariova (e-mail: [email protected]). Todos los activos están disponibles a través de la licencia Creative Commons.

      archivos de código fuente

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

      Adición de la recompensa batalla

      Vamos a empezar por la adición de una recompensa batalla por cada encuentro enemigo. Para simplificar las cosas, la recompensa será siempre la misma, pero se puede añadir varios premios con diferentes probabilidades usando una estrategia similar a los encuentros enemigos.

      La recompensa se describirá en el archivo JSON nivel con los datos de encuentros de enemigos, como se muestra a continuación. Tenga en cuenta que estamos describiendo la experiencia, que será utilizado para aumentar los niveles de unidades de los jugadores y los elementos que se pueden obtener de ese encuentro.
      «enemy_encounters»: [{ «probabilidad»: 0,3, «enemy_data»: { «lizard1»: { «tipo»: «enemy_unit», «Posición»: { «x»: 100, «Y»: 100}, «propiedades «: { «textura»: «lizard_spritesheet», «grupo»: «enemy_units», «estadísticas»: { «ataque»: 30, «defensa»: 10, «salud»: 50, «velocidad»: 15}}} }, «recompensa»: { «experiencia»: 100, «elementos»: [{ «type»: «poción», «propiedades»: { «grupo»: «elementos», «health_power»: 50}}]}} , { «probabilidad»: 0,5, «enemy_data»: { «bat1»: { «type»: «enemy_unit», «posición»: { «x»: 100, «y»: 90}, «propiedades»: { » textura «: «bat_spritesheet», «grupo»: «enemy_units», «estadísticas»: { «ataque»: 10, «defensa»: 1, «salud»: 30, «velocidad»: 20}}} » bat2″ : { «type»: «enemy_unit», «posición»: { «x»: 100, «y»: 170}, «propiedades»: { «textura»: «bat_spritesheet», «grupo»: «enemy_units», » estadísticas «: { «ataque»: 10, «defensa»: 1, «salud»: 30, «velocidad»: 20}}}}, «recompensa»: { «experiencia»: 100, «elementos»: [{» type «: «poción», «propiedades»: {» grupo «: «elementos», «health_power»: 50}}]}}, {» probabilidad «: 1,0,» enemy_da ta «: { «scorpion1»: { «type»: «enemy_unit», «posición»: {» x «: 100, «y»: 50}, «propiedades»: { «textura»: «scorpion_spritesheet»,» grupo «: «enemy_units», «Estadísticas»: { «ataque»: 15, «defensa»: 1, «salud»: 20, «velocidad»: 10}}} » scorpion2″: { «type»: «enemy_unit» , «posición»: { «x»: 100, «y»: 100}, «propiedades»: { «textura»: «scorpion_spritesheet», «grupo»: «enemy_units», «estadísticas»: { «ataque»: 15 , «defensa»: 1, «salud»: 20, «velocidad»: 10}}}, «scorpion3»: { «type»: «enemy_unit», «posición»: { «x»: 100, «y»: 150}, «propiedades»: { «textura»: «scorpion_spritesheet», «grupo»: «enemy_units», «estadísticas»: { «ataque»: 15, «defensa»: 1, «salud»: 20, «velocidad» : 10}}}}, «recompensa»: { «experiencia»: 100, «elementos»: [{ «type»: «poción», «propiedades»: { «grupo»: «elementos», «health_power»: 50 }}]}} 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109″ enemy_encounters «: [{» probabilidad «: 0,3,» enemy_data «: {» lizard1 «: {» type «:» enemy_unit», «posición»: { «x»: 100, «Y»: 100}, «propiedades» : { «textura»: «lizard_spritesheet», «grupo»: «enemy_units», «estadísticas»: { «ataque»: 30, «defensa»: 10, «salud»: 50, «velocidad»: 15}}}} , «recompensa»: { «experiencia»: 100, «elementos»: [{ «type»: «poción», «propiedades»: { «grupo»: «elementos», «health_power»: 50}}]}}, { «probabilidad»: 0,5, «enemy_data»: { «bat1»: { «type»: «enemy_unit», «posición»: { «x»: 100, «y»: 90}, «propiedades»: { «textura «:» bat_spritesheet», «grupo»: «enemy_units», «estadísticas»: { «ataque»: 10, «defensa»: 1, «salud»: 30, «velocidad»: 20}}} » bat2″: { «type»: «enemy_unit», «posición»: { «x»: 100, «Y»: 170}, «propiedades»: { «textura»: «bat_spritesheet», «grupo»: «enemy_units», «estadísticas «: {» ataque «: 10,» defensa «: 1,» salud «: 30,» velocidad «: 20}}}},» recompensa «: {» experiencia «: 100,» elementos «: [{» tipo «:» poción», «propiedades»: { «grupo»: «elementos», «health_power»: 50}}]}}, { «probabilidad»: 1,0, «enemy_data»: { «scorpion1»: { «tipo» : «enemy_unit», «posición»: { «x»: 100, «y»: 50}, «propiedades»: { «textura»: «scorpion_spritesheet», «grupo»: «enemigo _units » «Estadísticas»: { «ataque»: 15, «defensa»: 1, «salud»: 20, «velocidad»: 10},}} «scorpion2»: { «type»: «enemy_unit»,» Posición «: {» x «: 100,» y «: 100},» propiedades «: {» textura «:» scorpion_spritesheet » «grupo»: «enemy_units», «estadísticas»: { «ataque»: 15,» defensa «: 1,» salud «: 20,» velocidad «: 10}}},» scorpion3 «: {» type «:» enemy_unit», «posición»: { «x»: 100, «y»: 150}, «propiedades»: { «textura»: «scorpion_spritesheet», «grupo»: «enemy_units», «estadísticas»: { «ataque»: 15, «defensa»: 1, «salud»: 20, «velocidad»: 10} }}}, «recompensa»: { «experiencia»: 100, «elementos»: [{ «type»: «poción», «propiedades»: { «grupo»: «elementos», «health_power»: 50}}] }}

      el aumento de la experiencia de las unidades jugador

      Vamos a utilizar la misma tabla de experiencia para todas las unidades de jugador, que definirán la experiencia necesaria para llegar a cada nivel y aumentar el corresponsal estadísticas. Esta tabla se define en un archivo JSON como se muestra a continuación. Tenga en cuenta que he utilizado las mismas estadísticas aumentan para todos los niveles sin considerar el equilibrio del juego, pero se debe utilizar la que más nos encuentre.
      [{ «Required_exp»: 100, «stats_increase»: { «ataque»: 1, «defensa»: 1, «velocidad»: 1, «salud»: 10}}, { «required_exp»: 200, «stats_increase»: { «ataque»: 1, «defensa»: 1, «velocidad»: 1, «salud»: 10}}, { «required_exp»: 300, «stats_increase»: { «ataque»: 1, «defensa»: 1 , «velocidad»: 1, «salud»: 10}}, { «required_exp»: 400, «stats_increase»: { «ataque»: 1, «defensa»: 1, «velocidad»: 1, «salud»: 10 }}, { «required_exp»: 500, «stats_increase»: { «ataque»: 1, «defensa»: 1, «velocidad»: 1, «salud»: 10}}, { «required_exp»: 600, «stats_increase «: {» ataque «: 1, «defensa»: 1, «velocidad»: 1, «salud»: 10}}] 12345678 [{» required_exp «: 100,» stats_increase «: {» ataque «: 1,» defensa «: 1,» velocidad «: 1,» salud «: 10}}, {» required_exp «: 200,» stats_increase «: {» ataque «: 1,» defensa «: 1,» velocidad «: 1,» la salud «: 10}}, {» required_exp «: 300,» stats_increase «: {» ataque «: 1,» defensa «: 1,» velocidad «: 1,» salud «: 10}}, {» required_exp «: 400, «stats_increase»: { «ataque»: 1, «defensa»: 1, «velocidad»: 1, «salud»: 10}}, { «required_exp»: 500, «stats_increase»: { «ataque»: 1 , «defensa»: 1, «velocidad» : 1, «salud»: 10}}, { «required_exp»: 600, «stats_increase»: { «ataque»: 1, «defensa»: 1, «velocidad»: 1, «salud»: 10}}] < p> Esta tabla experiencia debe ser cargado en el método de “precarga” del BattleState, y se inicializa en su método “crear”, como se muestra a continuación.
      RPG.BattleState.prototype.preload = function () { «utilizar estricta»; this.load.text ( «experience_table», «activos / niveles / experience_table.json»);}; // Guardar experiencia tabla this.experience_table = JSON.parse (this.game.cache.getText ( «experience_table»)); 1234567RPG.BattleState.prototype.preload = function () { «use strict»; this.load.text ( «experience_table», «activos / niveles / experience_table.json»);}; // Guardar experiencia tablethis.experience_table = JSON. parse (this.game.cache.getText ( «experience_table»));

      para añadir experiencia y los niveles de las unidades jugador vamos a añadir un método “receive_experience” para el prefabricado PlayerUnit. Este método se muestra en el código de abajo y aumenta la experiencia unidad. A continuación, se comprueba si la experiencia actual es suficiente para llegar al siguiente nivel. Esto se hace utilizando la tabla de experiencia cargada en el estado del juego. Cuando se alcanza un nuevo nivel, las estadísticas se incrementan de acuerdo a lo que se define en la tabla de experiencia. Además, la experiencia se pone a cero cuando se alcanza un nuevo nivel.
      RPG.PlayerUnit.prototype.receive_experience = function (experiencia) { «use strict»; next_level_data var, stat; // aumento experiencia this.stats.experience + = experiencia; next_level_data = this.game_state.experience_table [this.stats.current_level]; // si la experiencia actual es mayor que la necesaria para el siguiente nivel, la unidad gana un nivel si (this.stats.experience> = next_level_data.required_exp) {this.stats.current_level + = 1; this.stats.experience = 0; // estadísticas aumento unidad de acuerdo con nuevo nivel para (stat en next_level_data.stats_increase) {if (next_level_data.stats_increase.hasOwnProperty (STAT)) {this.stats [stat] + = next_level_data.stats_increase [Stat]; }}}}; 123456789101112131415161718RPG.PlayerUnit.prototype.receive_experience = función (experiencia) { «utilizar estricta»; varnext_level_data, stat; // aumento experiencethis.stats.experience + = experiencia; next_level_data = this.game_state.experience_table [this.stats. current_level]; // si la experiencia actual es mayor que la necesaria para el siguiente nivel, la unidad gana un levelif (this.stats.experience> = next_level_data.required_exp) {this.stats.current_level + = 1; this.stats.experience = estadísticas // aumento unidad de acuerdo con nueva levelfor (stat innext_level_data.stats_increase) {if (next_level_data.stats_increase.hasOwnProperty (STAT)) {this.stats [stat] + = next_level_data.stats_increase [stat];}} 0}};

      por último, hay que añadir la experiencia de recompensa de cada encuentro en el método “end_battle”, como se muestra a continuación. Esto puede hacerse dividiendo la experiencia para cada unidad de jugador, y llamando al método “receive_experience” para cada uno.
      RPG.BattleState.prototype.end_battle = function () { «utilizar estricta»; received_experience var; // reciben batalla recompensa received_experience = this.encounter.reward.experience; this.groups.player_units.forEach (function (player_unit) {// recibir la experiencia de player_unit.receive_experience enemigo (received_experience / this.groups.player_units.children.length); // Guardar actual partido Totales this.party_data [player_unit.name] .properties.stats = player_unit.stats;}, this); // volver a WorldState con el this.game.state.start de datos actual partido ( «BootState», verdadero, falso, «activos / niveles / level1.json», «WorldState», {party_data: this.party_data}); }; 12345678910111213141516RPG.BattleState.prototype.end_battle = function () { «utilizar estricta»; varreceived_experience; // recibir batalla rewardreceived_experience = this.encounter.reward.experience; this.groups.player_units.forEach (function (player_unit) {// recibir la experiencia de enemyplayer_unit.receive_experience (received_experience / this.groups.player_units.children.length); // Guardar statsthis.party_data actual partido [player_unit.name] .properties.stats = player_unit.stats;}, this); // go de nuevo a WorldState con el datathis.game.state.start actual partido ( «BootState», verdadero, falso, «activos / niveles / level1.json», «WorldState», {party_data: this.party_data});};

      Ahora, ya se puede tratar de juego y comprobar si las unidades jugador están recibiendo la cantidad correcta de experiencia en batalla.

      experiencia

      Adición de elementos y un inventario

      creará inventario y artículo prefabricados para representar los objetos del juego, el jugador puede llevar y utilizar en batalla. Después de terminar la creación de los artículos, vamos a añadir menús a la BattleState para permitir que el jugador utilice esos artículos.

      En primer lugar, el Inventario prefabricada se muestra a continuación. Se tendrá una lista de elementos y métodos para recopilar y utilizar objetos. El “collect_item” recibe un objeto con el tipo de elemento y las propiedades, y una instancia de la prefabricada elemento apropiado, de añadir a la lista. El “use_item” método consume el artículo, de sacarla de la matriz items.
      var = RPG RPG || {}; RPG.Inventory = function (game_state, nombre, posición, propiedades) { «utilizar estricta»; RPG.Prefab.call (esto, game_state, nombre, posición, propiedades); this.item_classes = { «poción»: RPG.Potion.prototype.constructor}; this.items = [];}; RPG.Inventory.prototype = Object.create (RPG.Prefab.prototype); RPG.Inventory.prototype.constructor = RPG.Inventory; RPG.Inventory.prototype.collect_item = function (item_object) { «utilizar estricta»; elemento var; // crear el elemento de elemento prefabricado = nuevos this.item_classes [item_object.type] (this.game_state, item_object.type + this.items.length, {x: 0, y: 0}, item_object.properties); this.items.push (elemento);}; RPG.Inventory.prototype.use_item = function (item_name, objetivo) { «utilizar estricta»; var ITEM_INDEX; // elemento Eliminar de la lista artículos para (ITEM_INDEX = 0; ITEM_INDEX Ahora, vamos a crear el elemento PREFA Bs. En primer lugar, vamos a crear una casa prefabricada de artículos genéricos, que todos los artículos se extenderán. Inicialmente, este prefabricada sólo tendrá un método de “uso”, que destruye a sí misma.
      var = RPG RPG || {}; RPG.Item = function (game_state, nombre, posición, propiedades) { «utilizar estricta»; RPG.Prefab.call (esto, game_state, nombre, posición, propiedades);}; RPG.Item.prototype = Object.create (RPG.Prefab.prototype); RPG.Item.prototype.constructor = RPG.Item; RPG. Item.prototype.use = function () { «utilizar estricta»; // Por defecto, el elemento se destruye this.kill ();}; 123456789101112131415varRPG = RPG || {}; RPG.Item = function (game_state, nombre, posición, propiedades) { «utilizar estricta»; RPG.Prefab.call ( esto, game_state, nombre, posición, propiedades);}; RPG.Item.prototype = Object.create (RPG.Prefab.prototype); RPG.Item.prototype.constructor = RPG.Item; RPG.Item.prototype.use = function () { «uso estricto»; // por defecto el artículo es destroyedthis.kill ();};

      Después de crear el prefabricada de artículo, podemos crear una casa prefabricada poción, como se muestra a continuación. La poción tendrá una potencia de salud, y debe poner en práctica el método de “uso” para aumentar la salud de la unidad de jugador objetivo.
      var = RPG RPG || {}; RPG.Potion = función (game_state, nombre, posición, propiedades) { «uso estricto»; RPG.Item.call (esto, game_state, nombre, posición, propiedades); this.health_power = properties.health_power;}; RPG.Potion.prototype = Object.create (RPG.Item.prototype); RPG.Potion.prototype.constructor = RPG.Potion; RPG.Potion.prototype.use = función (objetivo ) { «utilizar estricta»; RPG.Item.prototype.use.call (this); target.stats.health + = this.health_power;}; 1234567891011121314151617varRPG = RPG || {}; RPG.Potion = function (game_state, nombre, posición, propiedades) { «uso estricto»; RPG.Item.call (esto, game_state , nombre, posición, propiedades); this.health_power = properties.health_power;}; RPG.Potion.prototype = Object.create (RPG.Item.prototype); RPG.Potion.prototype.constructor = RPG.Potion; RPG.Potion .prototype.use = función (objetivo) { «utilizar estricta»; RPG.Item.prototype.use.call (this); target.stats.health + = this.health_power;};

      Finalmente, en el “end_battle” método que debe recoger los artículos obtenidos a partir de la derrota de los enemigos. Esto se puede hacer mediante la iteración a través de todos los elementos de la recompensa y llamando a la “collect_item” del inventario.
      RPG.BattleState.prototype.end_battle = function () { «utilizar estricta»; received_experience var; // reciben batalla recompensa received_experience = this.encounter.reward.experience; this.groups.player_units.forEach (function (player_unit) {// recibir la experiencia de player_unit.receive_experience enemigo (received_experience / this.groups.player_units.children.length); // Guardar actual partido Totales this.party_data [player_unit.name] .properties.stats = player_unit.stats;}, this); this.encounter.reward.items.forEach (function (item_object) {this.prefabs.inventory.collect_item (item_object);}, this); // volver a WorldState con el actual partido this.game.state.start datos ( «BootState», verdadero, falso, «activos / niveles / level1.json», «WorldState», {party_data: this.party_data, inventario: this.prefabs.inventory});}; 123456789101112131415161718192021RPG.BattleState.prototype.end_battle = function () { «utilizar estricta»; varreceived_experience; // recibir rewardreceived_experience batalla = this.encounter.reward.experience; this.groups.player_units.forEach (function (player_unit) {// recibir la experiencia de enemyplayer_unit.receive_experience (received_experience / this.groups.player_units.children.length); // Guardar statsthis.party_data actual partido [player_unit.name] .properties.stats = player_unit.stats; }, this); this.encounter.reward.items.forEach (function (item_object) {this.prefabs.inventory.collect_item (item_object);}, this); // volver a WorldState con el datathis.game actual partido. state.start ( «BootState», verdadero, falso, «activos / niveles / level1.json», «WorldState», {party_data: this.party_data, inventario: this.prefabs.invent ORY});};

      Ahora, ya puedes intentar jugar y comprobar si los artículos están siendo recogidos correctamente. Puesto que no hay diferencia de juego, sin embargo, usted tiene que imprimir algo de información en la consola para comprobar esto.

      Uso de los objetos en la batalla

      Para utilizar los elementos, vamos a añadir una acción elemento al menú de acciones. Cuando se selecciona, se mostrará los artículos disponibles para ser utilizados. Puesto que debemos alternar a través de menús, añadiremos métodos para ocultar y mostrar en el prefabricado de menú, como se muestra a continuación.
      RPG.Menu.prototype.show = function () { «utilizar estricta»; this.menu_items.forEach (function (menu_item) {menu_item.visible = true;}, this);}; RPG.Menu.prototype.hide = function () { «utilizar estricta»; this.menu_items.forEach (function (menu_item) {menu_item.visible = false;}, this);}; 12345678910111213RPG.Menu.prototype.show = function () { «uso estricto»; this.menu_items.forEach (function (menu_item ) {menu_item.visible = true;}, this);}; RPG.Menu.prototype.hide = function () { «utilizar estricta»; this.menu_items.forEach (function (menu_item) {menu_item.visible = false;} , this);};

      Ahora, tenemos que crear los elementos del menú y añadir la acción de artículos en el menú de acciones. El menú de artículos se creará en el Inventario prefabricada, por iteración a través de todos sus elementos para crear elementos de menú, de una manera similar como se hace para crear los menús de unidades. Para agregar el elemento de acción, hay que cambiar el método de “show_player_actions” en BattleState añadir que, como se muestra a continuación.
      RPG.Inventory.prototype.create_menu = función (posición) { «utilizar estricta»; menu_items var, ITEM_INDEX, artículo, menu_item, items_menu; // crear unidades de elementos de menú ITEM_INDEX = 0; menu_items = []; para (ITEM_INDEX = 0; ITEM_INDEX Tenga en cuenta que en aquellos menús que utilizamos dos nuevas casas prefabricadas elemento del menú: ItemMenuItem, que se utiliza para seleccionar los elementos a utilizar y IventoryMenuItem, utiliza para seleccionar el elemento de acción. Ambos prefabs se muestran a continuación. El ItemMenuItem debe desactivar el menú de objetos y activar el menú de unidades de jugador para seleccionar la unidad de jugador en el que se utilizará el elemento seleccionado. Por otro lado, el InventoryMenuItem debe desactivar y ocultar el menú de acciones, mientras que muestra y permite a los elementos del menú. Tenga en cuenta que la IventoryMenuItem se puede seleccionar sólo cuando hay más elementos restantes.
      var = RPG RPG || {}; RPG.ItemMenuItem = function (game_state, nombre, posición, propiedades) { «utilizar estricta»; RPG.MenuItem.call (esto, game_state, nombre, posición, propiedades);}; RPG.ItemMenuItem.prototype = Object.create (RPG.MenuItem.prototype); RPG.ItemMenuItem.prototype.constructor = RPG.ItemMenuItem; RPG. ItemMenuItem.prototype.select = function () { «utilizar estricta»; // acciones desactivar this.game_state.prefabs.items_menu.disable menú (); // Activar menú de unidades de jugador por lo que el jugador puede elegir el this.game_state.prefabs.player_units_menu.enable objetivo (); // Guardar elemento seleccionado this.game_state.current_item = This.Text;}; 12345678910111213141516171819varRPG = RPG || {}; RPG.ItemMenuItem = function (game_state, nombre, posición, propiedades) { «utilizar estricta»; RPG.MenuItem.call (esto, game_state, nombre, posición, propiedades);}; RPG.ItemMenuItem.prototype = Object.create (RPG.MenuItem.prototype); RPG.ItemMenuItem.prototype.constructor = RPG.ItemMenuItem; RPG.ItemMenuItem.prototype.select = function () { «uso estricto»; // acciones desactivar menuthis.game_state.prefabs.items_menu.disable (); // activar menú de unidades de jugador por lo que el jugador puede elegir el targetthis.game_state.prefabs.player_units_menu.enable (); // Guardar la selección itemthis.game_state.current_item = This.Text;}; var RPG RPG = || {}; RPG.InventoryMenuItem = function (game_state, nombre, posición, propiedades) { «utilizar estricta»; RPG.MenuItem.call (esto, game_state, nombre, posición, propiedades);}; RPG.InventoryMenuItem.prototype = Object.create (RPG.MenuItem.prototype); RPG.InventoryMenuItem.prototype.constructor = RPG.InventoryMenuItem; RPG. InventoryMenuItem.prototype.select = function () { «utilizar estricta»; // seleccionar sólo si hay elementos restantes si (this.game_state.prefabs.inventory.items.length> 0) {// menú de acciones desactivar this.game_state.prefabs.actions_menu.disable (); this.game_state.prefabs.actions_menu.hide (); // Activar menú de unidades enemigas por lo que el jugador puede elegir el objetivo this.game_state.prefabs.items_menu.show (); this.game_state.prefabs.items_menu.enable (); }}; 12345678910111213141516171819202122varRPG = RPG || {}; RPG.InventoryMenuItem = function (game_state, nombre, posición, propiedades) { «utilizar estricta»; RPG.MenuItem.call (esto, game_state, nombre, posición, propiedades);}; RPG.InventoryMenuItem.prototype = Object.create (RPG.MenuItem.prototype); RPG.InventoryMenuItem.prototype.constructor = RPG.InventoryMenuItem; RPG.InventoryMenuItem.prototype.select = function () { «uso estricto»; // seleccionar sólo si no se están quedando ItemsIf (this.game_state.prefabs.inventory.items.length> 0) {// acciones desactivar menuthis.game_state.prefabs.actions_menu.disable (); this.game_state.prefabs.actions_menu.hide (); / / activar menú de unidades enemigas por lo que el jugador puede elegir el targetthis.game_state.prefabs.items_menu.show (); this.game_state.prefabs.items_menu.enable ();}};

      todavía hay algunas cosas más hay que cambiar . En primer lugar, hay que cambiar el método de PlayerMenuItem “seleccionar” a utilizar el elemento actual seleccionado. En segundo lugar, debemos poner en práctica el método de “matar” de la casa prefabricada de artículos para quitarla de los elementos del menú. Ambas modificaciones se muestran a continuación.
      RPG.PlayerMenuItem.prototype.select = function () { «utilizar estricta»; player_unit var; // Obtener el reproductor seleccionado unidad player_unit = this.game_state.prefabs [This.Text]; // uso actual elemento seleccionado en la unidad seleccionada this.game_state.prefabs.inventory.use_item (this.game_state.current_item, player_unit); // Mostrar menú de acciones nuevo this.game_state.prefabs.items_menu.disable (); this.game_state.prefabs.items_menu.hide (); this.game_state.prefabs.actions_menu.show (); this.game_state.prefabs.actions_menu.enable ();}; RPG.Item.prototype.kill = function () { «utilizar estricta»; Phaser.Sprite.prototype.kill.call (this); var menu_item_index, menu_item; // elemento quitar del menú menu_item_index = this.game_state.prefabs.items_menu.find_item_index (this.name); menu_item = this.game_state.prefabs.items_menu.remove_item (menu_item_index); menu_item.kill ();}; 123456789101112131415161718192021222324RPG.PlayerMenuItem.prototype.select = function () { «utilizar estricta»; varplayer_unit; // obtener jugador seleccionado unitplayer_unit = this.game_state.prefabs [This.Text]; // actual uso seleccionan punto del unitthis.game_state.prefabs.inventory.use_item seleccionado (this.game_state.current_item, player_unit); // Mostrar menú de acciones againthis.game_state.prefabs.items_menu.disable (); this.game_state.prefabs.items_menu.hide () ; this.game_state.prefabs.actions_menu.show (); this.game_state.prefabs.actions_menu.enable ();}; RPG.Item.prototype.kill = function () { «utilizar estricta»; Phaser.Sprite.prototype. kill.call (this); varmenu_item_index, menu_item; // elemento remove de la menumenu_item_index = this.game_state.prefabs.items_menu.find_item_index (this.name); menu_item = this.game_state.prefabs.items_menu.remove_item (menu_item_index); menu_item .kill ();};

      por último, hay que mantener el inventario a través de la BattleState y WorldState. Esto puede hacerse mediante la adición de un nuevo parámetro en el método “init” de ambos estados que salva el inventario y las que se utilizará en cada transición de estado. Además, si no existe un inventario creado todavía (al comienzo del juego), debemos crear un vacío en el método de “crear” de BattleState.

      Ahora, ya puedes intentar jugar utilizando elementos. Recuerde verificar si todos los menús están funcionando correctamente y si las recompensas de objetos se actualizan correctamente.

      artículos

      Adición de ataques mágicos

      Nuestra última modificación agregará un nuevo ataque posible para cada unidad, llamada ataque mágico. Esos ataques se basan en un nuevo stat y se han aumentado los daños, pero se consumen maná.

      Para hacer eso, primero tenemos que cambiar nuestro código de ataque para ponerlo en una nueva prefabricada de ataque, como se muestra a continuación. El Ataque prefabricada tendrá una unidad de propietario, lo que representa la unidad que ataca e inicialmente contiene un método “show_message”, que mostrará el mensaje de ataque, como ya hacíamos. Ahora, vamos a crear un PhysicalAttack y unas casas prefabricadas MagicAttack que se extenderán éste y poner en práctica un método de “éxito”. Este método va a ejecutar el ataque.
      var = RPG RPG || {}; RPG.Attack = function (game_state, nombre, posición, propiedades) { «utilizar estricta»; RPG.Prefab.call (esto, game_state, nombre, posición, propiedades); this.owner = this.game_state.prefabs [properties.owner_name];}; RPG.Attack.prototype = Object.create (RPG.Prefab.prototype); RPG.Attack.prototype.constructor = RPG.Attack; RPG.Attack. prototype.show_message = función (objetivo, daños) { «utilizar estricta»; var action_message_position, action_message_text, attack_message; // Mostrar mensaje ataque action_message_position = new Phaser.Point (this.game_state.game.world.width / 2, this.game_state.game.world.height * 0,1); action_message_text = this.owner.name + «ataques» + target.name + «con» «daño» + daño +; attack_message = new RPG.ActionMessage (this.game_state, this.name + «_action_message», action_message_position, {grupo: «HUD», textura: «rectangle_image», escala: {x: 0,85, y: 0.2}, duración: 1, mensaje: action_message_text});}; 1234567891011121314151617181920varRPG = RPG || {}; RPG.Attack = function (game_state, nombre, posición, propiedades) { «utilizar estricta»; RPG.Prefab.call (esto, game_state, nombre, posición, propiedades); this.owner = this.game_state.prefabs [properties.owner_name];}; RPG.Attack.prototype = Object.create (RPG.Prefab.prototype); RPG.Attack.prototype.constructor = RPG.Attack; RPG .Attack.prototype.show_message = función (objetivo, daños) { «utilizar estricta»; varaction_message_position, action_message_text, attack_message; // espectáculo ataque messageaction_message_position = newPhaser.Point (this.game_state.game.world.width / 2, this.game_state .game.world.height * 0,1); action_message_text = this.owner.name + «ataques «+ target.name +» con «» daño «+ daño +; attack_message = newRPG.ActionMessage (this.game_state, this.name +» _ action_message», Actuar ion_message_position, {grupo: «HUD», textura: «rectangle_image», escala: {x: 0.85, Y: 0,2}, duración: 1, mensaje: action_message_text});};

      El código tanto para PhysicalAttack y MagicAttack es mostrado a continuación. El primero de ellos es exactamente el ataque que ya teníamos. Se calcula multiplicadores de ataque y defensa en base a las estadísticas de ataque y defensa, respectivamente, y se aplica el daño correcto. Por otro lado, el MagicAttack tiene tres diferencias principales: 1) que tiene un coste de maná; 2) el ataque multiplicador se basa en una estadística de ataque mágico; 3) El multiplicador de ataque es mayor, lo que resulta en aumento de los daños.
      var = RPG RPG || {}; RPG.PhysicalAttack = function (game_state, nombre, posición, propiedades) { «utilizar estricta»; RPG.Attack.call (esto, game_state, nombre, posición, propiedades);}; RPG.PhysicalAttack.prototype = Object.create (RPG.Attack.prototype); RPG.PhysicalAttack.prototype.constructor = RPG.PhysicalAttack; RPG. PhysicalAttack.prototype.hit = función (objetivo) { «utilizar estricta»; daño var, attack_multiplier, defense_multiplier, action_message_position, action_message_text, attack_message; // Calcular ataque al azar y los multiplicadores de defensa attack_multiplier = this.game_state.game.rnd.realInRange (0.8, 1.2); defense_multiplier = this.game_state.game.rnd.realInRange (0.8, 1.2); // daño daños calculate = Math.max (0, Math.round ((attack_multiplier * this.owner.stats.attack) – (defense_multiplier * target.stats.defense))); // aplicar target.receive_damage daños (daños); this.show_message (objetivo, daños);}; 1234567891011121314151617181920212223varRPG = RPG || {}; RPG.PhysicalAttack = function (game_state, nombre, posición, propiedades) { «utilizar estricta»; RPG.Attack.call (esto, game_state, nombre , posición, propiedades);}; RPG.PhysicalAttack.prototype = Object.create (RPG.Attack.prototype); RPG.PhysicalAttack.prototype.constructor = RPG.PhysicalAttack; RPG.PhysicalAttack.prototype.hit = función (objetivo) { «utilizar estricta»; vardamage, attack_multiplier, defense_multiplier, action_message_position, action_message_text, attack_message; // Calcular ataque al azar y defensa multipliersattack_multiplier = this.game_state.game.rnd.realInRange (0.8,1.2); defense_multiplier = this.game_state.game.rnd .realInRange (0.8,1.2); // Calcular damagedamage = Math.max (0, Math.round ((* attack_multiplier this.owner.stats.attack) – (* defense_multiplier target.stats.defense))); // aplicar damagetarget.receive_damage (daño); this.show_message (objetivo, daños);}; var RPG = RPG || {}; RPG.MagicAttack = function (game_state, nombre, posición, propiedades) { «utilizar estricta»; RPG.Attack.call (esto, game_state, nombre, posición, propiedades); this.mana_cost = properties.mana_cost;};RPG.MagicAttack.prototype = Object.create(RPG.Attack.prototype);RPG.MagicAttack.prototype.constructor = RPG.MagicAttack;RPG.MagicAttack.prototype.hit = function (target) { «use strict»; daño var, attack_multiplier, defense_multiplier, action_message_position, action_message_text, attack_message; // the attack multiplier for magic attacks is higher attack_multiplier = this.game_state.game.rnd.realInRange(0.9, 1.3); defense_multiplier = this.game_state.game.rnd.realInRange (0.8, 1.2); // calculate damage using the magic attack stat damage = Math.max(0, Math.round((attack_multiplier * this.owner.stats.magic_attack) – (defense_multiplier * target.stats.defense))); // apply damage target.receive_damage(damage); // reduce the unit mana this.game_state.current_unit.stats.mana -= this.mana_cost; this.show_message(target, damage);};12345678910111213141516171819202122232425262728varRPG=RPG||{};RPG.MagicAttack=function(game_state,name,position,properties){«use strict»;RPG.Attack.call(this,game_state,name,position,properties);this.mana_cost=properties.mana_cost;};RPG.MagicAttack.prototype=Object.create(RPG.Attack.prototype);RPG.MagicAttack.prototype.constructor=RPG.MagicAttack;RPG.MagicAttack.prototype.hit=function(target){«use strict»;vardamage,attack_multiplier,defense_multiplier,action_message_position,action_message_text,attack_message;// the attack multiplier for magic attacks is higherattack_multiplier=this.game_state.game.rnd.realInRange(0.9,1.3);defense_multiplier=this.game_state.game.rnd.realInRange(0.8,1.2);// calculate damage using the magic attack statdamage=Math.max(0,Math.round((attack_multiplier*this.owner.stats.magic_attack)-(defense_multiplier*target.stats.defense)));// apply damagetarget.receive_damage(damage);// reduce the unit manathis.game_state.current_unit.s tats.mana-=this.mana_cost;this.show_message(target,damage);};

      Now, we are going to change the Attack menu item to instantiate an Attack prefab and create the Magic menu item. The modification in AttackMenuItem is shown below. Instead of calling the “attack” method in the current unit it simply create a new Attack prefab. The MagicAttackMenuItem code is shown below. It can be selected only when the current unit has enough mana and create a new MagicAttack prefab. Notice that I’m using the same mana cost for all units, but you can change that if you want.

      var = RPG RPG || {}; RPG.AttackMenuItem = function (game_state, nombre, posición, propiedades) { «utilizar estricta»; RPG.MenuItem.call (esto, game_state, nombre, posición, propiedades);}; RPG.AttackMenuItem.prototype = Object.create (RPG.MenuItem.prototype); RPG.AttackMenuItem.prototype.constructor = RPG.AttackMenuItem; RPG. AttackMenuItem.prototype.select = function () { «utilizar estricta»; // acciones desactivar this.game_state.prefabs.actions_menu.disable menú (); // enable enemy units menu so the player can choose the target this.game_state.prefabs.enemy_units_menu.enable(); // save current attack this.game_state.current_attack = new RPG.PhysicalAttack(this.game_state, this.game_state.current_unit.name + «_attack», {x: 0, y: 0}, {group: «attacks», owner_name: this.game_state.current_unit.name});};12345678910111213141516171819varRPG=RPG||{};RPG.AttackMenuItem=function(game_state,name,position,properties){«use strict»;RPG.MenuItem.call(this,game_state,name,position,properties);};RPG.AttackMenuItem.prototype=Object.create(RPG.MenuItem.prototype);RPG.AttackMenuItem.prototype.constructor=RPG.AttackMenuItem;RPG.AttackMenuItem.prototype.select=function(){«use strict»;// disable actions menuthis.game_state.prefabs.actions_menu.disable();// enable enemy units menu so the player can choose the targetthis.game_state.prefabs.enemy_units_menu.enable();// save current attackthis.game_state.current_attack=newRPG.PhysicalAttack(this.game_state,this.game_state.current_unit.name+»_attack»,{x:0,y:0},{group:»attacks»,owner_name:this.game_state.current_unit.name});};var RPG = RPG || {};RPG.MagicAttackMenuItem = function (game_state, name, position, properties) { «use strict»; RPG.MenuItem.call (esto, game_state, nombre, posición, propiedades); this.MANA_COST = 10;};RPG.MagicAttackMenuItem.prototype = Object.create(RPG.MenuItem.prototype);RPG.MagicAttackMenuItem.prototype.constructor = RPG.MagicAttackMenuItem;RPG.MagicAttackMenuItem.prototype.select = function () { «use strict»; // use only if the current unit has enough mana if (this.game_state.current_unit.stats.mana >= this.MANA_COST) { // disable actions menu this.game_state.prefabs.actions_menu.disable(); // enable enemy units menu so the player can choose the target this.game_state.prefabs.enemy_units_menu.enable(); // save current attack this.game_state.current_attack = new RPG.MagicAttack(this.game_state, this.game_state.current_unit.name + «_attack», {x: 0, y: 0}, {group: «attacks», mana_cost: this.MANA_COST, owner_name: this.game_state.current_unit.name}); }};123456789101112131415161718192021222324varRPG=RPG||{};RPG.MagicAttackMenuItem=function(game_state,name,position,properties){«use strict»;RPG.MenuItem.call(this,game_state,name,position,properties);this.MANA_COST=10;};RPG.MagicAttackMenuItem.prototype=Object.create(RPG.MenuItem.prototype);RPG.MagicAttackMenuItem.prototype.constructor=RPG.MagicAttackMenuItem;RPG.MagicAttackMenuItem.prototype.select=function(){«use strict»;// use only if the current unit has enough manaif(this.game_state.current_unit.stats.mana>=this.MANA_COST){// disable actions menuthis.game_state.prefabs.actions_menu.disable();// enable enemy units menu so the player can choose the targetthis.game_state.prefabs.enemy_units_menu.enable();// save current attackthis.game_state.current_attack=newRPG.MagicAttack(this.game_state,this.game_state.current_unit.name+»_attack»,{x:0,y:0},{group:»attacks»,mana_cost:this.MANA_COST,owner_name:this.game_state.current_unit.name});}};

      In the next step we must change the HUD to show those new features. First, we change the “show_player_action” method in BattleState to add the Magic menu item, as shown below. Then, we change the PlayerMenuItem prefab to show its remaining mana, and not only its health.

      actions = [{text: «Attack», item_constructor: RPG.AttackMenuItem.prototype.constructor}, {text: «Magic», item_constructor: RPG.MagicAttackMenuItem.prototype.constructor}, {text: «Item», item_constructor: RPG.InventoryMenuItem.prototype.constructor}];123actions=[{text:»Attack»,item_constructor:RPG.AttackMenuItem.prototype.constructor},{text:»Magic»,item_constructor:RPG.MagicAttackMenuItem.prototype.constructor},{text:»Item»,item_constructor:RPG.InventoryMenuItem.prototype.constructor}];

      Finally, now you can define the initial mana and magic attack stats for each unit and try playing the game with all its contents. Try using different attacks to see if everything is working properly.

      magic

      And now, we finished this tutorial series! I hope you liked it, tell me your opinions in the comments section!

      Mensajes relacionados

Deja una respuesta

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