Mundo continuo, adiós a los cambios de mapa en el AO

En una entrada previa expuse la estructura de datos que se utiliza en dinasty para almacenar los datos, tanto en ficheros para el cliente como en una base de datos SQL para el servidor. De esta forma nos alejamos, y de largo, de los formatos habituales que encontramos en el Argentum Online(o mods como el ImperiumAO).

A la hora de diseñar el sistema reparamos en que necesitaremos dividir el mundo en regiones para poder suscribir al jugador a aquellas en las que esté interesado. Después del proceso anterior las regiones del mapa quedaron de un tamaño de 82 de ancho por 86 de alto. Esto implicaría que si queremos que el usuario se suscriba a las «regiones de interés» en cada momento tendría que recibir la información actualizada de la región en la que está y las adyacentes. Esto supondría tenerlo al día de la información de 82*86*9=63468 tiles. Sin duda una cantidad excesiva e inútil en su mayoría.

La ventana «común» del AO tiene un tamaño de 17*13=221 (0,0035% de los 63468). Para evitar que el jugador vea una zona del área de la que no tiene información bastaría con que la región fuera de la mitad del tamaño de la ventana de juego. Sin embargo, hay que tener en cuenta que puede jugar con cierta latencia(lag) o tener que dibujar algo de un tamaño superior a un tile por lo que es necesario dejar un margen.

mundo_continuo_0

El tamaño de las subregiones que se utilizarán para el desarrollo son las que se muestran imagen. Dividiendo en 4×4 cada región se consigue reducir a un 6,25%.

Una vez decidida esta arquitectura entramos en consideraciones concretas a la hora de llevar a cabo la implementación teniendo en cuenta que es un juego online con comunicación vía socket entre cliente y servidor.

Cuando se entra al mundo, ya sea un personaje o una criatura, se calculan todas las subregiones de interés, esto es, en la que se encuentra y las 8 que la rodean. Para cada una de estas, se debe enviar la información de las mismas al que acaba de ingresar, a todos los suscritos a ellas el hecho de que esta entidad ha ingresado y por ultimo se suscribe al nuevo a cada una de las subregiones.

En cuanto al cliente, recibirá su posición actual y la subregion en la que se encuentra. Y en base a eso dibujara el mapa y todo lo que reciba de información de las subregiones a las que está suscrito(items, npcs, items…).

mundo_continuo_1

Uno de los conceptos mas importantes a tener en cuenta es que, independientemente de la posición en la que el cliente crea estar, es el servidor el que define la subregion en la que este se encuentra. De esta forma, el cliente liberará y cargará las subregiones en función de los cambios de región que el servidor le indique. Es en este momento cuando el cliente limpiará las entidades(personajes, npcs, items…) que han quedado en las áreas de las que el servidor le habrá dado de baja.

mundo_continuo_2

Si esto no se hace así, y es el cliente el que decide hacer la limpieza de regiones en función de la posición que cree tener, introduciríamos una serie bugs o incongruencias entre el cliente y el servidor.

Casos como, por ejemplo, que el cliente cambie de subregion borrando a otra entidad que ha quedado fuera de sus subregiones de interés porque aun no le ha llegado un mensaje del servidor sobre el movimiento del mismo. Cuando el cliente recibiera el mensaje de movimiento de la entidad este ya no tendría conocimiento de la existencia si quiera de la misma.

Siguiendo estas normas básicas, el servidor notifica al cliente de las entradas, salidas y movimientos de las entidades. El cliente será el que, sabiendo en que región se encuentra(no la posición), eliminará de su memoria las entidades que se muevan fuera de sus regiones de interés.

Aquí dejo los apuntes que se utilizaron para ilustrar el diseño que es de donde se han extraído las imágenes insertadas a lo largo de la entrada.

Esquema del diseño del mundo continuo

Por ultimo, el resultado puede verse aquí: (por aquel entonces usando reddwarf server y slick2d con nifty-gui aunque ha día de hoy se utilice Avocado y libgdx con scene2d)

Deja un comentario