Huge Performance Hit when moving touch rapidly. Ideas?

(FYI, running Build 863. Originally thought this was a Lime issue but excised Lime and problem remains)

Simple Project:

  1. A 64x64 tile grid. Each tile pulls from a single image sheet.
  2. A sprite, unanimated, that you can move around using…
  3. An enterFrame function to translate. (Code below)
  4. A touch function to enable the enterFrame function to “go” whenever you touch the screen.

Results:

  1. OSX Simulator (MBA) fine regardless
  2. iPad3 Device Build: seems fine
  3. iPhone4 Device Build: If I touch and hold to a single location, performance rarely drops and is mostly 60fps
  4. iPhone4 Device Build: If I touch and drag slowly (i.e.: arcs, circle) performance cuts down heavily by at least half
  5. iPhone4 Device Build: If I make an eraser-like rapid drag gesture, performance cuts down to single-frames

Code: I’d be ecstatic if this was just user-error on my part. But I’m utterly stumped as to what it could be, so any help would be appreciated…

[code]-- The enterFrame function.
function movePlayer(event)
if not pause then
– If moveDirection is set, the player is already moving…
if player.moveDirection then
– Update progress
player.moveProgress = player.moveProgress - speed
– Continue moving. Impulse is just a table. Speed is always 4px right now
player:translate( impulse[player.moveDirection][1], impulse[player.moveDirection][2] )

– If finished moving…
if player.moveProgress == 0 then

– Clear the movement direction
player.moveDirection = nil
end

– If the player has finished reaching the next tile (or has never moved before)…
else
– Find the best direction to move.
local xDifference = press.x - player.contentBounds.xMin
local yDifference = press.y - player.contentBounds.yMin

local direction

if math.abs(xDifference) > math.abs(yDifference) then

if xDifference < 0 then direction = “left” else direction = “right” end

else

if yDifference > 0 then direction = “down” else direction = “up” end

end

– If a movement direction was found…
if direction then

– Set the player’s direction flag
player.moveDirection = d.direction

– Reset the pixel progress
player.moveProgress = tileSize
player.moveProgress = player.moveProgress - speed

– Begin moving
player:translate( impulse[player.moveDirection][1], impulse[player.moveDirection][2] )
end
end

– If the game is paused but the player still has movement left to reach the tile edge…
elseif player.moveDirection then

– If finished moving…
if player.moveProgress == 0 then

– Clear the movement direction
player.moveDirection = nil

else
– Update progress
player.moveProgress = player.moveProgress - speed

– Continue moving
player:translate( impulse[player.moveDirection][1], impulse[player.moveDirection][2] )
end
end
end --/movePlayer()

– The touch-screen function. Attached to the tilemap.
function pressScreen(event)
– Since movePlayer() runs on enterFrame I need to store where the player is pressing.
press.x, press.y = event.x, event.y

if event.phase == “began” then
pause = false – whenever pause is false, movePlayer() is cranking away…

elseif event.phase == “ended” or event.phase == “cancelled” then
pause = true
end
end --/pressScreen()
[/code]

(Originally, my plan was to use transition.to, but there seems to be no way to link transition.to seamlessly so it doesn’t look like you’re stop-starting on every tile…) [import]uid: 41884 topic_id: 29141 reply_id: 329141[/import]

Ok I may be of zero help here but what the hey.

It would seem to me the slow down is from the translation. It’s the only thing here really doing any work.

How large is the sprite you are moving with moveplayer? I will assume it’s not large but had to ask.

Have you tried capping your moveplayer function to a slower framerate so it’s not running full speed when pause = false?

Have you tried alternatively setting x,y directly instead of using translate? Translate may be bugged in some way on Corona’s end. I know it’s a stretch but you can’t see their code so you have to rule it out. [import]uid: 56820 topic_id: 29141 reply_id: 117237[/import]

Hey, any thoughts are helpful. I literally just spent two days doing nothing but ripping out Lime because I thought that would be the culprit, and when I found out it wasn’t I didn’t really have much in the way of ideas left! (What makes it worse is that this is on-device only.)

  1. The sprite is the same size as the tiles, so 48x48. In the test app I’ve built to fix this problem, the sprite doesn’t even animate - I left that code out. It does pull from an imageSheet, but again, not terribly big.

  2. Just tried and the results are…well visually not pleasing. It masks the effect a but, but it’s still clearly “slower”. At every other frame a single touch looks barely smooth while moving your finger a bit makes it look like the sprite is almost strobing.

(The eraser example I gave is probably a poor one - when your finger is moving rapidly it can be hard to distinguish the framerate elsewhere given the size of the iPhone screen. Instead I recommend just drawing a slow border around the screen with your finger, and then compare that to just touch and hold on a single point - it’s really noticeable.)

  1. Great idea. Obviously I used translate after reading the great sticky post on performance optimization, but it’s worth a shot…

(tries)

Nope. Same thing. :frowning: In fact, you can notice a slingshot effect; just touch and hold on a single location but drag your finger very slightly - it will slow down until your finger stops, at which point it speeds up again.

Will gladly listen to any other ideas… [import]uid: 41884 topic_id: 29141 reply_id: 117243[/import]

First off, I don’t want to make it sound like the forest is on fire or something. The purpose of this thread is (a) find out if there really is a problem with input affecting framerate and (b) find out what expectations should be regarding tiles.

In preparation to submit this as a bug to Corona Labs, I’ve noticed the following:

  1. Reduced tile field from 64x64 (4096 tiles) to 32x32 (1024 tiles)
    This sharply improves performance. It becomes very difficult to notice frame drops at all while moving my finger on the screen.

Unfortunately, 32x32 would be difficult to work with for many projects; the iPhone holds 6.5*10 tiles onscreen at any one time so realistically for a typical small RPG project one would need to write a sector loader/unloader. (Typical RPG world maps are 128x128 or 256x256, seemingly way beyond the performance capacity of the iPhone4 and Corona SDK)

  1. Switch from display.newGroup() to display.newImageGroup() while maintaining 4096 tiles.
    This also improves performance. Frame drops are more subtle but still there; the key sign is an occasional “hitch” where it seems relatively smooth, then jumps a noticeable amount of frames, then keeps smooth again. Most noticeably, drawing circles close to the player seems to cause the most hitch effects in a short timeframe.

Not to be critical, but the problem here is that while performance may be acceptable, once animations, NPCs, sound or extra tile layers are added I expect frame-rate to drop significantly. It’s already on the edge of slowdown, anything else seems likely to push it over the top.

  1. Reduce tile image size from 48x48 to 16x16 (with scaling to make up the difference) while maintaining 4096 tiles within an imageGroup.
    Virtually no improvement over using 48x48 tiles, and it still gets moments where the framerate drops severely. Texture memory is texture memory, I suppose :slight_smile:

  2. Add a native @2x tileset so no scaling is required while maintaining 4096 tiles within an imageGroup.
    Sharp! :slight_smile: There does seem to be some performance impact going to 96x96 tiles though. Still presses are still smooth but moving your finger around noticeably drops the frame-rate, similar to 48x48 with a displayGroup.

Comments : I’m still going to submit this as a bug to our hardworking Corona Labs staff.

a. Why is the problem not noticed on iPad 1-3G, which as far as I know has a lower performance profile and higher resolution than the iPhone 4?
b. Why does the frame-rate improve dramatically when not moving your finger?
c. How do these results compare to internal Corona work re: improving performance that came about with imageSheets and imageGroups?

Some of these questions may simply be a side-effect of how the new culling system works, but it’s impossible to tell without getting it past their eyes. (b) in particular is the one where I want to know if there is some other overhead I’m not considering.

For Lime… I hate to say this, but I’m not sure Lime is usable for anything above 32x32 maps. I think Graham may need to build some kind of loader to offload stress of maintaining the tile field. As it is, tile performance is identical to using my home-cooked 64x64 solution using displayGroups (not imageGroups). For users making side-scrollers, the space afforded at 32x32 is probably just fine - 32x32 stretches out pretty far into a line - but for users making overhead games it’s much more problematic and you may need to consider Zelda-style screen segregation. If Graham resurfaces I may try to work with him on some updates.

[import]uid: 41884 topic_id: 29141 reply_id: 117352[/import]