在 Phaser 3 TypeError 中调用 this.scene.restart(): this.body is undefined

Posted

技术标签:

【中文标题】在 Phaser 3 TypeError 中调用 this.scene.restart(): this.body is undefined【英文标题】:Calling this.scene.restart() in Phaser 3 TypeError: this.body is undefined 【发布时间】:2019-09-07 17:30:20 【问题描述】:

我正在尝试在 Phaser 3 中重新启动游戏场景,当调用 this.scene.restart 时,我在 phaser.js 脚本的 setVelocityX 处收到错误消息“this.body is undefined”(未缩小的第 169442 行)脚本,如果有帮助)

我正在使用最新版本的 Phaser,v3.19.0。 当玩家精灵与敌人碰撞时调用 hitEnemy 函数,这会暂停物理并将 gameOver 设置为 true。在 update() 函数中,我正在检查 gameOver 是否为真,以及是否按下了“R”键,在这种情况下会调用 scene.restart() 以下是我的部分代码:

var config = 
    scene: 'scene1',
    type: Phaser.AUTO,
    scene: 'scene1',
    width: 1080,
    height: 890,
    pixelArt: true,
    physics: 
        default: 'arcade',
        arcade: 
            gravity: 
                y: 500
            ,
            debug: true
        
    ,
    scene: 
        preload: preload,
        create: create,
        update: updateDirect
    
    ;
   function preload() 
        var progressBar = this.add.graphics();
        var progressBox = this.add.graphics();
        progressBox.fillStyle(0x222222, 0.8);
        progressBox.fillRect(380, 270, 320, 50);

        var width = this.cameras.main.width;
        var height = this.cameras.main.height;
        var loadingText = this.make.text(
            x: width / 2,
            y: height / 2 - 50,
            text: 'Loading...',
            style: 
                font: '20px monospace',
                fill: '#ffffff'
            
        );
        loadingText.setOrigin(0.5, 0.5);

        var percentText = this.make.text(
        x: width / 2,
        y: height / 2 - 5,
        text: '0%',
        style: 
            font: '18px monospace',
            fill: '#ffffff'
            
        );
        percentText.setOrigin(0.5, 0.5);

        var assetText = this.make.text(
            x: width / 2,
            y: height / 2 + 50,
            text: '',
            style: 
                font: '18px monospace',
                fill: '#ffffff'
            
        );
        assetText.setOrigin(0.5, 0.5);

        this.load.image('bgtile', 'bgtile.jpg');
        this.load.image('background', 'assets/lava/background2.png');
        this.load.image('platformdefault', 'assets/lava/lavaplatform.png');
        this.load.image('platform400', 'assets/lava/platform4002.png');
        this.load.image('platform500', 'assets/lava/platform500.png');
        this.load.image('platform300', 'assets/lava/platform300.png');
        this.load.image('platform200', 'assets/lava/platform200.png');
        this.load.image('platform100', 'assets/lava/platform100.png');

        this.load.image('stopper', 'assets/lava/stopper.png');
        this.load.image('sign', 'assets/lava/sign2.png');

        this.load.image('enemy', 'assets/lava/enemy2.png');
        this.load.spritesheet('dude', 'assets/sprites/dude.png', 
            frameWidth: 32,
            frameHeight: 48
        );

        this.load.spritesheet('lavafloor', 'assets/lava/lavasprite.png', 
            frameWidth: 320,
            frameHeight: 100
        );
        //scary flash ooo
        flash = this.load.image('flash', 'assets/images/blue-flash.png');
        this.load.image('floor', 'assets/lava/floor.png');

        //audio
        this.load.audio('fantastic', 'assets/audio/fantastic.mp3');
        this.load.audio('wait', 'assets/audio/wait.mp3');
        this.load.audio('ward', 'assets/audio/ward.mp3');
        this.load.audio('whisper1', 'assets/audio/whisper1.mp3');
        this.load.audio('whisper2', 'assets/audio/whisper2.mp3');
        this.load.audio('whisper3', 'assets/audio/whisper3.mp3');
        this.load.audio('whisper4', 'assets/audio/whisper4.mp3');
        this.load.audio('hey', 'assets/audio/hey.mp3');

    //  this.load.video('spider', 'assets/video/spider.mp4');
    //  this.load.video('skull', 'assets/video/skull.mp4');

        this.load.on('progress', function (value) 
            progressBar.clear();
            progressBar.fillStyle(0xffffff, 1);
            progressBar.fillRect(390, 280, 300 * value, 30);
            percentText.setText(parseInt(value * 100) + '%');
        );

        this.load.on('fileprogress', function (file) 
        //  console.log(file.src);
            assetText.setText('Loading asset: ' + file.key);
        );

        this.load.on('complete', function () 
            progressBar.destroy();
            progressBox.destroy();          
            loadingText.destroy();
            percentText.destroy();
            assetText.destroy();
        );
    


    function create() 
        bgtile = this.add.image(400, 300, 'background');
        this.cameras.main.setBounds(0, 0, 10392, 100);
        this.physics.world.setBounds(0, 0, 10392, 710);

        cameraHeight = this.cameras.height;
        cameraWidth = this.cameras.width;
        platforms = this.physics.add.staticGroup();
        stoppers = this.physics.add.staticGroup();

        var floor = platforms.create(400, 775, 'floor');

        sign = this.add.image(400, 560, 'sign').setScale(0.06);

        platform1 = createPlatform400(400, 600);
        platform2 = createPlatform100(1100, 200);
        platform3 = createPlatform300(700,500);
        platform4 = createPlatform200(900, 350);
        platform5 = createPlatform200(1325, 317);
        platform6 = createPlatform100(1605, 358);

        fantastic = this.sound.add('fantastic',  loop: false, volume: 0.2 );
        wait = this.sound.add('wait',  loop: true, volume: 0.3 );
        ward = this.sound.add('ward',  loop: true, volume: 0.2 );
        whisper1 = this.sound.add('whisper1',  loop: false, volume: 0.1 );
        whisper2 = this.sound.add('whisper2',  loop: false, volume: 0.2 );
        whisper3 = this.sound.add('whisper3',  loop: false, volume: 0.2 );
        whisper4 = this.sound.add('whisper4',  loop: false, volume: 0.2 );
        hey = this.sound.add('hey', loop: true, volume: 0.2)

        whisper2.play();
        whisper2.on('complete', function()
            fantastic.play();
        );
        fantastic.on('complete', function()
            hey.play();
        );

        var frameNames = this.anims.generateFrameNames('lavafloor', 
                     start: 1, end: 4
        );

        this.anims.create( key: 'lavaAnim', frames: frameNames, frameRate: 4, repeat: -1 );

        //player anims
        this.anims.create(
            key: 'left',
            frames: this.anims.generateFrameNumbers('dude', 
                start: 0,
                end: 3
            ),
            //frames refer to spritesheet frames, between 0 and 3 it will be left facing
            frameRate: 10, //10 fps
            repeat: -1 //stop animation
        );
        this.anims.create(
            key: 'turn',
            frames: [
                key: 'dude',
                frame: 4
            ],
            frameRate: 20
        );
        this.anims.create(
            key: 'right',
            frames: this.anims.generateFrameNumbers('dude', 
                start: 5,
                end: 8
            ),
            frameRate: 10,
            repeat: -1
        );

        physics = this.physics; //get the reference to physics to create lava and enemies or platforms

        dude = this.physics.add.sprite(0, 100, 'dude').setScale(1.5);
        createLava(1274, 760);//add 320 to x for continuous lava
        createLava(2000, 760); 


        enemies = this.physics.add.group();
        spawnEnemy(platform3);
        wasd = this.input.keyboard.addKeys(
            up: Phaser.Input.Keyboard.KeyCodes.W,
            down: Phaser.Input.Keyboard.KeyCodes.S,
            left: Phaser.Input.Keyboard.KeyCodes.A,
            right: Phaser.Input.Keyboard.KeyCodes.D,
            space: Phaser.Input.Keyboard.KeyCodes.SPACE,
            restart: Phaser.Input.Keyboard.KeyCodes.R,
            pause: Phaser.Input.Keyboard.KeyCodes.P,
            action: Phaser.Input.Keyboard.KeyCodes.F
        );

        dude.body.setGravityY(800);
        dude.setCollideWorldBounds(true); //prevent running outside game window

        this.cameras.main.startFollow(dude, true, 0.08, 0.08);
        this.cameras.main.setZoom(1);
        this.physics.add.collider(dude, platforms);

        this.physics.add.collider(enemies, stoppers, hitStopper, null, this);
        this.physics.add.overlap(dude, sign, showText, null, this);

        this.physics.add.collider(enemies, platforms);
        this.physics.add.collider(dude, enemies, hitEnemy, null, this);

        onScreenText = this.add.text(16, 16, '', 
            fontSize: '32px',
            fill: '#fff'
        );
        playerPosText = this.add.text(dude.x+300, 16, '', 
            fontSize: '32px',
            fill: '#fff'
        );

        playerPosText.setScrollFactor(0);
    
    function hitEnemy(dude, enemies) 
        this.physics.pause();
        dude.setTint(0xff0000);
        dude.anims.play('turn');
        gameOver = true;

    

    function updateDirect() 
        playerPosText.setText('X: ' + parseInt(dude.x) + ' ' + 'Y: ' + parseInt(dude.y));
        if ((dude.x >= 380 && dude.x <= 430) && dude.y == 544) 
            showText("test");
         else 
            showText('');
        

        if(gameOver)
            showText("You died\nPress R to restart");
            if(wasd.restart.isDown)
                this.scene.restart();
                gameOver = false;
            
        
    

我在一个主要基于教程示例的项目中使用了它,它运行良好,我在这里使用相同的代码。总的来说,我对 Phaser 和游戏开发非常陌生,因此将不胜感激。 谢谢

【问题讨论】:

能否将create()preload() 方法添加到您提供的代码中? 在提供的代码中添加了创建和预加载功能。我已经尝试多次调用scene.restart(),现在我得到了一个不同的错误,“this.frame.source is null”。我通过彻底销毁游戏、移除画布并创建新游戏来解决这个问题,但这并不理想 【参考方案1】:

你可以这样做:

create()
    duce.isReady = false
    // Your code here...
    dude.isReady = true


update()
    if(dude.isReady)
        dude.body.setVelocityX(...)
        // Rest of your code concerning dude
    

【讨论】:

以上是关于在 Phaser 3 TypeError 中调用 this.scene.restart(): this.body is undefined的主要内容,如果未能解决你的问题,请参考以下文章

在 Phaser 3 中更改场景的问题

Phaser移相器

Phaser 3 街机物理世界环绕

Phaser 3 阵列碰撞

如何在 Phaser 3 中启用单击数组中的单个项目并将每个项目显示在屏幕的不同部分?

如何在 Phaser 3, Spine 中获取边界框的大小?