Framerate drop on iPod Touch 4G when touching and moving

I don’t have a old device, but does this help at all.

-------------------------------------------------------------------------------------------------------- -- Constants -------------------------------------------------------------------------------------------------------- local RADIUS = 400; local OBJECT\_COUNT = 2000; local DEMONSTRATE\_BUG = true; -------------------------------------------------------------------------------------------------------- -- Helper Methods -------------------------------------------------------------------------------------------------------- local function getPointOnRadius(x, y, radius, angle) local a = math.rad(angle) local x = x + radius \* math.cos(a) local y = y + radius \* math.sin(a) return x, y; end local function recurseDisplayObjectsForCount(displayObject) local count = 1; if displayObject.numChildren then for i=1, displayObject.numChildren do local child = displayObject[i]; count = count + recurseDisplayObjectsForCount(child); end end return count; end -------------------------------------------------------------------------------------------------------- -- Variables to calculate delta time and average fps -------------------------------------------------------------------------------------------------------- local lastMillis = system.getTimer(); local millis = 0; local deltaTime = 0; local totalMillis = 0; local totalFrames = 0; -------------------------------------------------------------------------------------------------------- -- Scene initialization -------------------------------------------------------------------------------------------------------- local mainParent = display.newGroup(); mainParent.x = display.contentCenterX; mainParent.y = display.contentCenterY; local useParent = mainParent; for i=1, OBJECT\_COUNT do local angle = (i/OBJECT\_COUNT) \* 360; local square = display.newImageRect("Icon.png", system.ResourceDirectory, 100, 100); square.x, square.y = getPointOnRadius(0, 0, RADIUS + math.random(-100, 100), angle); square.rotation = angle + 45; useParent:insert(square); if DEMONSTRATE\_BUG == true then -- This code assigns a 1/3 chance of either creating a new child group, popping up the display list hierarchy, or staying at the current group object in the hierarchy -- This simply allows us to simulate a complex hierarchy of display objects. local decision = math.random(0, 99); if decision \<= 33 then if useParent ~= mainParent then useParent = useParent.parent; end elseif decision \<= 66 then local newParent = display.newGroup(); useParent:insert(newParent); useParent = newParent; else -- Nothing end end end -------------------------------------------------------------------------------------------------------- -- Update once per frame -------------------------------------------------------------------------------------------------------- Runtime:addEventListener("enterFrame", function (event) -- Find Delta Time millis = event.time - lastMillis; deltaTime = (millis/1000); -- Sumation for average FPS totalMillis = totalMillis + millis; totalFrames = totalFrames + 1; -- A little animation to know the scene is active mainParent.rotation = mainParent.rotation + deltaTime \* 60; -- Store for the next frame's delta time lastMillis = event.time; end); -------------------------------------------------------------------------------------------------------- -- Print the AVERAGE Frame rate and count objects in the scene every second -------------------------------------------------------------------------------------------------------- timer.performWithDelay(1000, function () local avgMillis = totalMillis/totalFrames; local stage = display.getCurrentStage(); local count = recurseDisplayObjectsForCount(stage); print("FPS", (1000/avgMillis), "# OBJECTS:", count); totalFrames = 0; totalMillis = 0; end, -1); local background = display.newRect( display.contentCenterX, display.contentCenterY, display.actualContentWidth, display.actualContentHeight ) background.alpha = 0.00000000001 background:addEventListener( "touch", function ( ) return true end )

Hi, thanks for responding.

I tried the code, when I looked at it, I thought of course! The display object on the top of the display list would receive the event and then return true, preventing further iteration on the display list.

Unfortunately, it does not solve the problem. The framerate remains the same on my HTC Rezound (normal=25-30, on move finger=8-10), and on my BLU DASH JR (which is like an extreme budget phone), I get about 56-60 fps at idle and 25-30 with my finger on the screen moving.

So it would seem that either Corona is still iterating the display list, even after returning true, or there is something else going on within the input/message pump that causes the framerate to drop.

Any other ideas?

Thanks,

Albert

You can try to figure out if device is weak and set the fps to 30
Thier is no exact api to tell if a device is slow or you can make it a switch( the app would have to be reopened). You use https://docs.coronalabs.com/api/library/system/getInfo.html#TOC to get an idea if it is a slow device.
30 fps is ok

Edit; plus a fps snob is not going to be hold a cheap android

Hi, I tested at 30 fps, but the problem is the same. I should add that I’m not using Box2D/physics, so I can really work with variable framerate and devices.

I have not tried this but here you go

edit: just tired does not work

system.deactivate( "touch" )

I optimize a little try this

https://www.dropbox.com/sh/zzxzetckfe816zf/AAC98BEKu6xWdm5fy2eaztkOa?dl=0

edit: for weak devices you do have to make cuts, also try building with a different versions of corona sdk

Hi thanks again.

Unfortunately this only slows the rotation speed of the scene, the “60” just means rotate 60 degrees per second. It does not handle the fact that a single tick in the game loop is slowed. The problem is that my game requires fast reflexes, and while 30 fps is perfectly fine for the game, when the player taps on the screen, there are noticeable delays in response time which makes my game unplayable (see trailer above a few posts)

Logging has shown that it is not in my game code, as I have removed all touch/mouse/tap event handlers and the game still has the brutal lag when touching and moving my finger around on the screen.

I’m hoping the folks at Corona have a few low-end devices that they can try the project on.

you could try just one image instead of loading a thousand images. I have not personal experience any lag but I have not tried older devices to be fair. Did test my big game on my iPhone 3GS and ran fine a month ago. I have test since then.

The sample I provided is only an example that simulates a complex hierarchy of display objects. Take a look at my game play footage a few posts earlier. I can’t use “one image”, the scene is built up using a bunch of display objects in parallax layers.

Edit: Changed Trailer to Game Play Footage

You could make a Sprite sheet animation that looks like that

I would also add, that in my game I believe I am really pushing Corona very hard, so I don’t think this scenario has come up in any testing. 

How would a sprite sheet animation help? The scene is gigantic, there are easily 25 layers that scroll in parallax. The trailer doesn’t completely give it away, but trust me, there is a lot going on. The scene is about 10000 pixels wide and is constructed using a single 2048x2048 tilesheet.

If it this complex how you expect older devices to run it. At the end of the day people with modern devices pay the most. It is nice that you want your folks to play but you should get them a new iPad or a good kindle instead. :slight_smile:

I appreciate your help. The problem here is that the framerate is completely acceptable at 30+ fps on even my worst devices, but once the player touches the screen, even without any touch event listeners (and with a single touch listener that returns true) the framerate drops. 

This is not a matter of me needing to change my scene complexity, this is a matter of determining why the touch events cause the frame rate to drop so drastically in a scene that is otherwise perfectly fine, even on my BLU DASH JR which is really the bottom of the barrel.

Did you run the sample application on your iPhone 3GS? Based on the specs of that device, the problem should be obvious.

How does one explain to customers that the game slows down not because of my game, but because of the underlying game engine? I like Corona for it’s simplicity, and I’m really hoping the root cause is something fixable, as I have a lot of time invested in this.

The bug has been assigned to an engineer. I’m not sure where on his schedule it is to look at.

Rob

Hi Rob,

Thanks for the update, even knowing that it may be looked into is good to hear.

I want to emphasize the problem here, there are two constants at the top:

local OBJECT\_COUNT = 2000; -- \<\< I changed this to 1500 in more recent tests of my own local DEMONSTRATE\_BUG = true;

With my finger on the screen making very fast circles:

  • Setting DEMONSTRATE_BUG = false will cause the scene to run very quickly.
  • With local DEMONSTRATE_BUG = true , the scene will run very poorly

The difference between the settings is that TRUE will create a random (and deep) hierarchy of display objects, and FALSE will create a flattened list of display objects in the “global” stage.

I tried the suggestion from @scottrules44, wherein I added this code to the MAIN.lua:

local background = display.newRect(display.contentCenterX, display.contentCenterY, display.contentWidth, display.contentHeight); background.alpha = 0.1; background:addEventListener("touch", function () return true end);

This seems to make logical sense, in that since “background” is on top of the display list, it should receive the first touch event, and since it always returns true, propagation to the rest of the display list is canceled.

I’ve even tried adding the listener to the Runtime global, and I’ve tried sending “background” to the back of the list to check if Corona was iterating the list backwards or forewards.

-- In case Corona iterates the Display List back-to-front local background = display.newRect(display.contentCenterX, display.contentCenterY, display.contentWidth, display.contentHeight); background.alpha = 0.1; background:addEventListener("touch", function () return true end); background:toBack(); -- In case Corona iterates front-to-back local foreground = display.newRect(display.contentCenterX, display.contentCenterY, display.contentWidth, display.contentHeight); foreground.alpha = 0.1; foreground:addEventListener("touch", function () return true end); -- Try to stop it at the system level Runtime:addEventListener("touch", function () return true; end);

In all cases, I receive frame rate drops when DEMONSTRATE_BUG = true.

On my HTC Rezound (http://www.gsmarena.com/htc_rezound-4099.php):

DEMONSTRATE_BUG = true:

–Idle: 30-33 fps

–Touching: 15-18 fps

DEMONSTRATE_BUG = false:

–Idle: 30-33 fps

–Touching: 26-27 fps

On my BLU DASH JR (http://www.gsmarena.com/blu_dash_jr-5662.php)

DEMONSTRATE_BUG = true:

–Idle: 59-60 fps
–Touching: 54-59 fps

DEMONSTRATE_BUG = false:

–Idle: 59-60 fps

–Touching: 45 fps

Thanks again,

Albert

I had a similar problem (with lots of layers) where panning was slow.  I solved it by only updating the screen if the delta change in x,y was > 5.  This greatly reduced the amount of times the full onTouch event processed.  Might help a bit?