Initializing groups as "layers" ?

Greetings all,

I’m new to Corona/Lua and I’m learning the ropes, so this might be a novice question.

I see that Corona doesn’t support “layers” per se, in terms of rendering objects in the z-index relation of each other. However, in my very brief testing so far, it appears that those objects added to the screen later (as in, further down in the code, or initiated by a function during runtime) are placed in front of those objects that were added to the screen earlier. Is this correct?

If so, can I use Groups to initialize a master “layer” setup as the game begins, and add/subtract objects from them as necessary?

Here’s my theoretical example: upon runtime, before any objects are added to the screen, some groups are set up.

local distant\_background\_Group = display.newGroup() local closer\_background\_Group = display.newGroup() local main\_Group = display.newGroup() local clouds\_Group = display.newGroup()

Initially, no objects are added to any group, although I suppose they could be in this step. More importantly, the groups are initialized to determine their “layer” order. If I’m correct (quite possibly I’m not), those 4 groups would be in a relational z-index to each other, with the “clouds” group in the very front because it was initialized last, and the “distant_background” group in the very back because it was initialized first.

If this practice will work properly – and please correct me if it won’t – will objects added to the scene later, if sorted into the proper group, be rendered in the respective layer? For example, if I use a function to spawn a new object, and I set the parent group to “clouds_Group” within display.newImageRect(), will that object be sorted into the clouds layer, and thus appear in front of all objects contained within “layers” further back, regardless of when they were added to the screen? If I then add a new object to “main_Group”, will it appear behind the clouds, even if some cloud images were added much earlier in game time?

Basically I’m trying to determine a layer management system, without actually having layer functionality. :slight_smile: I’m sure other Corona users have tackled and solved this issue, so please give me your advice. Thank you!

Brent
[import]uid: 9747 topic_id: 2542 reply_id: 302542[/import]

Welcome Brent!

Short answer is yes.

Sprites in a group get displayed in the order they inserted (last inserted=top in screen)
Groups in the stage do also respect the rule above.

I suppose that *for each frame* the first group created/inserted (whenever) in the stage is firstly get drawn, and this procedure starts with the first sprite inserted (whenever) in the group.

So, yes! A new cloud will always get drawn on top of a hill, even if the hill gets inserted in distant background group after the cloud got inserted in clouds group.

Is this what you exactly want to know?

Regards [import]uid: 7356 topic_id: 2542 reply_id: 7326[/import]

Yes, thank you Magenda! That’s exactly the issue I wanted to solve: a solution for creating a global “sorting” of images/objects, such that everything stays in its proper visual layer, regardless of when it’s added to the game. I’ll test the entire scenario soon within the SDK.

Best regards,
Brent
[import]uid: 9747 topic_id: 2542 reply_id: 7327[/import]

Don’t forget you can easily move objects and groups in the Z order. One simple way to bring something to the front is:

object.parent:insert(object)

The parent may be the stage or a group. Calling insert removes it from wherever it was and puts it at the end of the insert list of that particular parent. Or you can call insert and provide an index of where it is to be put in the display order.

Here’s another way to move things around reasonably intuitively. Just attach a field to the object that denotes depth and set that when required. Then sort the objects based on that. We track our images by keeping them in a table, but they’re also in a group. Example:

local function zSort()  
  
 table.sort(myImages,   
 function(a, b)  
 return a.depth \< b.depth -- depth is your custom field  
 end  
 )  
 for i = 1, #myImages do  
 myGroup:insert(myImages[i])  
 end  
  
end  

This can be pretty handy. [import]uid: 3953 topic_id: 2542 reply_id: 7868[/import]

Hi IgnisDesign,

quite there but not totally.

>>Initially, no objects are added to any group

This is not true as there is always the default group which is called STAGE. Every object you create is first inserted into this group.

The rule to render is the following:

Each group is rendered in their order of creation. Inside the group, objects are rendered in their order of their group index. When you take this behaviour into account, then you will see groups as layers.

So lets say you do this:

[lua]firstGroup = display.newGroup()
secondGroup = display.newGroup()

firstObject = display.newImage(“Image1.png”,160,160)
firstGroup:insert(firstObject)

secondObject = display.newImage(“Image2.png”,160,160)
thirdObject = display.newImage(“Image3.png”,160,160)[/lua]

The order of rendering will be now:

Stage  
 |  
 -secondObject  
 -thirdObject  
firstGroup  
 |  
 -firstObject  
secondGroup  
 |  

As you can see, the first Object is drawn on top of the others because the others are still in the stage group.

Now we do this:

[lua]secondGroup:insert(secondObject)[/lua]

The order of rendering will be now:

Stage  
 |  
 -thirdObject  
firstGroup  
 |  
 -firstObject  
secondGroup  
 |  
 -secondObject  

Next:

[lua]firstGroup:insert(thirdObject)[/lua]

The order of rendering will be now:

Stage  
 |  
firstGroup  
 |  
 -firstObject  
 -thirdObject  
secondGroup  
 |  
 -secondObject  

The parent of an object is always a group. First it is the stage group till you add it to a different group. At anytime you can insert an object into a different group and an object will always be just in ONE group at any time.

Cheers
Michael Hartlef

http://www.whiteskygames.com
http://www.twitter.com/mhartlef
[import]uid: 5712 topic_id: 2542 reply_id: 7929[/import]

Hi Guys.

I’m having trouble wrapping my head around groups. Apologies in advance in my questions are really simple.

I’ve set up two functions which each place a number of *.png files into different tables, (one table for each function) and spawn a random object to display on screen.

Currently, every time an object is spawned it’s drawn on top of everything else.

Is it possible to add the contents of each table to a group, so that every object in the first group is always drawn on top of the second, regardless of when it is spawned?

Also, is it possible to add an object to a group from within a function? I setup a group using:

local bground01=display.newGroup()

Then within my function I use: bground01:insert(back1)

Which gives the following error:

Bad argument #-2 to ‘insert’ (Proxy expected, got nil)

Is it a syntax error or can you not add to a group within a function? Is there a simpler way to add a whole table to a group?

Any help would be appreciated guys. I’m pulling my hair out, and I don’t have a lot left as it is!

Thanks

Dan [import]uid: 67933 topic_id: 2542 reply_id: 45090[/import]

I’ve modified the above code to order items inside a group based on a field, “layer”, added to each element.

I had to “copy” the group children to a new temporary table to sort them. I’m not sure this is really necessary, so correct this code if you can!

[code]
– Order objects in a display group by the “layer” field of each object
– This allows for ordered layering inside a group.
function zSort(myGroup)

local n = myGroup.numChildren
local kids = {}
for i=1,n do
kids[i] = myGroup[i]
end

table.sort(kids,
function(a, b)
return (a.layer or 1) < (b.layer or 1) – “layer” is your custom z-index field
end
)

for i = 1,n do
myGroup:insert(kids[i])
end
return myGroup
end


– g is a display group
– imageA, imageB, imageC are display images

imageA.layer = 5
imageB.layer = 10
imageC.layer = 1

g:insert(imageA)
g:insert(imageB)
g:insert(imageC)

zSort(g)

– Now the images will display in order of their layer

[/code] [import]uid: 37366 topic_id: 2542 reply_id: 68993[/import]