2009-04-28 8 views
11

Estoy creando un juego basado en cuadrículas en Java y quiero implementar la grabación y reproducción de juegos. No estoy seguro de cómo hacer esto, aunque yo he considerado 2 ideas:¿La mejor manera de implementar la reproducción del juego?

  1. Varias veces cada segundo, me gustaría grabar todo el estado del juego. Para reproducirlo, escribo un renderizador para leer los estados y tratar de crear una representación visual. Con esto, sin embargo, es probable que tenga un gran archivo guardado, y cualquier intento de reproducción probablemente tenga un retraso notable.

  2. También podría escribir cada pulsación de tecla y de clic del ratón en el archivo de salvar. Esto me daría un archivo más pequeño, y podría reproducir con menos retraso. Sin embargo, el más mínimo error al comienzo del juego (por ejemplo, disparar 1 milisegundo más tarde) daría lugar a un estado de juego muy diferente en varios minutos del juego.

¿Cuál es, entonces, la mejor forma de implementar la reproducción del juego?

Editar- no estoy seguro exactamente cómo determinista es mi juego, así que no estoy seguro de todo el juego puede ser reconstruido exactamente registrando sólo las pulsaciones de teclado y los clics del ratón.

Respuesta

14

Un buen mecanismo de reproducción no es algo que simplemente se puede agregar a un juego sin grandes dificultades. Lo mejor sería diseñar la infraestructura del juego teniendo esto en cuenta. El command pattern se puede usar para lograr una infraestructura de juegos de este tipo.

Por ejemplo:

public interface Command{ 
    void execute(); 
} 
public class MoveRightCommand implements Command { 
    private Grid theGrid; 
    private Player thePlayer; 

    public MoveRightCommand(Player player, Grid grid){ 
     this.theGrid = grid; 
     this.thePlayer = player; 
     } 

    public void execute(){ 
    player.modifyPosition(0, 1, 0, 0); 
    } 
} 

Y a continuación, el comando puede ser empujado en una cola de ejecución tanto cuando el usuario presiona un botón del teclado, el ratón se mueve o sin un disparador con el mecanismo de reproducción. El objeto de comando puede tener un valor de marca de tiempo (en relación con el inicio de la reproducción) para la reproducción precisa ...

+2

Esta es una manera elegante de manejarlo. Si el juego real y la grabación se basan en el mismo mecanismo de tiempo/marco, debe evitar errores debido a problemas de tiempo. Si tiene aleatoriedad en sus eventos, es posible que necesite registrar también el valor inicial de la semilla para su generador de números aleatorios. Así es como las funciones 'Random Map' en los juegos RTS te permiten regenerar un mapa aleatorio que te gusta. –

+0

Este patrón también puede darle la capacidad Deshacer/Rehacer. –

2

Por qué no grabar varias veces por segundo y luego comprimir su salida, o tal vez hacer esto:

recordInitialState(); 
... 
runs 30 times a second: 
recordChangeInState(previousState, currentState); 
... 

Si sólo registrar el cambio de estado con una marca de tiempo (y cada cambio es pequeño, y si hay no hay cambio, luego no registre nada), debe terminar con un tamaño de archivo razonable.

3

Suponiendo que su juego es determinista, podría ser suficiente si ha grabado las entradas de los usuarios (opción 2). Sin embargo, deberá asegurarse de reconocer los tiempos correctos y constantes para estos eventos, como cuando el servidor lo reconoció. No estoy seguro de cómo manejas los eventos en la grilla.

Mi preocupación es que si usted no tiene un mecanismo que puede hacer referencia de manera uniforme eventos en el tiempo, puede haber un problema con la manera en que su código controla usuarios distribuidos.

Considérese un juego como Halo 3 en Xbox 360, por ejemplo, - cada cliente registra su visión del juego, incluyendo las correcciones basadas en servidor.

2

No hay necesidad de guardar todo en la escena para cada cuadro. Guarde los cambios de forma incremental y use algunas buenas técnicas de interpolación. Realmente no utilizaría un enfoque basado en patrones de comando, sino que realizaría controles a una velocidad fija para cada objeto del juego y vería si ha cambiado algún atributo. Si hay un cambio, ese cambio se registra en una buena codificación y la repetición no será tan grande.

2

Cómo abordar esto dependerá en gran medida del idioma que está utilizando para su juego, pero en términos generales hay muchos enfoques, dependiendo de si desea utilizar una gran cantidad de almacenamiento o si desea un poco de retraso. Sería útil si pudieras dar algunas ideas sobre los sacrificios que estás dispuesto a hacer.

Pero, parecería que el mejor enfoque puede ser simplemente guardar la entrada del usuario, como se mencionó, y almacenar las posiciones de todos los actores/sprites en el juego al mismo tiempo, que es tan simple simplemente guardando la dirección, la velocidad y el mosaico x, y, o, si todo puede ser determinista, entonces ignora los actores/sprites a medida que puedas obtener su información.

Cómo no determinista es su juego también sería útil para dar una mejor sugerencia.

Si hay una gran cantidad de movimiento dinámico, como un choque derby, entonces es posible que desee guardar información en cada cuadro, ya que debe actualizar los jugadores/actores a un cierto índice de fotogramas.

2

Simplemente diría que la mejor manera de grabar una repetición de un juego depende totalmente de la naturaleza del juego. Estar basado en la cuadrícula no es el problema; el problema es qué tan predecible es el comportamiento después de un cambio de estado, con qué frecuencia hay nuevas entradas al sistema, si hay datos aleatorios que se inyectan en algún punto, etc. Se puede almacenar todo un juego de ajedrez simplemente registrando cada movimiento, pero eso no funcionaría para un tirador en primera persona donde no hay giros claros. Podría almacenar un tirador en primera persona al anotar la hora exacta de cada entrada, pero eso no funcionará para un juego de rol en el que el resultado de una entrada pueda ser modificado por el resultado de una tirada de dados al azar. Incluso la idea aparentemente infalible de tomar una instantánea tan a menudo como sea posible no es lo suficientemente buena si la información importante aparece instantáneamente y no persiste en ninguna forma capturable.

Curiosamente, esto es muy similar al problema que se obtiene con la creación de redes. ¿Cómo asegura una computadora que otra computadora se entere del estado del juego, sin tener que enviar todo el estado del juego a una frecuencia poco práctica? El enfoque típico termina siendo una mezcla personalizada de notificaciones de eventos y actualizaciones de estado, que es probablemente lo que necesitará aquí.

1

Lo hice una vez tomando prestada una idea de la compresión de video: fotogramas clave y fotogramas intermedios. Básicamente, cada pocos segundos guardas el estado completo del mundo. Luego, una vez por actualización del juego, guarda todos los cambios en el estado mundial que ocurrieron desde la última actualización del juego. Los detalles (¿con qué frecuencia guarda los fotogramas clave? ¿Qué cuenta exactamente como un "cambio en el estado mundial"?) Dependerá del tipo de información del juego que necesite conservar.

En nuestro caso, el mundo consistía en muchos, muchos objetos de juego, la mayoría de los cuales permanecían quietos en un momento dado, por lo que este enfoque nos ahorró mucho tiempo y memoria al registrar las posiciones de los objetos que no emocionante. En los tuyos, las compensaciones pueden ser diferentes.

Cuestiones relacionadas