How To Line Up An Animation's Sprite Frames When Sizes Are Different?

I’ve searched through the forums and read a few related posts. I’ve also scoured the internet and even read a tutorial in Japanese (I think?). However, I can’t seem to quite solve my problem. So, I’m hoping that you Corona experts can help me with this basic question…

I believe the answer lies in the SourceX / SourceY & SourceWidth / SourceHeight parameters used when detailing out complex frames in a sprite sheet. But, no matter how much I search and how many examples I read, I just can’t seem to understand exactly how it works??  (I understand different sized frames and complex frames, I just don’t understand re-positioning them to line up a single spot that is in different locations between different frames).

Let me explain my predicament more clearly and you all can tell me if I’m even in the right ball park.

Let’s say I have an animation of 3 frames. In this animation, a character is facing to the right side and swings a weapon, overhead, from behind to in-front. My goal is to play the animation and line up the frames so that the character is in the same spot on each of the displayed frames in the animation.

Herein lies my problem…my frames all have different widths, ie. when the weapon is behind him the frame is much wider, and the character is towards the right side of the frame (the weapon being behind him, on the left). However, on the last frame the character is on the left side of the frame and the weapon is in front of him. Likewise, in the 2nd frame the weapon is above his head and is taller, but the frame is much thinner than the first and third frames. So, when I play these frames in an animation, he will appear to ‘stutter’ from left to right.

Again, I think I’m the right track with the Source properties, but after reading the API, forums and interwebs, I still don’t fully grasp how they work. Perhaps, someone here can break it down visually, or explain it in a manner different than the API?

Thank you all for reading this, and for those who answer, giving their time.

Kenny

I use Texture Packer to create the sprite sheet. It creates a lua file that you require in your code and use as a parameter for the sprites. Sounds complicated, but is easy once understood. What it does is create a table with widths, heights for each individual sprite frame.

Thank you for your reply jadkins4! I actually use TexturePacker as well. The problem I’m having is not with the sizes of the sprites or their placement on the spritesheet, but rather, the character’s placement within the sprite. A character that is on the left of one sprite and on the right of the next sprite, appears to ‘jump’. I need to re-position the sprites so that the character is in the same x,y position on the screen and the sprite itself changes position. Almost like setting a root for each frame?

If I’m still unclear, I will be happy to give some visual examples. 

Hi Kenneth,

At a glance, it looks like you’re contending with the “common” misunderstanding of the “Trim” trim mode in TexturePacker and how it relates to positioning in Corona. Have you tried the other trim modes like “Crop: Flush Position” and “Crop: Keep Position”? These should still effectively pack the images into the smallest possible sheet, but they will generate different sheet positioning values for Corona. This might help you deal with the positioning issue. If you’re still having trouble, I can probably explain it in greater technical detail (and by looking at some of your sample frame table parameters).

Best regards,

Brent Sorrentino

Brent, thank you very much for your reply!  I have looked further into the different trim options in TexturePacker. It appears to me that to utilize their auto positioning, each of the sprites must be the same size before packing/trimming them. I’m not sure if I’m limited to this constraint, or if there is a way to solve the problem I am having w/o having to use this workaround.

I went ahead and assembled an example for your review. These are just 3 basic sprites that will help to illustrate my problem.

Here are the 3 sprites BEFORE packing them in texturepacker: (you may need to click the image to see the actual size)

frame1.png: 299x225

frame2.png: 208x346

frame3.png: 369x185

Notice that in each of the sprites, the character is in a different position? Either on the right side, middle or left side.

Now, I place them all into TexturePacker, select the Data Format: _Corona SDK (image sheet), _and export the sprite sheet.  I exported it with all 3 trim modes, and each of them gave the same results…

SheetInfo.sheet = { frames = { { -- frame1 x=2, y=189, width=299, height=225, }, { -- frame2 x=2, y=416, width=208, height=346, }, { -- frame3 x=2, y=2, width=369, height=185, }, }, sheetContentWidth = 512, sheetContentHeight = 1024 }

The exported sprite sheet appears as such: (I outlined the sprites for visual assistance, and shrunk down the sheet for the sake of space)

So, as you can see, I will most likely need to manually adjust the SourceX/SourceY & SourceWidth/SourceHeight properties.  I’ve been trying to do this with no success. It’s not that I’m unable to understand how it works, I believe I do understand it. I just am not getting any visual feedback from my changes. I’ve added the ‘Source’ properties to all the frames, and yet no differences appear when I play the animation.

Your expertise is coveted and very much appreciated Brent. Thank you for your time.

Kenny

I’m interested to hear Brent’s solution, but why not take the “easy” way out and expand the canvas of each image so they’re the same size and large enough to hold each guy in the same location?

So with frame 1 you have a lot of extra space to the right, frame 2 has some extra right and left, and frame 3 has a lot of extra space to the left. Of course, with trimming in TexturePacker all that empty space “goes away” anyway.

  Jay

Hi Jay!

I’m thinking that what you said is the way we’re going to do the sprites. My artist makes large sprites, so we’d work with something like a 512x512 canvas, and just let texturepacker trim extra space. I hope that having a SourceWidth/SourceHeight of 512x512 or 256x256 won’t create any adverse affects, However, last night I tested packing sprites exactly how you mentioned, and things seemed to work well.

Although, I too am interested to hear if there are any alternate implementations of which Brent may be aware?

Thanks for the input Jay, you definitely have the right idea!

Kenny

P.S. Last night, I also manually adjusted SourceX/SourceY & SourceWidth/SourceHeight, to perfectly line up the above sprites. So, Brent, unless you feel inspired, I won’t need an extended tutorial about how those properties work. However, it would be night to see the API documentation for the properties expanded. :slight_smile:

Hi Kenneth,

Good to hear you solved it. If I recall (and please confirm if you discovered this is true), the purpose of “sourceX” and “sourceY” in regards to trimming is to retain the “untrimmed” size of the frame for positioning purposes only, around the center reference point. So, your artist can create all of the frames at whatever size necessary, as long as the character is aligned properly among frames (that’s the artists job, ultimately). But, you can still use TexturePacker to trim them down to conserve texture memory… and doing so will give you the “sourceX” and “sourceY” values as if the frame was not trimmed, from a positioning standpoint.

So, let’s say you have 2 frames, each of them 512 x 512 from the artist. The first one has 40 pixels of transparent padding around the “content”, and the other only 23 pixels around it. Obviously, the main purpose behind TexturePacker is that it should trim off the transparent space and pack the frames into a compact sheet. It will do that, properly, and you’ll get two frames sized as follows in TexturePacker:

  1. 512 - 40 - 40 = 432  (we’ll assume same for width and height)

  2. 512 - 23 - 23 = 466

OK, so then, how do you ensure those images line up properly in Corona? Well, that’s what “sourceX” and “sourceY” are for. They treat the frames as if they were not trimmed, even though in effect they have been. So, from Corona’s side, it considers that both images reside on the original rectangular “canvas” of 512 x 512, and positioning will be respected as such, around the center point of that imaginary canvas. This allows you to use TexturePacker to compact your frames into sheets, while from a positional standpoint, treating those images as if they were never trimmed.

Note that this only works around the center reference point… I need to emphasize that yet again. We contemplated adding the ability to trim and position around other reference points, but it seemed to be a somewhat isolated use-case and quite possibly more confusing to users than it’s worth.

Anyway, does this make any sense? I’m just typing away and probably rambling now. :slight_smile:

Brent

Brent,

Your explanation was great!  You definitely nailed it on the head. Although, I’m not sure what you mean by “works around the center reference point”? I know that the x,y coordinates are based on the point at the top left of the sprite, both in the exported sprite sheet and in the untrimmed large sprite as well.  However, regardless, I thought it would be nice to create a visual guide that will hopefully help anyone else who stumbles upon this thread in search of the same answer as I previously was.

Ultimately, the solution is to create each sprite in the same large size and when you export them from TexturePacker, select Trim, and allow TexturePacker to create a .lua file which contains all the information Corona needs to keep the sprites lines up correctly when displaying them in your app.

Here are a couple of images I made using the same sprites as before to show how the X,Y / Height,Width / SourceX,SourceY / SourceHeight,SourceWidth properties are used to keep your sprites lined up and looking good!

Basically, Corona uses the SourceX / SourceY properties with the SourceWidth / SourceHeight to line up each sprite. Even though each sprite has been trimmed, and the spirte sizes and character positions are so mismatched there’s no way the Corona could ‘automatically’ line them up, it can line them up by know how they “originally” related to each other.

Thank you Brent, Jay and Jadkins for your helpful responses!

I use Texture Packer to create the sprite sheet. It creates a lua file that you require in your code and use as a parameter for the sprites. Sounds complicated, but is easy once understood. What it does is create a table with widths, heights for each individual sprite frame.

Thank you for your reply jadkins4! I actually use TexturePacker as well. The problem I’m having is not with the sizes of the sprites or their placement on the spritesheet, but rather, the character’s placement within the sprite. A character that is on the left of one sprite and on the right of the next sprite, appears to ‘jump’. I need to re-position the sprites so that the character is in the same x,y position on the screen and the sprite itself changes position. Almost like setting a root for each frame?

If I’m still unclear, I will be happy to give some visual examples. 

Hi Kenneth,

At a glance, it looks like you’re contending with the “common” misunderstanding of the “Trim” trim mode in TexturePacker and how it relates to positioning in Corona. Have you tried the other trim modes like “Crop: Flush Position” and “Crop: Keep Position”? These should still effectively pack the images into the smallest possible sheet, but they will generate different sheet positioning values for Corona. This might help you deal with the positioning issue. If you’re still having trouble, I can probably explain it in greater technical detail (and by looking at some of your sample frame table parameters).

Best regards,

Brent Sorrentino

Brent, thank you very much for your reply!  I have looked further into the different trim options in TexturePacker. It appears to me that to utilize their auto positioning, each of the sprites must be the same size before packing/trimming them. I’m not sure if I’m limited to this constraint, or if there is a way to solve the problem I am having w/o having to use this workaround.

I went ahead and assembled an example for your review. These are just 3 basic sprites that will help to illustrate my problem.

Here are the 3 sprites BEFORE packing them in texturepacker: (you may need to click the image to see the actual size)

frame1.png: 299x225

frame2.png: 208x346

frame3.png: 369x185

Notice that in each of the sprites, the character is in a different position? Either on the right side, middle or left side.

Now, I place them all into TexturePacker, select the Data Format: _Corona SDK (image sheet), _and export the sprite sheet.  I exported it with all 3 trim modes, and each of them gave the same results…

SheetInfo.sheet = { frames = { { -- frame1 x=2, y=189, width=299, height=225, }, { -- frame2 x=2, y=416, width=208, height=346, }, { -- frame3 x=2, y=2, width=369, height=185, }, }, sheetContentWidth = 512, sheetContentHeight = 1024 }

The exported sprite sheet appears as such: (I outlined the sprites for visual assistance, and shrunk down the sheet for the sake of space)

So, as you can see, I will most likely need to manually adjust the SourceX/SourceY & SourceWidth/SourceHeight properties.  I’ve been trying to do this with no success. It’s not that I’m unable to understand how it works, I believe I do understand it. I just am not getting any visual feedback from my changes. I’ve added the ‘Source’ properties to all the frames, and yet no differences appear when I play the animation.

Your expertise is coveted and very much appreciated Brent. Thank you for your time.

Kenny

I’m interested to hear Brent’s solution, but why not take the “easy” way out and expand the canvas of each image so they’re the same size and large enough to hold each guy in the same location?

So with frame 1 you have a lot of extra space to the right, frame 2 has some extra right and left, and frame 3 has a lot of extra space to the left. Of course, with trimming in TexturePacker all that empty space “goes away” anyway.

  Jay

Hi Jay!

I’m thinking that what you said is the way we’re going to do the sprites. My artist makes large sprites, so we’d work with something like a 512x512 canvas, and just let texturepacker trim extra space. I hope that having a SourceWidth/SourceHeight of 512x512 or 256x256 won’t create any adverse affects, However, last night I tested packing sprites exactly how you mentioned, and things seemed to work well.

Although, I too am interested to hear if there are any alternate implementations of which Brent may be aware?

Thanks for the input Jay, you definitely have the right idea!

Kenny

P.S. Last night, I also manually adjusted SourceX/SourceY & SourceWidth/SourceHeight, to perfectly line up the above sprites. So, Brent, unless you feel inspired, I won’t need an extended tutorial about how those properties work. However, it would be night to see the API documentation for the properties expanded. :slight_smile:

Hi Kenneth,

Good to hear you solved it. If I recall (and please confirm if you discovered this is true), the purpose of “sourceX” and “sourceY” in regards to trimming is to retain the “untrimmed” size of the frame for positioning purposes only, around the center reference point. So, your artist can create all of the frames at whatever size necessary, as long as the character is aligned properly among frames (that’s the artists job, ultimately). But, you can still use TexturePacker to trim them down to conserve texture memory… and doing so will give you the “sourceX” and “sourceY” values as if the frame was not trimmed, from a positioning standpoint.

So, let’s say you have 2 frames, each of them 512 x 512 from the artist. The first one has 40 pixels of transparent padding around the “content”, and the other only 23 pixels around it. Obviously, the main purpose behind TexturePacker is that it should trim off the transparent space and pack the frames into a compact sheet. It will do that, properly, and you’ll get two frames sized as follows in TexturePacker:

  1. 512 - 40 - 40 = 432  (we’ll assume same for width and height)

  2. 512 - 23 - 23 = 466

OK, so then, how do you ensure those images line up properly in Corona? Well, that’s what “sourceX” and “sourceY” are for. They treat the frames as if they were not trimmed, even though in effect they have been. So, from Corona’s side, it considers that both images reside on the original rectangular “canvas” of 512 x 512, and positioning will be respected as such, around the center point of that imaginary canvas. This allows you to use TexturePacker to compact your frames into sheets, while from a positional standpoint, treating those images as if they were never trimmed.

Note that this only works around the center reference point… I need to emphasize that yet again. We contemplated adding the ability to trim and position around other reference points, but it seemed to be a somewhat isolated use-case and quite possibly more confusing to users than it’s worth.

Anyway, does this make any sense? I’m just typing away and probably rambling now. :slight_smile:

Brent

Brent,

Your explanation was great!  You definitely nailed it on the head. Although, I’m not sure what you mean by “works around the center reference point”? I know that the x,y coordinates are based on the point at the top left of the sprite, both in the exported sprite sheet and in the untrimmed large sprite as well.  However, regardless, I thought it would be nice to create a visual guide that will hopefully help anyone else who stumbles upon this thread in search of the same answer as I previously was.

Ultimately, the solution is to create each sprite in the same large size and when you export them from TexturePacker, select Trim, and allow TexturePacker to create a .lua file which contains all the information Corona needs to keep the sprites lines up correctly when displaying them in your app.

Here are a couple of images I made using the same sprites as before to show how the X,Y / Height,Width / SourceX,SourceY / SourceHeight,SourceWidth properties are used to keep your sprites lined up and looking good!

Basically, Corona uses the SourceX / SourceY properties with the SourceWidth / SourceHeight to line up each sprite. Even though each sprite has been trimmed, and the spirte sizes and character positions are so mismatched there’s no way the Corona could ‘automatically’ line them up, it can line them up by know how they “originally” related to each other.

Thank you Brent, Jay and Jadkins for your helpful responses!