Come archiviare e visualizzare in modo efficiente una mappa dei riquadri sul Web?


9

Di

Queste sono in realtà due domande in una. Innanzi tutto, cerco un modo per archiviare in modo efficiente grandi quantità di dati sui riquadri. L'altro aspetto riguarda l'interrogazione del set di dati e la visualizzazione di riquadri. Lascia che ti dia prima qualche informazione.

Stiamo realizzando un gioco magnate multiplayer basato su browser utilizzando la libreria CraftyJS per renderlo su Canvas. Sullo sfondo della GUI stiamo eseguendo Yii Framework su PHP e tutto si collega a un generatore di mappe casuali Python e un motore di gioco.

Ecco come appare il primo rendering approssimativo della mappa: http://i.imgur.com/khAXtl.png

Memorizzare i dati della mappa

Il mondo di gioco viene generato casualmente ogni volta che inizia il gioco. La dimensione è di 100x100 tessere esagonali per ogni giocatore. Ciò significa che per una partita a tre giocatori, vengono create 90.000 tessere. Attualmente creo solo un array JavaScript da cui eseguo il rendering della mappa.

Funziona bene per il rendering, ma per qualsiasi tipo di interazione con la mappa dobbiamo memorizzare quale giocatore possiede la tessera, quale tipo di struttura è costruita su di essa, qual è il suo prezzo attuale e così via. Inizialmente, almeno per il prototipo, volevamo usare MySQL, ma dopo alcuni test, non è esattamente veloce come vorrei. Forse un negozio di oggetti come MongoDB sarebbe più adatto per l'archiviazione dei dati di tile invece di una tabella SQL. O forse qualcos'altro?

Visualizzazione della mappa

Un altro problema che vedo è muoversi sulla mappa. Attualmente sto creando entità Crafty per ogni riquadro anche se non è nella finestra. Questo è lento, perché anche se Crafty esegue il rendering solo di quelli nella finestra, memorizza e probabilmente scorre tutte le tessere su ciascun evento di rendering. Quello che ho attualmente è una mappa generata disegnata che è molto lenta da caricare e balbetta quando ti muovi, ora mi piacerebbe renderla giocabile.

La mia prima idea è stata quella di caricare il sottoinsieme visualizzato di riquadri presenti nella finestra. Ma quando un giocatore sposta la finestra in un'area vuota, devo interrogare il server e attendere la risposta, solo allora la mappa può essere renderizzata. Questo andrebbe bene in un'applicazione nativa, ma è lento in un gioco web.

Il modo per ottenere prestazioni fluide dalla mappa potrebbe essere il precaricamento di un sottoinsieme più grande di riquadri in un array javascript e utilizzarlo come cache. Il giocatore avrebbe alcune schermate "memorizzate nella cache" e quando sposta il viewport, caricavo più riquadri nella "cache" di JS.

Sono diretto nella giusta direzione? Mi piacerebbe avere qualche informazione in più da qualcuno che ha fatto qualcosa di simile. Sono nuovo nello sviluppo di giochi, ma ho passato molte fonti nelle ultime due settimane.


1
Sono sorpreso che tu abbia identificato MySQL come un collo di bottiglia. Cosa hai testato per arrivare alla conclusione che sta rallentando le cose?
Bummzack,

@bummzack Se ha una fila per tessera non vedo quasi come le cose non possano essere lente.
aaaaaaaaaaaa

1
@eBusiness Interrogare alcune migliaia di righe da un DB non dovrebbe essere un problema. Questo dovrebbe essere ancora nell'intervallo di alcuni millisecondi. Inoltre non sarebbero 90.000 file, ma piuttosto 30.000 file per 3 giocatori (100x100 per giocatore).
Bummzack,

Ci scusiamo per la matematica confusa, c'è anche il doppio dello spazio tra i giocatori oltre alla zona del giocatore in modo che siano a uguale distanza l'uno dall'altro, il che lo rende 90k. L'interrogazione non è un problema. Selezionare 90k tessere e costruire una mappa è. Ma non è un buon modo per farlo. Serializzerò i dati della mappa e userò la query sui riquadri nel db quando sono richieste informazioni dettagliate.
elemento

Risposte:


2

Gameplay
Prima di tutto vorrei chiederti, hai davvero bisogno di 10000 tessere per giocatore? Anche se non so che tipo di gioco stai realizzando, è generalmente vero che le mappe di grandi dimensioni creano giochi lunghi. La mappa più grande in Civilization 5 è 10240 tessere, e funziona solo perché non è necessario giocarci su più di una frazione.

Database
Non dovresti provare a eseguire un gioco come questo da un database, devi conservare i dati nella memoria dell'applicazione. È possibile utilizzare un database per eseguire il backup del gioco. Per un backup completo, salva una serializzazione dei dati di gioco, quindi puoi incrementarlo salvando gli ordini dati e rieseguire quelli se è necessario utilizzare il backup.

Memoria JavaScript
Per quanto riguarda il client, direi che è meglio mantenere l'intera mappa caricata, almeno se ti attieni alle tessere gazillion che hanno tutto in un bel albero di oggetti potrebbe essere un po 'troppo, quindi probabilmente dovresti conservare i dati in un formato codificato "semi-binario". Le stringhe funzionano in modo eccellente per questo tipo di cose, in alternativa, puoi tranquillamente memorizzare numeri interi senza segno fino a 53 bit in un float a 64 bit, roba molti di quelli in un array e penso che vedrai un footprint di memoria piuttosto modesto.

Visualizzazione JavaScript
Anche se non dirò che non dovresti necessariamente usare canvas, in realtà non ti serve per cose come questa. Imposta tutto come un gruppo di elementi img e modifica la proprietà src per visualizzare diverse parti della mappa.

Suggerimento pro
A proposito, a volte è più facile condividere il seme usato per generarlo che condividere l'intera mappa.


+1, ma purtroppo un'app Web scritta in PHP di solito non ha alcun mezzo per mantenere in memoria lo stato del gioco.
Bummzack,

@bummzack, Ahh, giusto, penso che in qualche modo ho saltato la parola PHP e ho appena letto Python. Quindi un cambiamento del framework back-end potrebbe essere in ordine. Node.js potrebbe essere un'opzione.
aaaaaaaaaaaa

Sto costruendo un magnate dei trasporti competitivo, penso a OpenTTD, una mappa delle dimensioni di 512x512 (262k) non è così grande per un paio di giocatori. Mi rendo conto che è ambizioso, ma se la mappa non è così grande, il gioco finirebbe troppo presto. Perché è un gioco multiplayer, devo sincronizzare le modifiche alla mappa tra i giocatori. Il mio primo istinto è stato quello di usare solo i concetti che conosco dallo sviluppo web e andare con una base di dati. Non deve essere super in tempo reale. Vado con la visualizzazione JS, perché mi piacerebbe avere elementi dinamici sulla mappa.
elemento

Considera la mia risposta come un suggerimento, alla fine dovrai capire tu stesso le prestazioni, è un problema serio e potresti dover scendere a compromessi.
aaaaaaaaaaaa

Sono d'accordo, la tua risposta mi ha dato un sacco di spunti di riflessione. Proverò a trovare un modo per mantenere in memoria i dati delle mappe serializzate e mantenere il database come backup. Ma poi devo capire come condividere i cambiamenti tra i giocatori. Tornerò con quello che mi viene in mente dopo aver fatto ulteriori test.
elemento

1

MySQL non è lento. Molto probabilmente stai eseguendo query ingenue o hai indici non ottimali. Approcci NoSQL come MongoDB potrebbero essere più veloci, forse no. Il modello di accesso e la scelta della query è ciò che conta davvero qui. È possibile dare consigli su come migliorare le prestazioni, ma non senza vedere ciò che si sta già facendo.

Il modo per ottenere prestazioni fluide dalla mappa potrebbe essere il precaricamento di un sottoinsieme più grande di riquadri in un array javascript e utilizzarlo come cache.

Sì, naturalmente. Non c'è molto da aggiungere qui: il client richiede i riquadri dal server, quindi devi solo assicurarti che quelli che richiedi coprano un'area più grande dello schermo.

Addendum:

stiamo eseguendo Yii Framework su PHP e tutto si collega a un generatore di mappe casuali Python e motore di gioco.

Se sei competente con Python, ti consiglio di abbandonare l'intermediario PHP. Se esegui il tuo gioco come un processo Python, puoi conservare i dati delle tessere in memoria molto più facilmente e ridurre significativamente gli accessi a MySQL. Aiuta che Python è anche un linguaggio molto più sano di PHP.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.