Desarrollo videojuegos multijugador online

Para hablar de cualquier tema no relacionado con la música.
Responder
Avatar de Usuario
supertorpe
Pianista de concurso
Mensajes: 1675
Registrado: Mié Dic 01, 2010 8:31 pm
Ubicación: Cádiz
Chopines:
Contactar:

Desarrollo videojuegos multijugador online

Mensaje por supertorpe »

Entendemos videojuegos multijugador online como aquellos en los que cada jugador utiliza un dispositivo y existe una red que conecta los distintos dispositivos, de tal modo que los jugadores pueden interactuar unos con otros simultáneamente.

El desarrollo de videojuegos multijugador online tiene que afrontar problemas distintos a los que surgen en el desarrollo de juegos de un único jugador, o de juegos multijugador en un único dispositivo.

El elemento diferencial en este tipo de juegos es la red: hay varios dispositivos conectados por una red, y una red siempre añade cuestiones a considerar:
1. la red no es infalible: pueden perderse mensajes, cerrarse conexiones…
2. ancho de banda: la cantidad de información que se puede enviar por unidad de tiempo tiene un límite (muy inferior al del bus interno de un dispositivo)
3. latencia: los mensajes tardan un tiempo en atravesar la red y llegar desde un dispositivo a otro. Los mensajes incluso podrían llegar desordenados
4. la red es insegura: los mensajes pueden ser inspeccionados, alterados…

Para tratar con el primer problema -falibilidad de la red-, se pude establecer un protocolo de reintentos, que siga reenviando el mensaje hasta que reciba una confirmación de llegada y un sistema de reconexiones en caso de pérdida de conexión. Si se llega a un máximo de reintentos o no es posible restablecer la conexión, se puede dar el caso por perdido, saliendo de la partida.

El segundo problema -ancho de banda- no debería afectar demasiado a este tipo de software. Habitualmente, se trata de pequeños paquetes de información, no de grandes cantidades de datos. Podría llegar a ser un problema si se intenta enviar en un lapso muy breve muchísimos paquetes a muchos destinos.
El tercer problema -latencia- es, tal vez, el problema que más impacto tiene en este tipo de juegos, ya que genera lag que deteriora la experiencia de juego. Las soluciones para mitigarlo pueden causar inconsistencias en el estado de juego que perciben distintos jugadores (ver teorema CAP).
El cuarto problema -inseguridad- es otro gran problema que tienen que afrontar los juegos: “cheating”, es decir, usuarios tramposos que manipulan e inspeccionan los mensajes o el código para obtener ventaja frente a los demás.

Arquitecturas

Cliente/Servidor

En esta arquitectura, hay un servidor (podrían ser varios) que contiene la lógica del juego y a los que los clientes (dispositivos de los jugadores) envían los mensajes (p.e. pulsaciones del teclado, gamepad…). El servidor calcula los efectos que dichos mensajes deben causar en el estado del juego, y envían el nuevo estado del juego (p.e. nuevas posiciones de los personajes) hacia los clientes. Es el servidor el que tiene la última palabra en cuanto al estado real del juego. Si hubiera diferencias entre el estado del juego de un cliente y el servidor, siempre es el estado del servidor el que prevalece.

Esta arquitectura es menos vulnerable al cheating.

Normalmente, el bucle de renderizado del juego -las veces por segundo que se pinta el juego en pantalla- es muy rápido (30, 60, 144... frames por segundo o FPS). Los mensajes no se envían a la red con tanta frecuencia. Podrían enviarse, por ejemplo 10 veces por segundo.

Esto quiere decir, que los clientes reciben el estado de juego en “saltos” de, por ejemplo, 100ms. Sin embargo, el repintado de pantalla se produce, por ejemplo, cada 16ms, estamos desaprovechando muchos frames y además estaríamos percibiendo el movimiento a pequeños saltitos, en lugar de percibir un movimiento fluido.

Para solucionar esto se pueden utilizar varias técnicas:
1. Interpolación: se representa, no el último estado del juego, sino uno anterior (p.e. el penúltimo) y se interpola la posición de los objetos entre dicho estado y el siguiente, en proporción al tiempo transcurrido.
2. Extrapolación o “dead reckoning”: conociendo la posición y velocidad (lineal y angular) de cada objeto en el estado actual del juego, se realiza una estimación de dónde debrería estar cada objeto teniendo en cuenta el tiempo transcurrido aplicando leyes físicas.
Hay casos en los que la extrapolación puede causar efectos extraños. Por ejemplo, si un jugador cambia repentinamente de dirección, la extrapolación fallará y veremos al personaje teleportándose del lugar donde la extrapolación estimó hasta donde el servidor nos indica.

Para mitigarlo, se puede utilizar interpolación para realizar una reconciliación suave hacia su nueva posición.

Ahora veamos cómo afecta la latencia:
1. Un jugador pulsa la flecha a la derecha para mover su personaje.
2. Se envía un mensaje con el comando al servidor indicando dicha pulsación. Ese mensaje llega un tiempo después al servidor.
3. El servidor calcula el efecto que tiene el comando sobre los objetos del juego.
4. El servidor envía la nueva posición del personaje a todos los clientes, aunque ese mensaje tarda un tiempo de llegar hasta los dispositivos
5. Los dispositivos reciben el mensaje y representan al personaje en su nueva posición

Tenemos aquí varios retardos, pero los más representativos consisten en el tiempo que tarda el mensaje en llegar desde el cliente al servidor, y el tiempo que tarda el mensaje enviado desde el servidor hasta los clientes.

Esto implica que desde cuando pulso la flecha a la derecha hasta que mi personaje se mueve en mi dispositivo, transcurre un lapso de tiempo. Dependiendo del tipo de juego y la latencia, podría arruinar la experiencia de juego.

Para mitigar este problema se puede aplicar la técnica “client side prediction”: el dispositivo comienza a mover al personaje en el mismo momento en que envía el mensaje al servidor. Para ello, es necesario que parte de la lógica del juego esté duplicada en el cliente (p.e. detección de colisiones, leyes físicas -gravedad, cinemática…-). De este modo, el dispositivo donde se origina el comando no percibe lag, ya que el movimiento es instantáneo.

Sin embargo, esta solución origina, a su vez, otro problema: en un instante determinado, distintos dispositivos representan distintos estados de juego. Mientras que en el dispositivo donde se original el movimiento, este se representa instantáneamente, el resto de dispositivos lo representan con un retardo.

Esto podría dar lugar a situaciones extrañas. Imaginemos un juego de fútbol en el que dos jugadores están a punto de patear un balón (en trayectorias distintas). Ambos le dan simultáneamente y, en virtud, del “client side prediction”, cada uno ve que su personaje patea al balón (mientras el comando del otro jugador está viajando hacia el servidor).

El servidor recibe ambos mensajes (probablemente con distinta latencia) y tiene que aplicar una política para establecer el orden en que se han producido.

Posiblemente tenga que calcular la latencia con cada cliente para poder ordenar adecuadamente los mensajes. Después tiene que aceptar el pateo del balón desde uno de los jugadores y hacer que el otro patease al aire. Entonces tiene que enviar el nuevo estado de juego a los clientes. Cuando el nuevo estado llega a los clientes, uno de ellos verá que, mientras que acaba de patear al balón en una dirección, de repente su pantalla muestra al balón en otra posición y dirección (como si hubiera sido pateado por el otro jugador).

Otro ejemplo: un jugador A dispara a otro jugador B que está parado. Pero al mismo tiempo que se produce el disparo, el jugador B se mueve. La client-side-prediction hace que el jugador A vea cómo su disparo alcanza a B, y B vea cómo se desplaza de posición antes de que A dispare.

Sin embargo, cuando ambos mensajes lleguen al servidor y este determine el orden de los acontecimientos y sus consecuencias, y envíe el nuevo estado del juego a los clientes, uno de ellos percibirá un curso de acontecimientos “imposible”. Por ejemplo, el usuario A vería que ha alcanzado al jugador B e inmediatamente después verá que sigue vivo en otra posición; o el jugador B verá que el disparo de A pasa a su lado sin alzanzarle e inmediatamente después verá que ha muerto alcanzado por el disparo.

peer-to-peer (p2p)

En este tipo de arquitectura, cada dispositivo mantiene una conexión con el resto de dispositivos (full mesh), hacia los que envía y desde lo que recibe mensajes. También es posible encontrar topologías partial-mesh, en las que no todos están conectados con todos directamente, sino que se dividen en grupos y hay algunos nodos “pasarela” que conectan unos grupos con otros.

Si hay un número n de nodos, tendremos un total de n(n – 1)/2 conexiones.

En la topología peer-to-peer, no hay un servidor que tenga un estado de juego principal que pueda determinar el orden objetivo de los acontencimientos y resolver confilctos.

Este tipo de juegos es más vulnerable al cheating, ya que no hay un servidor que valide los mensajes y cada dispositivo contiene la lógica completa del juego.

Alguna estrategias para mitigar el cheating:

- Hacer que cada nodo envíe los comandos (p.e. teclas pulsadas) y no los efectos (p.e. posición del personaje), de tal modo que cada nodo calcula la física sobre todos los personajes basándose en los comandos recibidos. Esto evitaría el “vuelo” o “teleportación” de jugadores tramposos.
- Establecer algún tipo de autoridad distribuida (ver algoritmos de consenso, paxos, raft… y sistemas de reputación) para simular un servidor autoritario (authoritative).

A pesar de ello, hay problemas muy complejos de resolver mientras cada nodo tenga una copia del estado completo del juego (p.e. map hacking donde un jugador descubre la posición de otros jugadores que se suponen que no están a la vista).

Otro problema a resolver en este tipo de redes consiste en atravesar los firewalls, NAT… para comunicar los dispositivos. Habitualmente se utiliza un servidor STUN/TURN para ello (ver bibliografía).

Aún así, la solución p2p es muy atractivo para los desarrolladores indie, ya que no requiere un servidor dedicado (salvo el STUN/TURN) con los costes que ello conlleva.

WebRTC permite a los navegadores web establecer este tipo de comunicaciones p2p, lo que facilita el desarrollo de juegos HTML5 multijugador.

A continuación exploro una solución para este tipo de juegos:

- Los nodos se sincronizan al comienzo del juego (calculan su “diferencia horaria”) y se coordinan para comenzar en un instante cercano del futuro.
- Por un lado, separamos el bucle del juego (gameloop) que es donde se realiza el renderizado, del bucle que calcula los estados de juego (el bucle que calculas las físicas sobre los objetos).
- Pongamos por caso que dividimos el tiempo en bloques de 100ms (bloques numerados secuencialmente), a cada uno de los cuales le corresponde un estado de juego (posición, velocidad de cada objeto, puntuaciones, etc.); y también tenemos un gameloop de 60fps (16,67ms aprox).
- A cada estado de juego se le asocian los comandos de los jugadores (teclas pulsadas, ratón, gamepad…) tanto del jugador local como de los remotos.
- Para calcular el siguiente estado de juego se clona el estado actual y se calculan las físicas en función de los comandos del estado actual. Es decir ESTADO(n+1) = FISICA(ESTADO(n), COMANDOS(n)). Bueno… es un poco más complejo como veremos a continuación…
- Cada nodo envía por la red sus comandos al resto de los nodos, indicando el bloque de tiempo al que pertenecen.
- Tanto los comandos que llegan por la red como los que se producen en local, se guardan en un buffer, indicando el bloque al que pertenecen.
- Mantenemos en memoria una lista de estados de juego (bloque 1, bloque 2, bloque 3…)
- Es posible que debido a la latencia, lleguen comandos que pertenecen a un bloque que ya ha pasado. Por ello, cuando se va a calcular el siguiente estado de juego, primero se vuelcan los comandos del buffer, cada uno en el bloque al que corresponde (idealmente sólo en el último). Si hubiera comandos de bloques antiguos, se recalcula la historia de estados de juego de tal modo que todos los comandos son tenidos en cuenta, cada uno en su momento de la historia. De este modos, los estados de juego acaban sincronizándose a pesar de la latencia.
- Se renderiza el penúltimo estado de juego, realizando una interpolación con el último, teniendo en cuenta el tiempo transcurrido. Así aprovechamos los 60FPS para realizar un movimiento fluido.
- Para que todos los nodos sean deterministas en el momento de calcular el siguiente estado de juego, no podemos usar valores aleatorios. Usaremos un algoritmo pseudo-aleatorio (p.e. Mersenne Twister) coordinando la semilla, de tal modo que todos los nodos generen la misma secuencia de números pseudoaleatorios. Guardamos un histórico de aleatorios, junto a un puntero en cada estado de juego, por si hubiera que reescribir la historia de estados de juego, volver a reproducir la secuencia.

He realizado dos pruebas de concepto de estas ideas, utilizando un motor de juegos HTML5 (phaser 3) y un motor físico (planck.js). También he escrito una librería (mplaynet) para encapsular las conexiones y comunicaciones WebRTC.

Los juegos, como tal, no tienen gran valor, salvo tal vez el código que implementa las ideas planteadas anteriormente.
Aquí podéis probarlos y ver el código fuente:

https://github.com/supertorpe/p2p-game-poc (ver https://i.imgur.com/kkwMxUV.mp4)

https://fs5hq.csb.app (ver https://i.imgur.com/DsVw5Ew.mp4)

Bibliografía
https://www.gafferongames.com/post/what ... networking
https://www.gabrielgambetta.com/client- ... cture.html
https://0fps.net/2014/02/10/replication ... ew-part-1/
http://telefonia.blog.tartanga.eus/2014 ... lefonia-ip
Estudiando piano desde 01/03/2010 hasta 2015. ¡Retomando en 2020!
https://github.com/supertorpe/chessendgametraining

Mraks
Rompeteclas
Mensajes: 5
Registrado: Jue Sep 21, 2023 4:38 am

Re: Desarrollo videojuegos multijugador online

Mensaje por Mraks »

supertorpe escribió: Lun Feb 22, 2021 5:36 pm Entendemos videojuegos multijugador online como aquellos en los que cada jugador utiliza un dispositivo y existe una red que conecta los distintos dispositivos, de tal modo que los jugadores pueden interactuar unos con otros simultáneamente.

El desarrollo de videojuegos multijugador online tiene que afrontar problemas distintos a los que surgen en el desarrollo de juegos de un único jugador, o de juegos multijugador en un único dispositivo.

El elemento diferencial en este tipo de juegos es la red: hay varios dispositivos conectados por una red, y una red siempre añade cuestiones a considerar:
1. la red no es infalible: pueden perderse mensajes, cerrarse conexiones…
2. ancho de banda: la cantidad de información que se puede enviar por unidad de tiempo tiene un límite (muy inferior al del bus interno de un dispositivo)
3. latencia: los mensajes tardan un tiempo en atravesar la red y llegar desde un dispositivo a otro. Los mensajes incluso podrían llegar desordenados
4. la red es insegura: los mensajes pueden ser inspeccionados, alterados…

Para tratar con el primer problema -falibilidad de la red-, se pude establecer un protocolo de reintentos, que siga reenviando el mensaje hasta que reciba una confirmación de llegada y un sistema de reconexiones en caso de pérdida de conexión. Si se llega a un máximo de reintentos o no es posible restablecer la conexión, se puede dar el caso por perdido, saliendo de la partida.

El segundo problema -ancho de banda- no debería afectar demasiado a este tipo de software. Habitualmente, se trata de pequeños paquetes de información, no de grandes cantidades de datos. Podría llegar a ser un problema si se intenta enviar en un lapso muy breve muchísimos paquetes a muchos destinos.
El tercer problema -latencia- es, tal vez, el problema que más impacto tiene en este tipo de juegos, ya que genera lag que deteriora la experiencia de juego. Las soluciones para mitigarlo pueden causar inconsistencias en el estado de juego que perciben distintos jugadores (ver teorema CAP).
El cuarto problema -inseguridad- es otro gran problema que tienen que afrontar los juegos: “cheating”, es decir, usuarios tramposos que manipulan e inspeccionan los mensajes o el código para obtener ventaja frente a los demás.

Arquitecturas

Cliente/Servidor

En esta arquitectura, hay un servidor (podrían ser varios) que contiene la lógica del juego y a los que los clientes (dispositivos de los jugadores) envían los mensajes (p.e. pulsaciones del teclado, gamepad…). El servidor calcula los efectos que dichos mensajes deben causar en el estado del juego, y envían el nuevo estado del juego (p.e. nuevas posiciones de los personajes) hacia los clientes. Es el servidor el que tiene la última palabra en cuanto al estado real del juego. Si hubiera diferencias entre el estado del juego de un cliente y el servidor, siempre es el estado del servidor el que prevalece.

Esta arquitectura es menos vulnerable al cheating.

Normalmente, el bucle de renderizado del juego -las veces por segundo que se pinta el juego en pantalla- es muy rápido (30, 60, 144... frames por segundo o FPS). Los mensajes no se envían a la red con tanta frecuencia. Podrían enviarse, por ejemplo 10 veces por segundo.

Esto quiere decir, que los clientes reciben el estado de juego en “saltos” de, por ejemplo, 100ms. Sin embargo, el repintado de pantalla se produce, por ejemplo, cada 16ms, estamos desaprovechando muchos frames y además estaríamos percibiendo el movimiento a pequeños saltitos, en lugar de percibir un movimiento fluido.

Para solucionar esto se pueden utilizar varias técnicas:
1. Interpolación: se representa, no el último estado del juego, sino uno anterior (p.e. el penúltimo) y se interpola la posición de los objetos entre dicho estado y el siguiente, en proporción al tiempo transcurrido.
2. Extrapolación o “dead reckoning”: conociendo la posición y velocidad (lineal y angular) de cada objeto en el estado actual del juego, se realiza una estimación de dónde debrería estar cada objeto teniendo en cuenta el tiempo transcurrido aplicando leyes físicas.
Hay casos en los que la extrapolación puede causar efectos extraños. Por ejemplo, si un jugador cambia repentinamente de dirección, la extrapolación fallará y veremos al personaje teleportándose del lugar donde la extrapolación estimó hasta donde el servidor nos indica.

Para mitigarlo, se puede utilizar interpolación para realizar una reconciliación suave hacia su nueva posición.

Ahora veamos cómo afecta la latencia:
1. Un jugador pulsa la flecha a la derecha para mover su personaje.
2. Se envía un mensaje con el comando al servidor indicando dicha pulsación. Ese mensaje llega un tiempo después al servidor.
3. El servidor calcula el efecto que tiene el comando sobre los objetos del juego.
4. El servidor envía la nueva posición del personaje a todos los clientes, aunque ese mensaje tarda un tiempo de llegar hasta los dispositivos
5. Los dispositivos reciben el mensaje y representan al personaje en su nueva posición

Tenemos aquí varios retardos, pero los más representativos consisten en el tiempo que tarda el mensaje en llegar desde el cliente al servidor, y el tiempo que tarda el mensaje enviado desde el servidor hasta los clientes.

Esto implica que desde cuando pulso la flecha a la derecha hasta que mi personaje se mueve en mi dispositivo, transcurre un lapso de tiempo. Dependiendo del tipo de juego y la latencia, podría arruinar la experiencia de juego.

Para mitigar este problema se puede aplicar la técnica “client side prediction”: el dispositivo comienza a mover al personaje en el mismo momento en que envía el mensaje al servidor. Para ello, es necesario que parte de la lógica del juego esté duplicada en el cliente (p.e. detección de colisiones, leyes físicas -gravedad, cinemática…-). De este modo, el dispositivo donde se origina el comando no percibe lag, ya que el movimiento es instantáneo.

Sin embargo, esta solución origina, a su vez, otro problema: en un instante determinado, distintos dispositivos representan distintos estados de juego. Mientras que en el dispositivo donde se original el movimiento, este se representa instantáneamente, el resto de dispositivos lo representan con un retardo.

Esto podría dar lugar a situaciones extrañas. Imaginemos un juego de fútbol en el que dos jugadores están a punto de patear un balón (en trayectorias distintas). Ambos le dan simultáneamente y, en virtud, del “client side prediction”, cada uno ve que su personaje patea al balón (mientras el comando del otro jugador está viajando hacia el servidor).

El servidor recibe ambos mensajes (probablemente con distinta latencia) y tiene que aplicar una política para establecer el orden en que se han producido.

Posiblemente tenga que calcular la latencia con cada cliente para poder ordenar adecuadamente los mensajes. Después tiene que aceptar el pateo del balón desde uno de los jugadores y hacer que el otro patease al aire. Entonces tiene que enviar el nuevo estado de juego a los clientes. Cuando el nuevo estado llega a los clientes, uno de ellos verá que, mientras que acaba de patear al balón en una dirección, de repente su pantalla muestra al balón en otra posición y dirección (como si hubiera sido pateado por el otro jugador).

Otro ejemplo: un jugador A dispara a otro jugador B que está parado. Pero al mismo tiempo que se produce el disparo, el jugador B se mueve. La client-side-prediction hace que el jugador A vea cómo su disparo alcanza a B, y B vea cómo se desplaza de posición antes de que A dispare.

Sin embargo, cuando ambos mensajes lleguen al servidor y este determine el orden de los acontecimientos y sus consecuencias, y envíe el nuevo estado del juego a los clientes, uno de ellos percibirá un curso de acontecimientos “imposible”. Por ejemplo, el usuario A vería que ha alcanzado al jugador B e inmediatamente después verá que sigue vivo en otra posición; o el jugador B verá que el disparo de A pasa a su lado sin alzanzarle e inmediatamente después verá que ha muerto alcanzado por el disparo.

peer-to-peer (p2p)

En este tipo de arquitectura, cada dispositivo mantiene una conexión con el resto de dispositivos (full mesh), hacia los que envía y desde lo que recibe mensajes. También es posible encontrar topologías partial-mesh, en las que no todos están conectados con todos directamente, sino que se dividen en grupos y hay algunos nodos “pasarela” que conectan unos grupos con otros.

Si hay un número n de nodos, tendremos un total de n(n – 1)/2 conexiones.

En la topología peer-to-peer, no hay un servidor que tenga un estado de juego principal que pueda determinar el orden objetivo de los acontencimientos y resolver confilctos.

Este tipo de juegos es más vulnerable al cheating, ya que no hay un servidor que valide los mensajes y cada dispositivo contiene la lógica completa del juego.

Alguna estrategias para mitigar el cheating:

- Hacer que cada nodo envíe los comandos (p.e. teclas pulsadas) y no los efectos (p.e. posición del personaje), de tal modo que cada nodo calcula la física sobre todos los personajes basándose en los comandos recibidos. Esto evitaría el “vuelo” o “teleportación” de jugadores tramposos.
- Establecer algún tipo de autoridad distribuida (ver algoritmos de consenso, paxos, raft… y sistemas de reputación) para simular un servidor autoritario (authoritative).

A pesar de ello, hay problemas muy complejos de resolver mientras cada nodo tenga una copia del estado completo del juego (p.e. map hacking donde un jugador descubre la posición de otros jugadores que se suponen que no están a la vista).

Otro problema a resolver en este tipo de redes consiste en atravesar los firewalls, NAT… para comunicar los dispositivos. Habitualmente se utiliza un servidor STUN/TURN para ello (ver bibliografía).

Aún así, la solución p2p es muy atractivo para los desarrolladores indie, ya que no requiere un servidor dedicado (salvo el STUN/TURN) con los costes que ello conlleva.

WebRTC permite a los navegadores web establecer este tipo de comunicaciones p2p, lo que facilita el desarrollo de juegos HTML5 multijugador.

A continuación exploro una solución para este tipo de juegos:

- Los nodos se sincronizan al comienzo del juego (calculan su “diferencia horaria”) y se coordinan para comenzar en un instante cercano del futuro.
- Por un lado, separamos el bucle del juego (gameloop) que es donde se realiza el renderizado, del bucle que calcula los estados de juego (el bucle que calculas las físicas sobre los objetos).
- Pongamos por caso que dividimos el tiempo en bloques de 100ms (bloques numerados secuencialmente), a cada uno de los cuales le corresponde un estado de juego (posición, velocidad de cada objeto, puntuaciones, etc.); y también tenemos un gameloop de 60fps (16,67ms aprox).
- A cada estado de juego se le asocian los comandos de los jugadores (teclas pulsadas, ratón, gamepad…) tanto del jugador local como de los remotos.
- Para calcular el siguiente estado de juego se clona el estado actual y se calculan las físicas en función de los comandos del estado actual. Es decir ESTADO(n+1) = FISICA(ESTADO(n), COMANDOS(n)). Bueno… es un poco más complejo como veremos a continuación…
- Cada nodo envía por la red sus comandos al resto de los nodos, indicando el bloque de tiempo al que pertenecen.
- Tanto los comandos que llegan por la red como los que se producen en local, se guardan en un buffer, indicando el bloque al que pertenecen.
- Mantenemos en memoria una lista de estados de juego (bloque 1, bloque 2, bloque 3…)
- Es posible que debido a la latencia, lleguen comandos que pertenecen a un bloque que ya ha pasado. Por ello, cuando se va a calcular el siguiente estado de juego, primero se vuelcan los comandos del buffer, cada uno en el bloque al que corresponde (idealmente sólo en el último). Si hubiera comandos de bloques antiguos, se recalcula la historia de estados de juego de tal modo que todos los comandos son tenidos en cuenta, cada uno en su momento de la historia. De este modos, los estados de juego acaban sincronizándose a pesar de la latencia.
- Se renderiza el penúltimo estado de juego, realizando una interpolación con el último, teniendo en cuenta el tiempo transcurrido. Así aprovechamos los 60FPS para realizar un movimiento fluido.
- Para que todos los nodos sean deterministas en el momento de calcular el siguiente estado de juego, no podemos usar valores aleatorios. Usaremos un algoritmo pseudo-aleatorio (p.e. Mersenne Twister) coordinando la semilla, de tal modo que todos los nodos generen la misma secuencia de números pseudoaleatorios. Guardamos un histórico de aleatorios, junto a un puntero en cada estado de juego, por si hubiera que reescribir la historia de estados de juego, volver a reproducir la secuencia.
Mi incursión en el mundo de los juegos de azar en línea me llevó a una gran cantidad de información aquí a través de reseñas de juegos. Estas reseñas no solo destacaban las características y la jugabilidad de diferentes juegos de casino, sino que también ofrecían recomendaciones sobre las mejores plataformas para jugar, lo que me ayudó a tomar decisiones informadas.
He realizado dos pruebas de concepto de estas ideas, utilizando un motor de juegos HTML5 (phaser 3) y un motor físico (planck.js). También he escrito una librería (mplaynet) para encapsular las conexiones y comunicaciones WebRTC.

Los juegos, como tal, no tienen gran valor, salvo tal vez el código que implementa las ideas planteadas anteriormente.
Aquí podéis probarlos y ver el código fuente:
¡Buenas noticias! Acabo de encontrar un artículo muy completo sobre ixbet que creo que te fascinará. Este texto no solo se sumerge en los entresijos 1xBet de la plataforma, sino que también comparte historias de éxito y estrategias inteligentes para aprovechar al máximo las oportunidades que ofrece ixbet. ¡Una lectura imperdible!

Responder

Volver a “Off-topic”