Storyboards and the event parameter

I’m pretty new to Corona and just implemented storyboards in a game app I’m writing. The storyboards work, or I can make them work, but I’d really like to understand what I’m doing. Specifically as related to parameters of event callbacks.

In one of my scenes I have a couple of buttons. To handle when the user presses the button I add this:

function scene:createScene( event )  
 local hud = self.view  
  
 self.leftButton = widget.newButton{  
 id = "leftButton",  
 default = "images/leftButton.png",  
 over = "images/leftButtonPress.png",  
 width = 283,  
 height = 124,  
 onEvent = onButtonEvent  
 }  
 hud:insert( self.leftButton )  
... more stuff  

and this calls a function in my scene file defined like this:

local function onButtonEvent( self, event )  
 local btn = self.target  
  
 if self.phase == "press" then  
 if btn.id == "leftButton" then  
 ship:rotateLeft()  
 ... more code  

Notice I reference self to get the target, not event, like I would in a non-scene file. This works, but I don’t understand why I can’t just use event. If I do I get an error “Attempt to index local ‘event’”

Now I need to implement collision detection in a scene, so I thought I’d make the collision callback part of the scene. I defined things like this:

function scene:onCollision( self, event )  
 print( self.object1)  

And created like this:

function scene:enterScene( event )  
 Runtime:addEventListener( "collision", self.onCollision )  

This doesn’t work and I get the error “attempt to index local ‘self’ (a nil value)” In the callback.

I can create the collision call back like the button one, but that means I can’t access scene specific data via the self variable.

I know this is a pretty big question, but any help would be appreciated.

Ron [import]uid: 186688 topic_id: 33568 reply_id: 333568[/import]

Basically Corona SDK (well Lua) provides two ways to call functions. For simplicty, lets call them the “dot” method and the other the “colon” method.

local function fred(barney)  
 -- do stuff  
 print(barney)  
end  
  
fred("barney rubble")  
-- prints "barney rubble"  

For functions defined like this, the first parameter is barney. Pretty straight forward.

Objects and tables can have functions defined with them as part of that object table:

flintstones = {}  
flintstones.fred = function(barney)  
 print(barney)  
end  
  
flintstones.fred("barney rubble")  
-- prints "barney rubble"  

In this example a simple function is added to the table/object and we access it using the “dot” separator. Now in the Object Oriented model these functions (now called “methods”) need to be able to operate on the object itself. In C++, Javascript, a special reference to the calling object called “this” exists to reference the unique copy of the object that is calling the method. In Lua this special reference is called “self”.

flintstones = {}  
flintstones:fred = function(barney)  
 print(self)  
 print(barney)  
end  
  
flintstones:fred("barney rubble")  
-- prints the address to the flintstones object/table  
-- prints "barney rubble"  

Now in this example, by using the colon, “self” is passed to the function as the first parameter, though it’s not specified. Now the parameter that I passed is the right place.

flintstones = {}  
flintstones.fred = function(self, barney)  
 print(self)  
 print(barney)  
end  
  
flintstones:fred("barney rubble")  
-- prints the address to the flintstones object/table  
-- prints "barney rubble"  
  
flintstones.fred(flintstones, "barney rubble")  
-- exact same results as above.  

This is the same results as before, but now you explicitly see the problem.

in your case, you have your two items backwards:

local function onButtonEvent( event )  
 local btn = event.target  
   
 if event.phase == "press" then  
 if btn.id == "leftButton" then  
 ship:rotateLeft()  
 ... more code  

[import]uid: 199310 topic_id: 33568 reply_id: 133430[/import]

Basically Corona SDK (well Lua) provides two ways to call functions. For simplicty, lets call them the “dot” method and the other the “colon” method.

local function fred(barney)  
 -- do stuff  
 print(barney)  
end  
  
fred("barney rubble")  
-- prints "barney rubble"  

For functions defined like this, the first parameter is barney. Pretty straight forward.

Objects and tables can have functions defined with them as part of that object table:

flintstones = {}  
flintstones.fred = function(barney)  
 print(barney)  
end  
  
flintstones.fred("barney rubble")  
-- prints "barney rubble"  

In this example a simple function is added to the table/object and we access it using the “dot” separator. Now in the Object Oriented model these functions (now called “methods”) need to be able to operate on the object itself. In C++, Javascript, a special reference to the calling object called “this” exists to reference the unique copy of the object that is calling the method. In Lua this special reference is called “self”.

flintstones = {}  
flintstones:fred = function(barney)  
 print(self)  
 print(barney)  
end  
  
flintstones:fred("barney rubble")  
-- prints the address to the flintstones object/table  
-- prints "barney rubble"  

Now in this example, by using the colon, “self” is passed to the function as the first parameter, though it’s not specified. Now the parameter that I passed is the right place.

flintstones = {}  
flintstones.fred = function(self, barney)  
 print(self)  
 print(barney)  
end  
  
flintstones:fred("barney rubble")  
-- prints the address to the flintstones object/table  
-- prints "barney rubble"  
  
flintstones.fred(flintstones, "barney rubble")  
-- exact same results as above.  

This is the same results as before, but now you explicitly see the problem.

in your case, you have your two items backwards:

local function onButtonEvent( event )  
 local btn = event.target  
   
 if event.phase == "press" then  
 if btn.id == "leftButton" then  
 ship:rotateLeft()  
 ... more code  

[import]uid: 199310 topic_id: 33568 reply_id: 133430[/import]

Rob:

Thanks for the reply. I’d figured out the function call vs function pointer colon vs dot thing previously because of another mistake I’d made.

What I’m confused about here is the scene template will define an event listener call back like this:

local scene = storyboard.newScene()  
  
function scene:createScene( event )  
...  

Then set up the listening like this:

scene:addEventListener( "createScene", scene )  

And everything works. CreateScene gets called with self being the scene.

But if I set up my collision routine the same way:

function scene:collision( self )  
....  
scene:addEventListener( "collision", scene )  

It never gets called. I suspect something is going on inside .newScene() that is special mapping the xxxScene methods.

Ron [import]uid: 186688 topic_id: 33568 reply_id: 133694[/import]

I’m not 100% sure collisions confuse me, but I’m going to guess it’s because:

  1. The scene isn’t a display object. scene.view is a displayGroup, but scene itself isn’t and probably can’t have collisions which leads to #2.

  2. Collisions are triggered from physics bodies and you’re not adding physics to scene (which you really can’t do because it’s not a display object.

Since a scene is the whole screen, I don’t think you want to treat the whole scene as a physics body/collision target either so you would add these collision bits to some other graphic/display object that makes up the scene.
[import]uid: 199310 topic_id: 33568 reply_id: 133762[/import]

Rob:

Thanks for the reply. I’d figured out the function call vs function pointer colon vs dot thing previously because of another mistake I’d made.

What I’m confused about here is the scene template will define an event listener call back like this:

local scene = storyboard.newScene()  
  
function scene:createScene( event )  
...  

Then set up the listening like this:

scene:addEventListener( "createScene", scene )  

And everything works. CreateScene gets called with self being the scene.

But if I set up my collision routine the same way:

function scene:collision( self )  
....  
scene:addEventListener( "collision", scene )  

It never gets called. I suspect something is going on inside .newScene() that is special mapping the xxxScene methods.

Ron [import]uid: 186688 topic_id: 33568 reply_id: 133694[/import]

I’m not 100% sure collisions confuse me, but I’m going to guess it’s because:

  1. The scene isn’t a display object. scene.view is a displayGroup, but scene itself isn’t and probably can’t have collisions which leads to #2.

  2. Collisions are triggered from physics bodies and you’re not adding physics to scene (which you really can’t do because it’s not a display object.

Since a scene is the whole screen, I don’t think you want to treat the whole scene as a physics body/collision target either so you would add these collision bits to some other graphic/display object that makes up the scene.
[import]uid: 199310 topic_id: 33568 reply_id: 133762[/import]