TexturePacker, spritsheets and @2x images...

Whoa, one would think Ansca would have updated their articles to account for this. I finally managed to load the high res textures… But it’s not working right…

2 problems arose: 1. It seems that it’s not using the @2x script, because animations are out of place. And 2. The higher res graphics are bigger than they should be (meaning, the hd images are being scaled up).

code for loading the spritesheet now looks like

 --get all sprite data  
 local oldStyleData = require("scripts.catsheet");  
 local oldSpriteSheetData = oldStyleData.getSpriteSheetData();  
 local options = { spriteSheetFrames = oldSpriteSheetData.frames };  
 local heroSheet = graphics.newImageSheet( "images/catsheet.png", options );  
 --prepare animations  
 local sequenceData = {  
 { name="death", start=1, count=3, time=800, loopCount=1 },  
 { name="falling", start=4, count=1, time=1, loopCount=1 },  
 { name="jumping", start=5, count=1, time=1, loopCount=1 },  
 { name="sliding", start=6, count=1, time=1, loopCount=1 },  
 { name="rolling", start=7, count=3, time=200, loopCount=0 },  
 { name="running", start=10, count=7, time=400, loopCount=0 }  
 };  
 --start everything  
 local hero = display.newSprite( heroSheet, sequenceData );  
 hero:setSequence("running");  
 hero:play();  

config.lua remains unchanged. [import]uid: 136402 topic_id: 30336 reply_id: 121881[/import]

Your expectation is correct.
Corona does load all resolutions using the ‘base’ one.
Unfortunately, because Texture Packer is redoing it’s algorithms for each of them, they may look different. Well they actually do. Up until week ago, you could use one of the betas, where there was an option to solve it by using base sorting by name, without trimming and NOT using auto-sd but scale.
Unfortunately, this beta has expired and all of the new betas will generate different layouts.

Although Andreas responds to issues pretty quick, this one seems to be either tough nut to crack or he is focused on something else. Either way I’m screwed :wink:
I’m looking into different ways of solving the problem.

I’ve got around 30 imagesheets which I generate using ant script, so It’s quite automated.
I will try to generate the sheet and lua file for HD files and then convert it to SD file on my own [imagemagick/automator here we come :)].
I think that by modifying the exporter to multiply all of the values by 0.5 I will be able to get the SD coordinates. Hopefully it will work.
If I get something working I will share. I’ve ran few queries here and there but couldn’t find a working solution. [import]uid: 109453 topic_id: 30336 reply_id: 122507[/import]

Well this is my process:

My hi-res images are @4x resolution (for the new ipad). And I make sure each image’s dimensions are evenly divisible by 4.
In Texture Packer, I import the @4x images and change the border padding and shape padding to 8.
Save it with the @4x suffix.
Then I change the filenames to the @2x suffix, the scale to .5, the border and shape padding to 4.
Save it.
Then I change the filenames to no suffix, the scale to .25, the border and shape padding to 2.
Save it.

I haven’t had any problems after that. [import]uid: 94868 topic_id: 30336 reply_id: 122513[/import]

@ScreamingLoaf:
but how do you load your fles?
If every one of the sheets created has a different layout, you will end up with 3 lua files, every one of them different. What then? [import]uid: 109453 topic_id: 30336 reply_id: 122514[/import]

Wow. I went back to my code and realized I wrote a bunch of code to figure this stuff out. I did this months ago and completely forgot about it until I just looked! lol.

I use a separate lua module to reference all of my images and I use the code below to figure out the correct data from the Texture Packer file. But again all of the data is based on the dimensions of the images in the 1x image, so all of the larger files need to be scaled correctly.

Hopefully that helps you out (and works).

[code]
local function getTPdata(fileName)
–this creates a formatted options table from the Texture Packer data
–Corona uses this for the sprite sheet

local optionTable = {}
optionTable.frames = {}

–get all of the data from the Texture Packer file
local tempTP = require(fileName)
local gotData = tempTP.getSpriteSheetData()
local tempData = gotData.frames

–print(“TEXTURE PACKER FILE:”,fileName)

for j=1,#tempData do

local tempName = tempData[j].name
–My image files all have the @4x.png ending, so this is here to remove it for searching purposes later

local atFind = string.find(tempName,"@")
if atFind then
tempName = string.sub(tempName,1,atFind-1) … “.png”
end

–print(" ",tempName,tempData[j].textureRect.x,tempData[j].textureRect.y,tempData[j].textureRect.width,tempData[j].textureRect.height)
optionTable.frames[#optionTable.frames+1] = { name=tempName,
x=tempData[j].textureRect.x,
y=tempData[j].textureRect.y,
width=tempData[j].textureRect.width,
height=tempData[j].textureRect.height
}
end

gotData = nil
tempData = nil
_G[fileName] = nil

return optionTable
end
–for each sprite sheet you need to setup the options table and define the dimensions of the 1x image file
local options_sprite1 = getTPdata(“sprites_all”)
options_sprite1.sheetContentWidth = 512
options_sprite1.sheetContentHeight = 512

–create the sprite sheet
local sheet_sprite1 = graphics.newImageSheet(“spriteFileName.png”,options_sprite1)

–add the sprite sheet data to a table
–purpose of this is so when you do a search for an image, it is all accessible in this table
local optionSheets = {}
optionSheets[#optionSheets+1] = {options=options_sprite1,sheet=sheet_sprite1}
local function findImage(name)
–this searches the big options table for a sprite with NAME
–returns the sheet the image was found in, frame index,width and height
for k=1,#optionSheets do
local imageTable = optionSheets[k].options.frames

for j=1,#imageTable do
if imageTable[j].name == name then
return optionSheets[k].sheet,j,imageTable[j].width,imageTable[j].height
end
end
end
end
–create your image
–to make use of image dynamic scaling, you have to use display.newImageRect
local tSheet,tFrame,tWidth,tHeight = findImage(imageName)
local imageObject = display.newImageRect(tSheet,tFrame,tWidth,tHeight)

[/code] [import]uid: 94868 topic_id: 30336 reply_id: 122525[/import]

@Screaming Leaf

Thanks for the code! Unfortunately I already have a code to figure out which image file to load. Unfortunately, as you’ve said. In order for this to work is to have all images with the same layout and use 1x coordinates. [import]uid: 109453 topic_id: 30336 reply_id: 122583[/import]

I think Andreas is working on this very problem - it’s the force identical layout option that is disabled in the auto-sd dialog.

For now I just create the highest res imagesheet and lua file then use photoshop to create the other lower res versions and edit the lua file to create the base resolution values (a pain!) [import]uid: 77943 topic_id: 30336 reply_id: 122631[/import]

@danedwar:
edit your exporter and add “* 0.5” after all of the values [or other multiplier you need].
When not using trimming this worked flawlessly for me. Now I’ll test it with trimming, but I think it would be pushing it :wink:

Anyway, just edit your exporter, generate the HD imagesheet and use imagemagick/automator/whatever else [even preview] to create an SD copy of your imagesheet.

Don’t forget to put the * 0.5 to the width and height of your imagesheet values in your exporter! [import]uid: 109453 topic_id: 30336 reply_id: 122632[/import]

I am not exactly sure what you mean by the @2x script, but I believe Corona will always use the data from the initial lua file; In other words if you have a 1x and a 2x file (with the 1x file not actually having the 1x suffix), Corona will base all of the coordinates off of the data in the 1x lua file that TexturePacker produced. So when it uses the images from the @2x sprite sheet, it is basing the height,width,x and y position off of the data in the 1x file. So if the two sprite sheets are not scaled correctly, your @2x images will be off.

So if your maximum resolution images are @2x, you images’ dimensions should be divisible by 2. Otherwise, when it produces the 1x sprite sheet, it will have 1/2 a pixel and it will either round up or down and then your spacing will be off between the two sprite sheets. Also make sure your border padding and shape padding are changed also.

I think I read somewhere that Texture Packer might be addressing the issue or has some additional code (or maybe that is what you were referring to?) Or maybe it is in the beta. No idea and haven’t looked into it.

And not sure about your second problem of the items being scaled up.

[import]uid: 94868 topic_id: 30336 reply_id: 122140[/import]

Nice one! I didn’t think of that :slight_smile:
I’ve been using trimming and it seems to work fine as long as the common divisor is set correctly for the highest res you are using.
[import]uid: 77943 topic_id: 30336 reply_id: 122806[/import]

I’ve just downloaded the latest beta 3.0.0b16 and force identical layout has been added.

Just given it a quick spin and looks like it’s all there and working!! Even sorts out the common divisor for you when you setup your scales in auto sd :slight_smile:

Thanks Andreas! [import]uid: 77943 topic_id: 30336 reply_id: 122810[/import]

Yeah, I’ve given it a try few moments ago. Everything works great, unfortunately the ‘force identical layout’ option was not added as the command line option.
I’ve got so many different imagesheets created, that creating a tps file for each and every one of them would be just a waste of time. Especially if I wanted to change a single thing in all of them later on. [import]uid: 109453 topic_id: 30336 reply_id: 122812[/import]

Whoa, who would have thought I was going to spark such a discussion! he he…

I’m currently worrying about other stuff, but when I get around to it I’ll play around with all things that have been mentioned, see what I can come up with. [import]uid: 136402 topic_id: 30336 reply_id: 122852[/import]

When I say “the @2x script” I talk about the script generated by Texture Packer. For example, if I create a spritesheet called heroanimations, and I use the AutoSD, then i get 4 files.

heroanimations.png
heroanimations.lua
heroanimations@2x.png
heroanimations@2x.lua

What I suspect is that even if Corona loads the higher res sprites, it still uses the original lua script. Causing the coordinates to be wrong and causing the messy animations. I upgraded to Texture Packer beta (that has a reworked AutoSD feature) but the issue is still the same.

I really don’t know what could be wrong here… [import]uid: 136402 topic_id: 30336 reply_id: 122355[/import]

Your expectation is correct.
Corona does load all resolutions using the ‘base’ one.
Unfortunately, because Texture Packer is redoing it’s algorithms for each of them, they may look different. Well they actually do. Up until week ago, you could use one of the betas, where there was an option to solve it by using base sorting by name, without trimming and NOT using auto-sd but scale.
Unfortunately, this beta has expired and all of the new betas will generate different layouts.

Although Andreas responds to issues pretty quick, this one seems to be either tough nut to crack or he is focused on something else. Either way I’m screwed :wink:
I’m looking into different ways of solving the problem.

I’ve got around 30 imagesheets which I generate using ant script, so It’s quite automated.
I will try to generate the sheet and lua file for HD files and then convert it to SD file on my own [imagemagick/automator here we come :)].
I think that by modifying the exporter to multiply all of the values by 0.5 I will be able to get the SD coordinates. Hopefully it will work.
If I get something working I will share. I’ve ran few queries here and there but couldn’t find a working solution. [import]uid: 109453 topic_id: 30336 reply_id: 122507[/import]

Well this is my process:

My hi-res images are @4x resolution (for the new ipad). And I make sure each image’s dimensions are evenly divisible by 4.
In Texture Packer, I import the @4x images and change the border padding and shape padding to 8.
Save it with the @4x suffix.
Then I change the filenames to the @2x suffix, the scale to .5, the border and shape padding to 4.
Save it.
Then I change the filenames to no suffix, the scale to .25, the border and shape padding to 2.
Save it.

I haven’t had any problems after that. [import]uid: 94868 topic_id: 30336 reply_id: 122513[/import]

@ScreamingLoaf:
but how do you load your fles?
If every one of the sheets created has a different layout, you will end up with 3 lua files, every one of them different. What then? [import]uid: 109453 topic_id: 30336 reply_id: 122514[/import]

Wow. I went back to my code and realized I wrote a bunch of code to figure this stuff out. I did this months ago and completely forgot about it until I just looked! lol.

I use a separate lua module to reference all of my images and I use the code below to figure out the correct data from the Texture Packer file. But again all of the data is based on the dimensions of the images in the 1x image, so all of the larger files need to be scaled correctly.

Hopefully that helps you out (and works).

[code]
local function getTPdata(fileName)
–this creates a formatted options table from the Texture Packer data
–Corona uses this for the sprite sheet

local optionTable = {}
optionTable.frames = {}

–get all of the data from the Texture Packer file
local tempTP = require(fileName)
local gotData = tempTP.getSpriteSheetData()
local tempData = gotData.frames

–print(“TEXTURE PACKER FILE:”,fileName)

for j=1,#tempData do

local tempName = tempData[j].name
–My image files all have the @4x.png ending, so this is here to remove it for searching purposes later

local atFind = string.find(tempName,"@")
if atFind then
tempName = string.sub(tempName,1,atFind-1) … “.png”
end

–print(" ",tempName,tempData[j].textureRect.x,tempData[j].textureRect.y,tempData[j].textureRect.width,tempData[j].textureRect.height)
optionTable.frames[#optionTable.frames+1] = { name=tempName,
x=tempData[j].textureRect.x,
y=tempData[j].textureRect.y,
width=tempData[j].textureRect.width,
height=tempData[j].textureRect.height
}
end

gotData = nil
tempData = nil
_G[fileName] = nil

return optionTable
end
–for each sprite sheet you need to setup the options table and define the dimensions of the 1x image file
local options_sprite1 = getTPdata(“sprites_all”)
options_sprite1.sheetContentWidth = 512
options_sprite1.sheetContentHeight = 512

–create the sprite sheet
local sheet_sprite1 = graphics.newImageSheet(“spriteFileName.png”,options_sprite1)

–add the sprite sheet data to a table
–purpose of this is so when you do a search for an image, it is all accessible in this table
local optionSheets = {}
optionSheets[#optionSheets+1] = {options=options_sprite1,sheet=sheet_sprite1}
local function findImage(name)
–this searches the big options table for a sprite with NAME
–returns the sheet the image was found in, frame index,width and height
for k=1,#optionSheets do
local imageTable = optionSheets[k].options.frames

for j=1,#imageTable do
if imageTable[j].name == name then
return optionSheets[k].sheet,j,imageTable[j].width,imageTable[j].height
end
end
end
end
–create your image
–to make use of image dynamic scaling, you have to use display.newImageRect
local tSheet,tFrame,tWidth,tHeight = findImage(imageName)
local imageObject = display.newImageRect(tSheet,tFrame,tWidth,tHeight)

[/code] [import]uid: 94868 topic_id: 30336 reply_id: 122525[/import]

@Screaming Leaf

Thanks for the code! Unfortunately I already have a code to figure out which image file to load. Unfortunately, as you’ve said. In order for this to work is to have all images with the same layout and use 1x coordinates. [import]uid: 109453 topic_id: 30336 reply_id: 122583[/import]

I think Andreas is working on this very problem - it’s the force identical layout option that is disabled in the auto-sd dialog.

For now I just create the highest res imagesheet and lua file then use photoshop to create the other lower res versions and edit the lua file to create the base resolution values (a pain!) [import]uid: 77943 topic_id: 30336 reply_id: 122631[/import]