0
votes

I am creating the "perfect" sprite packer. This is a sprite packer that makes sure the output sprite is compatible with most if not all game engines and animation software. It is a program that merges images into a horizontal sprite sheet.

  1. It converts (if needed) the source frames to BMP in memory

  2. It considers the top-left pixel fully transparent for the entire image (can be configured)

  3. It parses the frames each individually to find the real coordinates rect (where the actual frame starts, ends, its width and height (sometimes images may have a lot of extra transparent pixels).

  4. It determines the frame box, which have the width and height of the frame with the largest width/height so that it is long enough to contain every frame. (For extra compatibility, every frame must have the same dimensions).

  5. Creates output sprite with width of nFrames * wFrameBox

The problem is - anchor alignment. Currently, it tries to align each frame so that its center is on the frame box center.

if((wBox / 2) > (frame->realCoordinates.w / 2))
{
    xpos = xBoxOffset + ((wBox / 2) - (frame->realCoordinates.w / 2));
}
else
{
    xpos = xBoxOffset + ((frame->realCoordinates.w / 2) - (wBox / 2));
}

When animated, it looks better with it, but there is still this inconsistent horizontal frame position so that a walking animation looks like walking and shaking. I also tried the following: store the real x pixel position of the widest frame and use it as a reference point: xpos = xBoxOffset + (frame->realCoordinates.x - xRef); It also gives a little better results, showing that this is still not the correct algorithm. Honestly, I don't know what am I doing.

What will be the correct way to align sprite frames (obtain the appropriate x position for drawing the next frame) given that the output sprite sheet have width of the number of frames multiplied by the width of the widest frame?

1

1 Answers

1
votes

Your problem is that you first calculate the center then calculate the size of the required bounding box. That is why your image 'shakes' because in each image that center is different to the original center.

You should use the center of the original bounding box as your origin, then find out the size of each sprite, keeping track of the leftmost, rightmost, topmost and bottommost non transparent pixels. That would give you the bounding box you need to use to avoid the shaking.

The problem is that you will find that most sprites are already done that way, so the original bounding box is actually defined as to the minimum space to paint the whole sprite's sequence covering these non transparent pixels.

The only way to remove unused sprite space is to store the first sprite complete, and then the origin and dimensions of each other sprite, like is done in animated GIF and APNG ( Animated PNG -> https://en.wikipedia.org/wiki/APNG )