10 de Diciembre, 2005

[PJRS] Todo es un bucle

Esta anotación forma parte de la serie Programando Juegos con Ruby y SDL.

En primer lugar creo que es indispensable saber qué queremos hacer antes de poder plantearnos cómo podemos hacerlo. Todos los juegos tienen un bucle principal en el que se implementa lo que se conoce como el motor del juego, y en este primer capítulo vamos a analizarlo.

El motor es importante, tanto que incluso en algunos juegos dicho bucle constituye el todo (como en Tetris, por ejemplo). En otros además hace falta proporcionar datos a ese bucle. Eso pasa con los niveles de DD2, que teniendo el motor completo, son los responsables de que el juego no esté acabado :(.

Aunque cada juego puede tener sus particularidades, voy a definir un esquema básico que nos permitirá partir de algo sencillo que luego podremos ir complicando.

Nuestro bucle tendrá las siguientes partes, expresadas en pseudocódigo con Ruby:

while ! terminar

	captura_eventos

	if toca_redibujar
		actualiza_estados
		dibuja
	end
end

Vamos a ver qué es cada cosa:

  • terminar: cuando terminar sea cierto, el bucle finalizará. Ningún juego es infinito :), por ejemplo: el jugador puede perder, ganar o decidir abandonar.
  • captura_eventos: esta parte se encarga de estudiar la comunicación con el usuario. ¿Se ha pusado UP? ¿El ratón ha hecho click en una posición determinada?
  • toca_redibujar: la máquina es capaz de dibujar en pantalla muy rápido pero, como seres humanos que somos (y por lo tanto criaturas limitadas :P), seriamos incapaces de apreciarlo. Así que con dibujar el equivalente a 60 FPS (Frames Por Segundo, o cuadros por segundo), será suficiente. Solo redibujaremos la pantalla cuando sea necesario y podremos emplear nuestra CPU para otras cosas también importantes.
  • actualiza_estados: en base a los eventos capturados, actualizamos las variables de nuestro juego. Por ejemplo: si se pulsó UP, actualizaremos la posición del objeto que controla el usuario para que se dibuje algo más arriba en la pantalla.
  • dibuja: este es el momento de actualizar la pantalla. En base a las variables que tenemos, redibujamos la pantalla representando el nuevo estado que refleja los eventos capturados.

Esto hay que entenderlo, es muy importante. Un ejemplo puede aclarar más las cosas. Supongamos TBOTK, y veamos qué corresponde con cada etapa.

El bucle
El bucle de TBOTK

terminar

Por ahora el juego no está muy avanzado y la única variable que se comprueba para salir del bucle es que se haya pulsado o no la tecla ESC. En el futuro esto será más complejo :).

captura_eventos

Esta parte es bastante estándar: primero me hago cargo de los eventos que genera SDL (como cuando el usuario cierra la ventana), y luego de las teclas generales que no requieren una atención especial (ESC para salir, se pulse como se pulse).

Posteriormente verifico si están pulsadas las teclas que controlan al personaje para saber al actualizar_estados si el usuario quiere que lo mueva o no, o si quiere que le diga qué ve, o lo que corresponda. Estas pulsaciones se procesan diferente: lo importante no es que se hayan pulsado, sino que estén pulsadas.

toca_redibujar

Aquí se verifican los ticks (milisegundos desde que se inicializó SDL), se pasa a frames por segundo, y si ha pasado al menos el tiempo deseado, redibujamos. En máquinas muy lentas puede ser que no lleguemos a tiempo, lo cual es malo. Los FPS nos ayudarán a ver qué tal va nuestro motor, porque si no conseguimos pasar de 20 en el hardware para el que estamos trabajando... es que algo marcha muy mal ;).

actualiza_estados

Por ejemplo, si nuestro héroe se está moviendo (en sentido figurado, solo sabemos que alquien pulsó la tecla adecuada), este es el momento de actualizar sus variables. Se tiene en cuenta que la posición a la que nos queremos desplazar sea pisable, porque las paredes del juego son sólidas y el personaje no debe traspasarlas, por ejemplo.

dibuja

Con los nuevos estados, redibujamos la pantalla.

En este caso se dibuja el mapa, compuesto por pequeñas imágenes de 16x16, luego se dibujan los objetos que tiene el mapa y finalmente al personaje. Es como componer un cuadro, pintando primero lo que queda más lejos, y al final lo que está más cerca.

Por esta entrega ya es suficiente. Recomiendo intentar identificar las diferentes etapas del bucle de juegos sencillos, como PONG o Space Invaders, detallando todo lo que seamos capaces de detallar empleando nuestro propio pseudocódigo. No importa cómo realmente pasen las cosas, sino cómo pensamos que pueden pasar. Es una buena práctica porque tarde o temprano tenderemos que pensar en el bucle de nuestro propio juego :).

Anotación por Juan J. Martínez, clasificada en: sdl, ruby, programming.

Hay 1 comentario

Gravatar

Me parece muy interesante todo lo que estás compartiendo en este blog. Siempre he tenido el sueño de desarrollar un juego propio. Aquí tienes un lector a partir de ahora.

por Urbanity, en 2005-12-10 01:04:55

Los comentarios están cerrados: los comentarios se cierran automáticamente una vez pasados 30 días. Si quieres comentar algo acerca de la anotación, puedes hacerlo por e-mail.

Algunas anotaciones relacionadas: