Hi, we had a performance issue with our new game on certain devices.
I've posted about it here:
http://developer.anscamobile.com/forum/2012/01/23/slow-performance-android-30
But as our own investigation progressed we actually found the root cause but we're not sure how to solve it.
The problem is with the number of transparent overlapping images in our game which probably loads the GPU on the device (btw, our texture memory consumption is quite low, less than 10mb)
I've isolated out of our code a small sample that exhibits this issue. Basically this is the theme of our main menu on which you have the play button and also some other buttons that bring up verious popups (options, settings, highscores, etc).
These popups have a semi transparent black background so you can still see the main menu theme through them.
The then is just 50 flakes that are dropping and are moved by an enterFrame event.
Here is the same code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | display.setStatusBar( display.HiddenStatusBar ) real_world_width = display.contentWidth - 2*display.screenOriginX real_world_height = display.contentHeight - 2*display.screenOriginY local centerX, centerY = display.contentWidth * 0.5, display.contentHeight * 0.5 local flakes = {} --array for all the flakes local back = display.newImage("small_back.jpg") back.x, back.y = centerX, centerY back.xScale, back.yScale = 2 * real_world_width / display.contentWidth, 2 * real_world_height / display.contentHeight --FPS bar stuff local prevTime = 0 local curTime = 0 local dt = 0 local fps = 50 local mem = 0 local underlay = display.newRoundedRect(0, 0, 300, 20, 12) underlay.x = 240 underlay.y = 11 underlay:setFillColor(0, 0, 0, 128) local displayInfo = display.newText("FPS: " .. fps .. " - Memory: ".. mem .. "mb", 120, 2, native.systemFontBold, 16) local function updateText() curTime = system.getTimer() dt = curTime - prevTime prevTime = curTime fps = math.floor(1000 / dt) mem = system.getInfo("textureMemoryUsed") / 1000000 --Limit fps range to avoid the "fake" reports if fps > 60 then fps = 60 end displayInfo.text = "FPS: " .. fps .. " - Memory: ".. string.sub(mem, 1, string.len(mem) - 4) .. "mb" underlay:toFront() displayInfo:toFront() end --generate one flake. local function generateFlake() local f = display.newGroup() local randX = math.random(0,display.contentWidth - 40) + display.screenOriginX local dist = math.abs(randX - centerX) local size = 15 + (dist/160) * 25 f.stepSize = size * 0.05 local flakeWhite = display.newImageRect("shiny_white.png", size, size) flakeWhite.alpha = 0.5 f:insert( flakeWhite ) local flakeLightGreen = display.newImageRect("shiny_green_soft.png", size, size) flakeLightGreen.isVisible = false flakeLightGreen.alpha = 0.6 f:insert( flakeLightGreen ) local flakeHardGreen = display.newImageRect("shiny_green_hard.png", size, size) flakeHardGreen.isVisible = false flakeHardGreen.alpha = 0.75 f:insert( flakeHardGreen ) local flakeShinyWhiteOut = display.newImageRect("shiny_white_out.png", size, size) flakeShinyWhiteOut.isVisible = false flakeShinyWhiteOut.alpha = 1 f:insert( flakeShinyWhiteOut ) f.stages = {} f.stages[1]= flakeWhite f.stages[2] = flakeLightGreen f.stages[3] = flakeHardGreen f.stages[4] = flakeShinyWhiteOut f.currStage = 1 f:setReferencePoint( display.TopLeftReferencePoint ) f.x, f.y = randX, 10 function f:toggleStage(idx) for i=1, #f.stages do if i == idx then f.stages[i].isVisible = true else f.stages[i].isVisible = false end end end flakes[#flakes + 1] = f end local function enterFrame( event ) for i=1, #flakes do local f = flakes[i] f.y = f.y + f.stepSize if f.y < 40 then f:toggleStage(1) elseif f.y < 80 then f:toggleStage(2) elseif f.y < 250 then f:toggleStage(3) elseif f.y > 340 then f:toggleStage(4) end if f.y > display.contentHeight then f.y = 10 end end updateText() end --generate the flakes local function startTheme() for x=1, 50 do local dly = math.random(1500, 1600) + 350*x timer.performWithDelay(dly, generateFlake) end Runtime:addEventListener("enterFrame", enterFrame) end startTheme() --generate a new semi transparent rect every 10 seconds local iteration = 1 local function addRect() local rect = display.newRect( 0, 0, real_world_width, real_world_height ) rect:setFillColor( 0, 0, 0, 127 ) rect:setReferencePoint( display.CenterReferencePoint ) rect.x, rect.y = centerX, centerY if iteration <= 10 then timer.performWithDelay( 10000, addRect ) end iteration = iteration + 1 end timer.performWithDelay( 10000, addRect ) |
I'm having exactly the same problem. My game works using Galaxy S2 and Xperia Ray, but it doesn't on Galaxy Tab 10.1.
Did you try it with the build 635? Maybe it's something related with that topic:
developer.anscamobile.com/forum/2011/12/12/performance-degradation-new-public-release
I'm using build 730. giving the older version a try now.
Tried 635 might be a little faster nothing meaningful.. this problem persists in 16bit so its a different thing