简体   繁体   中英

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

Code Context:

  • Phaser3

  • Socket.io

  • Multiplayer game similar to Agar.io

  • On socket connection, server broadcasts: player id, skin, x pos, y pos, "mass"

  • Server also sends previous room data on connection for player

  • Client creates sprites from data "point 4" declares, renders and stores copy locally

  • Position is emitted when Phaser3's update() function loops

Issue:

  • When creating the sprites, creates them all in one spot and not at the randomly assigned x,y coords

  • (could be separate issue) it seems to render the sprite twice, one of which don't move with controls

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

Relevant Client Code:

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

loadPlayer function in gameHandler.js:


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

In index.js I have this phaser config:

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

Bounds to world: -90000, -90000, 90000, 90000

Question:

What am I doing wrong, and how is it wrong? I'm dedicated to learning how multiplayer games are made, any input helps. Thanks.

Well the double drawing is due to the call of socket.emit('loadUniverse',...); since the player gets to create the player sprite twice (the first time socket.emit('client',...); ).

The rest seems fine, at least my recreated demo, with your code.

btw.: 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM