Issues with Imagesheets/Image Groups/Sprites from build 759+

So far, so good with Build 767… except… :slight_smile:

I’m seeing an issue with slight time “skipping” when using the new “timeScale” feature (and this is a brand-new addition to this API, which might work differently from the old version in the depreciated API).

Basically, as far as I can tell, there is a minor time-based frame skip when the timeScale is switched on the fly. For sake of example, let’s imagine that a sprite sequence has 1000 milliseconds *between* each frame. This is a somewhat unrealistic example; typically a sprite would animate much faster, but I need to illustrate what seems to be happening. Consider the following…

  1. Sprite changes from Frame 1 to Frame 2. Now there are 1000 milliseconds before it switches to Frame 3.
  2. After about 700 milliseconds from this time, the app sets “timeScale” to 2 (so, double the speed).
  3. Normally, 300 milliseconds would remain before the next frame switch, but since the timeScale has doubled, this time should actually be 150 milliseconds.

This is where the new API has a problem, I think… the “delta” time is not being adjusted according to the timeScale. The same happens on reverse action… if the timeScale goes from 2 back to 1, and there are 150 milliseconds before the next swap (at double speed), the swap should be adjusted back to 300 milliseconds. The sprite slows down in speed, thus the time between frames should instantly adjust to this speed too.

Is this possible Jonathan? Can you please ask the engineering team about this? I’m almost positive that the previous timeScale API adhered to the adjusted scale, because I never noticed skipping in my usage of it. Now I see obvious skipping, both in the Simulator and on devices.

Sincerely,
Brent Sorrentino
[import]uid: 9747 topic_id: 23275 reply_id: 93686[/import]

@jonathanbeebe

We need a mapping function for complex imagesheets. The documentation should be update. For more understanding how the mapping of every frame works.

It took me hours to get all my cards working. And it is a mess to calc it.

And for Sprite animations without cropping his all is useless. [import]uid: 86417 topic_id: 23275 reply_id: 94205[/import]

> If you want to switch between frames, you should still use sprites.
> You can either use them for animation or for switching between static frames.

Thanks Walter, but how do we do dynamic scaling (like for the new Retina display) for our animations where we use spritesheets?

At first I had figure that imageSheets would solve this problem, now I begin to understand it’s not the case… as we should still stick to using spritesheets for animations (and that was the whole point I used them for anyways previously).

A big feature request: Can Corona please support dynamic scaling for spritesheets? [import]uid: 10284 topic_id: 23275 reply_id: 94238[/import]

@ Philipp,

We now have dynamic sprite ability, thanks to image sheets. There aren’t really “sprite sheets” anymore with this new system, simply image sheets which are used for both animations and static frame-picked images (or you can still use "newImage()" and "newImageRect()" for single images, if you want… those APIs aren’t going to be depreciated, but the old “sprite.?” library will probably be phased out eventually.

To use dynamic sprite sizes, you define the “1x” size parameters of your entire sheet when you first declare the image sheet. Corona uses these numbers to pick the scaling for “Retina” sprites, according to your config.lua setup. If your base 1x target device is iPad1&2, and you have an image sheet that is 1024x1024 (with several frames for an animation), you just need to double that to 2048x2048 for iPad3… but you must declare the 1x sheet size when you declare your image sheet, using the parameters:

sheetContentWidth = , -- width of original 1x size of entire sheet  
sheetContentHeight = -- height of original 1x size of entire sheet  

Brent Sorrentino
Ignis Design
[import]uid: 9747 topic_id: 23275 reply_id: 94266[/import]

Thanks Brent for the explanation! I’ll start reworking my code tomorrow to make use of this. [import]uid: 10284 topic_id: 23275 reply_id: 94325[/import]

I got a question for Ansca and all of you that are working with tilebased games,

how many tiles have you been successful in creating?

I’m porting a game that on pc uses a grid that is 1000x1000 tiles which feels unachievable (for me at least) to do in Corona. I have no problem in scaling down the size of the game as I was prepared to do that from the start, I would however, like to know what’s been achieved in size when it comes to tilemaps in Corona.

For now I get 30 fps on the simulator using a grid consisting of 400x400 tiles without anything else going on, still, any action and fps drops down way low.

I’m sure there’s plenty of optimizations that I can do but I would still like something to compare to in order to have some sort of goal. [import]uid: 129450 topic_id: 23275 reply_id: 94771[/import]

How many of those tiles are visible on the screen at the same time? I remember Ansca saying as of a recent build they’re not computing the tiles off the screen as before, so that it wouldn’t significantly slow down the program. [import]uid: 10284 topic_id: 23275 reply_id: 94779[/import]

Yes I remember they added culling, the fps doesn’t seem to scale depending on how zoomed in/out I’am though. I.e I have the same fps when I’m viewing one tile as when I’m viewing all 160,000 of them.

Maybe I’m missing something? [import]uid: 129450 topic_id: 23275 reply_id: 94782[/import]

OK, so all in all you got 1000000 tiles at the same time ideally? Would it make sense to do some culling yourself, and only create tiles which are on the screen and its immediate surrounding? And provided you don’t have 1000s of different tiles, you could probably create re-usable display.newSprite(imageSheet) sprites, then just reassign the frame and shift them around the screen dynamically, keeping a constant limited amount of actual objects…

Also keep in mind that the simulator is not the actual speed on the device… the simulator may perform much, much faster than what you’ll end up seeing when you test on, say, iPhone 3G… [import]uid: 10284 topic_id: 23275 reply_id: 94786[/import]

I guess it would, but I don’t have any real experience with culling so I don’t really know its limits. Thing is that the tiles makes up a big topview map that the user is able to scroll freely and my first tought is that the type of culling you’re suggesting won’t allow this. Still I don’t have any experience with it so it’s just at thougt.

This is how I create my map atm

[lua]local spritemap = display.newGroup( )
for x=1,mapW,1 do
local row = display.newImageGroup( imageSheet )
for y=1,mapH,1 do
local tilesprite = display.newSprite( imageSheet, sequenceData )
tilesprite.x = x*60
tilesprite.y = y*60
tilesprite:setFrame( _dirt )
row:insert(tilesprite)
end
spritemap:insert(row)
end[/lua] [import]uid: 129450 topic_id: 23275 reply_id: 94790[/import]

Is there a posibility that in the future we can change the image of an object without having to resort to sprites?

That way we could roll our own, specialized, animation functions amongst other things.

[import]uid: 99737 topic_id: 23275 reply_id: 94793[/import]

That would be nice, Elk. Note you can already do some workarounds and come up with your own way to animate stuff (I did in my framework, mainly because the old spritesheets didn’t support good universal scaling for physics objects), but it will probably include lots of overhead and unnecessary object creation.

It would be nice if there was some memory management and caching too, so that basically we could just create images and have our favorite middleware – Corona! – handle the details! More time caring about game play, less about which image type to use :slight_smile: Anyone wants to post this in the Feature Wish forum? :slight_smile: [import]uid: 10284 topic_id: 23275 reply_id: 94794[/import]

Hi All ( and Ansca ),

I have a question that also relates to tile based maps as well and much as info583, built a demo to try out the new performance improvements and we succeeded in getting a map of 50x50 ( 64x64 px tiles ) tiles and physics per tile, with 70-80 sprites (with physics ) on the map, with full accelerometer control running at 60fps on the sim, and also running at 60fps on device ( iPhone4 ) as well.

This demo was mainly to test how we could apply the technique to the game we are working on. Just to be clear, the tiles are drawn once into an imageGroup, using tile images from an imageSheet. We do not need to animate tiles so this works well for us. I do not cull individual tiles as this performance update should ( as stated ) be doing off screen culling of objects anyway at low level.

This brings us to the game we are working on…

It makes use of Lime and Tiled to get our maps into the game, but as Lime doesnt yet make use of imageGroups, we rolled our own ‘tile drawing into layers’ that Lime would normally do for you with lime:createVisual(), lime:createPhysical(). We also set the map position and clamp it using our code. However to leverage some of lime’s functionality we do set references to our display layers ( imageGroup, displayGroups ) on the corresponding tile layers as Lime sees them ). In making use of an imageGroup for the tiles, we did get performance improvements ( average of 37 fps or less ) but not as we expected. And we noticed something quite interesting…

It should be pointed out that this game is doing player and game object movement, animation, collision ( the landscape has a large physics object attached to it ) and collision response, full headup display, in short, we are doing the usual things in a game loop to make any game playable.

Here is the odd thing… when the map is scrolling ( to keep the player centred on the screen ) we are getting 37fps or worse on device ( iPhone4 ) but when the map cant be scrolled ( its come to map edge, or x, y doesnt change ), the fps jumps to 60fps. And this is with everything else still running as before. Again, we are not doing any culling of tiles or gfx ourselves, just to be clear.

So what I want to know is why scrolling the map is losing us 20fps?

Does anyone have any idea why this should happen?

All I do to scroll is change the x and y ( and rounding it or you get gfx artifacts! ) of the displayGroup holding all the layers [I do not use Lime to do this] Its about the simpliest way you can do it.

Does anyone have any explanation or ideas?

Thanks [import]uid: 112449 topic_id: 23275 reply_id: 95171[/import]

Corona Simulator hangs & dies if you call display.newImage() with a greater index than is defined in the sheet. [import]uid: 70391 topic_id: 23275 reply_id: 95625[/import]

confirmed ! The simulator crashed when you try to call more frames than it the sheet are… [import]uid: 86417 topic_id: 23275 reply_id: 95785[/import]

Hi

Should a display.newImageRect using the new api and an imagesheet display less clearly than a straight display.newImageRect to a single image file?

While using an imageSheet and displaying an imageRect it is displaying really fuzzy for me, on simulator and devices, like half the quality of the exact same frame in a file on it’s own and called as a single image.

Perhaps there is something I’m missing. The full imageSheet, running an animation as a sprite, is also displaying this fuzzy version, while the imageSheet file is sharp and hi-res.

Any ideas much appreciated… [import]uid: 103802 topic_id: 23275 reply_id: 96356[/import]

My guess is that something is missing from your image sheet setup, because my tests have worked properly with image selection. Did you make sure to specify the overall “1x sheet size” (width and height) in the frames data that you pass to "graphics.newImageSheet()"? This is how the new API works along with "newImageRect()", to choose the proper images.

You can find reference to these parameters in the blog “documentation”:

"sheetContentWidth= , sheetContentHeight= "

Brent
[import]uid: 9747 topic_id: 23275 reply_id: 96372[/import]

I’ve run into a strange issue when attaching ImageSheet sprites to that ImageSheet’s ImageGroup. When I call removeSelf on a sprite based off an ImageSheet I expect that sprite to disappear. In the case where the sprite is not a child of an ImageGroup this is the behaviour I see. When the sprite is a child of an ImageGroup, however, the sprite simply stops playing. Below is some code to reproduce the issue, along with the fire.png texture atlas it uses.

The code creates an animated sprite at a random position. After 1 second the sprite removes itself from its display group. If we use the default display group the sprite disappears when it removes itself. If we use the image group, the sprite simply stops animating but is frozen on the screen.

Even more interestingly, if you uncomment the very last line, and set up this sprite creation and destruction as a recurring event, the old sprite disappears when the new one is displayed. I think maybe the image group stops updating if there are no sprites currently animating on it, but I don’t know enough about the Corona internals to be certain.

I’ve seen this in 2012.773-2012.775, I haven’t tried anything earlier.

[lua]local options = {
frames = {
{x = 13, y = 13, width = 12, height = 12},
{x = 13, y = 0, width = 12, height = 12},
{x = 0, y = 13, width = 12, height = 12},
}
}

local fireSequenceInfo = {
name = “fast”,
start = 1,
count = 3,
time = 250,
loopCount = 0,
loopDirection = “bounce”
}

local imageSheet = graphics.newImageSheet(“fire.png”, options) – our fire image sheet
local imageGroup = display.newImageGroup(imageSheet) – our fire image group
local tileSize = 12 – tile size in pixels, for placement on-screen

function createFireSprite()
local fireSprite = display.newSprite(imageSheet, fireSequenceInfo)
imageGroup:insert(fireSprite) – no bug if this line is commented out

fireSprite.x = math.random(100)
fireSprite.y = math.random(100)

fireSprite:play()

local function destroy()
fireSprite:removeSelf()
fireSprite = nil
end

timer.performWithDelay(1000, destroy)
end

createFireSprite()

–timer.performWithDelay(2000, createFireSprite, 0)[/lua]

[import]uid: 131129 topic_id: 23275 reply_id: 97030[/import]

Hi guys,

just wanted to pop a question. Is it possible to format a JSON table so it can “fit” the template required by the new Sprite API frame options?

The problem is that in Sprite API, the “frames” LUA table has no labels (keys) on them, it’s just a simple unordered array. However in JSON all tables need to have that label and when I try to pass the JSON data into the ImageSheet it produces an error.

The workaround I see is taking the JSON table, dismantling it element by element in loops and conditionals and then passing it into a new LUA table. Like this:

[lua]local frameOptions = {};
frameOptions.frames = {};

– convert JSON data to Sprite API frame data format
for index,value in pairs(entity) do
if(index == “sheetContentWidth”) then
frameOptions.sheetContentWidth = value;
end

if(index == “sheetContentHeight”) then
frameOptions.sheetContentHeight = value;
end

if(index == “frames”) then
for index,value in pairs(entity.frames) do
local newFrame = {};
newFrame[“x”] = value.x;
newFrame[“y”] = value.y;
newFrame[“width”] = value.width;
newFrame[“height”] = value.height;
table.insert(frameOptions.frames, newFrame)
end
end
end[/lua]

Looks terribly clunky though and another issue is that inserting frames like this messes up their order. Any ideas?

Thanks! [import]uid: 133145 topic_id: 23275 reply_id: 98736[/import]

@barjed,
I think others also have requested a “label” system to the new imageSheet API, so we could call frames by name instead of index number. This might be upcoming, but currently, it’s not implemented.

I think your looping idea is fine, however. Considering this process should only happen once, when you set up your sprite/image sheets from JSON data, even a “slow” pairs loop wouldn’t be noticeable, performance-wise.

The problem, as you say, is that the pairs loop doesn’t go in any predictable order. So, one solution is this: in addition to your other JSON data, add another element like "frameOptions.numberFrames=20". Before you loop through the individual frames, pre-fill your "frameOptions.frames" table with this number of “blank” tables, using a standard loop. In addition, “label” each frame in your JSON data with an index number (just one more number in addition to x, y, width, and height). Then, when you do the pairs loop, that index number is used to place the frame into the *correct* position. For example, instead of using "table.insert(frameOptions.frames, newFrame)", do this:

frameOptions.frames[indexNumber] = newFrame

Because you already pre-filled the new frames table with 20 “blank” tables, this should insert everything in the proper order, overwriting those blank tables with your specific frame tables containing the x, y, width, and height.

Does this help? I’m sure there are other approaches too, but this is how I’d solve the problem.

Brent
[import]uid: 9747 topic_id: 23275 reply_id: 98786[/import]