You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Socket.io从MySQL数据库为Phaser玩家分配坐标并显示?

问题分析与解决方案

你的代码存在几个关键问题导致玩家无法显示,以下是具体问题和修复方案:

客户端代码问题

  1. 错误的Socket事件监听逻辑:客户端不需要监听connection事件(这是服务端用来监听新连接的钩子),客户端连接成功后直接监听服务端发送的userData事件即可。
  2. 未使用服务端传来的坐标数据:创建玩家时用了未定义的x_position和y_position,需要从服务端发送的user对象中提取对应坐标字段(假设数据库中字段为x和y,请根据实际字段名调整)。

修改后的客户端代码:

const socket = io();
  
class BaseScene extends Phaser.Scene {
    constructor(key) {
        super({ key });
    }

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

    create() {
        this.cursors = this.input.keyboard.createCursorKeys();
        // 直接监听服务端推送的userData事件
        socket.on('userData', (user) => {
            // 替换为你数据库中实际的坐标字段名,比如user.x_position、user.y_position
            this.player = this.physics.add.image(user.x, user.y, 'player').setDisplaySize(200, 200);
        });    
    }

    update() {
        if (this.player) {
            if (this.cursors.left.isDown) {
                this.player.setVelocityX(-160);
            } else if (this.cursors.right.isDown) {
                this.player.setVelocityX(160);
            } else {
                this.player.setVelocityX(0);
            }
            if (this.cursors.up.isDown) {
                this.player.setVelocityY(-160);
            } else if (this.cursors.down.isDown) {
                this.player.setVelocityY(160);
            } else {
                this.player.setVelocityY(0);
            }
        }
    }
}

class FirstScene extends BaseScene {
    constructor() {
        super('first');
    }

    preload() {
      super.preload();
    }
    create() {
    super.create();
    }

    update() {
        super.update();
    }
}

服务端代码问题

  1. 错误的Socket事件绑定位置:将io.on('connection')放在/profile路由内会导致每次请求该路由都重复绑定连接事件,且无法在socket连接时正确触发。应该将socket连接监听放在路由之外,只绑定一次。
  2. 未在socket连接时动态获取用户数据:原代码在渲染页面时绑定socket事件,此时socket连接可能还未建立,无法正确发送数据。

修改后的服务端代码:

// 将socket连接监听放在路由外部,全局只绑定一次
io.on('connection', async (socket) => {
    // 从socket会话中获取用户ID(需确保你的会话中间件如express-session已正确配置)
    const userId = socket.request.session?.user?.id;
    if (!userId) {
        console.log('用户未登录,无法获取坐标');
        return;
    }
    try {
        const [rows] = await pool.query('SELECT * FROM users WHERE id = ?', [userId]);
        const user = rows[0];
        socket.emit('userData', user);
    } catch (error) {
        console.error('获取用户坐标失败:', error);
    }
});

app.get('/profile', async (req, res) => {
    try {
        const userId = req.session.user.id;
        const [rows] = await pool.query('SELECT * FROM users WHERE id = ?', [userId]);
        const user = rows[0];
        res.locals.user = user;
        res.render('profile');
    } catch (error) {
        console.error(error);
        res.status(500).send('An error occurred while receiving user data.');
    }
});

额外注意事项

  • 确保会话中间件(如express-session)已正确配置,且socket.io能访问到会话数据(可能需要使用express-socket.io-session等中间件桥接)。
  • 确认数据库用户表中存在坐标字段,且字段名与代码中使用的一致。
  • 可在客户端userData事件回调中添加console.log(user),验证是否收到了正确的坐标数据。

内容的提问来源于stack exchange,提问作者Iya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 08:42:18