2010-12-20 20 views
12

私は、プレーヤーの周囲のミニマップでブラウザゲームを構築しています。他のプレイヤーの位置を追跡し、誰かが移動するたびにこのミニマップを更新する必要があります。私はこれをNodeJSとCouchDBで実装しています。私のデザインは次のようになります:NodeJSで「スリープ」をエミュレートするにはどうすればよいですか?

私はすべての変化するゲームデータ用のデータベースを持っています。このデータベースでは、2次元配列の基本地図データを含む文書があり、グリッド上の各四角はこの配列の要素で表されています。私はマップを同時に動かしているたくさんの異なるユーザーを持つことができたので、誰かがそれを書いているときに私が読まないようにするための方法が必要でした(大量のユーザーが読んでいると、 1つの文書に書き込む)。このデータベースでは、個々の四角形を表す別々のドキュメントを用意することにしました。各ドキュメントには、四角形の「上に」あるプレーヤとその四角形に関連付けられた他のデータがあります。本質的に、マップドキュメントは、正方形ドキュメントのルックアップテーブルとしてのみ使用されます。これにより、マップ文書全体を書き直すことなく、単一の文書を変更することができ、同時に読み書きの問題を解決できます。

私の問題は、ユーザーが参照として使用するためのミニマップを取得する必要があるということです。このミニマップには、周囲の四角形の文書があります。私はこれをすべて同時に必要とするので、私はデータベースから9つのすべての四角形をつかみ、それを単一のAjaxレスポンスに戻すと思った。私の問題は、IOのブロック量を減らすことです。今、私はデータベースから必要な四角形を要求するネストループを持っています。ここに私のコードを見てみると、(位置とマップが渡されます)です。

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++; 
     }); 
    } 
} 

私の問題は、しかし、getDocはノンブロッキングなので、それはミニマップに正方形のデータを設定しますとき、私は知らないということです。私はこのような何かをやって考えた:

while(numDone < 9){ 
    sleep(10); 
} 
callback(miniMap); 

これはCouchDBのは、私のすべてのデータを取得して終了するまで、私は待つようになるが、JavaScriptがスリープ機能を持っていません。私が見つけた最も近いものはsetTimeoutでしたが、それも非ブロックであり、私がタイムアウトのために選んだ時間がCouchDBがデータを取得するのを十分にすることができるとは100%確信しません。

基本的に私は条件を持っていて、それをテストし、その条件が偽であれば再びイベントスタックに戻したいと思っています。これは私がこれを行うことができ、より良い方法はあります...かなりひどいようだ

function testCallback(data, condition, callback){ 
    if(data < condition){ 
     setTimeout(function(){ 
      testCallback(data, condition, callback); 
     }, 10); 
    }else{ 
     callback(data); 
    } 
} 

:私は考え唯一の解決策は、このような何かをするだろう再帰のsetTimeoutコールバックを持っていましたか?私はこのアプローチをあきらめ、更新されたデータを取得するために複数のajax呼び出しを強制する必要がありますか?私はブロッキングアプローチに向けるべきですか? 、これは、複数のノードのプロセスで実行する必要がある場合を除き、私はあなたのゲームについて多くを知らないが、それを

function getMiniMap(....., callback) { // supply the callback that sends the data 
    var miniMap = new Array(); 
    var keyMap = new Object(); 
    var numDone = 0; 
    ... 
       numDone++; 
       if (numDone === 9) { // as soon as everything has been collected... 
        callback(miniMap); // ... call the send callback and supply it the miniMap 
       } 
      }); 
     } 
    } 
} 

ああ、あなたのデータベースモデルは、本当に悪いです:

答えて

5

ちょうど別のコールバックを使用マップなどをJS配列に保持し、サーバーが状態を保存する必要があるときにのみDBに書き込むほうがよいでしょう。

ああ、あなたはまた、匿名関数呼び出しを使用してkeyMapを置き換えることができます。私たちは、イベント編システムについて話しているを考えると

(function(x, y) { 
     gameDB.getDoc(map[i][v].id, function(er, doc){ 
      var tPos = keyMap[doc._id]; 
      miniMap[tPos.y][tPos.x] = doc; 
      numDone++; 
     }); 
    })(x, y); // pass in a copy of x and y 
+1

私はマップの部分をすべて間違っていると思います。データベースの代わりにすべてをメモリに保存することは、確実に簡単な方法です。私は先に進み、すべてを私のマップ文書に入れて、再起動するか何かをする必要があるときだけ状態を保存すると思います。助けてくれてありがとう!! – tjameson

+1

[Redis](http://redis.io/)もチェックしてください。 redis-serverを起動してから、ノードにredisモジュールを使用します。文字列キーとjsonオブジェクトを与え、すべての子とデータをBAMに保存します。読み込んでキーを使用して、再びオブジェクトとしてメモリに戻します。 – BigOmega

+0

このタイプの状態情報の場合、Redisまたはリレーショナルデータストアの代わりに[Firebase](http://firebase.com)を使用することもできます。 Firebaseは、接続されているすべてのクライアントに状態をリアルタイムで同期させます。あなたのアプリケーションの種類に合わせて設計されています。 – DrFriedParts

1

、私はあなただけのイベントを行って負荷を発することができるならば、それはきれいだと思いますnumDone == 9のときにメインからキャッチし、そこから進みます。

ゲームを複数のノードにまたがって実行する必要がある場合でも、マップ全体を赤くすることができます。

関連する問題