Je construis un jeu par navigateur avec une mini carte des environs du joueur. J'ai besoin de suivre où sont les autres joueurs et de mettre à jour cette mini-carte chaque fois que quelqu'un bouge. Je l'implémente dans NodeJS et CouchDB. Ma conception va comme suit:Comment émuler "sleep" dans NodeJS?
J'ai une base de données pour toutes les données de jeu changeantes. Dans cette base de données, j'ai un document qui contient les données cartographiques de base dans un tableau bidimensionnel, chaque carré de la grille étant représenté par un élément dans ce tableau. Comme je pouvais avoir des tonnes d'utilisateurs différents qui se déplaçaient simultanément sur la carte, j'avais besoin de m'assurer que je ne lisais pas comme quelqu'un d'autre m'écrit (je pourrais obtenir des informations erronées si une tonne d'utilisateurs lisent et écrire sur un seul document). J'ai décidé d'avoir des documents séparés dans cette base de données qui représentent les carrés individuels, et chaque document a les joueurs qui sont "sur" ce carré et d'autres données associées à ce carré. Essentiellement, le document de carte est utilisé uniquement comme une table de recherche pour le document carré. Cela me permet de modifier un seul document sans avoir à réécrire l'intégralité du document cartographique, ce qui résout le problème des lectures et écritures simultanées. Mon problème, cependant, est que j'ai besoin d'obtenir une mini carte pour l'utilisateur à utiliser comme référence. Cette mini carte aura les documents des carrés environnants. Puisque j'ai besoin de tout cela en même temps, j'ai pensé que je voudrais simplement saisir tous les 9 carrés de la base de données et le renvoyer dans une seule réponse ajax. Mon problème est cependant de réduire la quantité d'IO de blocage que je fais. À l'heure actuelle, j'ai une boucle imbriquée qui demande les carrés dont j'ai besoin de la base de données. Voici un coup d'oeil à mon code (position et carte sont passés dans):
var miniMap = new Array();
var keyMap = new Object();
var numDone = 0;
for(i = position.y - 1, y = 0; i < position.y + 1 && i < map.length; i++, y++){
miniMap[i] = new Array();
for(v = position.x - 1, x = 0; v < position.x + 1 && v < map.length; v++, x++){
keyMap[map[i][v].id] = {'x': x, 'y': y};
gameDB.getDoc(map[i][v].id, function(er, doc){
var tPos = keyMap[doc._id];
miniMap[tPos.y][tPos.x] = doc;
numDone++;
});
}
}
Mon problème, cependant, est que GetDoc est non-blocage, donc je ne sais pas quand il établira les données carrés à minicarte . Je pensais faire quelque chose comme ceci:
while(numDone < 9){
sleep(10);
}
callback(miniMap);
Cela me laisse attendre jusqu'à ce que CouchDB est fini obtenir toutes mes données, mais JavaScript ne dispose pas d'une fonction sommeil. Le plus proche que j'ai trouvé était setTimeout, mais il est également non-bloquant et je ne serai jamais sûr à 100% que le temps que j'ai choisi pour le timeout sera suffisant pour permettre à CouchDB de finir d'obtenir mes données. Donc, fondamentalement, je veux avoir une condition, la tester, puis la renvoyer à la pile d'événements si la condition est fausse. La seule solution que je pensais était d'avoir un rappel setTimeout récursif qui ferait quelque chose comme ceci:
function testCallback(data, condition, callback){
if(data < condition){
setTimeout(function(){
testCallback(data, condition, callback);
}, 10);
}else{
callback(data);
}
}
Cela semble assez terrible ... Y at-il une meilleure façon que je puisse faire cela? Dois-je abandonner cette approche et forcer plusieurs appels ajax pour obtenir des données à jour? Devrais-je opter pour une approche bloquante?
Je suppose que je fais la partie de la carte tout faux. Garder tout en mémoire au lieu de la base de données sera certainement un moyen plus facile de faire les choses. Je pense que je vais aller de l'avant et tout mettre dans mon document de carte et enregistrer seulement l'état quand j'ai besoin de redémarrer ou quelque chose. Merci pour l'aide!! – tjameson
Consultez également [Redis] (http://redis.io/). Vous démarrez redis-server, puis utilisez le module redis dans le noeud. Vous donnez une clé de chaîne, puis un objet json, et BAM tous les enfants et les données sauvegardées. Chargez-le et utilisez la clé pour le remettre dans la mémoire en tant qu'objet. – BigOmega
Vous pouvez également envisager [Firebase] (http://firebase.com) comme alternative à Redis ou à un magasin de données relationnel pour ce type d'informations d'état. Firebase va synchroniser l'état en temps réel avec tous les clients attachés. Il a été conçu pour votre type d'application. – DrFriedParts