Game Running Slow on Android

Hello. I am developing a platforming game that uses a simple tile engine to display the level graphics.

The game is set to run at 60 fps. The game runs fine in the simulator and on apple ipad, but when I test it on android devices, it runs very slow when the game level starts. all objects are very sluggish.

The adroid devices I am testing are the Nexus 7, and Samsung Galaxy S4

After some testing, I found that the slow down was connected to the tile graphics that were generated when a level begins. The more tiles that were built, the slower it ran.

The game resolution is 480 x 320. The tile grid is 30 x 20. Each tile is 16 x 16 pixels @1x. The image sheet they are made from is 64 x 64 pixels @1x.

I have two tables of tiles, so thats 600 tiles each, 1200 in total on screen at once.

The player character’s collision detection is not tied to these graphics.

Hello Chris,

Are these tiles physics objects? You stated that they’re not tied to the collision detection, but are they physics objects at all? In either case, are you moving these tiles, and if so, how?

Best regards,

Brent

Hi.

The tiles are not physics objects.

They do not move. their position is static.

Hi Chris,

Does the slow-down only happen initially, when the level loads, or is overall performance impacted throughout the app running? If you simplify this project down to only the rendering of the tiles, does the same thing occur?

Brent

The slow down occurs when the level is loaded. As far as I know only the level gameplay is affected. The loading while navigating the title screen and level select before and after seem fine without any delay.

I have tried rendering only the player character and the level tiles, and it was slow.

I have tried removing all the tiles so that only the player character and the collectable items are rendered, and it runs fast.

Hi Chris,

We probably need to see your code on how these images are being loaded/placed. Simply loading an image sheet and placing down frames from it shouldn’t be causing a noticeable lag, but we’ll have to inspect further.

Brent

Okay. Here is a sample of how the images are being loaded.

tileegine class:
[lua]
local tileengine = {}
tileengine.layerA = {}
tileengine.layerB = {}

tileengine.buildLayer = function (layerName, imageSheet, sequences, sequenceName)
    local tileNumber = table tile number
    local xP = table tile x
    local yP = table tile y
    table.insert(layerName, display.newSprite(imageSheet, sequences))
    layerName[#layerName]:setSequence(sequenceName[tileNumber])
    layerName[#layerName]:play()
    layerName[#layerName].x = xP
    layerName[#layerName].y = yP
end
return tileengine
[/lua]

tiledata class:
[lua]
local options = {width = 16, height = 16, numFrames = 16, border = 0, sheetContentWidth = 64, sheetContentHeight = 64}

local tiledata = {
        sequenceNames = {“a”},
        sequences = {{name=“a”, frames={1}, time=1000, loopCount=1}},
        imageSheet = graphics.newImageSheet(“img/imageSheet.png”,  options)           
}
return tiledata
[/lua]

main class:
[lua]
local tileengine = require(“tileengine”)
local tiledata = require(“tiledata”)

local Main = {}
local buildLevel = {}

function Main()
        buildLevel()
end

function buildLevel()
    tileengine.buildLayer(tileengine.layerA, tiledata[“imageSheet”], tiledata[“sequences”], tiledata[“sequenceNames”])
    tileengine.buildLayer(tileengine.layerB, tiledata[“imageSheet”], tiledata[“sequences”], tiledata[“sequenceNames”])
end

Main()
[/lua]

Hi Chris,

As I initially review this code, am I correct that you’re animating 1200 sprites at the same time? This might be a performance issue in itself. Another thing you should probably do is create the sprite (in the buildLayer function) as a local object, then insert it into “layerName” using the “layerName[#layerName+1]” operation, instead of “table.insert()”. The latter is a notoriously slow Lua function, especially when performed in a huge loop as you’re doing. Changing it to what I suggest might not improve things vastly, but it could help somewhat.

Brent

Currently the images being created are sprites, but they were originally still images from an image sheet and the game was equally slow.

I will try your suggestion tomorrow.

Okay. I changed the tile generation part in the tile engine to:

[lua]

local tileimg

tileimg = display.newSprite(imageSheet, sequences)
tileimg.x = xP
tileimg.y = yP                         
tileimg:setSequence(sequenceName[tileNumber])
tileimg:play()

layerName[#layerName+1] = tileimg

[/lua]

Is this correct? It displayed the tiles properly in the simulator.

Hi Chris,

Yes, this looks correct. Any difference in the speed of output?

No. there was no change in speed.

Hi Chris,

How slow are we talking here? How many seconds to load/generate the tiles on the Android devices?

Brent

I don’t want to derail, but have you marked the performance levels when loading simple newRects instead of sprites? If you don’t have a performance meter running, here’s the github to the the modified version of Lerg’s version for Corona.

To Brent,

The actual time it takes to build the level as soon as the button is pressed is almost instant even on android. There may have been half a second delay for android, but it was barely noticable.

My main concern is that the more tiles are built in the level, the slower the gameplay runs The player character, the player projectiles, and all sprite animation runs slow.

The difference in speed of android gameplay looks like it runs closer to 25-30 fps instead of 60 fps.

To Alex,

I haven’t tried that but I’ll give it a shot. I was originally using display.newImage from an image sheet before I made them sprites and it ran just as slow. I just tried using display.newImageRect from an image sheet, and it runs just as slow.

I’ve run into a similar issue with image sheets and display.newImageRect on Android.  The problem for me happens when the app is suspended and then resumed (either showing an ad or manually exiting and reopening the app).  When a suspend/resume happens, apparently it messes up the amount of time for display.newImageRect to work.  Potentially having to reload the image sheet all over again?  (although I’m not releasing it ever)

These steps reproduce my problem (and possibly Chris’s):

  1. Load image sheet  (note: generated from Texture Packer)

  2. App suspend

  3. App resume

  4. Attempt to display.newImageRect on something in the image sheet.  -> SLOW 

On this forum topic that I posted:

http://forums.coronalabs.com/topic/50667-composer-scenes-and-interstitial-advertisements-on-android-slowness/

It was suggested that I break up my image sheet into several smaller image sheets.  That didn’t have any difference in loading times either.  iOS, it’s running fluidly.  

@ Brent , can you recreate my problem as described above?  

Hi @codprod.llc,

What you’re seeing is a limitation of Android. When you suspend an app, all of the textures are discarded from memory, so when you resume the app, it must re-load all of the textures again, as if they were never loaded to begin with. This is why it’s taking longer on Android. This is not an issue on iOS, hence no performance issue on that platform.

Brent

Hello Chris,

Are these tiles physics objects? You stated that they’re not tied to the collision detection, but are they physics objects at all? In either case, are you moving these tiles, and if so, how?

Best regards,

Brent

Hi.

The tiles are not physics objects.

They do not move. their position is static.

Hi Chris,

Does the slow-down only happen initially, when the level loads, or is overall performance impacted throughout the app running? If you simplify this project down to only the rendering of the tiles, does the same thing occur?

Brent