我有一个钉子精灵,在它的循环中有4帧.当球员与扣球精灵的第三帧重叠时,我想从健康变量中减go 1.

目前,无法正确加载.ON函数.我的游戏可以用,但重叠功能根本不能用.我编辑了我收到的代码,并删除了我认为不需要的方面(测试原始代码样本以判断它是否可以工作,我的更改仍然有效.也不能处理我收到的完整代码)

我的工作代码如下,

let CheckSpikeOverlap=this.physics.add.overlap(this.cPlayer, this.spikes, (player, spikeSprite)=> {
       if (spikeSprite.anims.currentFrame.index==4){
          PlayerHealth=PlayerHealth-EnemyDamage;
          CheckSpikeOverlap.active=false;
          this.time.addEvent({
                    delay: 1000,
                    callback: () => {
              CheckSpikeOverlap.active=true;
                    },
                });
       }
     });

我的完整代码(https://replit.com/@JackF99/test-2d-array#script%20(copy).js),

//CREATE GAME SCENE || CREATE GAME SCENE || CREATE GAME SCENE
class GameScene extends Phaser.Scene {
    constructor(config) {
        super(config);
    }
    preload() {
        //PRELOADING ASSETS || PRELOADING ASSETS || PRELOADING ASSETS
        //SPRITES
        this.load.spritesheet("player", "assets/sprites/player.png", {
            frameWidth: 16,
            frameHeight: 30
        });
        this.load.spritesheet("sword", "assets/sprites/sword.png", {
            frameWidth: 10,
            frameHeight: 22
        });
        this.load.spritesheet("spikes", "assets/sprites/spikes.png", {
            frameWidth: tileWidth,
            frameHeight: tileHeight
        });
        //TILES
        this.load.image("floor", "assets/tiles/floor.png");
        this.load.image("floor_1", "assets/tiles/floor_1.png");
        this.load.image("floor_2", "assets/tiles/floor_2.png");
        this.load.image("floor_3", "assets/tiles/floor_3.png");
        this.load.image("floor_4", "assets/tiles/floor_4.png");
        this.load.image("floor_5", "assets/tiles/floor_5.png");
        this.load.image("floor_6", "assets/tiles/floor_6.png");
        this.load.image("floor_7", "assets/tiles/floor_7.png");
        this.load.image("wallLeft", "assets/tiles/wallLeft.png");
        this.load.image("wallRight", "assets/tiles/wallRight.png");
        this.load.image("wallBottom", "assets/tiles/wallBottom.png");
        this.load.image("wallTop", "assets/tiles/wallTop.png");
        this.load.image("bg", "assets/tiles/bg.png");
        //DECLARE KEYS USED
        this.keys = this.input.keyboard.addKeys('SPACE,W,A,S,D,Q');
        this.cursors = this.input.keyboard.createCursorKeys();
    }
    create() {
    
        this.cameras.main.zoom = 5;
        //CREATE ANIMATIONS || CREATE ANIMATIONS || CREATE ANIMATIONS
        //PLAYER ANIMATIONS
        this.anims.create({
            key: 'stand',
            frames: this.anims.generateFrameNumbers('player', {
                frames: [0, 1, 2, 3]
            }),
            frameRate: 1,
            repeat: -1
        });
        this.anims.create({
            key: 'walk',
            frames: this.anims.generateFrameNumbers('player', {
                frames: [4, 5, 6, 7]
            }),
            frameRate: 10,
            repeat: -1
        });
        //WEAPON ANIMATIONS
        this.anims.create({
            key: 'sword',
            frames: this.anims.generateFrameNumbers('sword', {
                frames: [6]
            }),
        });
        this.anims.create({
            key: 'attack',
            frames: this.anims.generateFrameNumbers('sword', {
                frames: [0, 1, 2, 3, 4, 5]
            }),
            frameRate: 5
        });
        //GAME OBJECT ANIMATIONS
        this.anims.create({
            key: 'spikes',
            frames: this.anims.generateFrameNumbers('spikes', {
                frames: [0, 1, 2, 3]
            }),
            frameRate: 2,
            repeat: -1
        });
        //DECLARE GROUPS || DECLARE GROUPS || DECLARE GROUPS
        this.spikes = this.physics.add.staticGroup();
        //GENERATE MAP || GENERATE MAP || GENERATE MAP
        var level = getMap();
        let map = this.make.tilemap({
            data: level,
            tileWidth: tileWidth,
            tileHeight: tileHeight
        });
        map.addTilesetImage(0, 'bg', tileWidth, tileHeight, 0, 0, 0);
        map.addTilesetImage(1, 'floor', tileWidth, tileHeight, 0, 0, 1);
        map.addTilesetImage(2, 'wallLeft', tileWidth, tileHeight, 0, 0, 2);
        map.addTilesetImage(3, 'wallRight', tileWidth, tileHeight, 0, 0, 3);
        map.addTilesetImage(4, 'wallBottom', tileWidth, tileHeight, 0, 0, 4);
        map.addTilesetImage(5, 'wallTop', tileWidth, tileHeight, 0, 0, 5);
        map.addTilesetImage(6, 'floor_1', tileWidth, tileHeight, 0, 0, 6);
        map.addTilesetImage(7, 'floor_2', tileWidth, tileHeight, 0, 0, 7);
        map.addTilesetImage(8, 'floor_3', tileWidth, tileHeight, 0, 0, 8);
        map.addTilesetImage(9, 'floor_4', tileWidth, tileHeight, 0, 0, 9);
        map.addTilesetImage(10, 'floor_5', tileWidth, tileHeight, 0, 0, 10);
        map.addTilesetImage(11, 'floor_6', tileWidth, tileHeight, 0, 0, 11);
        map.addTilesetImage(12, 'floor_7', tileWidth, tileHeight, 0, 0, 12);
        map.addTilesetImage(13, 'spikes', tileWidth, tileHeight, 0, 0, 13);
        map.addTilesetImage(14, 'floor', tileWidth, tileHeight, 0, 0, 14);

        let mapLayer = map.createLayer(0, map.tilesets, 0, 0);
        map.forEachTile(tile => {
            //Generate sprites on specific map tiles
            if (tile.index == 13) {
                this.spikes.create(tile.pixelX + 8, tile.pixelY + 8, "spikes")
          .play('spikes')
                    .setDepth(10);
            }
        });
        map.setCollisionBetween(2, 5, true);
        //CREATE PLAYER || CREATE PLAYER || CREATE PLAYER
        this.cPlayer = this.add.container(176, 816);
        this.player = this.add.sprite(0, 0, "player");
        this.sword = this.add.sprite(10, 3, "sword");
        this.cPlayer.setSize(16, 20);
        this.physics.add.existing(this.cPlayer);
        this.cPlayer.add([this.player, this.sword]);
        this.physics.add.collider(this.cPlayer, mapLayer);
        this.cameras.main.startFollow(this.cPlayer);
    this.weapon = this.add.container(0, 0);
    this.weapon.setSize(12, 20);
        //FINAL CHANGES || FINAL CHANGES || FINAL CHANGES
        this.sword.play("sword", true);
        this.cPlayer.setDepth(100);
        this.physics.add.existing(this.cPlayer);
    this.physics.add.existing(this.weapon);
    //Damage function
    this.spikes.on(Phaser.Animations.Events.ANIMATION_UPDATE, (anim, frame) => {
      if(frame.index == 3){
        this.physics.add.overlap( this.spikes, this.cPlayer, () => {
          health--;
        });
      } 
    });
    }

推荐答案

Well there many ways to do this, my first idea is use the animation update event, and dealing damage on one (or more) specific frame indices.
In the event callback you only need to check if the player overlaps with the sprite and if the right frame is showing.

Assuming the spikes are going up and down only one frame would deal damage.

Here a short demo showcasing this (Updated to better solution):
In this updated Demo the Damage will occur only on frameindex == 3 and only damage every second. (this is done with the setTimeout function). But if you don't need to limit on with frame damage should happen, you can remove this part spikeSprite.anims.currentFrame.index == 3, from the if-clause.

document.body.style = 'margin:0;padding:5px';

class GameScene extends Phaser.Scene {
    constructor () {
        super();
    }
    preload () {
        /** CREATE SPRITE FRAME FOR ONLY DEMO --- START */
        const canvasFrame = this.textures
            .createCanvas('spikes', 60, 10);

        let ctx = canvasFrame.context;

        ctx.fillStyle = '#00FF33';
        ctx.fillRect(0, 0, 10, 10);
        
        ctx.fillStyle = '#FAFF00';
        ctx.fillRect(10, 0, 10, 10);
        
        ctx.fillStyle = '#FF0000';
        ctx.fillRect(20, 0, 10, 10);
        
        canvasFrame.add(1, 0, 0, 0, 10, 10);
        canvasFrame.add(2, 0, 10, 0, 10, 10);
        canvasFrame.add(3, 0, 20, 0, 10, 10);
        
        canvasFrame.refresh();
        
        /** CREATE SPRITE FRAME FOR ONLY DEMO --- END*/

        this.anims.create({
            key: 'pulse',
            frames: this.anims.generateFrameNumbers('spikes', { start: 1, end: 3 }),
            frameRate: 1,
            repeat: -1
        });
    }

    create(){
         let damageCounter = 0; 
         let infoText = this.add.text(10, config.height - 10, 'No Damage')
            .setOrigin(0, 1)

         let spikes = this.add.sprite(30, 30, 'spikes')
            .play('pulse')
            .setScale(3)
            .setOrigin(0);
            
         let player = this.add.rectangle(10, 10, 30, 30, 0xffffff)
             .setOrigin(0);
             
         this.physics.add.existing(spikes)
         this.physics.add.existing(player)
         
         this.cursor = this.input.keyboard.createCursorKeys();
         let wasHitWithSpike = false;
         this.physics.add.overlap(spikes, player, (spikeSprite, player) => {
              if( wasHitWithSpike == false && spikeSprite.anims.currentFrame.index == 3){
                  damageCounter++;
                  wasHitWithSpike = true;
                  let text = ` -> taking damage\nOverlapping\nDamage: ${damageCounter}`;
                  infoText.setText(text);
                  // here you can tweak how long between damages
                  setTimeout( () => wasHitWithSpike = false, 1000);
              }
          });

         /* OLD Animation based part
           spikes.on(Phaser.Animations.Events.ANIMATION_UPDATE, (anim, frame, ...rest) => {
              let text = '';
              if(frame.index == 3){
                  // Add damage
                  infoText.setText(`frameindex:${frame.index}\nNot Overlapping\nDamage: ${damageCounter}`);
                  this.physics.overlap( spikes, player, () => {
                      damageCounter++;
                      text = `frameindex:${frame.index} -> taking damage\nOverlapping\nDamage: ${damageCounter}`;
                      infoText.setText(text);
                  });
              } else {
                  infoText.setText(`frameindex:${frame.index}\n\nDamage: ${damageCounter}`);
              }
         });*/
         
         this.player = player;
    }
    
    update(){
        let speed = 100;
        
        if(!this.cursor || !this.player){
            return
        }
        
        this.player.body.setVelocity(0);
        
        if(this.cursor.down.isDown){
            this.player.body.setVelocityY(speed);
        } else if(this.cursor.up.isDown){
            this.player.body.setVelocityY(-speed);
        } else if(this.cursor.left.isDown){
            this.player.body.setVelocityX(-speed);
        } else if(this.cursor.right.isDown){
            this.player.body.setVelocityX(speed);
        }
    }
}

var config = {
    type: Phaser.AUTO,
    width: 536,
    height: 140,
    physics: { default: 'arcade' },
    scene: [ GameScene ],
    banner: false
}; 

new Phaser.Game(config);
<script src="//cdn.jsdelivr.net/npm/phaser/dist/phaser.min.js"></script>
<div style="font-family:Arial">
Use the <b>arrow keys</b> to move the player (white square)<br>
Damage will only be dealt on the <span style="color:red"> red frame</span><br>
</div>

Update specific for your code:

你必须在每个精灵上添加EventListener,不能在100上添加它.

map.forEachTile(tile => {
    //Generate sprites on specific map tiles
    if (tile.index == 13) {
        let spike = this.spikes.create(tile.pixelX + 8, tile.pixelY + 8, "spikes")
            .play('spikes')
            .setDepth(10);

        spike.on(Phaser.Animations.Events.ANIMATION_UPDATE, (anim, frame) => {
            if(frame.index == 3){
                this.physics.overlap( spike, this.cPlayer, () => {
                    health--;
                });
            } 
        });
    }
});

Update 2, maybe better solution:

该解决方案可能具有更好的性能(because it uses only one event listener),并且需要更少的代码行.

this.physics.add.overlap( this.cPlayer, this.spikes, (player, spikeSprite) => {
    if(spikeSprite.anims.currentFrame.index == 3){
        health--;
    }
});

这里的触发器是overlap事件(documentation),然后您只需判断与player重叠的精灵的animation frame index.你想要Phaser.Animations.Events.ANIMATION_UPDATE号.

btw.: becareful since:
this.physics.overlap(...) checks once for an overlap (when it is called),
this.physics.add.overlap(...) adds an eventlister, that triggers everytime an overlap occurs

Javascript相关问答推荐

React对话框模式在用户单击预期按钮之前出现

如何在使用fast-xml-parser构建ML时包括属性值?

模块与独立组件

我应该绑定不影响状态的函数吗?'

我的服务工作器没有连接到我的Chrome扩展中的内容脚本.我该怎么解决这个问题?

如何调用名称在字符串中的实例方法?

在WordPress中使用带有WPCode的Java代码片段时出现意外令牌错误

在运行时使用Next JS App Router在服务器组件中运行自定义函数

是什么导致了这种奇怪的水平间距错误(?)当通过JavaScript将列表项元素追加到无序列表时,是否在按钮之间?

在浏览器中触发插入事件时检索编码值的能力

TypeError:无法读取未定义的属性(正在读取';宽度';)

从逗号和破折号分隔的给定字符串中查找所有有效的星期几

无法检索与Puppeteer的蒸汽游戏的Bundle 包价格

使用Reaction窗体挂钩注册日历组件

Angel Auth Guard-用户只有在未登录时才能访问登录页面,只有在登录时才能访问其他页面

在将元素追加到DOM之前,createElement()是否会触发回流?混淆abt DocumentFragment行为

在Press Reaction本机和EXPO av上播放单个文件

更改管线时不渲染组件的react

使用Java脚本在div中创建新的span标记

CSS网格使页面自动滚动