Mes: agosto 2011

Game loop: el origen de todo

¡Volví de vacaciones!

Y lo hago con un tutorial que considero básico e imprescindible: cómo funciona un videojuego. A la hora de enfrentarnos a cualquier cosa, lo más complicado suele ser saber cómo empezar, cuál es el origen de todo lo que vamos a hacer después. Y creo que esta preocupación ocurre tanto a la hora de programar, como de enfrentarse a una hoja en blanco o al pedir nuestra primera subida de sueldo.

Con los videojuegos algunos motores nos darán esta base, y a partir de ahí podemos mirar un montón de tutoriales para seguir haciendo cosas, pero si no sabemos qué es lo que hace funcionar a nuestro juego, o en qué parte actúa el API que estemos utilizando, muchas veces iremos a ciegas. Y como todos ya nos conocemos el refrán “ojos que no ven, ostiazo que te pegas” vamos a intentar arrojar un poco de luz sobre todo esto.

Pues bien, un juego no es más que un bucle continuo llamado game loop:

  1. void run()
  2. {
  3.     bool playing = true;
  4.     while (playing)
  5.     {
  6.         ReadInput(); //Leemos las entradas del teclado
  7.         Update(); //Actualizamos el estado de los objetos
  8.         Render(); //Los dibujamos en pantalla
  9.     }
  10. }

Todo juego tiene una estructura similar, pero tenemos que tener en cuenta el API sobre el que estamos trabajando.

ReadInput()
Aquí comprobamos el estado de los distintos dispositivos de entrada (ratón y teclado sobre todo, pero podría ser un joystick o un joypad, una pantalla táctil en el caso de un smartphone, o incluso un micrófono). Es altamente recomendable separar la lógica del ReadInput de la del Update(), y utilizar flags que indiquen el estado del input para que el Update actúe en consecuencia.

También es ideal que almacenemos las teclas en variables, de este modo podremos cambiar fácilmente el mando del juego.

No recomendado:

  1. void run()
  2. {
  3.     bool playing = true;
  4.     while (playing)
  5.     {
  6.         ReadInput(); //Leemos las entradas del teclado
  7.         Update(); //Actualizamos el estado de los objetos
  8.         Render(); //Los dibujamos en pantalla
  9.     }
  10. }
  11. void ReadInput()
  12. {
  13.     //Cada API tiene su función para leer el Input.
  14.     if (isKeyPressed(Key.Space))
  15.     {
  16.         Jump();
  17.     }
  18. }

Recomendado:

  1. void run()
  2. {
  3.     bool playing = true;
  4.     //Input Keys
  5.     const Key KEY_JUMP = Key.Space;
  6.     //Input State
  7.     bool jump;
  8.     while (playing)
  9.     {
  10.         ReadInput(); //Leemos las entradas del teclado
  11.         Update(); //Actualizamos el estado de los objetos
  12.         Render(); //Los dibujamos en pantalla
  13.     }
  14. }
  15. void ReadInput()
  16. {
  17.     //Cada API tiene su función para leer el Input.
  18.     if (IsKeyPressed(KEY_JUMP))
  19.     {
  20.         jump = true;
  21.     }
  22. }
  23. void Update()
  24. {
  25.     if (jump)
  26.     {
  27.         Jump(); //Esta función terminaría con un jump=false;
  28.     }
  29. }

 

De este modo, separaremos de forma lógica ambas funciones y tendremos un código más ordenado, lo que nos ayudará enormemente cuando tengamos un Update complejo en el que tengamos que tener en cuenta un montón de variables.

Update()
Aquí desarrollaremos toda la lógica de juego, pero no os abruméis. Un juego no es más que unos cuantos objetos con una serie de estados, que realizan funciones. Así, en función de su estado, cambiaremos su posición en la pantalla, pero también deberemos de acordarnos de controlar la vida, la munición, los puntos o el resto de variables que estemos utilizando.

Dentro del Update deberíamos tener en cuenta también la física, pero por lo general nos la manejará automáticamente nuestro motor, por lo que no tendremos que preocuparnos. Si no lo hace, hoy en día existen motores físicos para absolutamente todas las plataformas que seguro podremos utilizar. Unity 3D, por ejemplo, tiene su propio manejador de físicas, por lo que sólo nos tendremos que preocupar de establecer en nuestro objeto una serie de propiedades físicas.

Los cálculos físicos suelen ser los últimos que se realizan en el Update

Render()
Cuando trabajamos con un motor gráfico, lo que hace básicamente es manejarnos automáticamente la función Render() (aunque luego pueda resolvernos más cosas, como la física), ya que es la que trabaja directamente sobre las librerías gráficas (DirectX u OpenGL), y muchas veces en nuestros juegos nos bastará con añadir nuestros elementos a un Graphic Layer (una capa que se encarga de dibujar todo lo que haya en ella), o heredar nuestros objetos de alguna clase que contenga toda la lógica de renderizado.

¿Dónde encaja todo esto en Unity 3D?

Efectivamente, en Unity 3D nosotros no vemos este bucle por ningún lado.

Antes que nada, hay que comprender que Unity 3D sigue una arquitectura basada en componentes, que es ligeramente distinta a la más familiar POO (Programación Orientada a Objetos). La diferencia entre un objeto y un componente es que los primeros necesitan ser instanciados, es decir, partimos de una clase que define un tipo de objeto que nos servirá de molde para crear objetos similares (por ejemplo, la claseEnemy nos podría servir para crear multitud de enemigos). Mientras tanto, los componentes se asemejan más a scripts, trozos de código que dan una funcionalidad determinada al objeto al que se anexan, y cuando uitilicemos la palabra clave “this“, no referenciaremos al componente, sino al objeto sobre el que está alojado.

De este modo, si en Unity creas un GameObject (que es cualquier cosa que actúe en el juego), tendrá toda la funcionalidad básica de un objeto del juego, pero si además le añades, por ejemplo, un componente RigidBody, el GameObject tendrá física, y si también le pones un componente Player, en el que defines la lógica del jugador, esteGameObject ahora responderá a las acciones del jugador.

Ambas arquitecturas pueden combinarse, y de hecho lo hacen. Tú, por ejemplo, puedes crear un componente cuya lógica utilice instancias de clases, y después agregarlo como componente a un GameObject.

Muy bonito todo este inciso, pero seguimos sin ver el game loop del que os he hablado al principio. La razón de esto es que Unity lo está manejando de forma transparente, sin que nosotros nos demos cuenta. Cada vez que Unity da una vuelta al bucle, llama a una serie de funciones contenidas en el MonoBehaviour. Por eso, cuando creamos un script en C# (el lenguaje recomendado), veremos que hereda de esta clase. Así, lo único que tenemos que hacer cuando creamos un script es definir estas funciones. Por defecto Unity nos creará Start() y Update().

Unity 3D nos ofrece la documentación de las funciones que utiliza en esta web: http://unity3d.com/support/documentation/Manual/Execution%20Order.html

Es imprescindible que tengáis en cuenta que cada vuelta al loop puede tomar un tiempo distinto en función de la carga del procesador, por lo que tendréis que utilizar este espacio de tiempo en vuestros cálculos. Para ello, Unity pone a vuestra disposición la variable Time.deltaTime, que no es más que los segundos que ha tardado el juego en completar el último frame.

La excepción es FixedUpdate(), que tiene un tiempo de llamada específicado en la variable global Application.targetFrameRate.

Aunque para trabajar con físicas FixedUpdate() es la función recomendada, debemos tener mucho cuidado al utilizarla, ya que procesos muy cargantes o frameratesdemasiado pequeños pueden hacer que nuestro juego haga cosas raras o nos vaya a saltos.

Ahora que comprendemos el game loop de un juego y sabemos cómo interactuar con él en Unity 3D, podemos empezar a hacer nuestros primeros scripts sin cortocircuitarnos en el intento ;).

Nintendo convoca un evento especial de Nintendo 3DS en Japón

Nintendo ha convocado un evento especial en Japón que girará en torno a Nintendo 3DS y que tendrá lugar poco antes del inicio del Tokyo Game Show, previsto para los días 15 a 18 de septiembre.

El anuncio de este evento ha producido un incremento inmediato en la cotización en bolsa de la empresa japonesa, subiendo su cotización en un 9,7% con respecto al valor con el que cerró ayer.

El evento de Nintendo será una conferencia a la que se ha convocado a los medios japoneses y que tendrá lugar el 13 de septiembre, por tanto, dos días antes del Tokyo Game Show.

Según parece la noticia viene a corroborar un rumor surgido a partir del portal francés 01net esta madrugada, en el que se aseguraba que sus fuentes declaran un interés por parte de Nintendo por lanzar en 2012 un rediseño de 3DS. Según este rumor, Nintendo rebajaría las capacidades 3D de la videoconsola y la vendería con un nombre diferente y con un segundo stick analógico. Un rumor que dista mucho de ser oficial de momento pero que ha ayudado a elevar el precio de las acciones de Nintendo en 9,7 puntos porcentuales.

Fuente 1 y 2

Rumor: Fire Emblem en 3DS

Fire Emblem: Blue Sacred Sword and Red Demon Lance. Éste sería el nombre con el que Nintendo pretendería bautizar a la próxima entrega de la serie de rol, que saldría a la venta en formato Nintendo 3DS y se presentaría próximamente, según The Magic Box.

La trama del juego transcurriría 100 años después de Sealed Sword y se centraría en las figuras de la Princesa de Bern y del Príncipe de Lycia. La aventura incluiría, además, dos modos de juego: el modo casual para nuevos jugadores y el modo “Lunatic” para usuarios avanzados.

Quedamos a la espera de la confirmación oficial por parte de Nintendo. Quizás el próximo Tokyo Game Show sirva para mostrar este título portátil.

Os dejamos con el speedrun de Fire Emblem Path of Radiance, que salió en Game Cube.

Fuente

Nuevos juegos en la eShop.

Esta semana, Capcom se anima por primera vez con la Consola Virtual de Nintendo 3DS y lo hace con un juego mítico donde los haya: Gargoyle’s Quest. Lanzado en Japón para NES en 1990, bajo el nombre de Red Arremer: Makaimura Gaiden​ y en EE.UU como Gargoyle’s Quest: Ghosts’n Goblins, el juego combina inteligentemente complejos niveles de plataformas con componentes roleros y una buena dosis de exploración. Su protagonista, Firebrand, es un demonio alado que está llamado a convertirse en el salvador del Reino de los Demonios. Con él tendremos que recorrer las ciudades, bosques, cementerios y ruinas del Reino de los Demonios aprendiendo nuevas habilidades que nos ayuden a derrotar al implacable Breager, Rey de la Destrucción. Un clasicazo que ahora puedes revivir en Nintendo 3DS descargándolo por sólo 4 euros desde la Nintendo eShop.

Si eres de los que prefieren tomarse las cosas con calma y aprovechar las tardes veraniegas para echarte una partidita de cartas, descárgate Bridge en tu Nintendo DSi. Se trata del juego de cartas de toda la vida con funciones multijugador. Puedes desafiar a la exigente Inteligencia Artificial del juego o bien disfrutar del modo multijugador local con tus amigos, todo por 5 euros en Nintendo eShop (Nintendo 3DS) o por 500 Puntos Nintendo en la Tienda Nintendo DSi.

Nuevas imágenes y detalles de Resident Evil: Revelations

Actualizamos con un vídeo de 11 minutos de la demo que había en GamesCom.

La revista española Nintendo Acción nos ofrece en su último número (226) un amplio reportaje sobre la demo de Resident Evil Revelations que tuvieron la oportunidad de probar en las oficinas de Koch Media. Esta demo incluye varios niveles: El lujoso crucero abandonado en mitad del mar Mediterráneo, donde manejaremos a Jill Valentine acompañada del miembro BSAA Parker Luciani, y en otra parte Chris Redfield junto a Jessica Sherawat andan perdidos en las escarpadas montañas del Este de Europa, incomunicados y aislados por la nieve y la intensa niebla.

En el reportaje se menciona que lucharemos contra criaturas acuáticas de toda clase, desde tiburones o pirañas hasta crustáceos infectados y de dimensiones gigantes. Chris y Jessica descubrirán el escondite del grupo terrorista Veltro, la sucesora de Umbrella en experimentos virales, ubicado en el aeropuerto de Valkoinen Mokki (Finlandia), en la cima de la montaña.

Fuente