Chebyshev distance x坐标在移动时出现错误

huangapple go评论58阅读模式
英文:

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 &amp;&amp; !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
);

huangapple
  • 本文由 发表于 2023年2月18日 00:29:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/75486890.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定