En la anterior entrada explicaba cómo se organizaba el juego que estábamos diseñando. Me gustaría entrar un poco a los detalles en todos los elementos para que veáis cómo funciona y cómo se relacionan las clases entre ellas, así que iré creando entradas para cada uno de los sistemas para poder explicar todo detenidamente.

Una cosa que me gustaría aclarar es que, ni hay una única forma de crear un juego, ni tampoco yo soy un experto en hacerlos. Sigo aprendiendo a día de hoy y lo único que pretendo es plasmar aquí las ideas que se me van quedando, por si a alguien le puede servir de guía.

En estas entradas vais a ver Coffeescript y Javascript continuamente. No es por liar, no os asustéis. Una vez se le pilla el truco es muy sencillo pasar de uno a otro. Probablemente dedique una entrada también a preparar el entorno y las herramientas que se encargan de “traducir” Coffeescript a Javascript más adelante.

El bucle principal

El bucle principal es un bloque de código que se ejecuta constantemente durante el juego. Normalmente se pueden distinguir tres elementos: procesar datos de entrada (teclado, ratón o joystick), actualizar los datos del juego (como las posiciones, o las velocidades de los objetos, por ejemplo) y dibujar los elementos en pantalla.

En cualquier otro lenguaje de programación podríamos usar un simple bucle while para implementar este bucle. En Javascript, tenemos la función setInterval, que nos permite especificar una función a ejecutar y un tiempo en milisegundos. Cada vez que pasen esos milisegundos, la función especificada será llamada.

function buclePrincipal() {
  console.log("Leyendo entrada");
  console.log("Actualizando datos del juego");
  console.log("Dibujando elementos en pantalla");
}

setInterval(buclePrincipal, 1000);

El tema de los bucles principales no acaba aquí, por supuesto. El problema que hay con el bucle que yo he presentado (a pesar de que es el que estamos usando ahora mismo), es que si el sistema tarda mucho en leer los datos de entrada o en actualizar los datos del juego  (por el motivo que sea) va a pasar más tiempo durante cada fase de dibujo y esto va a provocar que visualmente el juego se vea “a saltos”.

Os dejo un enlace a un artículo de Arthur Schreiber en nokarma.org donde enseña distintos tipos de bucles principales en Javascript y qué beneficios y desventajas tiene cada uno de ellos sobre los demás.

La clase Game

Normalmente, el bucle principal se suele encapsular en una clase que yo he denominado Game. Es la clase principal, que se encarga básicamente de inicializar el juego, crear todos los objetos necesarios y de almacenar el bucle principal del juego (que en mi caso es un método llamado update).

El código que vais a ver es la clase Game que nosotros estamos utilizando ahora mismo, con algunos pequeños cambios. Hay clases y objetos que no he nombrado hasta ahora, pero creo que aún así el código se puede “interpretar” para tener una idea general de lo que hace.

En cualquier caso, como ya he dicho antes, en próximas entradas hablaré de cada elemento por separado.

class Game
  constructor: ->
    # Global-accessible unique instances
    Singleton.EventDispatcher = new EventDispatcher
    Singleton.ResourceManager = new ResourceManager
    Singleton.InputListener = new InputListener

    # Current map
    @map = new Map "Map01"

    # Game-specific handlers
    @render = new Render "canvas"
    @render.set_dimensions @map.get_dimensions()

    # Instance entities
    @entities = []
    @entities.push new Minicom.Entity.Player

    # Collisions and physics
    @physics = new PhysicsSystem @map, @render, @entities

  update: ->
    # Clear screen and draw tiles
    @render.clear()
    @render.all @map.tiles
    # Check collisions and draw them
    @physics.update()
    # Render all entities (except map tiles)
    @render.all @entities
    # Update all behaviors for all entities
    for entity in @entities
      entity.update()