Memory optimisation for tiled graphics

Hello again,

I’m almost done building a game that has a tile based level structure. Some of our levels are quite big, like 48x48 tiles, and the game is slowing down dramatically during those levels. We’re talking about 700 in system memory.

As the player cannot touch any of the surfaces in the game, the tiles have to be physics objects, in order to enable collision detection. I’ve seen some algorithms out there for doing collision without physics, but only for squares, rectangles and circles. I need it for polygon shapes as well.

I’m currently doing some partial rendering, where every display object not in view is hidden and their animations are stopped, but the game is still sucking too much juice.

So my question is, do any of you know of effective ways to reduce memory usage on tile based levels? Maybe even a collision detection method that I’ve missed?

Thanks in advance [import]uid: 117153 topic_id: 26135 reply_id: 326135[/import]

(if you haven’t already):

Set any tile bodies that are off screen to be inactive ie: myTile.isBodyActive = false

That should help a lot [import]uid: 84637 topic_id: 26135 reply_id: 105897[/import]

Ooh, that sounds like a plan :slight_smile: Thanks.

However, I am currently using the physics engine to determine whether an object is in view or not ( I know, it sounds pretty heavy ). I can’t find any mention on how to do it in these forums or indeed any lua documentation I’ve come across.

Would I have to do something like:
[lua]local function checkView ()
for i, o in pairs ( allObjects ) do
– if “o” is in view
o.isVisible = true
– else
o.isVisible = false
end
end

Runtime : addEventListener ( “enterFrame”, checkView )[/lua]

Because I tried that earlier, and it took up even more memory. Is there something clever that I have overlooked?

EDIT:
All right, I tried that, and it actually seems to improve performance. I have a lot of display objects to deal with though, so it still gets laggy sometimes. I guess we’ll have to redo some levels to account for that.

Here’s the code, in case anyone wants to know:
[lua]checkObjects = function ()
local w = display.viewableContentWidth * 0.75
local h = display.viewableContentHeight * 0.75
local p = lvlGroup.player

local checkIt = function ( o )
if o.x < ( p.x + w ) and o.x > ( p.x - w ) and o.y < ( p.y + h ) and o.y > ( p.y - h ) then
o.isVisible = true

if o.animating == false and not o.objectType == “player” then
o : prepare ( o.sequence )
o : play ()
end

o.isBodyActive = true

else
o.isVisible = false

if o.animating then
o : pause ()
end

o.isBodyActive = false

end
end

local iterate = function ()
for i, o in pairs ( lvlGroup.tiles ) do
checkIt ( o )
end

for i, o in pairs ( lvlGroup.items ) do
checkIt ( o )
end

for i, o in pairs ( lvlGroup.env ) do
checkIt ( o )
end

for i, o in pairs ( lvlGroup.npcs ) do
checkIt ( o )
end

for i, o in pairs ( lvlGroup.doors ) do
checkIt ( o )
end

for i, o in pairs ( lvlGroup.switches ) do
checkIt ( o )
end

for i, o in pairs ( lvlGroup.overlays ) do
checkIt ( o )
end

for i, o in pairs ( lvlGroup.propellers ) do
checkIt ( o )
end

for i, o in pairs ( lvlGroup.reversers ) do
checkIt ( o )
end

checkIt ( lvlGroup.goal )
end

iterate ()
end[/lua]

A timer is calling that function every 500 ms [import]uid: 117153 topic_id: 26135 reply_id: 105988[/import]

You can optimize that a bit more:

(untested code)

local \_pairs = pairs  
  
local w = display.viewableContentWidth \* 0.75  
local h = display.viewableContentHeight \* 0.75  
  
checkObjects = function ()  
  
 local p = lvlGroup.player  
   
 local checkIt = function ( o )  
 if o.x \< ( p.x + w ) and o.x \> ( p.x - w ) and o.y \< ( p.y + h ) and o.y \> ( p.y - h ) then  
 o.isVisible = true  
  
 if o.animating == false and not o.objectType == "player" then  
 o: prepare( o.sequence )  
 o: play()  
 end  
  
 o.isBodyActive = true  
  
 else  
 o.isVisible = false  
  
 if o.animating then  
 o : pause ()  
 end  
  
 o.isBodyActive = false  
  
 end  
 end  
   
 local iterate = function ()  
 for i, o in \_pairs ( lvlGroup.tiles ) do  
 local tiles = lvlGroup.tiles[o]  
 checkIt ( tiles )  
 end  
  
 for i, o in \_pairs ( lvlGroup.items ) do  
 local items = lvlGroup.items[o]  
 checkIt ( items )  
 end  
  
 for i, o in \_pairs ( lvlGroup.env ) do  
 local env = lvlGroup.env[o]  
 checkIt ( env )  
 end  
  
 for i, o in \_pairs ( lvlGroup.npcs ) do  
 local npcs = lvlGroup.npcs[o]  
 checkIt ( npcs )  
 end  
  
 for i, o in \_pairs ( lvlGroup.doors ) do  
 local doors = lvlGroup.doors[o]  
 checkIt ( doors )  
 end  
  
 for i, o in \_pairs ( lvlGroup.switches ) do  
 local switches = lvlGroup.switches[o]  
 checkIt ( switches )  
 end  
  
 for i, o in \_pairs ( lvlGroup.overlays ) do  
 local overlays = lvlGroup.overlays[o]  
 checkIt ( overlays )  
 end  
  
 for i, o in \_pairs ( lvlGroup.propellers ) do  
 local propellers = lvlGroup.propellers[o]  
 checkIt ( propellers )  
 end  
  
 for i, o in \_pairs ( lvlGroup.reversers ) do  
 local reversers = lvlGroup.reversers[o]  
 checkIt ( reversers )  
 end  
  
 checkIt ( lvlGroup.goal )  
 end  
   
 iterate ()  
end  

I would suggest though you might save a lot of cpu cycles by instead of checking if the object has left the screen via comparing pixel coordinates every frame/x number of seconds, you do this :

  1. Set up a dynamic sensor body that is the full size of the screen
  2. Set it’s linear damping high so it doesn’t move
  3. In your collision handlers ended phase, check if an object has no longer collided with the rectangle, if so, set it invisible. [import]uid: 84637 topic_id: 26135 reply_id: 106066[/import]

Yeah, that’s what I did previously, but I just thought it wouldn’t work when disabling the physics objects. Like, if they’re inactive, how would they know when they collided with the dynamic sensor body? :slight_smile:

But I guess I should have tried that out before making assumptions. Thanks a lot, Danny. That’s really helpful. [import]uid: 117153 topic_id: 26135 reply_id: 106246[/import]

Ok, I tested it out, and it’s as I expected. When the object re-enters the dynamic sensor body, it doesn’t show up, because the physics body of the object is not active. Danny, is there anything else that can be done this way?

EDIT: I saw that someone marked this as “resolved”, but I still found no solution to optimise the performance beyond what I had already done. I’d still like a way to deactivate unused physics objects :slight_smile: [import]uid: 117153 topic_id: 26135 reply_id: 106472[/import]