Two Display Object Questions from a Newbie

Greetings, everyone,

I’m a SQL developer who has been playing around with LUA and Corona SDK on his off-time to learn a bit about application development. I’ve learned a whole lot, but there are two issues that are still throwing me for a loop. I’ve done a bit of research, and don’t have answers for them. I’m at work now, so I don’t have access to the specific code, but hopefully someone will be able to shed some light on these for me.

1. The Lack of Z-Coordinate Definition
Let’s say that I have two groups:
groupA contains groupAObjectA, groupAObjectB, and groupAObjectC, inserted in that order.
groupB contains groupBObjectA, groupBObjectB, and groupBObjectC, inserted in that order.

I can move individual groups in front of each other-- for example, groupB:toFront() will move its objects in front of groupA. However, I don’t have any capability to set cross-group display priority. Let’s say that I wanted everything but groupAObjectA to be in front of groupB’s objects. As far as I know, there’s no explicit toBack() function or moveBackOne() function, and I don’t see any way to retrieve/use Z values. A display object can only be a member of a single group at a given time, so no creative solutions with multiple display groups. Is managing display object/group order not a major issue? Something big that’s getting past me?

2. The Inability to Destroy Objects
Again, I may not be understanding how all this works, but there are quite a few situations in which I will write–

display.remove( groupAObjectA )
groupAObjectA = nil

And yet the object still appears on the screen. Sometimes, those two lines are sufficient to remove a display object, but other times they are not. My working theory is that the problem has to do with whether the object is local and where it’s called from, but that’s an area that I need to do more research on. Is that probably the right line of reasoning? Do I need to try having the function that calls the removal code inside the function that groupAObjectA is defined in (encapsulated functions, I think it’s called)? Something else that could be going on here? [import]uid: 191085 topic_id: 32971 reply_id: 332971[/import]

  1. I don’t think there’s any way round this. You might just have to sub-divide your display groups to enable a bit more flexibility as to what appears in front of what.

  2. Your issue probably is the scope of the object. You don’t have to have the removal code inside the function that created it, as long as you create the reference to the object first outside the function.

e.g

[lua]local object

local createObject = function ()

object = display.newRect(100,100,50,50)

end

createObject()

display.remove(object)
object = nil[/lua]

is different to:

[lua]local createObject = function ()

local object = display.newRect(100,100,50,50)

end

createObject()

display.remove(object)
object = nil[/lua]

In the second example, the object handle is not visible outside of the createObject function so there is nothing for display.remove to remove.

Just define anything you might need to manipulate or remove later on at the top of your lua file, even if you don’t actually create the object until later on. [import]uid: 93133 topic_id: 32971 reply_id: 130924[/import]

Awesome; thanks, Nick. This evening, when I’m off work, I’ll take a look at the scope of the problematic object and see if that’s what the issue is. I’ll also see what I can do about the display objects.

Appreciate your help! [import]uid: 191085 topic_id: 32971 reply_id: 130937[/import]

Regarding 1, while we call them display groups, functionally, they act like display layers (where the objects in any group all display at the same depth layer).

So, from your example above, GroupObjectA becomes LayerObjectA.

And we can’t have only a single layer object, LayerObjectA, be behind Layer B (however all of Layer A can be moved there if you want).

If you need an object from layer A to behind Layer B, you can move the entire Layer A, remove LayerAObjectA from its layer, put it in Layer B (toback), make a third layer… etc

wow. Now I said it so many times, the word layer seems really really weird. [import]uid: 79933 topic_id: 32971 reply_id: 130945[/import]

  1. I don’t think there’s any way round this. You might just have to sub-divide your display groups to enable a bit more flexibility as to what appears in front of what.

  2. Your issue probably is the scope of the object. You don’t have to have the removal code inside the function that created it, as long as you create the reference to the object first outside the function.

e.g

[lua]local object

local createObject = function ()

object = display.newRect(100,100,50,50)

end

createObject()

display.remove(object)
object = nil[/lua]

is different to:

[lua]local createObject = function ()

local object = display.newRect(100,100,50,50)

end

createObject()

display.remove(object)
object = nil[/lua]

In the second example, the object handle is not visible outside of the createObject function so there is nothing for display.remove to remove.

Just define anything you might need to manipulate or remove later on at the top of your lua file, even if you don’t actually create the object until later on. [import]uid: 93133 topic_id: 32971 reply_id: 130924[/import]

Awesome; thanks, Nick. This evening, when I’m off work, I’ll take a look at the scope of the problematic object and see if that’s what the issue is. I’ll also see what I can do about the display objects.

Appreciate your help! [import]uid: 191085 topic_id: 32971 reply_id: 130937[/import]

Regarding 1, while we call them display groups, functionally, they act like display layers (where the objects in any group all display at the same depth layer).

So, from your example above, GroupObjectA becomes LayerObjectA.

And we can’t have only a single layer object, LayerObjectA, be behind Layer B (however all of Layer A can be moved there if you want).

If you need an object from layer A to behind Layer B, you can move the entire Layer A, remove LayerAObjectA from its layer, put it in Layer B (toback), make a third layer… etc

wow. Now I said it so many times, the word layer seems really really weird. [import]uid: 79933 topic_id: 32971 reply_id: 130945[/import]

Wow, that’s extremely helpful. So, I should really think of display groups as display layers? Huzzah-- that’s fantastic!

Out of curiosity, is there a function I could use to print out the priority/order (whatever the right word is) of various display groups at a given time in the console? That could potentially help with troubleshooting.

Thanks, everyone. Appreciate your help. [import]uid: 191085 topic_id: 32971 reply_id: 131057[/import]

@eluros,

Yes. Think of groups a layers and you’ll be in good shape. I was thinking of writing an article over the next few days about this, but for now let me drop some code on you that you might find useful.

Quick Layers
[lua]function quickLayers( parentGroup, … )

local layers = display.newGroup()
if( parentGroup ) then
parentGroup:insert(layers)
end

layers._db = {}

local lastGroup

if( parentGroup ) then
print( “\ (parentGroup)”)
else
print( “\”)
end

for i = 1, #arg do
local theArg = arg[i]

if(type(theArg) == “string”) then
print( "|–\ " … theArg)
local group = display.newGroup()
lastGroup = group
layers._db[#layers._db+1] = group
layers[theArg] = group

if( parentGroup ) then
parentGroup:insert( group )
end

else – Must be a table – ALLOW UP TO ‘ONE’ ADDITIONAL LEVEL OF DEPTH
for j = 1, #theArg do
local theArg2 = theArg[j]
print( " |–\ " … theArg2)
if(type(theArg2) == “string”) then
local group = display.newGroup()
layers._db[#layers._db+1] = group
layers[theArg2] = group
lastGroup:insert( group )
else
error(“layers() Only two levels allowed!”)
end
end
end
end

function layers:destroy()
for i = #self._db, 1, -1 do
print("quickLayers(): Removing layer: " … i)
self._db[i]:removeSelf()
end
self:removeSelf()
end

return layers
end[/lua]

The above code take a variable number of unique string ‘names’ and creates a bottom-to-top layer tree.

Create three layer system [lua] local layers = quickLayers( nil, “background”, “content”, “interfaces” )[/lua]

In the above case, background is behind content is behind interfaces. i.e. The ‘interfaces’ layer is on top.

Put Content In The Layers [lua] – Put something in the background
layers.background:insert( backImage )

– Put content in the middle layer (‘content’ layer)
layers.content:insert( player )
layers.content:insert( enemy1)
layers.content:insert( enemy2 )

– Put some buttons (or whatever in the interfaces layer)
layers.interfaces:insert( button1 )
layers.interfaces:insert( button2 )
layers.interfaces:insert( button3 )[/lua]

Notice that in the above code the object ‘layers’ as named references to the layer groups (which is why they must have unique names). This makes it easy to write and read your code.

Note, you access the named groups in two ways:
[lua] layers.interfaces:insert( obj )

– equivalent to

layers[“interfaces”]:insert( obj )[/lua]
Create more complex layer system: [lua] local layers = quickLayers( displayGroup,
“background”,
“scrollers”,
{ “scroll3”, “scroll2”, “scroll1” },
“content”,
“interfaces” )[/lua]

quickLayers() also handles a single extra level of depth. In the above case you have a layer system like this (listed bottom to top).

\ (parentGroup)
|--\ background
|--\ scrollers
 |--\ scroll3
 |--\ scroll2
 |--\ scroll1
|--\ content
|--\ interfaces

Notice that ‘scroll3’ is below ‘scroll2’ is below ‘scroll1’ and the are all inside a master group called ‘scrollers’. Again, all accesses are by name:
[lua] layers.background:insert( obj )

layers.scrollers:insert( obj )

layers.scroll3:insert( obj )

– … etc.[/lua]
Extra Notes

  • The above code is from a free library and framework (SSKCorona) I have provided to the community and am still improving. The quickLayers() function can be found in this file.

  • SSKCorona has a Wiki … but I haven’t put up docs for the ‘new’ display objects and builders yet.

  • Finally, I will have more to say on this matter when I have time to write that article.

[import]uid: 110228 topic_id: 32971 reply_id: 131078[/import]

Wow, that’s extremely helpful. So, I should really think of display groups as display layers? Huzzah-- that’s fantastic!

Out of curiosity, is there a function I could use to print out the priority/order (whatever the right word is) of various display groups at a given time in the console? That could potentially help with troubleshooting.

Thanks, everyone. Appreciate your help. [import]uid: 191085 topic_id: 32971 reply_id: 131057[/import]

@eluros,

Yes. Think of groups a layers and you’ll be in good shape. I was thinking of writing an article over the next few days about this, but for now let me drop some code on you that you might find useful.

Quick Layers
[lua]function quickLayers( parentGroup, … )

local layers = display.newGroup()
if( parentGroup ) then
parentGroup:insert(layers)
end

layers._db = {}

local lastGroup

if( parentGroup ) then
print( “\ (parentGroup)”)
else
print( “\”)
end

for i = 1, #arg do
local theArg = arg[i]

if(type(theArg) == “string”) then
print( "|–\ " … theArg)
local group = display.newGroup()
lastGroup = group
layers._db[#layers._db+1] = group
layers[theArg] = group

if( parentGroup ) then
parentGroup:insert( group )
end

else – Must be a table – ALLOW UP TO ‘ONE’ ADDITIONAL LEVEL OF DEPTH
for j = 1, #theArg do
local theArg2 = theArg[j]
print( " |–\ " … theArg2)
if(type(theArg2) == “string”) then
local group = display.newGroup()
layers._db[#layers._db+1] = group
layers[theArg2] = group
lastGroup:insert( group )
else
error(“layers() Only two levels allowed!”)
end
end
end
end

function layers:destroy()
for i = #self._db, 1, -1 do
print("quickLayers(): Removing layer: " … i)
self._db[i]:removeSelf()
end
self:removeSelf()
end

return layers
end[/lua]

The above code take a variable number of unique string ‘names’ and creates a bottom-to-top layer tree.

Create three layer system [lua] local layers = quickLayers( nil, “background”, “content”, “interfaces” )[/lua]

In the above case, background is behind content is behind interfaces. i.e. The ‘interfaces’ layer is on top.

Put Content In The Layers [lua] – Put something in the background
layers.background:insert( backImage )

– Put content in the middle layer (‘content’ layer)
layers.content:insert( player )
layers.content:insert( enemy1)
layers.content:insert( enemy2 )

– Put some buttons (or whatever in the interfaces layer)
layers.interfaces:insert( button1 )
layers.interfaces:insert( button2 )
layers.interfaces:insert( button3 )[/lua]

Notice that in the above code the object ‘layers’ as named references to the layer groups (which is why they must have unique names). This makes it easy to write and read your code.

Note, you access the named groups in two ways:
[lua] layers.interfaces:insert( obj )

– equivalent to

layers[“interfaces”]:insert( obj )[/lua]
Create more complex layer system: [lua] local layers = quickLayers( displayGroup,
“background”,
“scrollers”,
{ “scroll3”, “scroll2”, “scroll1” },
“content”,
“interfaces” )[/lua]

quickLayers() also handles a single extra level of depth. In the above case you have a layer system like this (listed bottom to top).

\ (parentGroup)
|--\ background
|--\ scrollers
 |--\ scroll3
 |--\ scroll2
 |--\ scroll1
|--\ content
|--\ interfaces

Notice that ‘scroll3’ is below ‘scroll2’ is below ‘scroll1’ and the are all inside a master group called ‘scrollers’. Again, all accesses are by name:
[lua] layers.background:insert( obj )

layers.scrollers:insert( obj )

layers.scroll3:insert( obj )

– … etc.[/lua]
Extra Notes

  • The above code is from a free library and framework (SSKCorona) I have provided to the community and am still improving. The quickLayers() function can be found in this file.

  • SSKCorona has a Wiki … but I haven’t put up docs for the ‘new’ display objects and builders yet.

  • Finally, I will have more to say on this matter when I have time to write that article.

[import]uid: 110228 topic_id: 32971 reply_id: 131078[/import]