【问题标题】:Javascript : Phaser call a method inside another method classJavascript:Phaser 在另一个方法类中调用一个方法
【发布时间】:2019-05-22 18:52:09
【问题描述】:

我在使用 Phaser 开发 javascript 时遇到了一个问题。我尝试在类的方法中调用方法,但出现错误。

这是我的课:

import Enemy from '../classes/Enemy';
import Turret from '../classes/Turret';
import Bullet from '../classes/Bullet';


class GameScene extends Phaser.Scene {

    constructor() {
        super({
            key: 'GameScene'
        });
    }

    preload()
    {
        this.load.image('turret', './www/assets/tour_simple.png');
    }

    drawGrid(graphics)
    {
        graphics.lineStyle(1, 0x0000ff, 0.8);
        for(var i = 0; i < 8; i++)
        {
            graphics.moveTo(0, i * 64);
            graphics.lineTo(640, i * 64);
        }
        for(var j = 0; j < 10; j++)
        {
            graphics.moveTo(j * 64, 0);
            graphics.lineTo(j * 64, 512);
        }
        graphics.strokePath();
    }

    canPlaceTurret(i, j)
    {
        return this.map[i][j] === 0;
    }

    placeTurret(pointer)
    {
        var i = Math.floor(pointer.y/64);
        var j = Math.floor(pointer.x/64);
        if(this.canPlaceTurret(i, j)) {
            var turret = this.turrets.get();
            if (turret)
            {
                turret.setActive(true);
                turret.setVisible(true);
                turret.place(i, j);
            }
        }
    }

    damageEnemy(enemy, bullet)
    {
        // only if both enemy and bullet are alive
        if (enemy.active === true && bullet.active === true) {
            // we remove the bullet right away
            bullet.setActive(false);
            bullet.setVisible(false);

            //todo mettre dans une classe constante
            var BULLET_DAMAGE = 25;
            // decrease the enemy hp with BULLET_DAMAGE
            enemy.receiveDamage(BULLET_DAMAGE);
        }
    }



    create() {
        this.add.text(200, 230, 'good!', { fill: '#0f0' });

        var graphics = this.add.graphics();

        this.map = [[ 0,-1, 0, 0, 0, 0, 0, 0, 0, 0],
            [ 0,-1, 0, 0, 0, 0, 0, 0, 0, 0],
            [ 0,-1,-1,-1,-1,-1,-1,-1, 0, 0],
            [ 0, 0, 0, 0, 0, 0, 0,-1, 0, 0],
            [ 0, 0, 0, 0, 0, 0, 0,-1, 0, 0],
            [ 0, 0, 0, 0, 0, 0, 0,-1, 0, 0],
            [ 0, 0, 0, 0, 0, 0, 0,-1, 0, 0],
            [ 0, 0, 0, 0, 0, 0, 0,-1, 0, 0]];

        //TODO creer une classe qui dessine le path
        // the path for our enemies
        // parameters are the start x and y of our path
        this.path = this.add.path(96, -32);
        this.path.lineTo(96, 164);
        this.path.lineTo(480, 164);
        this.path.lineTo(480, 544);

        graphics.lineStyle(3, 0xffffff, 1);
        // visualize the path
        this.path.draw(graphics);

        this.enemies = this.physics.add.group({ classType: Enemy, runChildUpdate: true });

        this.nextEnemy = 0;

        var graphics = this.add.graphics();
        this.drawGrid(graphics);

        this.turrets = this.add.group({ classType: Turret, runChildUpdate: true });
        this.input.on('pointerdown', this.placeTurret);

        this.bullets = this.physics.add.group({ classType: Bullet, runChildUpdate: true });

        this.physics.add.overlap(this.enemies, this.bullets, this.damageEnemy);
    }

    update(time, delta) {
        if (time > this.nextEnemy)
        {
            var enemy = this.enemies.get();
            console.log(enemy);
            if (enemy)
            {
                enemy.setActive(true);
                enemy.setVisible(true);
                // place the enemy at the start of the path
                enemy.startOnPath();

                this.nextEnemy = time + 2000;
            }
        }
    }


}

export default GameScene;

我的游戏过程中出现错误:

TypeError: this.canPlaceTurret 不是函数

错误来自我调用canPlaceTurret 方法的placeTurret 方法。

我尝试了一些方法,例如向我的类添加属性:self = this; 并使用self.canPlaceTurret 调用我的函数,但问题总是存在。我认为这是一个范围问题,但我不知道如何解决。

另一个重要信息:我们正在使用 Webpack

感谢阅读:)。

【问题讨论】:

    标签: javascript class methods phaser-framework


    【解决方案1】:

    尝试替换:

    this.input.on('pointerdown', this.placeTurret);
    

    与:

    this.input.on('pointerdown', pointer => this.placeTurret(pointer));
    

    (根据您的评论稍作修改)

    基本上,当您将方法作为回调传递时,它就变成了一个简单的函数引用。稍后调用该函数时,this 不会引用您期望的类实例,因为它不再在您的类的上下文中调用。

    通过使用粗箭头语法,您可以创建一个特定的回调,并明确告诉它在当前的上下文中调用该方法(如在定义所述回调时)this

    或者,您也可以这样做:

    this.input.on('pointerdown', this.placeTurret.bind(this));
    

    这不是创建一个新的匿名函数,而是将您的方法作为参考(就像它开始所做的那样),但手动将当前的 this 绑定到它。

    更详细的解释请参考this post

    【讨论】:

    • 是的,就是这样!非常感谢。只是我已经替换为:this.input.on('pointerdown', (pointer) =&gt; this.placeTurret(pointer)); 因为我需要函数的指针对象:)
    • 就像答案提到的那样,这绑定了一个新的函数引用,它需要更多的内存来做一些不必要的事情。您需要绑定函数的范围,以便“this”不是事件:this.input.on('pointerdown', this.placeTurret.bind(this)); 我相信会是性能更高的解决方案。如果我错了,请告诉我!
    【解决方案2】:

    在调用 canPlaceTurret() 时,在你的 placeTurret() 方法中完全不使用 this 关键字会不会工作?

     placeTurret(pointer)
            {
                var i = Math.floor(pointer.y/64);
                var j = Math.floor(pointer.x/64);
                if(canPlaceTurret(i, j)) {
                    var turret = this.turrets.get();
                    if (turret)
                    {
                        turret.setActive(true);
                        turret.setVisible(true);
                        turret.place(i, j);
                    }
                }
            }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多