How to access the BitmapData of the current frame an animated FlxSprite

230 views
Skip to first unread message

sano98

unread,
Apr 25, 2016, 11:23:02 AM4/25/16
to HaxeFlixel


I have an animated FlxSprite and I want to manipulate the bitmap of the current frame.
Where is it located?
 
Changing mySprite.framePixels doesn't change anything.
 mySprite.frame.parent.bitmap is the bitmap of the whole spritesheet, not just the bitmap of the current frame.
 mySprite.frame itsself doesn't seem to have any bitmap attribute.

Any ideas? Thx.

Gama11

unread,
Apr 25, 2016, 4:06:11 PM4/25/16
to HaxeFlixel
framePixels should be what you're looking for. If you're on a native target, try setting useFramePixels to true as well.

sano98

unread,
Apr 26, 2016, 5:21:37 AM4/26/16
to HaxeFlixel
Doesn't seem to work. I am on flash target. Maybe the changes get overwritten later - during the draw call or something like that?

Example code shows an animated sprite (a running girl), and what I would expect is each frame, the sprite rectangle to be filled with completely with white whenever the current animation frame changes, so basically there should be a static white rectangle.
But it simply continues to show the original animation.
(Of course, in reality I want to do fancier shenanigans with the bitmap, but for testing purposes, filling the rectangle with white seems fine enough for now.)

This is the relevant code segment:




this.girlSprite = new FlxSprite(450, 20);
this.girlSprite.loadGraphic("assets/images/arron jes cycle.png", true, 48, 61, false);
this.girlSprite.animation.add("running", [0, 1, 2, 3, 4, 5, 6, 7], 16);
this.girlSprite.animation.callback = function(n:String, i:Int, j:Int):Void
{

trace("frame changed");
girlSprite.framePixels = new BitmapData(48, 61);
}


this.add(girlSprite);
this.girlSprite.animation.play("running");




And here is a link to the github project; the relevant lines are 160 following.


The usage of .drawFrame(); doesn't seem to have any effect, either.


Sam Bellman

unread,
Apr 26, 2016, 10:52:31 AM4/26/16
to HaxeFlixel
Yep, framePixels is the temporary bitmapData currently being used to display the FlxSprite, then the animationController will just overwrite this when it sets the next frame. What it sounds like you are looking for is frames.parent.bitmap, which is the bitmapData used for the animation textureAtlas. Try 
girlSprite.frames.parent.bitmap.fillRect(girlSprite.frames.parent.bitmap.rect, 0xFFFF0000);
Remember that changing the bitmapData won't change that frames data that defines the frames so if the frames aren't exactly the same size and positions your going to get a lot of weirdness and maybe runtime errors.

sano98

unread,
Apr 27, 2016, 5:46:56 AM4/27/16
to HaxeFlixel
Hey Sam,

thanks for your input! Unfortunately, there are several issues with your proposal.

First, I only want to manipulate the bitmap of the current frame. My example with painting the same rectangle over every bitmap was a simplification. I guess I could somehow identify the position of the frame in question in the spritsheet and apply the manipulations there, by considering the size of a single animation frame and the size of the whole spritesheet

But then, the manipulation would be applied to each instance of the FlxSprite, and not just the one I want to affect. (If I hvae several girls running through my level, all will now show the changes)

I guess the solution must be to somehow inject my changes when the animationController does his work. When draw() actually adds the current bitmapData to the camera, there must be a point when the final bitmapData to be drawn exists and I can grab it and manipulate it?

Sam Bellman

unread,
Apr 27, 2016, 6:14:47 AM4/27/16
to HaxeFlixel
I should have mentioned - when you load the graphic if you set the unique parameter to true it will make that graphic unique in the cache so it shouldn't affect other instances with the same graphic loaded.
this.girlSprite.loadGraphic("assets/images/arron jes cycle.png", true, 48, 61, true);
If you want to change individual frames you can get the positioning on the spritesheet from frames.frames[frameNumber]. What kind of changes are you making? If you are drawing stuff on top you might be better off just using a group.

sano98

unread,
Apr 27, 2016, 7:02:53 AM4/27/16
to HaxeFlixel

Good point with the unique parameter!

What I am trying to do is connected to this post:




In step one, I darken the sprite via a colorTransform operation
In step two, I make an overlap check with a FlxSprite that serves as a light source
In step three, I do an modified alpha-masking, which basically copies the original, unmodified Pixels from the sprite, before they were darkened by the colorTransform, onto the bitmap; but only in that regios that overlap with the lightsource.

It works for static Sprites, and with lots of tricks I found a solution for FlxTilemaps (I actually create a FlxSprite with the looks of the illuminated area of the Tilemap and place it in front of it), but I am still struggling with animated sprites.

How do I actually get the bitmap of my current frame from the spritesheet when I have the frameNumber? Do I have to manually set the position for the bitmap grabbing by multiplying frameNumber * frame.width and furthermore considering the format on the sprite sheet (like is it arranged in one singe line like in my example spritesheet or is it arranged over multiple rows?)







Sam Bellman

unread,
Apr 27, 2016, 10:16:42 AM4/27/16
to HaxeFlixel
Hmmm I think I misunderstood what you were using this for. You could get the frames rectangles from frames.frame[frameIndex] then use this to render all of the frames of an animation with alterations but if you're using it for dynamic lighting it would mean redrawing all of the animation every time the light or the character moved, which wouldn't be very efficient. You could try this:

girlSprite.animation.callback = function(n:String, i:Int, j:Int):Void
{
var frame:FlxFrame = new FlxFrame(FlxGraphic.fromBitmapData(new BitmapData(46, 61)), 0, true, false);
frame.frame = new FlxRect(0, 0, 46, 61);
frame.sourceSize.set(frame.frame.width, frame.frame.height);
frame.offset.set(0, 0);
girlSprite.frame = frame;
}

There are probably better ways to do and I'm sure you could do some kind of caching or other ways so this isn't called on every animation update this but I think this should work.

sano98

unread,
May 2, 2016, 8:27:04 AM5/2/16
to HaxeFlixel
Hey Sam,

thank you. I think this went into the right direction (although I ultimately didn't get it to work the way I wanted).
The frustrating part is that in the end, I am always searching for a bitmap to manipulate, but I only find frames and graphics - data structures, which I have not yet fully understood.

But you also layed the finger on the basic problem with my approach: It requires a lot of operations each frame and I would need to make every single FlxSprite a unique one in the memory.
While I am convinced that it could work, I'll try a different approach for now, which I believe to be cheaper and yet yield a comparable result.
Reply all
Reply to author
Forward
0 new messages