Control class that return a Display.Group object ?

How do i access group object of external class from main.lua?

I have googling around but can’t find much about corona display.group object…

Let’s say this is world.lua

[lua]

local world = {}

function world.new()

    local worldGroup = display.newGroup()

    local sky = display.newImageRect( “sky.png”, 480,360 )

    sky:setReferencePoint( display.TopLeftReferencePoint )
    sky.x = 0; sky.y = 0

    worldGroup:insert(sky)

    local ground = display.newImageRect( “ground.png”, 480,360 )

    ground:setReferencePoint( display.TopLeftReferencePoint )
    ground.x = 0; ground.y = 0

    worldGroup:insert(ground)

    return worldGroup

end

function world.move()

    – I’m trying to scroll sky and ground from new() above. And this function will be called

    – from main.lua

    – How do i do this ?

end

return world

[/lua]

And this is main.lua

[lua]

local World = require “world”

local thisWorld = World.new()

Runtime:addEventListener( “enterFrame”, World.move)

[/lua]

My idea is calling World.move() to scroll thisWorld in main.lua.

Or i have wrong concept and need to alter those 2 files above?

Feel free to correct me. Thanks in advance…

Actually, you’re not far off, you should declare the functions like this (with a colon, not a period):

function world:move() ... end

If you need to call them you also use the colon, but if you want to pass them as a reference to addEventListener you would use the period:

thisworld:move() -- calling the function on the object ... Runtime:addEventListener( "enterFrame", World.move ) -- passing the function on the object as a reference 

Thanks horacebury about colon and period thing.

So how do i access children of worldGroup in

[lua]

function world:move()

    local thisSky = world[1]

    sky.x = sky.x - 10  – this gave me nil

end

[/lua]

?

I tried world[1] as stated on http://developer.coronalabs.com/content/application-programming-guide-graphics-and-drawing

But i got nil value.

You ‘world’ class is a table, which has no ‘objects’ in it currently, just a few functions. Your new() function creates the worldGroup, but doesn’t insert it into the world table at all.

You need to make ‘worldGroup’ a property of ‘world’ when you create it.

function world.new() local worldGroup = display.newGroup() local sky = display.newImageRect( "sky.png", 480,360 ) sky:setReferencePoint( display.TopLeftReferencePoint ) sky.x = 0; sky.y = 0 worldGroup:insert(sky) local ground = display.newImageRect( "ground.png", 480,360 ) ground:setReferencePoint( display.TopLeftReferencePoint ) ground.x = 0; ground.y = 0 worldGroup:insert(ground) --I'll add it separately here for simplicity world.worldGroup = worldGroup return worldGroup end

Now you can access the worldGroup property, and find it’s children:

local thisSky = world.worldGroup[1] sky.x = sky.x - 10 -- this gave me nil

That should work.

Thanks a lot Alan, and yes this is what i missed:

world.worldGroup = worldGroup

But now i face another problem.

I tried to put the world.worldGroup into a scene view in main.lua, like

[lua]

local storyboard = require “storyboard”  – just to inform you that i use storyboard API

function scene:enterScene( event )

    local screenGroup = self.view

    local thisWorld = World.new()

    local i

    for i=1, thisWorld.worldGroup.numChildren do

        local child = thisWorld.worldGroup[i]

        screenGroup:insert(child)  – error here

    end

end

[/lua]

resulting “error: table expected”.

I print out those child, and the terminal does display a list of anonymous table.

While i thought scene view accept display object as input,

and child = thisWorld.worldGroup[1] = sky is a display object from the start. Or not? Confused…

So how do i insert those tables to screenGroup ?

Things get trickier, or i myself make this over complicate ouch…

@horacebury (and everyone else…)

About using colon and period, i got nailed again…

I change function World :move () to be called by touch event, to function World:move( event ).

And put it in [lua]somebutton:addEventListener(“touch”, World.move)[/lua]

But it can’t catch the event, giving nil value. I realize this by capturing event.phase of the move function.

I tried thisWorld.move() (thisWorld is an instance on main.lua), giving assertion failed.

I print out thisWorld, it doesnt have function move like World does. How could they differ. i dont quite understand.

Could you please help some more.

Or if you have any link for me to work this around. Thanks before.

Display objects always print out as tables (I believe that technically everything in Lua is actually a table - but that’s another matter), so when it says it expects a table it’s safe to say it is expecting a group or display object.

I think your problem is that your function is passing ‘nil’ into the insert function.

The way you have setup your enterScene function means it is not trying to put the worldgroup into the sceneGroup, it’s taking the objects inside worldGroup and moving those to sceneGroup instead:

--this loops through the worldGroup for i=1, thisWorld.worldGroup.numChildren do --this takes an object (such as 'sky') from the worldGroup --and assigns it to the vari local child = thisWorld.worldGroup[i] --and inserts 'sky' into the sceneGroup screenGroup:insert(child) -- error here end

Display objects can only be inside one display group at a time, so by inserting ‘sky’ into the sceneGroup, it is removed from worldGroup.

worldGroup now has 1 less child, but your loop is still counting as if it had the original amount, and so it reaches a nil value. Where ‘ground’ would have been the second child, it is now the first.

If you want to insert the whole worldGroup itself into the sceneGroup then do the following:

function scene:enterScene( event ) local screenGroup = self.view local thisWorld = World.new() screenGroup:insert(thisWorld.worldGroup) end

If you really do want to put the worldGroup children objects into the sceneGroup, then loop through them backwards. In your example this will remove the last child 2 (ground) and then look for child 1 (sky):

function scene:enterScene( event ) local screenGroup = self.view local thisWorld = World.new() --local i--no need to declare i as local variable --set i to be the number of children, set the loop to end at 1 --and make it count down by setting the increment to -1 for i = thisWorld.worldGroup.numChildren, 1, -1 do local child = thisWorld.worldGroup[i] screenGroup:insert(child) -- error here end end

Hopefully that gets you past your error.

wow sir you are fast… and precise.

So those object removed from worldGroup, that’s what happened.

So i do as you suggested, just put the whole worldGroup to scene view. It went well. Many thanks.

Gosh i did over complicate things… T-T

Maybe you could help me with that nil event too… :slight_smile:

Well if your earlier code is still the same, this is your problem:

--you name the object 'thisSky' local thisSky = world[1] --but try to move an object called 'sky' not 'thisSky' sky.x = sky.x - 10 -- this gave me nil

@wilychristian:

It also might be easier to put the move function inside of the world object:

[lua]

local world = {}

function world.new()

    local worldGroup = display.newGroup()

  

    local sky = display.newImageRect( “sky.png”, 480,360 )

    sky:setReferencePoint( display.TopLeftReferencePoint )

    sky.x = 0; sky.y = 0

    worldGroup:insert(sky)

  

    local ground = display.newImageRect( “ground.png”, 480,360 )

    ground:setReferencePoint( display.TopLeftReferencePoint )

    ground.x = 0; ground.y = 0

    worldGroup:insert(ground)

        function worldGroup.move()

            – Now when you want to move it, just use the reference you have to the worldGroup itself

        end

    return worldGroup

end

return world

[/lua]

  • C

@Alan

Ehm its quite different actually. :move now is waiting for touch action.

[lua]

function world:move(event)

   if (event.phase == “began”) then  – i believe this is where event = nil

   …

   end

end

[/lua]

Other object has been successfully passed in.

@Caleb

Thanks for your suggestion. I got question:

  1. Why is it easier? What are the differences with my version?

  2. In your code above, how can i call worldGroup.move() from main.lua?

  3. How do you implement it as touch event listener?

Lets say this is main.lua

[lua]

local World = require “world”

local thisWorld = World:new()

thisWorld:move()

– 2) will this call :move one time ?

somebutton:addEventListener(“touch”, World.move)

– 3) is this how you add the touch listener? It cant be this simple…

–     how did it pass the ‘event’ parameter?

[/lua]

I havent tested your code though… hehe sorry for bluntly asking.

  1. It’s easier because you don’t have to add an entry to your World class - it keeps things local, clean, and neat.

[lua]

local World = require(“world”)

local thisWorld = World.new()

thisWorld.move()

[/lua]

  1. Just put it in your touch function:

[lua]

local function onTouch(event)

  if “began” == event.phase then

    thisWorld.move()

  end

end

[/lua]

Or something to that effect. Check out the docs for events: http://docs.coronalabs.com/guide/events/detectEvents/index.html

  • C
  1. The diference between ours is you put your function :move inside function :new, while i don’t.

I thought mine was local already. Well thanks for your input Caleb.

  1. ok

  2. I have done that, but somehow the ‘event’ parameter pass nil value.

I use external lua file, and passing that ‘event’ from main.lua to anpther lua.

Oh well i’ll try some more and look on the forum again. Hopefully find something similar about this.

Thanks again Caleb.

  1. Adding the .move function inside of the .new means that your objects don’t have to be added to your library (World[1]) . Having multiple references to one object is something that can get very dangerous, very fast (memory wise). Example: you delete the thisWorld object but forget to delete the World[1] object - which are the same thing - creating a memory leak. When I said “local”, that was a slip up - I meant not somewhere in the World :D 

  2. Usually something not passing an event parameter is because of a collision between dots and colons. Make sure you’ve got all of your function declarations right:

[lua]

function world.move()

end

function world:touch(event)

  – touch function

end

world:addEventListener(“touch”)

[/lua]

Actually, you’re not far off, you should declare the functions like this (with a colon, not a period):

function world:move() ... end

If you need to call them you also use the colon, but if you want to pass them as a reference to addEventListener you would use the period:

thisworld:move() -- calling the function on the object ... Runtime:addEventListener( "enterFrame", World.move ) -- passing the function on the object as a reference 

Thanks horacebury about colon and period thing.

So how do i access children of worldGroup in

[lua]

function world:move()

    local thisSky = world[1]

    sky.x = sky.x - 10  – this gave me nil

end

[/lua]

?

I tried world[1] as stated on http://developer.coronalabs.com/content/application-programming-guide-graphics-and-drawing

But i got nil value.

You ‘world’ class is a table, which has no ‘objects’ in it currently, just a few functions. Your new() function creates the worldGroup, but doesn’t insert it into the world table at all.

You need to make ‘worldGroup’ a property of ‘world’ when you create it.

function world.new() local worldGroup = display.newGroup() local sky = display.newImageRect( "sky.png", 480,360 ) sky:setReferencePoint( display.TopLeftReferencePoint ) sky.x = 0; sky.y = 0 worldGroup:insert(sky) local ground = display.newImageRect( "ground.png", 480,360 ) ground:setReferencePoint( display.TopLeftReferencePoint ) ground.x = 0; ground.y = 0 worldGroup:insert(ground) --I'll add it separately here for simplicity world.worldGroup = worldGroup return worldGroup end

Now you can access the worldGroup property, and find it’s children:

local thisSky = world.worldGroup[1] sky.x = sky.x - 10 -- this gave me nil

That should work.

Thanks a lot Alan, and yes this is what i missed:

world.worldGroup = worldGroup

But now i face another problem.

I tried to put the world.worldGroup into a scene view in main.lua, like

[lua]

local storyboard = require “storyboard”  – just to inform you that i use storyboard API

function scene:enterScene( event )

    local screenGroup = self.view

    local thisWorld = World.new()

    local i

    for i=1, thisWorld.worldGroup.numChildren do

        local child = thisWorld.worldGroup[i]

        screenGroup:insert(child)  – error here

    end

end

[/lua]

resulting “error: table expected”.

I print out those child, and the terminal does display a list of anonymous table.

While i thought scene view accept display object as input,

and child = thisWorld.worldGroup[1] = sky is a display object from the start. Or not? Confused…

So how do i insert those tables to screenGroup ?

Things get trickier, or i myself make this over complicate ouch…

@horacebury (and everyone else…)

About using colon and period, i got nailed again…

I change function World :move () to be called by touch event, to function World:move( event ).

And put it in [lua]somebutton:addEventListener(“touch”, World.move)[/lua]

But it can’t catch the event, giving nil value. I realize this by capturing event.phase of the move function.

I tried thisWorld.move() (thisWorld is an instance on main.lua), giving assertion failed.

I print out thisWorld, it doesnt have function move like World does. How could they differ. i dont quite understand.

Could you please help some more.

Or if you have any link for me to work this around. Thanks before.

Display objects always print out as tables (I believe that technically everything in Lua is actually a table - but that’s another matter), so when it says it expects a table it’s safe to say it is expecting a group or display object.

I think your problem is that your function is passing ‘nil’ into the insert function.

The way you have setup your enterScene function means it is not trying to put the worldgroup into the sceneGroup, it’s taking the objects inside worldGroup and moving those to sceneGroup instead:

--this loops through the worldGroup for i=1, thisWorld.worldGroup.numChildren do --this takes an object (such as 'sky') from the worldGroup --and assigns it to the vari local child = thisWorld.worldGroup[i] --and inserts 'sky' into the sceneGroup screenGroup:insert(child) -- error here end

Display objects can only be inside one display group at a time, so by inserting ‘sky’ into the sceneGroup, it is removed from worldGroup.

worldGroup now has 1 less child, but your loop is still counting as if it had the original amount, and so it reaches a nil value. Where ‘ground’ would have been the second child, it is now the first.

If you want to insert the whole worldGroup itself into the sceneGroup then do the following:

function scene:enterScene( event ) local screenGroup = self.view local thisWorld = World.new() screenGroup:insert(thisWorld.worldGroup) end

If you really do want to put the worldGroup children objects into the sceneGroup, then loop through them backwards. In your example this will remove the last child 2 (ground) and then look for child 1 (sky):

function scene:enterScene( event ) local screenGroup = self.view local thisWorld = World.new() --local i--no need to declare i as local variable --set i to be the number of children, set the loop to end at 1 --and make it count down by setting the increment to -1 for i = thisWorld.worldGroup.numChildren, 1, -1 do local child = thisWorld.worldGroup[i] screenGroup:insert(child) -- error here end end

Hopefully that gets you past your error.