2010-12-20 2 views
12

저는 플레이어 주변의 미니지도로 브라우저 게임을 만들고 있습니다. 다른 플레이어가있는 곳을 추적하고 누군가가 움직일 때마다이 미니 맵을 업데이트해야합니다. 나는 이것을 NodeJS와 CouchDB에서 구현하고있다. 내 디자인은 다음과 같습니다 :NodeJS에서 "sleep"을 에뮬레이트하려면 어떻게해야합니까?

나는 모든 변화하는 게임 데이터에 대한 데이터베이스를 가지고 있습니다. 이 데이터베이스에는 2 차원 배열의 기본지도 데이터가 들어있는 문서가 있는데이 격자의 각 사각형은이 배열의 요소로 표시됩니다. 여러 사용자가지도를 동시에 움직일 수 있었기 때문에 다른 사용자가 글을 쓰고있는 것처럼 읽을 수 없도록하는 방법이 필요했습니다 (많은 사용자가 읽는다면 잘못된 정보를 얻을 수 있습니다. 단일 문서 작성). 나는이 데이터베이스에서 개별 사각형을 나타내는 별도의 문서를 가지기로 결정했으며, 각 문서에는 해당 사각형이 "켜져"있는 플레이어와 해당 사각형과 관련된 다른 데이터가 있습니다. 기본적으로지도 문서는 정사각형 문서의 조회 테이블로만 사용됩니다. 이를 통해 전체 맵 문서를 다시 작성하지 않고도 단일 문서를 변경하고 동시 읽기 및 쓰기 문제를 해결할 수 있습니다.

그러나 내 문제는 사용자가 참조 용으로 사용할 수있는 미니 맵을 가져와야한다는 것입니다. 이 미니지도에는 주변 사각형의 문서가 있습니다. 이후이 모든 것을 동시에 필요로하기 때문에 데이터베이스에서 9 개의 사각형을 모두 가져 와서 단일 아약스 응답으로 반환한다고 생각했습니다. 내 문제는 내가 할 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를 내 모든 데이터를 받고 완료하지만, 자바 스크립트가 슬립 기능을 가지고 있지 않을 때까지 내가 기다릴 수있게된다. 내가 찾은 가장 가까운 것은 setTimeout이지만, 그것은 또한 블로킹이 아니므로 CouchDB가 내 데이터를 가져 오는 것을 끝내기에는 타임 아웃을 위해 선택한 시간이 충분하다는 것을 100 % 확신 할 수는 없습니다.

기본적으로 나는 조건을 갖고 그것을 테스트 한 다음 조건이 거짓 일 경우 다시 이벤트 스택으로 반환하려고합니다. 이것은 내가이 일을 할 수있는 더 좋은 방법이 있나요 ... 꽤 끔찍한 보인다

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

: 내가 생각 유일한 해결책은 같은 것을 할 것 재귀의 setTimeout 콜백을 가지고 있었다? 이 접근법을 포기하고 업데이트 된 데이터를 얻기 위해 여러 아약스 호출이 있어야만합니까? 차단 접근 방법을 선택해야합니까? 이 여러 노드 프로세스를 실행하는 데 필요하지 않는 한 나는 게임에 대해 잘 모르겠지만, 그것을

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 Array에서 Map 등을 유지하고 서버가 상태를 저장해야 할 때만 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 일 때 메인에서 캐치하고 거기에서부터 진행하십시오.

게임을 여러 노드에서 실행해야하는 경우에도 전체 맵을 다시 설정할 수 있습니다.

관련 문제