Kory
Kory

Reputation: 55

How to display all players in an online game node.js + socket.io + phaser 3?

The first player can see the second player and his movement. The second player can't see the first player, let alone the movement. If you reload, they change places and so on ad infinitum. I don't have any errors, I think the error is in the algorithm. I use node.js, socket.io, phaser 3, express and so on. I want all players to see each other and their movement.

Part of the code on the server

    io.on('connection', (socket) => {
        console.log('A user connected');

        socket.on('createPlayer', async () => {
            try {
                const userId = socket.handshake.session.user.id;
                socket.emit('currentUserId', userId);

                const [rows] = await pool.query('SELECT * FROM users WHERE id = ?', [userId]);

                if (rows.length > 0) {
                    let playerData = {
                        playerId: userId,
                        x: rows[0].x_position,
                        y: rows[0].y_position,
                    };

                    socket.broadcast.emit('newPlayer', playerData);

                    io.emit('playerCreated', playerData);
                } else {
                    io.to(socket.id).emit('playerCreationError', 'Игрок не найден.');
                }
            } catch (error) {
                console.error(error);
                io.to(socket.id).emit('playerCreationError', 'Error');
            }
        });

    socket.on('playerMovement', async (data) => {
        try {
            const userId = socket.handshake.session.user.id;
            const { x, y } = data;

            await pool.query('UPDATE users SET x_position = ?, y_position = ? WHERE id = ?', [x, y, userId]);

            socket.broadcast.emit('playerMoved', { playerId: userId, x, y });
        } catch (error) {
            console.error(error);
        }
    });

Сode on the client

const socket = io();

class BaseScene extends Phaser.Scene {
    constructor(key) {
        super({ key });
        this.currentUserId = null;
        this.currentPlayers = {};
    }

    preload() {
        this.load.image('player', 'assets/player.png');
    }

    create() {

        const self = this;

        this.cursors = this.input.keyboard.createCursorKeys();

        socket.emit('createPlayer');

        socket.on('currentPlayers', (players) => {
            this.currentPlayers = players;
        });

        socket.on('currentUserId', (userId) => {
            console.log('Current user ID:', userId);
            this.currentUserId = userId;
        });

        socket.on('playerCreationError', (message) => {
            console.log(message);
        });

        socket.on('playerCreated', (playerData) => {
            if (playerData.playerId === this.currentUserId) {
                
                this.player = this.physics.add.image(playerData.x, playerData.y, 'player').setDisplaySize(200, 200);
                this.add.existing(this.player);
            } else {
                
                const otherPlayer = this.physics.add.image(playerData.x, playerData.y, 'player').setDisplaySize(200, 200);
                this.add.existing(otherPlayer);
                this.currentPlayers[playerData.playerId] = { sprite: otherPlayer };
            }
        });

        socket.on('playerMoved', (playerData) => {
            if (this.currentPlayers[playerData.playerId]) {
                const otherPlayer = this.currentPlayers[playerData.playerId].sprite;
                if (otherPlayer) {
                    otherPlayer.x = playerData.x;
                    otherPlayer.y = playerData.y;
                    otherPlayer.setPosition(playerData.x, playerData.y);
                }
            }
        });

        socket.on('newPlayer', (playerData) => {
        
        });

    }

    update() {
        if (this.player) {
            let moved = false;

            if (this.cursors.left.isDown) {
                this.player.setVelocityX(-160);
                moved = true;
            } else if (this.cursors.right.isDown) {
                this.player.setVelocityX(160);
                moved = true;
            } else {
                this.player.setVelocityX(0);
            }

            if (this.cursors.up.isDown) {
                this.player.setVelocityY(-160);
                moved = true;
            } else if (this.cursors.down.isDown) {
                this.player.setVelocityY(160);
                moved = true;
            } else {
                this.player.setVelocityY(0);
            }

            if (moved) {
                socket.emit('playerMovement', { x: this.player.x, y: this.player.y });
            }
        }

    }
}

Upvotes: 1

Views: 74

Answers (1)

winner_joiner
winner_joiner

Reputation: 14695

Since you didn't post the all the relevant code, I'm not 100% sure what the problem could be. That said, it seems, that only new players are created, not the already created. Are you emiting the created players from the server with the event currentPlayers?

The easy solution, would be just to pass all current other users in the playerCreated event. Something like this, on player creation, all players are generate:

...
// on the serverside
io.emit('playerCreated', { playerData, otherPlayerData });
...   

It's best to use as few as possible emiting/broadcasting events. That makes the debugging also easier.

A better solution would be would to use a headless Phaser running on the server, this could prevent many problems and you would just have to move non-physics gameObjects on the client-side (checkout this article). This two part article is a bit old, but it showcases the headless mode and how to use it.

Upvotes: 0

Related Questions