viernes, 4 de noviembre de 2011

[Culebrilla] Empezado con el juego: actualización del estado

En la entrada anterior hemos visto el bucle principal que tienen todos los juegos y cómo hay un paso que es el "corazón" del juego, donde se hacen los cálculos para que todo funcione. Es decir, la parte donde se actualiza el estado del juego.

Pongamos un caso concreto muy simple para entender mejor el concepto de actualizar el estado: tenemos una bala que empieza a la izquierda del todo (X = 0) y acaba en la derecha (X = 800). El estado en este caso sería la posición 2D de la bala, o si queremos reducirlo aún más, su posición en el eje horizontal (ya que en el vertical no hay cambios). En el sistema de coordenadas del ejemplo el eje horizontal es el X y el vertical el Y. El origen (0, 0) está arriba a la izquierda y abajo a la derecha es (799, 599). Por lo tanto tenemos una pantalla de 800x600 píxeles:


Recordemos el bucle del juego:
Inicializar
Mientras la cosa sigue:
  Atender eventos del SO
  Comprobar entrada del usuario (teclado, ratón, joystick, etc)
  Actualizar el estado (enemigos, disparos, reproducir sonidos, etc etc)
  Pintar los gráficos
Desinicializar
Vamos a ver cómo sería a grandes rasgos cada paso en nuestro ejemplo:

Inicializar
Creamos una variable llamada bulletPos y fijamos su valor a 0. Cargamos el gráfico de la bala y por último creamos la variable booleana done, que fijamos a false. Como veis uso nombres en inglés en el código.

Mientras la cosa sigue
Comprobamos si done es true. Si es así salimos del bucle, sino hacemos otra pasada. Básicamente sería esto:

while(!done)
{
// ...
}
Atender eventos del SO y Comprobar entrada del usuario
En este ejemplo obviamos estos pasos

Pintar los gráficos
Aquí con la librería de gráficos que tengamos dibujamos el gráfico que hemos cargado en el paso de inicialización en la posición (bulletPos, 300)

Desinicializar
Liberamos los recursos que hemos cargado, es decir, el gráfico de la bala

Nos falta el paso Actualizar estado, que vamos a explicar ahora: tenemos que hacer que la bala se mueva y que cuando llegue a la derecha salir del bucle. Esta condición es fácil, bastaría con algo así:

if(800 <= bulletPos)
{
 done = true;
}

Con esto el while saldría del bucle. Ahora el movimiento: tenemos la posición del eje X de la bala en la variable bulletPos, y queremos que la bala vaya de izquierda a derecha. Muy fácil: le añadimos una cantidad a bulletPos en un for y listos. Algo así:

for(int i = 0; i < 800; ++ i)
{
 bulletPos += 1;
}

Ejecutamos el programa y vemos que la bala aparece directamente en la derecha. Bueno, no lo veríamos porque el programa saldría enseguida ya que al hacer la primera pasada del while bulletPos es igual a 800, en la segunda pasada done sería true y al volver a comprobar la condición del while este ya saldría del bucle.

¿Entonces cómo se hace el movimiento? La clave es entender que lo que va dentro del bucle es un pasito del juego, un frame como dijimos en la entrada anterior. En cada frame la bala se mueve un poquito, creando así la ilusión del movimiento. El bucle correcto quedaría así:

while(!done)
{
 // Actualizar estado
 bulletPos += 1;
 if(800 <= bulletPos)
 {
  done = true;
 }
 /* Pintar la bala. bulletImg es donde tenemos guardado  la imagen de la bala y que la función para pintar es drawSprite(Img, posX, posY) */
 drawSprite(bulletImg, bulletPos, 300);
}

La función drawSprite me la he inventado para el ejemplo por lo que carece de importacia. Lo importante es lo que se hace con la variable bulletPos: En cada iteración, "movemos" la bala una unidad a la derecha, comprobamos que ha llegado o no al borde de la pantalla y luego pintamos la bala. Según el valor que le añadamos a bulletPos la bala irá más o menos rápida.

En la siguiente entrada veremos porque esto es conceptualmente correcto pero una chapuza.

¡Hasta pronto!

No hay comentarios:

Publicar un comentario