Emitter.simulate() [Feature discussion]

(Jacob Albano) #1

In my Flashpunk-inspired framework [Indigo][1], I have a method on my Emitter class that allows me to simulate the passage of time. It allows you to work around ugly effects like snow that doesn’t start until you load the world. I’d like to integrate this functionality into Flashpunk as a way to give back. It’s a really useful feature and I miss it whenever I’m not using my engine.

Here’s how I use it in Indigo (C# syntax of course):

var simFrames = FP.Framerate; // simulate running the emitter for a full second
for (int frame = 0; frame < simFrames; ++frame)
    emitter.Emit("type", 0, 0);

The end result is that 60 frames-worth of particles are emitted in the space of one actual frame, and they position, animate, and fade themselves appropriately.

The only notable change to the rest of the engine is the FP.engine.interval property, a constant value which is (in the ideal case) equal to FP.elapsed – but with the exception that it has a non-zero value before the first frame is run. It’s essentially a shortcut for 1f / FP.framerate in variable framerate mode.

So, my reason for bringing this up is to make sure the functions I’m adding make the most sense for everyone involved. Is this something that would be useful to others as a part of Flashpunk? Should interval be on FP or FP.engine? Let me hear your thoughts! [1]: https://bitbucket.org/jacobalbano/indigo

(Martí Angelats i Ribera) #2

Well since it’s constant we could do something like:

private var _internal:Number;
public function get interval():Number
    return _internal || (_internal = 1 / FP.framerate);

or even make it static and add it into the FP directly. This way do don’t make the operation 'till the first time it’s called and saves memory if never called.

PD: But since it’s a simple Number it shouldn’t take too much memory ether so…

(Mike Evmm) #3

FP.Engine.Interval would definitely be useful, I’ve had (been having) problems with FP.elapsed being 0 in the integration of Nape into FP. As far as the simulate function goes, I’m afraid I haven’t used particles all that much

(Jacob Albano) #4

There’s no good reason to do lazy initialization here. In my engine I set Interval at the same time as FP.Framerate, and I would do the same for Flashpunk.

In either case, it wouldn’t actually save memory, since Numbers are value types and are default-initialized with a fixed memory size.

(Jacob Albano) #5

Here’s what it looks like, using @Darrin’s flame effect to demonstrate.

The only difference between the emitter on the left and the one on the right is that the former is simulated for two seconds’ worth of frames before it’s added to the world, whereas the latter doesn’t start emitting until it’s added. As you can see, one of them looks like it’s existed since long before you arrived, while with the other it’s pretty obvious that it was created just for you. Little tweaks like this go a long way towards improving immersion.

I’ll be submitting a pull request shortly.

(Martí Angelats i Ribera) #6


I just noticed that in the Engine there is a variable called _rate with is 1000/FP.frameRate. It’s private though.

(Jacob Albano) #7

Well that’s exactly 1000x the value that interval needs to be in order to be useful. :stuck_out_tongue_winking_eye:

(Martí Angelats i Ribera) #8

XD. I now that, but what i tried to mean is that maybe we can make some kind of wizard trickary to delete that variable and only use the interval (yes i know 1000/x = 1000*1/x; i’m not that bad in maths >.<)

(Jacob Albano) #9

I don’t think it’s that big of a deal. The memory usage is totally unimportant and having two variables instead of doing that extra math operation every frame is a tradeoff I’m happy to make.

(Jacob Albano) #10

Pull request created!

Have at it.

(Zachary Lewis) #11

I’ll take a look at it! If I get someone else to look at it and let me know it’s good to go, I’ll pull it in.

(Darrin) #12

Very cool. Just a quick question. This turns this feature on and off right? The reason being is that there are times when I want the emitter to start up on screen. For example, burning a piece of paper, etc.

(Jacob Albano) #13

There’s no enabling/disabling involved, actually. The only thing simulate() does is advance each particle’s lifetime by the value passed to it. If you stop calling it (or never call it at all), everything behaves as normal.

In the example above, I only simulate the emitter during its setup. Afterwards it behaves normally.

override public function added():void 
    for (var i:int = 0; i < FP.assignedFrameRate * 2; i++) 

override public function update():void 
    emitter.emit("fireL", -2 - FP.rand(3), -30);
    emitter.emit("fireR", 2 + FP.rand(3), -30);

(Zachary Lewis) #14

Do you have to actually emit particles during your simulation loop for it to simulate them?

(Jacob Albano) #15

No, it’ll update all the existing particles regardless. The example above emits every iteration to demonstrate the fire effect, but you could just as easily emit one burst and simulate it for a full second with one call, like if you wanted to create a fireworks burst or something.

(Zachary Lewis) #16

I’m talking about this part. This doesn’t actually emit anything, does it?

(Jacob Albano) #17

It does because I have my emit code in the update() function. Without that call, no new particles would be emitted. On its own, simulate() doesn’t add any more.

(Zachary Lewis) #18

Ah, didn’t notice the call to update(). If that was removed then the emitter would simulate two seconds of time, but nothing would be emitted, right?

(Jacob Albano) #19

Exactly – and at that point it would be more optimal to make one call with the whole timespan:

emitter.simulate(FP.assignedFrameRate * 2 * FP.interval);

(Jacob Albano) #20

@AbelToy any chance I could get a third pair of eyes on this? I’ve got another pull request I’d like to make which fixes a few bugs that have somehow persisted since about four years ago.