excaliburjs / Excalibur

🎮 Your friendly TypeScript 2D game engine for the web 🗡️
https://excaliburjs.com
BSD 2-Clause "Simplified" License
1.77k stars 189 forks source link

Fast fadeBy action doesn't sometimes complete (probably under stress) #3092

Open spustlik opened 3 months ago

spustlik commented 3 months ago

Steps to Reproduce

        for (let i = 0; i < 100; i++) {
            let a = new ex.Actor({
                pos: ex.vec(100, 100),
                opacity: 0,
                width: 20,
                height: 20,
                color: ex.Color.Blue
            });
            this.add(a);
            a.actions
                .fade(1, 100)
                .callMethod(() => console.log('done'));
        }

Expected Result

100x console.log

Actual Result

When using on more actors (100 for example), fade action is not complete, none 'done' in console. When count is less or speed is greater, it is OK.

Environment

Current Workaround

slower fadeBy

Motivation

In fact, I am using actions for own particle system with animated sprites and when actions are completed calling cleanup, typically removing particle actor from scene. For sure, actors are childs of another actor, and it is removed after some delay;

eonarheim commented 3 months ago

@spustlik Thanks for the issue, definitely a bug. The fade routines are flawed

There are situations where it is possible for this to never be true because of the discrete simulation

image

You might be able to use coroutine in place of the fade action


var newFadeBy = (actor: ex.Actor, fadeChange: number, durationSeconds: number) => {
  // coroutines start automatically
  ex.coroutine(function* () {
    let duration = durationSeconds * 1000; // milliseconds
    let fadeChangeRate = fadeChange / duration;
    let targetOpacity = actor.graphics.opacity + fadeChange;
    while (duration > 0) {
      const elapsed = yield;
      duration -= elapsed;
      actor.graphics.opacity += fadeChangeRate * elapsed;
    }
    actor.graphics.opacity = targetOpacity;
  });
};

actor.onInitialize = () => {
  newFadeBy(actor, -1.0, 2);
};
github-actions[bot] commented 1 month ago

This issue hasn't had any recent activity lately and is being marked as stale automatically.