英文:
Chebyshev distance x coordinate bugs when moving
问题
这是您提供的代码的翻译部分:
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.updateMap();
}
updateMap() {
console.log(this.gameState);
var origin = this.gameState.map.getTileAtWorldXY(
this.player.x,
this.player.y
);
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);
}
}
请注意,翻译中保留了代码的格式和结构。如果您需要关于代码的任何具体帮助或解释,请随时提出您的问题。
英文:
So I was replicating the Phaser Chebyshev Distance example, And After a solution here
I encounter the error Cannot read properties of null (reading 'x')
for origin.x
,
And the strange part is, this happens after I travel a few tiles from x=0
code
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.updateMap();
}
updateMap() {
console.log(this.gameState);
var origin = this.gameState.map.getTileAtWorldXY(
this.player.x,
this.player.y
);
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);
}
}
答案1
得分: 1
自从您使用物理速度移动玩家,玩家可能在地图外或者没有瓷砖的位置。
当调用map.getTileAtWorldXY
时,如果传入的位置在地图外(或者是其他无效位置),或者在该层中没有放置瓷砖,该函数将返回null
,这可能是您收到特定错误的原因。(文档链接)
解决方案之一是在origin
等于null
时退出函数,如下所示:
updateMap() {
var origin = this.gameState.map.getTileAtWorldXY(
this.player.x,
this.player.y
);
if (!origin) {
return;
}
// ...
}
或者您可以使用一个变量,例如this.gameState.lastValidPosition
,当玩家拥有有效位置时设置该变量,并在出现错误时使用该变量:
updateMap() {
var origin = this.gameState.map.getTileAtWorldXY(
this.player.x,
this.player.y
);
if (!origin && !this.gameState.lastValidPosition) {
// origin 无效且我们没有有效的上一个位置
return;
} else if (!origin) { // origin 为 null,使用上一个有效位置
origin = this.gameState.lastValidPosition;
} else { // origin 不为 null,保存这个位置
this.gameState.lastValidPosition = origin;
}
// ...
}
这两种解决方案会产生相同的结果(对于大多数用例),即保持光源在最后已知/有效位置。
更新:
更简单的解决方案是使用map.getTileAtWorldXY
函数的第三个参数nonnull
(如果问题是缺少瓷砖),这将返回索引为-1
的瓷砖,而不是null
,如下所示:
var origin = this.gameState.map.getTileAtWorldXY(
this.player.x,
this.player.y,
true
);
英文:
Since you are moving the player with physics velocity, the player could be outside of the map, or on a position without a tile.
When map.getTileAtWorldXY
is called with a position outside of the map (or some other invalid position), or there is no tile placed in that position on the layer, this function will return null
, that's probably why you get this specific error.
(link to the documentation)
The easy solution would be just to exit the function, when the origin
equals null
. Like this:
<!-- languages-all lang-js -->
updateMap() {
var origin = this.gameState.map.getTileAtWorldXY(
this.player.x,
this.player.y
);
if(!origin){
return;
}
...
}
Or you could have a variable like: this.gameState.lastValidPosition
, that you set when the player has a valid position, and use this variable, in case of an error
updateMap() {
var origin = this.gameState.map.getTileAtWorldXY(
this.player.x,
this.player.y
);
if(!origin && !this.gameState.lastValidPosition ){
// origin is invalid and we have no valid last position
return;
} else if( !origin ) { // origin is null, w use the last valid position
origin = this.gameState.lastValidPosition;
} else { // origin is not null, so we save this position
this.gameState.lastValidPosition = origin;
}
...
}
> Both solution will produce the exact same result (for most of the usecases). Which os keeping the light source at the last known/valid position.
Update:
a more easy solution could be to use the third parameter nonnull
, of the function map.getTileAtWorldXY
(if the issue is a missing tile), this would return a tile with index -1
instead of null
.
like:
var origin = this.gameState.map.getTileAtWorldXY(
this.player.x,
this.player.y,
true
);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论