Phaser实现Chebyshev Distance时移动后出现origin.x空指针错误
问题解决:Phaser中
Cannot read properties of null (reading 'x')错误 问题描述
复现Phaser的切比雪夫距离示例时,解决了gameState变量识别问题后,触发Cannot read properties of null (reading 'x')错误,该错误在玩家从x=0位置移动几个tile后出现。
错误原因
错误出现在updateMap方法中:this.gameState.map.getTileAtWorldXY(this.player.x, this.player.y)返回了null,此时访问origin.x自然会报错。导致返回null的核心原因有两个:
- 玩家移动到了tilemap范围之外,当前位置没有对应的tile
- 代码中
down方向的速度设置错误(写成了-50),导致玩家移动逻辑异常,更容易意外移出地图边界
修复方案
1. 增加空值判断,避免访问空对象属性
修改updateMap方法,先检查origin是否有效,再执行后续切比雪夫距离计算:
updateMap() { var origin = this.gameState.map.getTileAtWorldXY(this.player.x, this.player.y); // 先判断origin是否存在,不存在则直接返回 if (!origin) return; this.gameState.map.forEachTile(function (tile) { var dist = Phaser.Math.Distance.Chebyshev( origin.x, origin.y, tile.x, tile.y ); tile.setAlpha(1 - 0.1 * dist); }, this); }
2. 修正方向速度错误
在update方法中,down方向的velocityY应设置为正数值,否则会和up方向一样向上移动:
else if (this.gameState.cursors.down.isDown) { this.player.setVelocityY(50); // 将-50改为50 }
3. 限制玩家在tilemap范围内移动(可选)
如果不想让玩家移出地图,可以在update方法中添加边界限制,避免玩家跑到没有tile的区域:
// 在update方法末尾、调用updateMap之前添加 const mapWidth = this.gameState.map.widthInPixels; const mapHeight = this.gameState.map.heightInPixels; // 考虑玩家精灵的锚点和尺寸,避免半移出地图 this.player.x = Phaser.Math.Clamp(this.player.x, this.player.width/2, mapWidth - this.player.width/2); this.player.y = Phaser.Math.Clamp(this.player.y, this.player.height/2, mapHeight - this.player.height/2);
完整修正后的代码
import Phaser from "../lib/phaser.js"; export default class Game extends Phaser.Scene { constructor() { super("game1"); } preload() { this.load.image( "Tileset", "https://cdn.glitch.global/cc90578e-c3d0-47c5-bb0d-f5a81263b5b6/pixil-frame-0%20(17).png?v=1675985219390" ); this.load.tilemapTiledJSON( "map", "https://cdn.glitch.global/cc90578e-c3d0-47c5-bb0d-f5a81263b5b6/Map.tmj?v=1675985261369" ); this.load.spritesheet( "player", "https://cdn.glitch.global/cc90578e-c3d0-47c5-bb0d-f5a81263b5b6/pixil-frame-0%20(13).png?v=1675904194091", { frameWidth: 32, frameHeight: 32 } ); } create() { this.gameState = { map: "", cursors: "", }; this.gameState.map = this.make.tilemap({ key: "map" }); this.tiles = this.gameState.map.addTilesetImage("tileSet", "Tileset"); this.worldLayer = this.gameState.map.createLayer( "Block Layer", this.tiles, 0, 0 ); this.player = this.physics.add.sprite(0, 1600, "player", 1); this.cameras.main.setBounds( 0, 0, this.gameState.map.widthInPixels, this.gameState.map.heightInPixels ); this.cameras.main.startFollow(this.player); this.gameState.cursors = this.input.keyboard.createCursorKeys(); this.physics.add.collider(this.player, this.worldLayer); } update() { if (this.gameState.cursors.left.isDown) { this.player.setVelocityX(-50); } else if (this.gameState.cursors.right.isDown) { this.player.setVelocityX(50); } else if (this.gameState.cursors.up.isDown) { this.player.setVelocityY(-50); } else if (this.gameState.cursors.down.isDown) { this.player.setVelocityY(50); // 修正方向速度 } else { this.player.setVelocityX(0); this.player.setVelocityY(0); // 补充停止Y方向速度 } // 限制玩家在地图范围内移动 const mapWidth = this.gameState.map.widthInPixels; const mapHeight = this.gameState.map.heightInPixels; this.player.x = Phaser.Math.Clamp(this.player.x, this.player.width/2, mapWidth - this.player.width/2); this.player.y = Phaser.Math.Clamp(this.player.y, this.player.height/2, mapHeight - this.player.height/2); this.updateMap(); } updateMap() { var origin = this.gameState.map.getTileAtWorldXY( this.player.x, this.player.y ); // 检查origin有效性 if (!origin) return; this.gameState.map.forEachTile(function (tile) { var dist = Phaser.Math.Distance.Chebyshev( origin.x, origin.y, tile.x, tile.y ); tile.setAlpha(1 - 0.1 * dist); }, this); } }
内容的提问来源于stack exchange,提问作者Vatsa Pandey
相关产品推荐
相关产品推荐

