javascript express - Fix lag dans le jeu multijoueur socket.io




1 Answers

Comme vous l'avez dit vous-même, à première vue, mon opinion est que les auditeurs pourraient être les coupables. Si updateGameArea () du côté client est la méthode répété pour mettre à jour le jeu, chaque fois que la mise à jour se produit, vous ajoutez un écouteur à l'événement socket. Ce qui est, après pour ex. 5 itérations via cette méthode de mise à jour, si un message arrive par le socket, il exécute le code dédié 5 fois.

Vous avez seulement besoin de dire une fois à la socket comment gérer un certain message (même chose pour n'importe quel écouteur), et vous pouvez le faire lors de l'installation, pas besoin de le lancer encore et encore avec la boucle.

Voici une tentative de refactoriser le code que vous avez posté pour aller avec ce que je dis. Remarquez comment j'utilise des booléens ou d'autres variables lorsqu'un message est reçu du côté client pour alerter la méthode updateGameArea () qu'une tâche doit être effectuée (après quelle tâche le booléen / variable se réinitialise et attend à nouveau le message si nécessaire).

Cela suppose que vous avez déjà initialisé une variable 'socket'.

J'espère que je n'ai rien cassé.

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

J'essaie de reproduire un jeu simple en mode multijoueur (max 2 joueurs). J'utilise javascript, node.js, socket.io et express pour le faire. Tout était bien, mais à partir du moment où j'ai activé le cycle principal dans le serveur et dans les clients, le jeu commence si fluide mais après 2 ou 3 secondes, le retard et le gel augmentent exponentiellement. Je sais que c'est pour l'infini de l'auditeur d'événements que j'appelle dans les cycles infinis ..... Comment puis-je éviter cela?

Voici le cycle du serveur:

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

    });
}

Voici le cycle client:

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

}



Related

javascript node.js express socket.io server