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

Phaser.js中this.gameState未识别,报Cannot read properties of undefined错误

问题描述

我在Glitch平台复刻Phaser实验室的瓦片切比雪夫距离实验,参考Stack Overflow方案用Phaser.gameState存储需多处更新的变量,但控制台报错:Cannot read properties of undefined (reading 'gameState')。调整this上下文后问题依旧,以下是初始代码和更新后代码:

初始代码

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, 0, "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();
  }

  update() {
    function 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);
    }

    if (this.gameState.cursors.left.isDown) {
      this.player.setVelocityX(-50);
      this.player.anims.play("left", true);
    } else if (this.gameState.cursors.right.isDown) {
      this.player.setVelocityX(50);
      this.player.anims.play("right", true);
    } 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);
    }

    updateMap();
  }
}

更新后代码(将updateMap函数外置)

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, 0, "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();
  }

  update() {
    if (this.gameState.cursors.left.isDown) {
      this.player.setVelocityX(-50);
      this.player.anims.play("left", true);
    } else if (this.gameState.cursors.right.isDown) {
      this.player.setVelocityX(50);
      this.player.anims.play("right", true);
    } 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);
    }

    updateMap();
  }
}

function 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);
}
问题解决

报错核心原因是updateMap函数的this上下文未指向当前Scene实例,导致无法访问this.gameState,以下是三种修复方案:

方案1:将updateMap定义为类方法

把updateMap改成Scene类的成员方法,调用时this会自动绑定到Scene实例:

import Phaser from "../lib/phaser.js";

export default class Game extends Phaser.Scene {
  constructor() {
    super("game1");
  }

  preload() {
    // 原有代码不变
  }

  create() {
    // 原有代码不变
  }

  // 定义为类方法
  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);
  }

  update() {
    // 原有输入控制代码不变
    // 调用类方法
    this.updateMap();
  }
}

方案2:调用时绑定this

若保留独立函数,调用时用bind或箭头函数绑定上下文:
在update方法里修改调用逻辑:

// 用bind绑定当前Scene的this
updateMap.bind(this)();

// 或用箭头函数包裹
(() => updateMap.call(this))();

方案3:用箭头函数定义updateMap

箭头函数会继承外部作用域的this,若在update内部定义函数,改成箭头函数即可:

update() {
  const updateMap = () => {
    console.log(this.gameState);
    // 原有updateMap代码不变
  };

  // 原有输入控制代码不变

  updateMap();
}

额外注意:代码中向下移动的setVelocityY写为-50,会导致上下移动方向反转,建议改为50。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 03:09:27