¿Cómo almacenar y mostrar eficientemente un mapa de mosaico en la web?

9

Acerca de

Estas son en realidad dos preguntas en una. En primer lugar, estoy buscando una manera de almacenar eficientemente grandes cantidades de datos de mosaico. El otro aspecto trata de consultar el conjunto de datos y mostrar mosaicos. Déjame darte algunos antecedentes primero.

Estamos haciendo un juego de magnate multijugador basado en navegador usando la biblioteca CraftyJS para representarlo en Canvas. En el fondo de la GUI, estamos ejecutando Yii Framework en PHP y todo se conecta a un generador de mapas aleatorios de Python y un motor de juegos.

Así es como se ve el primer renderizado del mapa aproximado: http://i.imgur.com/khAXtl.png

Almacenar los datos del mapa

El mundo del juego se genera aleatoriamente cada vez que comienza el juego. El tamaño es de 100x100 fichas hexagonales para cada jugador. Eso significa que para un juego de tres jugadores, se crean 90,000 fichas. Actualmente solo creo una matriz de JavaScript desde la que renderizo el mapa.

Esto funciona bien para renderizar, pero para cualquier tipo de interacción con el mapa necesitamos almacenar qué jugador posee el mosaico, qué tipo de estructura se construye encima, cuál es su precio actual, etc. Al principio, al menos para el prototipo, queríamos usar MySQL, pero después de algunas pruebas, no es exactamente tan rápido como me gustaría. Quizás un almacén de objetos como MongoDB sería más adecuado para almacenar datos de mosaico en lugar de una tabla SQL. O tal vez algo más?

Mostrar el mapa

Otro problema que veo es moverse por el mapa. Actualmente estoy creando entidades Crafty para cada mosaico, incluso si no está en la ventana gráfica. Esto es lento, porque a pesar de que Crafty representa solo los que están en la ventana gráfica, almacena y posiblemente repite todos los mosaicos en cada evento de representación. Lo que tengo actualmente es un mapa generado generado que es muy lento para cargar y tartamudea cuando te mueves, ahora me gustaría hacerlo jugable.

Mi primera idea fue cargar el subconjunto de mosaicos que se muestran en la ventana gráfica. Pero cuando un jugador mueve la ventana gráfica a un área en blanco, necesito consultar el servidor y esperar la respuesta, solo entonces se puede representar el mapa. Esto estaría bien en una aplicación nativa, pero es lenta en un juego web.

La forma de obtener un rendimiento uniforme del mapa podría ser precargar un subconjunto más grande de mosaicos en una matriz de JavaScript y usarlo como caché. El jugador tendría algunas pantallas "en caché" y cuando mueva la ventana gráfica, cargaría más fichas en el "caché" de JS.

¿Me dirijo en la dirección correcta? Me encantaría obtener más información de alguien que haya hecho algo similar. Soy nuevo en el desarrollo de juegos, pero he pasado por muchas fuentes en las últimas semanas.

elemento
fuente
1
Me sorprende que hayas identificado a MySQL como un cuello de botella. ¿Qué probaste para llegar a la conclusión de que está ralentizando las cosas?
bummzack
@bummzack Si tiene una fila por ficha, apenas puedo ver cómo las cosas no podrían ser lentas.
aaaaaaaaaaaa
1
@eBusiness Consultar miles de filas desde una base de datos no debería ser realmente un problema. Esto todavía debería estar en el rango de algunos milisegundos. Tampoco serían 90,000 filas, sino 30,000 filas para 3 jugadores (100x100 por jugador).
bummzack
Perdón por las matemáticas confusas, también hay dos veces el espacio entre los jugadores, además de la zona del jugador, de modo que están a la misma distancia entre sí, lo que hace que sea 90k. Consultar no es un problema. Seleccionar 90k fichas y construir un mapa es. Pero no es una buena manera de hacerlo. Serializaré los datos del mapa y usaré la consulta de los mosaicos en el DB cuando se solicite información detallada.
elemento

Respuestas:

2

Jugabilidad
Antes que nada me gustaría preguntarte, ¿realmente necesitas 10.000 fichas por jugador? Si bien no sé qué tipo de juego estás haciendo, generalmente es cierto que los mapas grandes son juegos largos. El mapa más grande en Civilization 5 es 10240 fichas, y eso solo funciona porque no necesitas jugar en más de una fracción.

Base de datos
No debe intentar ejecutar un juego como este desde una base de datos, debe mantener los datos en la memoria de la aplicación. Puedes usar una base de datos para hacer una copia de seguridad del juego. Para una copia de seguridad completa, guarde una serialización de los datos del juego, y luego puede incrementarla guardando las órdenes dadas y luego volver a ejecutarlas si la copia de seguridad necesita ser utilizada.

Almacenamiento de JavaScript
En cuanto al cliente, diría que es mejor que mantenga todo el mapa cargado, al menos si se adhiere a los miles de mosaicos que lo tienen todo en un bonito árbol de objetos podría ser demasiado, por lo que probablemente debería mantener los datos en un formato codificado "semi-binario". Las cadenas funcionan excelente para este tipo de cosas, alternativamente, puede almacenar de forma segura enteros sin firmar de hasta 53 bits en un flotante de 64 bits, rellenar muchos de ellos en una matriz y creo que verá una huella de memoria bastante modesta.

Visualización de JavaScript
Si bien no diré que no necesariamente debe usar el lienzo, en realidad no lo necesita para cosas como esta. Configúrelo todo como un grupo de elementos img y cambie la propiedad src para mostrar diferentes partes del mapa.

Consejo profesional
Por cierto, a veces es más fácil compartir la semilla utilizada para generarla que compartir todo el mapa.

aaaaaaaaaaaa
fuente
+1, pero lamentablemente una aplicación web escrita en PHP generalmente no tiene medios para mantener el estado del juego en la memoria.
bummzack
@bummzack, Ahh, claro, creo que de alguna manera salté la palabra PHP y solo leí Python. Entonces un cambio de marco de back-end podría estar en orden. Node.js podría ser una opción.
aaaaaaaaaaaa
Estoy construyendo un magnate de transporte competitivo, piense en OpenTTD, un mapa del tamaño de 512x512 (262k) no es tan grande para un par de jugadores. Me doy cuenta de que es ambicioso, pero si el mapa no es tan grande, el juego terminaría demasiado pronto. Debido a que es un juego multijugador, necesito sincronizar los cambios en el mapa entre jugadores. Mi primer instinto fue usar los conceptos que conozco del desarrollo web e ir con una base de datos. No necesita ser súper en tiempo real. Voy con la visualización JS, porque me gustaría tener cosas dinámicas en el mapa.
elemento
Considere que mi respuesta son algunos consejos, al final tendrá que calcular el rendimiento usted mismo, es un problema grave y es posible que tenga que hacer algunos compromisos.
aaaaaaaaaaaa
Estoy de acuerdo, tu respuesta me dio mucho que pensar. Intentaré encontrar una manera de mantener los datos del mapa serializados en la memoria y mantener la base de datos como respaldo. Pero luego tengo que descubrir cómo compartir los cambios entre los jugadores. Volveré con lo que se me ocurrió después de hacer más pruebas.
elemento
1

MySQL no es lento. Lo más probable es que esté realizando consultas ingenuas o que tenga índices subóptimos. Los enfoques NoSQL como MongoDB pueden ser más rápidos, tal vez no. Su patrón de acceso y elección de consulta es lo que realmente importa aquí. Es posible dar consejos sobre cómo mejorar el rendimiento, pero no sin ver lo que ya está haciendo.

La forma de obtener un rendimiento uniforme del mapa podría ser precargar un subconjunto más grande de mosaicos en una matriz de JavaScript y usarlo como caché.

Sí, por supuesto. No hay mucho que agregar aquí: el cliente solicita mosaicos del servidor, por lo que solo debe asegurarse de que los que solicite cubran un área más grande que la pantalla.

Apéndice:

estamos ejecutando Yii Framework en PHP y todo se conecta a un generador de mapas aleatorios de Python y un motor de juegos.

Si eres competente con Python, te aconsejo que abandones al intermediario de PHP. Si ejecuta su juego como un proceso de Python, puede mantener sus datos de mosaico en la memoria mucho más fácilmente y reducir significativamente los accesos de MySQL. Ayuda que Python sea un lenguaje mucho más sano que PHP también.

Kylotan
fuente