@ agnasg

Receta para Programar un juego

10-03-2006 8:17 PM
(actualizado 20-07-2011)

Introducción

Si Ud. está buscando apoyo para programar juegos en C/C++ ( es decir, en lenguaje C, o en su sucesor, lenguaje C++), definitivamente puedo darle unos cuantos consejos. Yo he estado dedicado al tema durante muchos años con resultados, por decirlo diplomáticamente, mixtos.
Primero, comience por leer las distintas secciones que encontrará aquí para darse

una idea general de la cantidad de información de la que debe enterarse. Debe navegar en internet en unos cuantos sitios para familiarizarse con las distintas herramientas, motores gráficos, y demás librerías.

¿Qué queremos hacer?

Antes de comenzar, tal como digo en otros sitios, lo importante es fijarse una meta real, sencilla, cercana, factible, posible, alcanzable. Si tratamos de acometer un proyecto tipo Dungeon Siege II, bueno, realmente, eso va a estar difícil. Así que como primer proyecto, deberíamos pensar en algo más simple, algo como un juego tipo pac man, tetris, o minesweeper. Cualquier cosa más complicada nos llevará a la frustración. El objetivo en una primera fase es familiarizarse con el proceso de creación, uso del compilador de C/C++, cómo ensamblar los distintos módulos del juego, y comenzar a ver resultados sencillos. Luego, podemos pensar en cosas más complicadas.

Por ejemplo en este artículo de Gamasutra aparece el trabajo de un grupo de estudiantes que desarrollaron 50 juegos cada uno en 7 días: ninguno de ellos es complicado, son juegos simples pero divertidos (uno de ellos fue el más jugado en el mes en que fue lanzado) Son juegos del tipo: “ayuda a la abeja Rosita a llegar al panal. Es tonto, pero puede resulta divertido de jugar y divertido de programar. Y en el proces
o es bastante lo que vas a descubrir.
Ud. debe estar pensando en saltarse esta parte e ir directamente a cómo se hace esto o aquello: mi recomendación es que no lo haga, lo que le voy a decir en este momento le va ahorrar meses de trabajo inútil e infructuoso: el párrafo anterior es mucho más importante de lo que parece. Debemos fijarnos una meta realizable o de lo contrario estamos destinados al fracaso. Por ello, seleccione una idea para un juego sencilla para empezar, a menos que ud. forme parte de un grupo grande, las probabilidades de que pueda emprender un proyecto tipo Dungeon Siege, Quake Arena, The Sims son nulas. Entiéndalo: es imposible. Pero si comienza por algo sencillo, puede ir adquiriendo las destrezas para realizar cosas más complejas, hasta acometer projectos de alta complejidad.

Diseño del juego

Antes de comenzar a echar código debemos tener un diseño. Es la respuesta a la pregunta formulada en la sección anterior (¿qué queremos hacer?) Este diseño debe incluir una descripción en 3 líneas del juego. Por ejemplo: “es un juego donde el personaje debe comerse unos puntos en cada nivel, y hay 4 enemigos que lo persiguen por todas partes. El movimiento de cada uno es diferente, y su estrategia para perseguirnos es distinta. Una vez que nos hemos comido todos los puntos, pasamos al siguiente nivel”. Esa es la descripción de pacman. Simple pero efectivo. Y si la implementación es buena, el juego se convierte en el mejor.

El diseño debe tomar en cuenta elementos básicos:

  1. El juego debe ser bueno. Eso significa divertido, atractivo, y que atrape al jugador y lo motive continuamente a seguir jugando. nadie quiere jugar un juego aburrido, repetitivo, desalentador, que no ofrezca un reto interesante, y que sea feo.
  2. Debe ser original. O al menos innovador. Si hacemos nuevamente pacman, tetris, o Doom, la gente terminará comparándolo con el original.
  3. El juego debe ser fácil de jugar. O al menos la interfase debe ser intuitiva. Si el juego incluye una interminable lista de comandos, al menos el juego debe ser lo suficientemente interesante para que el jugador justifique dedicar mucho tiempo a aprender a jugarlo.
  4. El juego debe ser fácil de jugar desde el punto de vista de la mecánica y la interfase, pero la dificultada del juego en sí es otra historia. Debe haber un equilibrio entre la dificultad del juego y diversión. Un juego muy fácil se pone aburrido muy pronto. Un juego muy difícil desalienta al jugador casual y al juego duro por igual. La dificultad debe venir en función de habilidad, destreza, rápidez y estrategia. El juego perfecto es el que combina adecuadamente estos elementos. Un juego con excesiva carga en la destreza o rapidez del jugador desanimará al jugador lento. Un juego basado principalmente en estrategia desalentará al jugador que busca acción.
  5. Los retos en cada nivel, o a través del desarrollo del juego deben ser de dificultad creciente. El jugador debe ser recompensado de alguna forma. Y esta recompensa debe ser proporcional a la dificultad del reto. El reto debe ser diferente cada vez, o al menos tener modificaciones consistentes a través del juego.

Para garantizar que este diseño cumple con todas estas características Ud. debe someter el juego a pruebas con jugadores reales, por ejemplo, sus amigos. Es probable que lo que Ud. considere el mejor juego nunca antes diseñado, tenga en realidad fallas obvias que Ud, por ser su creador, simplemente no detectó en el momento del diseño. Finalmente si Ud. va a diseñar un juego hay un requisito fundamental: Ud. debe ser un jugador consumado. Es muy difícil (por no decir imposible) diseñar un buen juego si nunca ha jugado o si ha jugado solamente en forma ocasional.

Diseño del juego: tipos, temática y estilos de juegos

Los juegos los podemos clasificar segun su tipo en:

  1. Shooters o FPS (First person shooter, disparador en primera persona). En estos juegos el objetivo es disparar y eliminar cualquier ser viviente que se nos atraviese. Aqui la temática no tiene mucha importancia , el objetivo es eliminar a los enemigos. Los jugadores que prefieren este tipo de juegos solo quieren acción. Ejemplos de este tipo de juegos son Quake, Grand Theft Auto, Half Life, etc..
  2. Aventuras. Un género donde la idea es explorar los ambientes y resolver acertijos.  Los jugadores que prefieren estos juegos están en búsqueda de aventuras (de ahi el nombre) más que acción. Ejemplos de estos juegos son Syberia, The Longest Journey, etc..
  3. Juego de rol. Son el tipo de juegos bassados en Calabozos y Castillo, donde el personaje asume un rol como guerrero, mago, cazador, etc.. El mejor ejemplo de este tipo de juegos es Diablo. Los MMORPG son juegos basados en este estilo, siendo World of Warcraft el más famoso.
  4. Estrategia. Estos juegos están basados en juegos de mesa, normalmente del estilo ajedrez y damas. El jugador que prefiere este tipo de juegos está en búsqueda de retos a su agilidad y habilidad mental.
  5. Arcades. Son una combinación de los shooters y los juegos de estrategia. En este tipo de juegos el objetivo es eliminar a los enemigos, pero aparte de agilidad y destreza, se requiere alguna estrategia de ataque. Pac man puede ser un buen ejemplo. No solamente hay que eliminar a los enemigos, sino que también es necesario una estrategia para hacerlo.
  6. Simulación. El juego presenta una simulación lo más realista posible de la operación un vehiculo. Ejemplos: aviones (Fligh Simulator), carros (Need for Speed), submarinos (Silent Hunter).

Por otro lado está la técnica (y tecnología) utilizada para desarrollar el juego. Las principales opciones aquí son las siguientes:

  1. 2D: Los juegos de aventuras (La isla del tesoro, Leisure Suit Larry) o Mario Bros son juegos 2D, donde la perspectiva en los ambientes y escenarios es simulada a través de un dibujo estático.
  2. 3D: Doom, Quake, Half Life, Medal of Honor son juegos 3D, donde los ambientes son dibujados dinámicamente por un motor gráfico.
  3. isométrica. Presenta una vista tridimensional en 2D. Los ejemplos más famosos son Fallout y Diablo.

¿Qué lenguaje de programación debemos usar?

¿Por qué C/C++? Un juego es un proyecto complejo que requiere varios meses de desarrollo. hasta el más sencillo juego (pacman, pong, go) necesita más de 1000 líneas de código. Eso siginifica que Ud. va a estar trabajando con un conjunto de archivos de código fuente para generar una aplicación compleja, la cual debe estar complemtamente bajo su dominio. De otra forma, la aplicación nofuncionará como Ud desea, tendrá bugs o errores que la harán inestable, y su proyecto de programación de un juego fracasará. El lenguaje de programación C++ es el mejor lenguaje de porogramación para realizar esta actividad, porque es potente y le permite controlar mejor su aplicación. Con C o C++ Ud. podrá saber en todo momento qué está pasando internamente con su juego. Otros lenguajes dificultan este objetivo.

Olvídese de Delphi, pascal, basic, o cualquier otro lenguaje por el estilo. Son ineficientes, y el código termina siendo demasiado desordenado para hacerle mantenimiento, es decir, para ampliarlo, corregirlo o modificarlo.
Si quiere hacer un juego en línea, por ejemplo, un juego MMORPG, o un juego que funcione en un browser, mi recomendación es que no lo haga en java. Yo he estado pensando en desarrollar un juego en línea, tipo Urban Dead, y tal como ese juego, lo quiero hacer en javascript, php y mysql. Son lenguajes y plataformas sencillas, poderosas, fáciles de mantener y, en definitiva, divertidas, que es lo que estamos buscando: diversión. Java es horrible, complejo, pesado, complicado, fastidioso, y como ya han dicho varios expertos, académicos, y autoridades en el tema, Java es 4 veces más dificil de mantener que php, un proyecto en java dura 4 veces más, java es 4 veces más frustrante que el equivalente en C++, o php. Es decir, es menos divertido. Tal vez Ud. no esté de acuerdo conmigo. Solo le voy a decir algo: muy pronto, dentro de unos meses, o dentro de pocos años, Ud. me dará la razón.

Si todavía en duda aquí está el diagrama de flujo definitivo para decidir las tecnologías para desarrollar un juego. Hay que seguirlo al pié de la letra.

Herramientas: compilador
Bien, nuestro tema es programar juegos en C/C++, así vamos a comenzar a adentrarnos en el tema central de este tutorial. Primero Ud. debe revisar detenidamente mi lista de sitios especializados en programación de juegos, ahi encontrará cursos de lenguaje C/C++, los motores gráficos, más importantes y las librerías requeridas para no reinventar la rueda. He agregado un resumen adicional de herramientas necesarias: Gamewood.

¿Dónde consigo un compilador?

Si tienes dinero, compra el Visual C++ de Microsoft, no inventes. Tiene el mejor ambiente de desarrollo y garantizas que lo que vas a producir correrá perfectamente en Windows. Si prefieres un compilador software libre, no lo pienses ni dos segundos, utiliza Bloodshed Dec C++, es el más completo, muy estable y bien documentado. Aqui hay un magnífico tutorial para utilizarlo. Otra posibilidad, en el caso de que eres más del tipo hacker, es utilizar el gcc. Aqui encontrarás una explicación de cómo instalarlo.

Herramientas: motor gráfico

Para determinar cuál motor gráfico debemos usar primero debemos estar seguro del tema de nuestro juego: ¿qué tipo de juego queremos hacer? Un arcade tipo pacman, una aventura tipo Duke Nukem, una simulación tipo Submarino, un juego de acción tipo Doom o Quake. Lo importante es que la primera idea que trates de implementar sea sencilla y que
la termines. De nada sirve un juego medio terminado. Además, produce mucha frustración.

Si te decides por un juego 2D, es decir, un juego de dos dimensiones tipo Pong, o pacman, o Duke Nukem el original, trata en la medida de lo posible de utilizar una librería gráfica universal como SDL. La puedes descargar aqui. Y aqui hay un excelente tutorial sobre cómo utilizarlo.

Otra alternativa más compleja es utilizar DirectX que es el API gráfico con el que es desarrollado la mayoría de los juegos actuales. Yo ofrezco un curso completo de 20 horas de iniciación en el uso de este API. Más información aqui.

La última alternativa es utilizar una librería gráfica (un motor o engine). En este lugar podrás encontrar una lista con cientos de motores gráficos (lo dejaron de actualizar en el 2000, pero también puedes buscar en Sourceforge o haciendo simplemente una búsqueda en Google). Yo personalmente recomiendo Irrlicht. Es simple, fácil de utilizar y extremadamente poderosa. Puedes hacer casi cualquier cosa.

Una nota sobre estos motores: ninguno incluye programación de juegos, sino solamente la parte gráfica. Es decir, le falta manejo de scripts, inteligencia artificial, sonido, búsqueda de caminos etc. Yo no recomiendo ninguna librería para desarrollo de juegos en particular. Si tuviera que realizar una recomiendación esta sería Gamestudio.
>No es gratis, los precios varían entre $99 y $799. Yo he utilizado el demo y puede ser una buena plataforma.
Una vez decidido el tema (un juego sencillo como Pong), el lenguaje (C++) y la plataforma (SDL, Irrlicht o API DirectX) ya tenemos todo listo para comenzar a trabajar.

¿Y los gráficos?

Uno de los dolores de cabeza de los programadores son los gráficos. Normalmente (hay ilustres excepciones) los programadores son incompetentes en lo que se refiere a hacer gráficos bonitos (la escenografía, los personajes, los iconos, etc.) Mi recomendación: trata de hacer un juego sin muchos gráficos, o trata que los gráficos sean simples. Por supuesto la otra posibilidad es buscarte un grafista que te ayude con esa parte, pero usualmente te va a pedir dinero por su trabajo (nadie va a ayudarte gratis en tu hobbie) y si lo hace gratis los resultados van a ser desalentadores porque tu ritmo de trabajo posiblemente no coincida con la velocidad de trabajo del artista. No dejes que todo esto te frustre: haz el juego de todas formas recuerda el adagio: un juego con menos bombos y platillos es mejor que ningún juego.

Componentes y Módulos

Tu juego va a requerir entre otros elementos los siguientes:

  1. Interfase: es el módulo que maneja toda la interacción con el jugador. Puede haber hasta tres componentes aqui:
    1. Menú principal: ofrece al usuario la posibilidad de crear un nuevo personaje o iniciar un juego nuevo, cargar un juego ya iniciado, modificar las opciones y configuración del juego, y salir.
    2. La interfase principal del juego, que controla los movimientos del personaje, o la dinámica principal del juego. Incluye comandos (bien sea con el mouse o con el teclado)
    3. La cónsola, es una interfase adicional y opcional, que permite agregar facilidades de configuración al juego, o agregar elementos no incluidos en la interfase principal.
  2. Motor gráfico: controla y permite todo el despliegue gráfico, carga y despliegue de los objetos del juego (personajes, personajes pseudo inteligentes, items del juego (armas, tesoros, libros). También se encarga del despliegue de los escenarios. Idealmente se debe utilizar un motor gráfico comercial o de dominio público como Irrlicht.
  3. Manejo de la lógica del juego. Es el módulo principal que controla todas las acciones del juego, que despliega todo lo que está sucediendo través de la interfase con el usuario . Tiene interfases con todos los demás módulos del sistema, incluyendo  el módulo de inteligencia artificial para controlar los objetos y psi. Lo ideal es que utilice un lenguaje interpretado para su manejo de forma tal que sea fácil de programar.
  4. Módulo de inteligencia artificial. Se encarga del manejo de los personajes pseudo inteligentes (PSI, controlados por el programa), su movimiento (pathfinding), rutinas de conversación, manejo de combates, etc. Este puede ser hasta el 25%-30% de la lógica principal del juego. Cada PSI requiere una lógica particular de cómo va a moverse, conversaciones si las tiene, estadísticas de combate, etc.. Esta es una famosa página que resume la mayoría de los conceptos que se manejan en IA, y también esta página que está dedicada específicamente a AI en los juegos.
  5. Lenguaje interpretado. La lógica del juego puede ser programado directamente en el lenguaje de programación utilizado (C++, por ejemplo) o puede utilizarse un lenguaje que permite de una forma sencilla utilizar los distintos objetos del juego. Un lenguaje interpretado ahorra mucho tiempo de programación porque no se requiere recompilar el juego cada vez que se agrega una nueva característica, un nuevo nivel, o un nuevo tipo de personaje.
  6. Módulo de sonido: reproductor de sonidos del juego y música.
  7. Módulo de entrada y salida. Controla la carga y gravación de los juegos en curso. Esto puede lucir simple pero en realidad requiere de una codificación cuidadosa.

Conclusión

Programar un juego es un trabajo difícil. Parece un laberinto, y Ud. debe saber moverse en él y “disfrutarlo“. Para el momento que estoy escribiendo esto me encuentro programando un roguelike (ver la sección dedicada a este tipo de juegos). Básicamente está listo, así que estoy programando la parte más compleja que es el combate. Específicamente el ataque de los monstruos (el ataque del jugador ya está programado). Una vez que lo terminé, el siguiente proceso es programar la rutina que controla la muerte del jugador (en los juegos roguelike hay permadead, es decir, la muerte es definitiva, no hay resurrección (como en Warcraft). Pero eso significa que debería programar un mecanismo para restaurar el estado del juego a como está al comienzo. Es decir, como si el juego estuviera comenzado desde cero. Para garantizar eso, hay que borrar toda la memoria asignada, y ejecutar el proceso de inicialización nuevamente (en los juegos roquelike esto es complejo, hay creación de los niveles, objetos, monstruos, estructuras de inventario, estructuras de diálogos, estructura para la lógica del juego, etc.). Se me ocurrió, que ya que estaba en esta fase, podía aprovechar de construir el menú principal al mismo tiempo, ya que el mismo incluye la opción de comenzar un juego nuevo (además de cargar un juego salvado, y salir del juego). Esta opción de comenzar un juego nuevo debe hacer lo mismo que cuando el personaje del juego muere. Ya yo había programado un sistema para manejo de la memoria, utilizando un banco central de memoria que es asignada al comienzo del juego y liberada al finalizar. Pero para este momento esto es utilizado solamente por los textos (los mensajes). Tenía que agregar las demás estructuras a este manejo. Hay muchas formas de hacerlo, pero la forma correcta en C++ (el juego está programado en este lenguaje) es codificar una clase base que incluye el manejo de los operadores de asignación de memoria. Entonces, lo único que tenía que hacer es que estos operadores utilizaran el sistema de manejo de memoria central. Una vez que el juego requiera colocar el juego a su estado inicial (como he dicho, bien porque el personaje muera o porque se seleccione la opción de iniciar un juego nuevo) lo unico que el sistema debe hacer es borrar el banco de memoria, y ejecutar el proceso de inicialización.

Lo anterior es una descripción resumida de todos los pasos que hay que hacer cuando quieres programar un pequeño elemento del juego. A veces resulta un rompecabezas (o un laberinto) bien complicado de entender. Pero este es un laberinto muy particular: no hay atajos. Los caminos que parecen conducirnos a la salida de una forma fácil, son en realidad trampas, caminos sin salida. Por ello, al programar un juego deberemos cumplir todos y cada uno de los pasos descritos en este tutorial. Sin excepciones.