2016-07-07 3 views
3

멀티 플레이어 (최대 2 명의 플레이어)에서 간단한 게임을 재현하려고합니다. 자바 스크립트, node.js, socket.io를 사용하고 있습니다. 모두 좋았지 만 서버에서 메인주기를 활성화하고 클라이언트에서 게임이 너무 유동적으로 시작했지만 2 ~ 3 초 후 지연과 동결이 기하 급수적으로 증가했습니다. 이 무한한주기에서 호출 이벤트 리스너의 무한한 것입니다 ..... 어떻게 피할 수 있습니까?socket.io 멀티 플레이어 게임에서 지연 지연 수정

다음은 서버의주기이다 :

function updateGameArea(){ 

    frameNo+=1; 
    if (players.length < 2){ 
      if (players[0]!=socket.id){ 
       console.log('Logged',socket.id); 
       players.push(socket.id); 
      } 

    } 
    for (i=0;i<players.length;i++){ 
     if (socket.id==players[i]){ 

      var c=i; 
     } 
    } 
    if (!id1 || !id0){ 
    socket.emit('id',{'id':c}); 
    } 




    socket.on('info',(data)=>{ 

     if (data.c==0){ 

      myGamePiece=data.x; 
      info0=true; 
     } 
     else { 

      yourGamePiece=data.x; 
      info1=true; 
     } 
    }) 

    socket.on('id0',()=>{ 
     id0=true; 

    }) 

    socket.on('id1',()=>{ 

     id1=true; 
    }) 


    if (id0 & id1 & info0 & info1){ 
    socket.emit('go'); 
    socket.emit('frame',{'f':frameNo}); 
    socket.on('newpos',(data)=>{ 
     console.log('Wroking'); 
     if (data.c==0){ 
      myGamePiece.newPos(); 
      socket.emit('info0',{'o':myGamePiece.gravitySpeed,'x':myGamePiece.x,'y':myGamePiece.y,'sy':myGamePiece.speedY}); 
     } 
     else if(data.c==1){ 
      yourGamePiece.newPos(); 
      socket.emit('info1',{'o':yourGamePiece.gravitySpeed,'x':yourGamePiece.x,'y':yourGamePiece.y,'sy':yourGamePiece.speedY}); 
     } 
    }) 

    socket.on('numob',(data)=>{ 
     myObstacles[myObstacles.length-1]=data.i; 
     myObstacles[myObstacles.length-1]=data.l; 
    }) 

    if (frameNo ==1 || everyinterval(150)){ 
     socket.emit('createob');       
    } 

    for (i=0;i<myObstacles.length;i+=1){ 
     myObstacles[i].x += -1 ; 
     socket.emit('agobj',{'i':i}); 
    } 

    for (i=0;i<myObstacles.length; i+=1){ 
     if (myGamePiece.crashWith(myObstacles[i])){ 
      socket.emit('dead0'); 
     } 
     else if(yourGamePiece.crashWith(myObstacles[i])){ 
      socket.emit('dead1'); 
     } 
    } 


    socket.on('push',(data)=>{ 
     var l=speed(data.id); 
     if (l=0){ 
      var id=0; 
      y=-3.5 
      socket.emit('pushinf',{'y':y,'id':id}) 
     } 
     else{ 
      var id=1; 
      y=-3.5; 
      socket.emit('pushinf',{'y':y,'id':id}) 
     } 
    }) 

    socket.on('disconnect',() => { 
     console.log('id attivo',socket.id); 
     console.log('disconnected!',socket.id); 
     for (i=0;i<players.length;i++){ 
      if (players[i]==socket.id){ 
       players.splice(i,1); 
      } 
     } 

    }); 
} 

다음은 클라이언트주기입니다 :

function updateGameArea(){ 

    socket.on('connect', function() { 
      console.log("connected from the client side"); 
    }); 

    socket.on('id',function(data){ 
     console.log('server sent info id to me') 
     console.log(data.id) 
     var id=data.id; 
     console.log(id); 
     if (id==0){ 
     socket.emit('id0'); 
     } 
     else { 
      socket.emit('id1'); 
     } 
     socket.emit('info',{'x':myGamePiece,'c':id}); 
    }); 
    socket.on('go',function(){ 
     go=true; 
    }) 
    if (go){ 
      socket.on('frame',function(data){ 
       frameNo=data.f; 
      }) 
      socket.on('createob',function(){ 
       x=myGameArea.canvas.width; 
       minHeight=60; 
       maxHeight=140; 
       height=Math.floor(Math.random()*(maxHeight-minHeight+1)+minHeight); 
       minGap=60; 
       maxGap=90; 
       var gap=Math.floor(Math.random()*(maxGap-minGap+1)+minGap);  
       myObstacles.push(new component(10,height,"green",x,0)); 
       myObstacles.push(new component(10,x-height-gap,"green",x,height + gap)); 
       socket.emit('numob',{'l':myObstacles[myObstacles.length],'i':myObstacles[myObstacles.length-1]}) 
      }); 
      socket.emit('newpos',{'c':id}); 
      socket.on('info0',function(data){ 
       if (id==0){ 
        myGamePiece.gravitySpeed=data.o 
        myGamePiece.x=data.x; 
        myGamePiece.y=data.y; 
        myGamePiece.speedY=data.sy; 
       } 
       else{ 
        yourGamePiece.gravitySpeed=data.o; 
        yourGamePiece.x=data.x; 
        yourGamePiece.y=data.y; 
        yourGamePiece.speedY=data.sy; 
       } 
      }) 
      socket.on('info1',function(data){ 
       if (id==1){ 
        myGamePiece.gravitySpeed=data.o; 
        myGamePiece.x=data.x; 
        myGamePiece.y=data.y; 
        myGamePiece.speedY=data.sy; 
       } 
       else{ 
        yourGamePiece.gravitySpeed=data.o; 
        yourGamePiece.x=data.x; 
        yourGamePiece.y=data.y; 
        yourGamePiece.speedY=data.sy; 
       } 
      }) 

      socket.on('dead0',function(){ 
       if (id==0){ 
       myGameArea.stop(); 
       mySound.play(); 
       GameO=true; 
       } 
       else{ 
       mySound.play(); 
       yourGamePiece.gravitySpeed==3.5; 
       } 
      }) 
      socket.on('dead1',function(){ 
       if (id==1){ 
       myGameArea.stop(); 
       mySound.play(); 
       GameO=true; 
       } 
       else{ 
       mySound.play(); 
       yourGamePiece.gravitySpeed==3.5; 
       } 
      }) 
      socket.on('agobj',function(data){ 
       myObstacles[data.i].x+=1; 
      }) 
      myGameArea.canvas.addEventListener('click',function(){ 
       socket.emit('push',{'id':id}); 
       if (mSoundw.sound.pausedy) { 
         mySoundw.sound.play(); 
        } 
        else{ 
         mySoundw.sound.currentTime = 0 
        } 

       socket.on('pushinf',function(data){ 
        if (id==data.c){ 
          myGamePiece.gravitySpeed=y; 
          myGamePiece.image.src="angry.png"; 
        } 
        else{ 
          yourGamePiece.gravitySpeed=y; 
          yourGamePiece.image.src="angryb.png"; 
        } 
       }) 
      },false) 
    } 

} 

답변

0

당신이 자신을 말했듯이, 첫눈에, 내 의견은 청취자가 범인이 될 수 있다는 것입니다. 클라이언트 측의 updateGameArea()가 게임을 업데이트하기 위해 반복되는 메서드 인 경우 업데이트가 발생할 때마다 소켓 이벤트에 리스너가 추가됩니다. 전직을위한 것입니다. 이 업데이트 메소드를 통한 5 번의 반복을 통해 하나의 메시지가 소켓을 통해 도착하면 전용 코드가 5 번 실행됩니다.

특정 메시지 (모든 수신기에 대해 동일)를 처리해야하는 방법을 소켓에 한 번만 알려주기 만하면됩니다. 설정시 루프를 반복해서 실행할 필요가 없습니다.

내가 말한 것과 함께 가기 위해 게시 한 코드를 리팩터링하려는 시도가 있습니다. updateGameArea() 메소드에게 어떤 작업을 수행해야한다는 경고를하기 위해 클라이언트 측에서 boolean이나 다른 변수를 사용하는 방법에 유의하십시오 (부울/변수가 재설정 된 후 필요한 경우 메시지를 다시 기다립니다).

이것은 '소켓'변수를 이미 초기화했다고 가정합니다.

희망 나는 아무것도 부수 지 않았다.

var id = null;//as long as it's null, no message is emitted from the client 
var go; 
var createob = false; 
var clicked = false; 

socket.on('connect', function() { 
    console.log("connected from the client side"); 
}); 

socket.on('id',function(data){ 
    console.log('server sent info id to me') 
    console.log(data.id) 
    id = data.id;//set the id 
    console.log(id); 
}); 

socket.on('go',function(){ 
    go = true; 
}); 

socket.on('frame',function(data){ 
    if (go) { 
     frameNo=data.f; 
    } 
}); 

socket.on('createob',function(){ 
    if (go) { 
     createob = true; 
    } 
}); 

socket.on('info0',function(data){ 
    if (id==0){ 
     myGamePiece.gravitySpeed=data.o 
     myGamePiece.x=data.x; 
     myGamePiece.y=data.y; 
     myGamePiece.speedY=data.sy; 
    } 
    else{ 
     yourGamePiece.gravitySpeed=data.o; 
     yourGamePiece.x=data.x; 
     yourGamePiece.y=data.y; 
     yourGamePiece.speedY=data.sy; 
    } 
}); 

socket.on('info1',function(data){ 
    if (id==1){ 
      myGamePiece.gravitySpeed=data.o; 
      myGamePiece.x=data.x; 
      myGamePiece.y=data.y; 
      myGamePiece.speedY=data.sy; 
     } 
     else{ 
      yourGamePiece.gravitySpeed=data.o; 
      yourGamePiece.x=data.x; 
      yourGamePiece.y=data.y; 
      yourGamePiece.speedY=data.sy; 
     } 
}); 


socket.on('dead0',function(){ 
    if (id==0){ 
     myGameArea.stop(); 
     mySound.play(); 
     GameO=true; 
    } 
    else{ 
     mySound.play(); 
     yourGamePiece.gravitySpeed==3.5; 
    } 
}); 

socket.on('dead1',function(){ 
    if (id==1){ 
     myGameArea.stop(); 
     mySound.play(); 
     GameO=true; 
    } 
    else{ 
     mySound.play(); 
     yourGamePiece.gravitySpeed==3.5; 
    } 
}); 

socket.on('agobj',function(data){ 
    myObstacles[data.i].x+=1; 
}); 

myGameArea.canvas.addEventListener('click',function(){ 
    clicked = true; 
    socket.emit('push',{'id':id}); 
    if (mSoundw.sound.pausedy) { 
     mySoundw.sound.play(); 
    } 
    else{ 
     mySoundw.sound.currentTime = 0 
    } 
},false); 

socket.on('pushinf',function(data){ 
    if (clicked) {//I was not sure if you need this to run only when there's been click. If it's independent of the click then remove this condition and the 'clicked = false' below 
     if (id==data.c){ 
       myGamePiece.gravitySpeed=y; 
       myGamePiece.image.src="angry.png"; 
     } 
     else{ 
       yourGamePiece.gravitySpeed=y; 
       yourGamePiece.image.src="angryb.png"; 
     } 
     clicked = false; 
    } 
}) 

function updateGameArea(){ 
    //whenever the 'id' message from the server arrives, it sets the id; 
    //whenever the game updates again it sees a non-null id and emits the 
    //corresponding message below, then sets the id to null again 
    if (id != null) { 
     if (id==0){ 
      socket.emit('id0'); 
     } 
     else { 
      socket.emit('id1'); 
     } 
     socket.emit('info',{'x':myGamePiece,'c':id}); 
     id = null; 
    } 


    if (go){ 
     if (createob) { 
      x=myGameArea.canvas.width; 
      minHeight=60; 
      maxHeight=140; 
      height=Math.floor(Math.random()*(maxHeight-minHeight+1)+minHeight); 
      minGap=60; 
      maxGap=90; 
      var gap=Math.floor(Math.random()*(maxGap-minGap+1)+minGap);  
      myObstacles.push(new component(10,height,"green",x,0)); 
      myObstacles.push(new component(10,x-height-gap,"green",x,height + gap)); 
      socket.emit('numob',{'l':myObstacles[myObstacles.length],'i':myObstacles[myObstacles.length-1]}) 

      /* 
      Depending on if you only want this body to be executed if and only if the 'createob' message has been received, 
      you may want to reinitialize the boolean 
      */ 
      createob = false;//comment this out if this body should run from the moment the message is received until further in the game, without depending on the createob message. 
     } 
     socket.emit('newpos',{'c':id}); 
    } 
} 
관련 문제