Stardust and Flixel integration

55 views
Skip to first unread message

Nyxo

unread,
Sep 2, 2011, 12:22:42 AM9/2/11
to Stardust Particle Engine
I'm having some troubles integrating stardust 1.3 into Flixel.
I'm attempting to do this by having stardust directly alter the
BitmapData of a FlxSprite, which I've seen on some blogs, is supposed
to be possible.
There's a couple of places that I'm really not sure about whether I'm
doing it correctly, so some insight would be appreciated.

My [simplified] code is as follows:

[Embed(source = "temp.png")]
private static const TEMP_PNG:Class;

...

var s:FlxSprite = new FlxSprite();
s.width = 640;
s.height = 480;
add(s);

var handler:BitmapHandler = new BitmapHandler(s.pixels);

_emitter = new Emitter2D(new SteadyClock(8));
_emitter.particleHandler = handler;
_emitter.addInitializer(new DisplayObjectClass(TEMP_PNG));
_emitter.addInitializer(new Position(new Line(0, 0, 1280, 0)));
_emitter.addInitializer(new Velocity(new LazySectorZone(4, 0.5)));


And later in my code, in my loop,

_emitter.step();


All I'm getting in my normal scene rendering, and the little Flixel
logo up in the top left corner (which is by default what a FlxSprite
looks like...). I'm sure I'm doing something wrong with tying the
FlxSprite to stardust, but I really don't know what it is..

Allen Chou

unread,
Sep 2, 2011, 1:00:12 AM9/2/11
to stardust-par...@googlegroups.com
Sorry, I'm not familiar with how Flixel works, so I'm not sure if you can just directly edit the bitmap pixels like that.

However, I suggest you first use the BitmapHandler to draw to a BitmapData and display it through ordinary Bitmap classes, just to see if things are correctly rendered. If yes, then you probably are not allowed to directly alter pixels like this in Flixel.
--
CJ Cat (Ming-Lun "Allen" Chou)
http://blog.cjcat.net

Nyxo

unread,
Sep 2, 2011, 8:57:17 AM9/2/11
to Stardust Particle Engine
Yeah, that's the unfortunate thing about trying to integrate two third-
party systems-- neither one really knows the other, so it's hard to
get help unless somebody has direct experience integrating them;;;

So, ignoring the Flixel specific stuff, does it appear that I'm doing
things correctly then? I'm mostly suspicious of the 3 lines:


[Embed(source = "temp.png")]
private static const TEMP_PNG:Class;
...
_emitter.addInitializer(new DisplayObjectClass(TEMP_PNG));


As I haven't been able to find any examples of using Stardust with
anything BUT .FLA files for the graphics, I'm really not sure what the
accepted method is of loading these graphics-- as you can see here,
I'm using Flex, and loading my .PNG file via an Embed metatag, and I'm
only guessing about how to use that .PNG with Stardust..

Allen Chou

unread,
Sep 2, 2011, 2:47:13 PM9/2/11
to stardust-par...@googlegroups.com
I've never worked with the [Embed] tag before. Did it work if you just use it this way with ordinary BitmapData and Bitmap classes for visual display?
 
As long as you are passing a class reference to a subclass of DisplayObject to the DisplayObjectClass constructor, you're doing it right.

Nyxo

unread,
Sep 2, 2011, 8:54:44 PM9/2/11
to Stardust Particle Engine
Ok, it's all working when I used a DisplayObjectHandler and the Embed
metatag, so I'm obviously doing something wrong with the
BitmapHandler.

I'll have to poke around some more and see what I can make work.

Nyxo

unread,
Sep 2, 2011, 10:28:19 PM9/2/11
to Stardust Particle Engine
Alright, to add to this post, in case anybody else comes looking, full
applicable source code:

<Class variable declarations>

[Embed(source = "raindrop.png")]
private static const RAINDROP_PNG:Class;

private var _emitter:Emitter;
private var _particleSprite:FlxSprite;


<Constructor, or some initialization function>

_particleSprite = new Sprite();
_particleSprite.makeGraphic(320, 240, 0x00000000);
add(_particleSprite);

var handler:ParticleHandler = new
BitmapHandler(_particleSprite.pixels);

_emitter = new Emitter2D(new SteadyClock(8));
_emitter.particleHandler = handler;
_emitter.addInitializer(new DisplayObjectClass(RAINDROP_PNG));
_emitter.addInitializer(new Position(new Line(0, 0, 640, 0)));
_emitter.addInitializer(new Velocity(new LazySectorZone(4, 0.5)));

var gravity:Gravity = new Gravity();
_emitter.addAction(gravity);
_emitter.addAction(new Move());
_emitter.addAction(new DeathZone(new RectZone(0, 0, 640, 480), true));


<draw function (NOT update!- updates may occur multiple times per
draw, making particles have shadows)>
_emitter.step();

_particleSprite.drawFrame(true); //This is the most important part!
It forces the FlxSprite to show the particles that were added by
Stardust!
super.draw(); //This is where _particleSprite gets drawn
_particleSprite.fill(0x00000000); //This is the second most important
part! If we don't do this, the particles leave trails!

Allen Chou

unread,
Sep 2, 2011, 10:30:14 PM9/2/11
to stardust-par...@googlegroups.com
Wait a minute.
Logically, I think fill(0x00000000) should be after draw(), right?

Nyxo

unread,
Sep 3, 2011, 1:31:04 AM9/3/11
to Stardust Particle Engine
It is after draw- _particleSprite.fill(0x00000000); is the last line
in the code I posted.

Allen Chou

unread,
Sep 3, 2011, 2:34:28 PM9/3/11
to stardust-par...@googlegroups.com
Yes, fill() is the last line of code.

I mean, isn't that the line of code that erases all the particle on the screen, and should be the line "before" particle update, i.e. draw()? Otherwise, you'll just get blank screen every frame.

Nyxo

unread,
Sep 4, 2011, 8:40:53 PM9/4/11
to Stardust Particle Engine
Nope- it's because of how Flixel works internally with FlxSprites.

FlxSprites maintain 2 different BitmapDatas for the purposes of
animations. The first one is a graphic buffer that contains all of the
pixels for the graphic of the FlxSprite-- calling FlxSprite.pixels
retrieves this buffer. The second one is a frame buffer that is a copy
of a portion of the graphic buffer (or in the case of a single frame
graphic, the entire graphic buffer)-- there is no way to directly
manipulate this buffer, as it is a temporary buffer intended only for
the purposes of storing what actually gets drawn on the screen at the
time draw() is called.

FlxSprites normally function fine without need for the programmer to
care about this, but it's even commented within FlxSprite, that if
you're doing some procedural graphics or something like that, you'll
need to manually force the frame buffer to update from the graphic
buffer.

So here's some extra comments to clear up that last piece of code:


_emitter.step(); //Make the emitter draw the particles to the
FlxSprite's GRAPHICS buffer

_particleSprite.drawFrame(true); //Copies the GRAPHICS buffer into
the FRAME buffer
super.draw(); //Draw the FRAME buffer
_particleSprite.fill(0x00000000); //Blank out the GRAPHICS buffer
(this is just preparation for the next frame-- I guess it could have
been done before the emitter.step() call...)

Nyxo

unread,
Sep 5, 2011, 12:38:22 AM9/5/11
to Stardust Particle Engine
To make this all that much faster, as I've done locally, you could
derive a class from FlxSprite, and instead use the protected
FlxSprite.framePixels instead of the public FlxSprite.pixels, and then
there will be no need to call drawFrame anymore, which will eliminate
the copying of pixels to the frame buffer.
The downside of this is that if you call any of the functions for
loading graphics, it'll blow away your frame buffer, and it'll look
like Stardust stopped working-- but if you're using the FlxSprite
exclusively for particles, it shouldn't be a problem at all.
Reply all
Reply to author
Forward
0 new messages