Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/469.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 修复socket.io多人游戏中的延迟_Javascript_Node.js_Express_Socket.io_Server - Fatal编程技术网

Javascript 修复socket.io多人游戏中的延迟

Javascript 修复socket.io多人游戏中的延迟,javascript,node.js,express,socket.io,server,Javascript,Node.js,Express,Socket.io,Server,我正在尝试在多人游戏(最多2名玩家)中复制一个简单的游戏。我使用javascript、node.js、socket.io和express来实现这一点。 这一切都很好,但从我启动服务器和客户端的主循环开始,游戏开始时非常流畅,但在2秒或3秒后,延迟和冻结会成倍增加。我知道这是为了无限循环中我调用的无限多个事件监听器…我如何避免这种情况 以下是服务器的周期: function updateGameArea(){ frameNo+=1; if (players.length &l

我正在尝试在多人游戏(最多2名玩家)中复制一个简单的游戏。我使用javascript、node.js、socket.io和express来实现这一点。 这一切都很好,但从我启动服务器和客户端的主循环开始,游戏开始时非常流畅,但在2秒或3秒后,延迟和冻结会成倍增加。我知道这是为了无限循环中我调用的无限多个事件监听器…我如何避免这种情况

以下是服务器的周期:

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

    });
}

就像你自己说的,乍一看,我的观点是听众可能是罪魁祸首。如果客户端的updateGameArea()是更新游戏的重复方法,那么每次更新发生时,您都会向套接字事件添加一个侦听器。也就是说,在通过该更新方法进行了例如5次迭代之后,如果一条消息通过套接字到达,它将运行专用代码5次

您只需要告诉套接字一次它应该如何处理某个消息(对于任何侦听器都是如此),您可以在设置时这样做,而无需反复运行循环

下面是一个重构您发布的代码的尝试,以符合我的说法。请注意,当客户端收到消息时,我是如何使用布尔值或其他变量来提醒updateGameArea()方法需要执行某些任务的(在此任务之后,布尔值/变量将重置,并在必要时再次等待消息)

这是假设您已经初始化了一个变量“socket”

希望我没有弄坏任何东西

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