btw: what is an offscreen?
c [import]uid: 24 topic_id: 5910 reply_id: 22413[/import]
btw: what is an offscreen?
c [import]uid: 24 topic_id: 5910 reply_id: 22413[/import]
erm… not on screen? Outside of the viewing area. i.e. cannot be seen. [import]uid: 5883 topic_id: 5910 reply_id: 22415[/import]

C [import]uid: 24 topic_id: 5910 reply_id: 22416[/import]
Still +1 [import]uid: 11904 topic_id: 5910 reply_id: 22584[/import]
I wrote some code to handle something very similar to this , but with an array of hi-res images. I found that only 50 or so can be loading before the app will crash due using all memory. And more importantly, even loading 15+ or so on a 2nd gen iPod or 3gsiPhone, cause performance problems.
Would the fix not be possible in Lua ?
[import]uid: 7727 topic_id: 5910 reply_id: 22780[/import]
that’s a completely different matter. loading more resources into memory than the phone has available is obviously going to cause issues [import]uid: 10744 topic_id: 5910 reply_id: 24043[/import]
Any news on this? Average size maps become immediately unplayable on real iphone hw. [import]uid: 10482 topic_id: 5910 reply_id: 25489[/import]
I haven’t heard anything back since I sent over the Lime Viewer app, I’m taking this to mean they are all too busy working on it to look up from their monitors
[import]uid: 5833 topic_id: 5910 reply_id: 25490[/import]
Sorry but i totally disagree that this should be implemented.
Of screen culling would have to be done in a generic way in corona to support all the various scenarios that different games would expose. And i think no matter the implementation no one will be totally happy.
If you want/need off screen culling it can be achieved programatically, and you can optimise what you do for the exact situation you have.
Lime should be able to implement its own off screen culling really easily. Its based on fixed size tiles etc, so when you move a set, just check if its on or off screen and disable its visibility.
I’m surprised Lime doesn’t do this already. I designed a simple tile based puzzle game without using lime (because i heard of the performance issues) and do exactly that, detect the new position of the tiles and remove them or disable their visibility.
I just think these kind of ‘generic’ things shouldn’t be done inside corona. Although it would make your game faster than if you don’t bother to do any culling yourself, it would make other games slower where you could do more efficient culling programatically.
The solution to your problem is already there, you really don’ need or want corona to fix it for you. Trust me! [import]uid: 8872 topic_id: 5910 reply_id: 25506[/import]
kam187, the problem is that we dont have low level access to the rendering pipeline, and operations in Lua are slower as it’s interpreted not compiled.
even reading x/y properties from a display object is slow
http://developer.anscamobile.com/forum/2010/11/13/performance-tip-setting-isvisiblefalse-slow-reading-display-object-xy-slow
i don’t see why it would be a problem having an implementation at low level that removed objects from the rendering pipeline if they are not on screen. what projects can you suggest this would affect negatively? I dont understand why it doesnt suit all scenarios. If they’re not onscreen they dont need to be rendered surely? Or is it to do with texture caching? (ie is it quicker to remove a static display group once it is cached in memory,than it is to add/remove elements from a screen sized area?)
a couple of other questions:
thanks for any comments
j [import]uid: 6645 topic_id: 5910 reply_id: 26397[/import]
Alright I finally got around to testing out the tilemap performance in Corona and writing my own visibility culling sample. I’ve been meaning to do this for almost a month when I first saw some people chirping about this problem.
In summation, I made a map with 1600 tiles at 64x64 pixels per tile, and I optimized the code so that the map scrolls around easily on my iPhone 3Gs.
–
First off, I tried displaying a big tilemap (like 40x40) without making any attempt to optimize things just to see how it performs; I hadn’t tried that before so I wanted to see for myself. As you all are pointing out, it performs like a pig. At first I was confused what the complaints were about because it seemed fine in the simulator, but then I tried it on device and it was terrible.
So then I whipped up a modified version of my hitTestObjects function from Code Exchange to use for visibility culling. The modification was to simply check the screen boundaries instead of the boundaries of any specific display object.
Then I tried looping through all the tiles to check visibility. That helped a little but it was still chugging badly, so I needed to optimize the code further.
I split up the map into 8x8 quadrants and checked visibility for those quadrants instead of the individual tiles. That really boosted performance and I got up to 1600 tiles (40x40) with performance that was still pretty good. The reason this ran faster is that instead of calling isVisible() 1600 times I only had to call it 25 times.
If I wanted an even bigger map I could optimize further, probably by nesting quadrants within quadrants to reduce the number of calls to isVisible(), but 1600 tiles was already plenty for me to demonstrate this approach. Setting up the quadrants procedurally for a tool like Lime could be tricky, but the basic idea isn’t that complicated.
Here’s the code and tileset for my sample (incidentally, if you want to see how it performs without the culling, just delete the first dash in the line “—visibility culling optimized w/quadrants”):
local function isVisible(obj)
local screen = display.getCurrentStage().contentBounds
local bounds = obj.contentBounds
local left = bounds.xMin \<= screen.xMin and bounds.xMax \> screen.xMin
local right = bounds.xMin \>= screen.xMin and bounds.xMin \<= screen.xMax
local up = bounds.yMin \<= screen.yMin and bounds.yMax \>= screen.yMin
local down = bounds.yMin \>= screen.yMin and bounds.yMin \<= screen.yMax
return (left or right) and (up or down)
end
--tiles are 64x64 in 576x1216 image for 9x19=171 tiles
local sprite = require("sprite")
local tileSheet = sprite.newSpriteSheet("tiles.png", 64, 64)
local tileSet = sprite.newSpriteSet(tileSheet, 1, 171)
--init random function
local randomseed = math.randomseed
local random = math.random
local time = os.time
randomseed(time())
random() --bug in first use
--setup tile map w/quadrants
local map = display.newGroup()
for i = -2, 2 do
for j = -2, 2 do
local quad = display.newGroup()
quad.x = i \* 512
quad.y = j \* 512
map:insert(quad)
--tiles in quadrant
for i = 0, 7 do
for j = 0, 7 do
local tile = sprite.newSprite(tileSet)
tile.currentFrame = random(171)
tile.x = i \* 64
tile.y = j \* 64
quad:insert(tile)
end
end
end
end
--move tile map
local prevX, prevY
local function drag(event)
if event.phase == "began" then
prevX = event.x
prevY = event.y
elseif event.phase == "moved" then
local dX = event.x - prevX
local dY = event.y - prevY
map.x = map.x + dX
map.y = map.y + dY
prevX = event.x
prevY = event.y
---[[visibility culling optimized w/quadrants
for i = 1, map.numChildren do
if isVisible(map[i]) then
map[i].isVisible = true
else
map[i].isVisible = false
end
end
--]]
end
end
map:addEventListener("touch", drag)

ADDITION: hm maybe I should repost this in one the publicly viewable areas, instead of subscribers only. [import]uid: 12108 topic_id: 5910 reply_id: 26391[/import]
ps if anyone’s having trouble getting that example working, the image attached has been downsized so the tiles you need to use are 41x41 and the quadrant is (41*8) rather than 512 (64*8)
making those tweaks to the code above makes it work fine [import]uid: 6645 topic_id: 5910 reply_id: 26448[/import]
1) does physics still work ok when the objects are in quad display groups?
Probably not, since physics are isolated to within a group. I haven’t actually tested that though.
there’s no need to check quads that are 100 screens away, or even 10 screens away… it’s just slowing down the processor
You are correct, and that’s why I noted that I could make the tilemap even bigger with further optimizations.
(thanks for the example though jhocking)
I just updated the example, check it out. This morning I found that simply organizing the tilemap into quadrants without doing any culling boosted performance a lot, making the whole culling aspect redundant for small quadrants. This meant I could increase the number of tiles in each quadrant without really changing the number of quadrants, resulting in a much larger overall tilemap.
It turns out that the cost of checking visibility for a quadrant is greater than the overdraw from large quadrants. Also, the cost of changing visibility on a quadrant is much much less than the summed costs of changing visibility for all the tiles in that quadrant. Both these facts favor a small number of large quadrants. Also, in retrospect both these facts make sense because OpenGL tends to favor a small number of complex objects.
This is just one example of how I could spend a long time tweaking this code to optimize further, but I just wanted to convey the general idea. [import]uid: 12108 topic_id: 5910 reply_id: 26446[/import]
doh I didn’t mean to downsize the image, that must be because I posted it on Photobucket. I’ll see if I can repost the image at the correct size. Thanks for figuring that out. [import]uid: 12108 topic_id: 5910 reply_id: 26449[/import]
try changing it to [lua]for i = -2, 200 do[/lua] though . how do you optimize for that?
i still think this is a low level issue.
i don’t know what slows it down at this point. theoretically the rendering is just sprite batch draws, but my guess is it’s still trying to draw the whole lot (someone at ansca said culling wasnt optimized). drawing the whole lot if its 200 screens wide means there are a lot of wasted roundtrips to the GPU i’m sure.
like i said without knowing how the render process works, we can’t really speculate anyway.
However I’d be keen to know if there is a solution available at the moment using your method… i just found anything i tried to be too slow.
[import]uid: 6645 topic_id: 5910 reply_id: 26450[/import]
ok, yes. 200 bad example. and for something that big i was more probably more thinking of 1 way scrollers which would be implemented more simply anyway, as you already know the tiles going off left can be disposed or whatever, and where the next tiles will come from
really i’m thinking more of games like Monkey Flight, Lucky Coins etc…
http://www.youtube.com/watch?v=1rFzUd5TOaQ
http://www.youtube.com/watch?v=ssqYe2eWQ8I
i think these have about a 10-screen sized map max
but i think it needs better low level culling of off-screen physics objects in order to optimize this. maybe your techniques are possible but i’m not sure the quad approach works with physics at the moment [import]uid: 6645 topic_id: 5910 reply_id: 26457[/import]
i still think this is a low level issue.
I’m not arguing that it couldn’t be improved at a low level, but I was showing how to attack this problem with the tools we currently have at our disposal. Making feature requests is fine and all, but I don’t want anyone actually giving up when it’s not that hard to roll your own system.
try changing it to for i = -2, 200 do though . how do you optimize for that?
Well you could try a quadtree approach like you had mentioned (quadrants nested within quadrants) but ultimately I’m wondering how practical this situation is anyway. I mean, you’re talking about a map that’s over 1600 tiles on a side (if that were a square map then it’s over 2,560,000 tiles.)
Once you’re talking about maps that big, maybe you should just plain redesign your game. Sorry if that seems like a cheeky response, but there’s a reason most games limit the play area into separate levels with loading screens between the levels. Once you have really ginormous maps the bottleneck is more about bandwidth for data delivery and not the rendering performance. Games that don’t have load screens between limited levels are doing all kinds of stuff under the hood to stream the data on the fly.
ADDITION: While following links you posted here I found my way to this thread:
http://developer.anscamobile.com/forum/2010/12/11/another-scrolling-performance-test
The approach you take there is basically the same thing as these quadrants I have going on, except that setting the visibility of a display group is much faster than setting the visibility of each tile within the group. You were on the right track. [import]uid: 12108 topic_id: 5910 reply_id: 26452[/import]
Haven’t seen those games before, Monkey Flight looks similar to the demo that comes with cocos2D. Well the first thing I’d do is separate the physics objects from everything else. I mean, the only objects that actually have physics on them is the monkey and the ground. I don’t know if it’s more efficient to do the yaks with sensors or simply checking for objects overlapping, I’d have to test that.
There’s the thing, it’s not like I know off the top of my head how exactly to do that but I can think of plenty of techniques to try and optimize things. Pushing the envelope takes experimentation, and depending on how experienced you are the envelope may be pretty small. It’s like with my current game: I’d never used Corona before so the first approach I tried didn’t work, then I tried something else and that did work. [import]uid: 12108 topic_id: 5910 reply_id: 26583[/import]
a challenger appears!
http://developer.anscamobile.com/forum/2011/01/29/object-culling-render-process-when-not-content-area#comment-26658 [import]uid: 12108 topic_id: 5910 reply_id: 26666[/import]