Nunca antes había hecho mucha programación de juegos, una pregunta bastante directa.
Imagina que estoy construyendo un juego de Tetris, con el bucle principal más o menos así.
for every frame
handle input
if it's time to make the current block move down a row
if we can move the block
move the block
else
remove all complete rows
move rows down so there are no gaps
if we can spawn a new block
spawn a new current block
else
game over
Hasta ahora, todo en el juego ocurre instantáneamente: las cosas se generan instantáneamente, las filas se eliminan instantáneamente, etc. ¿Pero qué pasa si no quiero que las cosas sucedan instantáneamente (es decir, animar cosas)?
for every frame
handle input
if it's time to make the current block move down a row
if we can move the block
move the block
else
?? animate complete rows disappearing (somehow, wait over multiple frames until the animation is done)
?? animate rows moving downwards (and again, wait over multiple frames)
if we can spawn a new block
spawn a new current block
else
game over
En mi clon de Pong esto no fue un problema, ya que cada cuadro solo estaba moviendo la pelota y buscando colisiones.
¿Cómo puedo resolver este problema? Seguramente, la mayoría de los juegos implican alguna acción que toma más de un marco, y otras cosas se detienen hasta que se realiza la acción.
Action
clase y una cola de acciones para realizar. Cuando se completa una acción, retírela de la cola y realice la siguiente acción, etc. Mucho más flexible que una máquina de estado.Estoy tomando esto de Game Coding Complete por Mike McShaffry.
Habla de un 'Administrador de procesos', que se reduce a una lista de tareas que deben hacerse. Por ejemplo, un proceso controlaría la animación para dibujar una espada (AnimProcess), abrir una puerta o, en su caso, hacer que la fila desaparezca.
El proceso se agregaría a la lista del administrador de procesos, que se iteraría en cada cuadro y Update () llamado en cada uno. Entidades muy parecidas, pero para acciones. Habría una bandera de matar para eliminar de la lista cuando haya terminado.
La otra cosa interesante acerca de ellos es cómo pueden vincularse, al tener un puntero al siguiente proceso. De esta manera, su proceso de fila animada puede consistir en:
(Dado que los procesos pueden ser cosas de un solo uso, condicionalmente allí o allí durante X cantidad de tiempo)
Si quieres más detalles, pregunta.
fuente
Puede usar una cola de acciones prioritaria. Empujas una acción y un tiempo. En cada cuadro, obtienes el tiempo y eliminas todas las acciones que tienen un tiempo especificado antes de ese tiempo y las ejecutas. Bonificación: el enfoque es muy similar y puedes implementar casi toda la lógica del juego de esta manera.
fuente
Siempre necesita saber la diferencia horaria entre el marco anterior y el actual, luego debe hacer dos cosas.
-Decida cuándo actualizar su modelo: por ejemplo. en tetris, cuando comienza la eliminación de una fila, ya no desea que las cosas choquen con la fila, por lo que elimina la fila del "modelo" de su aplicación.
-A continuación, debe manejar el objeto que está en un estado de transición a una clase separada que resuelve la animación / evento durante un período de tiempo. En el ejemplo de tetris, la fila se desvanecería lentamente (cambie un poco la opacidad de cada fotograma). Después de que la opacidad es 0, transfiere todos los bloques en la parte superior de la fila uno hacia abajo.
Esto puede parecer un poco complicado al principio, pero entenderás esto, solo asegúrate de abstraer mucho en diferentes clases, esto lo hará más fácil. También asegúrese de que los eventos que toman tiempo, como la eliminación de una fila en tetris, sean del tipo "Fire and Forget", simplemente cree un nuevo objeto que maneje todo lo que debe hacerse automáticamente y que, cuando todo esté hecho, se elimina de su escenagrama.
fuente
Debes pensar en el juego como una "máquina de estados finitos". El juego puede estar en uno de varios estados: en su caso, "esperando entrada", "pieza moviéndose hacia abajo", "explosión de fila".
Haces cosas diferentes según el estado. Por ejemplo, durante la "pieza que se mueve hacia abajo", ignora la entrada del jugador y, en cambio, anima la pieza desde su fila actual a la siguiente. Algo como esto:
fuente