Javascript,Phaser3,Socket.io 玩家起始位置不正确,多人游戏

Javascript, Phaser3, Socket.io Player Starting Position Not As Set, Multiplayer

代码上下文:

问题:

server.js:

function hypotenuse(x,y,x1,y1)
{
    deltaX = x1-x;
    deltaY = y1-y;
    a = Math.sqrt((deltaX * deltaX) + (deltaY * deltaY));
    return a;
}
function randomInt() {

    min = Math.ceil(0.1);
    max = Math.floor(8000);
    return Math.floor(Math.random() * (max - min) + min);
  }
io.on('connection',(socket)=>
{
    console.log(`${socket.id} joined the universe!`); 

    universe['0'].players[socket.id] = {playerID:socket.id,x:randomInt(),y:randomInt(),mass:50}; //assign an arbitrary value for x and y, set it client side.

    socket.emit('client',socket.id,universe['0'].players[socket.id].x,universe['0'].players[socket.id].y,null,universe['0'].players[socket.id].mass);

    socket.broadcast.emit('join',socket.id,universe['0'].players[socket.id].x,universe['0'].players[socket.id].y, null,universe['0'].players[socket.id].mass); 

    socket.emit('loadUniverse', universe['0'].players); //sending to client only
    


    socket.on('updatePos',({player,vx,vy,x,y})=> //make into object
    { 

        if(universe['0'].gameRules.mass<200)
        {
            
            let id = 'mass:'+ randomInt() + randomInt() + randomInt();

            console.log(`mass id: ${id}`);

            universe['0'].players[id] = {playerID:id,x:randomInt(),y:randomInt(),mass:10};
            
            //do not use this, broadcast to individual rooms with io.to(room).emit(channel,content)
            io.emit('spawnMass',id,universe['0'].players[id].x,universe['0'].players[id].y,null,universe['0'].players[id].mass);

            universe['0'].gameRules.mass+=1;
        }

        if(player in universe['0'].players)
        {

        universe['0'].players[player].x = x;
        universe['0'].players[player].y = y;


        for(const player1 in universe['0'].players)
        {
            if(player1!==player)
            {
                //distance between two coord pairs
                let distance  = hypotenuse(universe['0'].players[player1].x,universe['0'].players[player1].y,x,y);

                //console.log(distance); 
                //console.log('debugging NaN1')

                if(distance < 100) 
                {
                    console.log('overlapping')
                    if(universe['0'].players[player].mass>universe['0'].players[player1].mass)
                    {
                        universe['0'].players[player].mass+=universe['0'].players[player1].mass
                        socket.emit('attracted',universe['0'].players[player].playerID,universe['0'].players[player1].playerID)
                        socket.emit('eliminated',universe['0'].players[player1].playerID) //have all state change in same socket event
                        delete universe['0'].players[player1]

                    }
                    else
                    {
                        universe['0'].players[player1].mass+=universe['0'].players[player].mass
                        socket.emit('attracted',universe['0'].players[player1].playerID,universe['0'].players[player].playerID)
                        socket.emit('eliminated',universe['0'].players[player].playerID) //have all state change in same socket event
                        delete universe['0'].players[player]
                    }
                }
                //if in radius, remove player from room and add points to winner
            }
            
        }
        }
        
            
                socket.broadcast.emit("updatePos1", player,vx,vy); 
            
    })


    socket.on('disconnect',()=>
    {
        delete universe['0'].players[socket.id]
        //emit a delete event
        console.log(`${socket.id}player left the universe!`)
    })
})

相关客户代码:

        scene.socket.on('connect',()=> //needs to chain from the connect
        {
            this.scene.socket.emit('join',this.socketID) //gives id to server, server chooses skin, server broadcasts
            console.log(`connected`);
        })
        scene.socket.on('updatePos1',(socketID1,vx,vy)=>
        { 
           
                if(this.socketID!==socketID1)
                {  
                    //console.log('socket was not yours!');
                    this.scene.gameHandler.players[socketID1].sprite.body.setVelocity(vx,vy);
                }
            
        })
        //ITEM BREAKS UP INTO SMALLER CHUNKS IF GRAVITY IS "VIOLENT" ENOUGH
        scene.socket.on('attracted',(player,player1)=>
        {
            this.scene.gameHandler.players[player].mass+=this.scene.gameHandler.players[player1].mass
        }) 
        scene.socket.on('eliminated',(player)=>
        {
            console.log('eliminated',player,this.scene.gameHandler.players[player])
            this.scene.gameHandler.players[player].sprite.destroy(true);
            delete this.scene.gameHandler.players[player];
        })
        scene.socket.on('join',(socketID0,x,y,skin,mass)=>
        {
            console.log(`Player ${socketID0} joined`);
            
            this.scene.gameHandler.loadPlayer(socketID0,x,y,skin,mass);
            
        })

        scene.socket.on('client',(socketID0,x,y,skin,mass)=>
        {
            this.socketID = socketID0;
            this.scene.gameHandler.loadPlayer(socketID0,x,y,skin,mass);
        })

        scene.socket.on('loadUniverse',(universe)=>
        {
            for(const property in universe)
            {
                console.log(`propery:${property}`);
                console.log(universe[property].x,universe[property].y)
                this.scene.gameHandler.loadPlayer(property,universe[property].x,universe[property].y,null,universe[property].mass);//make this dynamic
    
            }
        })
        scene.socket.on('spawnMass',(id,x,y,skin,mass)=>
        {
            this.scene.gameHandler.loadPlayer(id,x,y,skin,mass);
            this.scene.gameHandler.players[id].sprite.setScale(0.2,0.2)
        })
        
    }
    updatePos()
    {
        console.log(`${this.socketID} for updatePos()`)


        this.scene.socket.emit(
        'updatePos',
        {
            player:this.socketID,
            vx:this.scene.gameHandler.players[this.socketID].sprite.body.velocity.x, 
            vy:this.scene.gameHandler.players[this.socketID].sprite.body.velocity.y,
            x:this.scene.gameHandler.players[this.socketID].sprite.body.x,
            y:this.scene.gameHandler.players[this.socketID].sprite.body.y
        }
        )
       
    }

gameHandler.js 中的 loadPlayer 函数:


    loadPlayer(socketID,x,y,skin,mass) //get websocket to load player
    {
        if(socketID)
        {       //id:{sprite:x}
            this.players[socketID] = 
            {
                sprite: this.scene.physics.add.sprite
                (
                    x,//this.scene.game.config.width * 0.5,
                    y,//this.scene.game.config.height * 0.5,
                    "arc_pink"
                ),
                mass: mass
            }
        }

        console.log(`Load player returned: ${this.players[socketID].mass}`)
        this.players[socketID].sprite.x = x;
        this.players[socketID].sprite.y = y;

        this.players[socketID].sprite.setOrigin(0.5,0.5);
        this.players[socketID].sprite.body.setCollideWorldBounds(true);

        socketID == this.scene.socketsHandler.socketID?this.scene.cameras.main.startFollow(this.players[socketID].sprite):null;

        console.log(`Load player returned: ${this.players[socketID]}`)
       
     
    }

在 index.js 我有这个移相器配置:

const config = {
  parent: "phaser-example",
  type: Phaser.AUTO,
  scale:
  {
    mode: Phaser.Scale.FIT,
    width: 1800,
    height: 1600
  },
  autoCenter: Phaser.Scale.CENTER_BOTH,
  physics: {
    default: "arcade",
    arcade: {
      Gravity: { x: 0, y: 0 },
      debug: false,
    },
  },
  scene: MyGame,
};

世界范围: -90000, -90000, 90000, 90000

问题:

我做错了什么,怎么错了?我致力于学习多人游戏是如何制作的,任何输入都会有所帮助。谢谢。

嗯,两次绘制是由于 socket.emit('loadUniverse',...); 的调用,因为玩家需要创建玩家精灵两次(第一次 socket.emit('client',...);)。

其余的看起来不错,至少我用你的代码重新创建了演示。

btw. 1: You could check the default phaser libraries / functions. Phaser has many helper functions, like for example:

btw. 2: a compact phaser multiplayer game tutorial can be found here https://gamedevacademy.org/create-a-basic-multiplayer-game-in-phaser-3-with-socket-io-part-1/ uses phaser headless on the server side. Just if you want to se an other approach