Unlimited WordPress themes, graphics, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Game Development
  2. Roguelike
Gamedevelopment

Cómo hacer su primer Roguelike

by
Difficulty:IntermediateLength:LongLanguages:

Spanish (Español) translation by Elías Nicolás (you can also view the original English article)

Roguelikes han estado en el centro de atención recientemente, con juegos como Dungeons of Dredmor, Spelunky, The Binding of Isaac y FTL llegando a un público amplio y recibiendo elogios de la crítica. Durante mucho tiempo disfrutado por los jugadores hardcore en un pequeño nicho, elementos roguelike en diversas combinaciones ahora ayudan a traer más profundidad y repetición a muchos géneros existentes.

Wayfarer a 3D roguelike currently in development
Wayfarer, un 3D roguelike actualmente en desarrollo.

En este tutorial, aprenderá cómo hacer un roguelike tradicional usando JavaScript y el motor de juego HTML 5 Phaser. ¡Al final, tendrás un juego totalmente funcional y simple como roguelike, jugable en tu navegador! (Para nuestros propósitos un roguelike tradicional se define como un solo jugador, aleatorio, basado en turnos de mazmorras-rastreador con permadeath.)

Click to play the game
Haga clic para jugar el juego.

Nota: Aunque el código de este tutorial utiliza JavaScript, HTML y Phaser, debería ser capaz de utilizar la misma técnica y conceptos en casi cualquier otro lenguaje de codificación y motor de juego.


Preparándose

Para este tutorial, necesitará un editor de texto y un navegador. Utilizo Notepad++, y prefiero Google Chrome por sus extensas herramientas de desarrollo, pero el flujo de trabajo será prácticamente el mismo con cualquier editor de texto y navegador que elija.

A continuación, debe descargar los archivos y comenzar con la carpeta init; Contiene Phaser y los archivos HTML y JS básicos de nuestro juego. Escribiremos nuestro código de juego en el archivo rl.js actualmente vacío.

El archivo index.html simplemente carga Phaser y nuestro archivo de código de juego antes mencionado:


Inicialización y definiciones

Por el momento, vamos a utilizar gráficos ASCII para nuestro roguelike—en el futuro, podríamos reemplazar estos con gráficos de mapa de bits, pero por ahora, el uso de ASCII simple hace nuestra vida más fácil.

Vamos a definir algunas constantes para el tamaño de la fuente, las dimensiones de nuestro mapa (es decir, el nivel) y cuántos actores aparecen en él:

También vamos a inicializar Phaser y escuchar los eventos  key-up del teclado, ya que estaremos creando un juego basado en turnos y queremos actuar una vez por cada golpe de tecla:

Dado que las fuentes monospace predeterminadas tienden a ser alrededor del 60% tan anchas como altas, hemos inicializado el tamaño del lienzo para que sea 0,6 * el tamaño de fuente * el número de columnas. También le decimos a Phaser que debería llamar a nuestra función create() inmediatamente después de que haya terminado de inicializar, momento en el cual inicializaremos los controles del teclado.

Puedes ver el juego hasta ahora aquí—¡no que hay mucho que ver!


El mapa

El mapa representa nuestro área de juego: una matriz 2D discreta (en oposición a continua) de azulejos, o células, cada una representada por un carácter ASCII que puede significar una pared (#: bloquea el movimiento) o el piso (.: Bloqueo de movimiento):

Vamos a utilizar la forma más simple de la generación de procedimientos para crear nuestros mapas: decidir al azar qué celda debe contener una pared y que un piso:

Esto nos debe dar un mapa donde el 80% de las celdas son paredes y el resto son pisos.

Inicializamos el nuevo mapa para nuestro juego en la función create(), inmediatamente después de configurar los oyentes de eventos de teclado:

Puedes ver la demo aquí—aunque, de nuevo, no hay nada que ver, ya que no hemos procesado el mapa todavía.


La pantalla

¡Es hora de dibujar nuestro mapa! Nuestra pantalla será una matriz 2D de elementos de texto, cada uno de los cuales contiene un solo carácter:

Dibujar el mapa rellenará el contenido de la pantalla con los valores del mapa, ya que ambos son simples caracteres ASCII:

Finalmente, antes de dibujar el mapa tenemos que inicializar la pantalla. Volvemos a nuestra función create():

Ahora debería ver un mapa aleatorio que se muestra al ejecutar el proyecto.

Click to view the game so far
Haz clic para ver el juego hasta ahora.

Actores

A continuación de la fila están los actores: nuestro personaje jugador, y los enemigos que deben derrotar. Cada actor será un objeto con tres campos: x e y para su ubicación en el mapa, y hp para sus puntos de golpe.

Mantenemos todos los actores en la matriz actorList (el primer elemento del cual es el jugador). También mantenemos una matriz asociativa con los lugares de los actores como claves para la búsqueda rápida, de modo que no tengamos que iterar sobre la lista completa de actores para encontrar qué actor ocupa un determinado lugar; Esto nos ayudará cuando codifiquemos el movimiento y el combate.

Creamos todos nuestros actores y asignamos una posición aleatoria libre en el mapa a cada uno:

¡Es hora de mostrar a los actores! Vamos a dibujar todos los enemigos como e y el personaje del jugador como tambien su número de puntos de vida:

Hacemos uso de las funciones que acabamos de escribir para inicializar y dibujar a todos los actores en nuestra función create():

¡Ahora podemos ver a nuestro personaje jugador y enemigos extendidos en el nivel!

Click to view the game so far
Haz clic para ver el juego hasta ahora.

Bloqueo y baldosas

Tenemos que asegurarnos de que nuestros actores no están corriendo de la pantalla y a través de las paredes, así que vamos a agregar este simple cheque para ver en qué direcciones un actor dado puede caminar:


Movimiento y combate

Finalmente hemos llegado a alguna interacción: ¡movimiento y combate! Puesto que, en los roguelikes clásicos, el ataque básico se dispara al moverse a otro actor, manejamos ambos en el mismo lugar, nuestra función moveTo(), que toma un actor y una dirección (la dirección es la diferencia deseada en x e Y a la posición en que el actor entra):

Básicamente:

  1. Nos aseguramos de que el actor esté tratando de moverse en una posición válida.
  2. Si hay otro actor en esa posición, lo atacamos (y lo matamos si su recuento de HP llega a 0).
  3. Si no hay otro actor en la nueva posición, nos movemos allí.

Tenga en cuenta que también mostramos un simple mensaje de victoria una vez que el último enemigo ha sido asesinado, y devolveremos false o true dependiendo de si hemos logrado o no realizar un movimiento válido.

Ahora, volvamos a nuestra función onKeyUp() y lo alteramos para que, cada vez que el usuario presione una tecla, borremos las posiciones del actor anterior desde la pantalla (dibujando el mapa en la parte superior), moveremos el personaje del jugador al nuevo Ubicación, y luego redibujar a los actores:

Pronto usaremos la variable acted para saber si los enemigos deben actuar después de cada entrada del jugador.

Click to view the game so far
Haz clic para ver el juego hasta ahora.

Inteligencia Artificial Básica

Ahora que nuestro personaje jugador se está moviendo y atacando, vamos a nivelar las probabilidades haciendo que los enemigos actúen de acuerdo a una ruta de búsqueda muy simple, siempre y cuando el jugador este a seis pasos o menos de ellos. (Si el jugador está más lejos, el enemigo camina aleatoriamente.)

Note que nuestro código de ataque no le importa a quién el actor está atacando; Esto significa que, si los alineas justo a la derecha, los enemigos se atacarán mientras tratan de perseguir al personaje del jugador, ¡estilo Doom!

También hemos añadido un mensaje de juego, que se muestra si uno de los enemigos mata al jugador.

Ahora todo lo que queda por hacer es hacer que los enemigos actúen cada vez que el jugador se mueve, lo que requiere agregar lo siguiente al final de nuestras funciones onKeyUp(), justo antes de dibujar a los actores en su nueva posición:

Click to view the game so far
Haz clic para ver el juego hasta ahora.

Bonus: Versión Haxe

Originalmente escribí este tutorial en un Haxe, un gran lenguaje multiplataforma que compila JavaScript (entre otros idiomas). A pesar de que he traducido la versión de arriba a mano para asegurarse de que obtener Javascript idiosincrásico, si, como yo, usted prefiere Haxe a JavaScript, puede encontrar la versión Haxe en la carpeta haxe de descarga de la fuente.

Primero debe instalar el compilador haxe y puede usar cualquier editor de texto que desee y compilar el código haxe llamando a haxe build.hxml o haciendo doble clic en el archivo build.hxml. También incluí un proyecto FlashDevelop si prefiere un IDE agradable a un editor de texto y una línea de comandos; Simplemente abra rl.hxproj y presione F5 para ejecutar.


Resumen

¡Eso es todo! Ahora tenemos un simple simple roguelike, con generación aleatoria de mapas, movimiento, combate, AI y condiciones tanto ganar y perder.

Estas son algunas ideas para las nuevas características que puede agregar a su juego:

  • Múltiples niveles
  • potenciadores
  • inventario
  • consumibles
  • equipo

¡A disfrutar!

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.