Phaser 3 - 我发射粒子的次数越多,粒子就越多?

Phaser 3 - Particles become more the more often I emit them?

当我在某个对象上单击并移动鼠标时,我会发出粒子。然而我注意到,虽然粒子开始时很小,但随着我点击和移动鼠标的频率越来越高,它们变得越来越多,直到粒子流变得过于密集。

这似乎只发生在我多次向下点击时(因此多次触发 pointerdown 事件),而不是当我点击一次并继续移动时。

我该如何阻止它?

function pet(start, scene, pointer = null)
{
    if(start){
        scene.input.on('pointermove', function(){
            if (scene.input.activePointer.isDown && gameState.chara.getBounds().contains(scene.input.activePointer.x, scene.input.activePointer.y)){
                gameState.sparkle.emitParticle(1,scene.input.activePointer.x, scene.input.activePointer.y);   // !!!! Here is where I emit my particles
            }
        });
    } else {
        gameState.sparkle.stop();   // !!!! Here I stop my particles
    }
}

const gameState = {
    gameWidth: 800,
    gameHeight: 800,
    menu: {},
    textStyle: { 
        fontFamily: "'Comic Sans MS'", 
        fill: "#fff", 
        align: "center",
        boundsAlignH: "left", 
        boundsAlignV: "top"
    },
};

function preload()
{
    this.load.baseURL = 'assets/';
    
    //  Chara
    this.load.atlas('chara', 'chara.png', 'chara.json');
    
    // Particle
    this.load.image('sparkle', 'sparkle.png');  // Here I load my particle image
    
}

function create()
{
    // Scene
    let scene = this;
    
    // Chara
    this.anims.create({
        key: "wag",
        frameRate: 12,
        frames: this.anims.generateFrameNames("chara", {
            prefix: 'idle_000',
            start: 0, 
            end: 5}),
        repeat: 0,
    });
    this.anims.create({
    key: "happy",
        frameRate: 12,
        frames: this.anims.generateFrameNames("chara", {
            prefix: 'happy_000',
            start: 0, 
            end: 5}),
        repeat: -1
    });
    gameState.chara = this.add.sprite(400, 400, "chara", "idle_0000");
    gameState.chara.setInteractive({cursor: "pointer"});
    
    // !!!! Here I set up my Particle Emitter !!!!
    gameState.sparkle = this.add.particles('sparkle').createEmitter({
        x: gameState.height/2,
        y: gameState.width/2,
        scale: { min: 0.1, max: 0.5 },
        speed: { min: -100, max: 100 },
        quantity: 0.1,
        frequency: 1,
        lifespan: 1000,
        gravityY: 100,
        on: false,
    });

    gameState.chara.on('pointerdown', function(){ pet(true, scene) });
    gameState.chara.on('pointerout', function(){ pet(false, scene, 'default') });
    gameState.chara.on('pointerup', function(){ pet(false, scene, 'pointer') });
}

function update()
{   

}

// Configs

var config = {
    backgroundColor: "0xf0f0f0",
    scale: {
        width: gameState.gameWidth,
        height: gameState.gameHeight,
        autoCenter: Phaser.Scale.CENTER_BOTH
    },
    scene: {
        preload, create, update
    }
};
var game = new Phaser.Game(config);
<script src="https://cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js"></script>

问题是,您在每次点击时都会在 pet 函数中添加一个新的 scene.input.on('pointermove',...) event-handler。

我只会稍微更改代码 (看下面),这应该可以防止生成太多粒子和太多 event-handlers (太许多 event-handler 可能会影响性能,因此在添加它们时要小心)。

下面是我将如何修改代码:
(我删除并添加了一些东西来制作演示,更容易理解和更短。而且该代码段可以在没有 errors/warnings 的情况下执行)

The main changes are marked and explained in the code, with comments

function pet(start, scene, pointer = null)
{
    if(start){
        // Update: remove Event listener add click state
        gameState.mouseDown = true
    } else {
        // Update: add click state
        gameState.mouseDown = false;
        gameState.sparkle.stop();
    }
}

const gameState = {
    gameWidth: 400,
    gameHeight: 200,
   // Update: add click state
    mouseDown: false
};

function create()
{
     // Scene
     let scene = this;
    
     // Just could for Demo START
     var graphics = this.add.graphics();
     graphics.fillStyle(0xff0000);
     graphics.fillRect(2,2,10,10);
     graphics.generateTexture('particle', 20, 20);
     graphics.clear();
     graphics.fillStyle(0xffffff);
     graphics.fillRect(0,0,40,40);
     graphics.generateTexture('player', 40, 40);
     graphics.destroy();
     // Just Code for Demo END

    gameState.chara = this.add.sprite(200, 100, "player");
    gameState.chara.setInteractive({cursor: "pointer"});
    
    gameState.sparkle = this.add.particles('particle').createEmitter({
        scale: { min: 0.1, max: 0.5 },
        speed: { min: -100, max: 100 },
        quantity: 0.1,
        frequency: 1,
        lifespan: 1000,
        gravityY: 100,
        on: false,
    });

    gameState.chara.on('pointerdown', function(){ pet(true, scene) });
    gameState.chara.on('pointerout', function(){ pet(false, scene, 'default') });
    gameState.chara.on('pointerup', function(){ pet(false, scene, 'pointer') });
    
    // Update: add new single Event Listener
    gameState.chara.on('pointermove', function(pointer){
        if(gameState.mouseDown){
          gameState.sparkle.emitParticle(1,pointer.x, pointer.y); 
        }
    });
}

// Configs
var config = {
    width: gameState.gameWidth,
    height: gameState.gameHeight,
    scene: { create }
};
var game = new Phaser.Game(config);
<script src="https://cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js"></script>