2016-07-07 6 views
3

Ich versuche, ein einfaches Spiel im Multiplayer (max 2 Spieler) zu reproduzieren. Ich benutze Javascript, node.js, socket.io und Express, um das zu tun. Es war alles gut, aber als ich den Hauptzyklus im Server und in den Clients aktivierte, begann das Spiel so flüssig, aber nach 2 oder 3 Sekunden nahmen die Verzögerung und der Einfrierfaktor exponentiell zu. Ich weiß, dass dies für die Unendlichkeit des Ereignishörers ist, den ich in den unendlichen Zyklen anrufe ... Wie kann ich das vermeiden?Fix Verzögerung in socket.io Multiplayer-Spiel

Hier ist der Zyklus des Servers:

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

    }); 
} 

Hier ist der Client-Zyklus:

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

} 

Antwort

0

wie Sie selbst gesagt, auf den ersten Blick, meine Meinung ist, dass die Zuhörer könnten die Täter sein. Wenn updateGameArea() auf der Clientseite wiederholt wird, um das Spiel zu aktualisieren, fügen Sie jedes Mal, wenn die Aktualisierung stattfindet, dem Socket-Ereignis einen Listener hinzu. Was ist, nach z. 5 Iterationen durch diese Update-Methode, wenn eine Nachricht über den Socket ankommt, wird der dedizierte Code fünfmal ausgeführt.

Sie müssen dem Socket nur einmal mitteilen, wie er mit einer bestimmten Nachricht umgehen soll (dasselbe gilt für jeden Listener), und Sie können dies beim Setup tun, ohne dass Sie es immer wieder mit der Schleife ausführen müssen.

Hier ist ein Versuch Refactoring der Code, den Sie gepostet haben, um mit dem zu gehen, was ich sage. Beachten Sie, wie ich Boolesche oder andere Variablen verwende, wenn eine Nachricht auf der Client-Seite empfangen wird, um die updateGameArea() -Methode zu benachrichtigen, dass eine Aufgabe ausgeführt werden muss (nach welcher Aufgabe die boolesche/Variable zurückgesetzt wird und ggf. auf die Nachricht wartet).

Dies setzt voraus, dass Sie bereits eine Variable 'Socket' initialisiert haben.

Ich hoffe, ich habe nichts kaputt gemacht.

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