¿Qué es un bucle?
Entendemos por un bucle algo que se repite muchas veces o por un rizo del pelo...Aunque creo que este último a nosotros no nos importa mucho.
Un bucle en términos de programación,es un conjunto de instrucciones que se repiten una y otra vez mientras se cumpla una condición ,por ejemplo:
1 2 3 4 5 6 7 | while(1<2){ cout<<"Todo va bien"; } //------ for(int i=0;i<3;i++){ cout<<"Vas a leerme 3 veces!"; } |
Nota:todo el código que vas a ver en el blog será C++ o C# ya que son los lenguajes que más uso y que más conocimiento sobre ellos tengo.
Muy bien , ya sabes lo que es un bucle pero ¿Por qué es tan importante para un juego?.
Para responder esta pregunta vamos a pensar que hace un videojuego:
- Leer los dispositivos de entrada (teclados, ratón,pedales etc).
- Mover las cosas del juego , actualizar datos en relación a acciones del juego (como la física, o el simple movimiento de un personaje).
- Pintar el juego en si.
Y todas estas cosas las está haciendo todo el rato.
Ahora imaginemos que no tenemos un bucle, ¿Cómo narices comprobamos esto todo el rato? tendríamos que tener millones de líneas de código ya que sino nuestro código solo duraría unos segundos, y nuestro código sería imposible de mantener.
Espero que comprendas así la necesidad de tener un bucle haciendo estas cosas todo el rato...Pero,¿Cada cuanto rato? , para ser exactos una pasada del bucle significa un frame del juego ya que estamos pintado al menos 1 vez cada vuelta.
No me quiero meter ahora mismo con el tema de los FPS (frames per second) ya que es un tema a parte pero quiero dejar claro la relación de los FPS y de nuestro bucle (que es mucha):
Un juego a 60 FPS, se está pintando unas 16,6666666 veces por segundo por lo que todo nuestro bucle está haciendo sus tareas 16 veces por segundo de esta manera al jugador le da sensación de dinamismo y movimiento como si de una película se tratase.
Volviendo al tema bucle,vamos a plantear una idea sencilla que podemos aplicar a cualquier tipo de juego en el ordenador o aplicación que tenga que pintar algo.
Primero simplifiquemos nuestras acciones del bucle:
- Input: comprobamos los dispositivos de entrada.
- Update: actualizamos el estado actual del juego.
- Render: pintamos este frame acorde con el estado actual del juego.
De está manera tendremos el siguiente bucle:
1 2 3 4 5 6 7 8 | //en un juego de verdad aquí no tendríamos un //true, sino una condición que controlase //si estamos en la aplicacion (ej:bool ingame) while(true){ Input(); Update(); Render(); } |
Este bucle realizará de manera continuada a la máxima velocidad que le sea posible las tareas que le hemos indicado.
Y ahora os preguntaréis...¿Por qué ese orden? si lo pensamos bien este es un orden "lógico" , pero os voy a dar una razón más.
Imaginemos que tenemos el "Render()" en primer lugar , este lo que hará será renderizar los elementos actuales del juego pero... ¡No hay nada que pintar! esto puede causar errores muy graves ya que podemos estar intentando pintar cosas que no existen ya que aunque sabemos que está ahí no han sido inicializadas.
Otro problema que podría causar descoordinación sería tener el "Update();" primero, ya que estaríamos usando los inputs del frame anterior y no los del actual lo cual podría causarnos problemas.
Así que espero que hayáis comprendido un poco el bucle de un juego aunque esta ha sido una explicación muy sencilla, en otra entrada hablaremos más sobre los FPS y como limitarlos o de como organizar el juego.
Un saludo!
Nacho