如何通过Socket.io从MySQL数据库为Phaser玩家分配坐标并显示?
问题分析与解决方案
你的代码存在几个关键问题导致玩家无法显示,以下是具体问题和修复方案:
客户端代码问题
- 错误的Socket事件监听逻辑:客户端不需要监听
connection事件(这是服务端用来监听新连接的钩子),客户端连接成功后直接监听服务端发送的userData事件即可。 - 未使用服务端传来的坐标数据:创建玩家时用了未定义的
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(); } }
服务端代码问题
- 错误的Socket事件绑定位置:将
io.on('connection')放在/profile路由内会导致每次请求该路由都重复绑定连接事件,且无法在socket连接时正确触发。应该将socket连接监听放在路由之外,只绑定一次。 - 未在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
相关产品推荐
相关产品推荐

