Event handlers - inside or outside the function?

I have a question I haven't been able to figure out by reading the forums, documentation, and looking through sample code. Let's say I want a function to create an object (like a game character). I expect to create a lot of these. I've seen it done this way:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function createCharacter(params)        
 
        local myCharacter = display.newImage("character.png")           
        -- create the character, add physics, set status, insert in groups, etc. 
        
        function myCharacter:touch(event) -- for some reason this gives an error when it's local. Maybe it's destroyed when function ends?                      
                -- handle touch event, there could be a lot in here, calling other functions, etc.
                return true             
        end     
        
        function myCharacter:collision(event)
                -- handle collision event, there could be a lot in here, calling other functions, etc.          
                return true
        end
 
        myCharacter:addEventListener( "touch", myCharacter )
        myCharacter:addEventListener( "collision", myCharacter )
        
        return myCharacter
 
end

I'm actually interested in this too. I have an opinion (which is likely wrong) so Ill wait till someone more knowledgeable replys.. but great question s2alexan.

"Does this create a different copy of the collision and touch handlers every time I call createCharacter? Is the second way the "right" way to handle this?"
Yes and yes.

In your first version, you're creating a new function every time. This actually a very good feature of Lua when used properly. Google "lua closures" to read about it.
The second version creates only two functions.
Watch out about what you read/get from the forum/code exchange. A lot of people give advice/code without fully understanding what they are writing. Always try to understand a concept/technique before using it.
Even the heavily-used Director class by Ricardo is not all mighty. I actually don't use it as I prefer my own version.

Anyway, you shouldn't just trust my words and see it by yourself:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
function createCharacter1(params)        
                
                local myCharacter = display.newGroup()
        -- create the character, add physics, set status, insert in groups, etc. 
        
        function myCharacter:touch(event) -- for some reason this gives an error when it's local. Maybe it's destroyed when function ends?                      
                -- handle touch event, there could be a lot in here, calling other functions, etc.
                return true             
        end     
        
        function myCharacter:collision(event)
                -- handle collision event, there could be a lot in here, calling other functions, etc.          
                return true
        end
 
        myCharacter:addEventListener( "touch", myCharacter )
        myCharacter:addEventListener( "collision", myCharacter )
        
        return myCharacter
 
end
 
local a = createCharacter1()
local b = createCharacter1()
local c = createCharacter1()
 
print( "Version 1:" )
print (a.touch)
print (b.touch)
print (c.touch)
 
 
local function myCharacterTouchHandler(self,event)                      
        -- handle touch event, there could be a lot in here, calling other functions, etc.
        return true             
end     
        
local function myCharacterCollisionHandler(self,event)
        -- handle collision event, there could be a lot in here, calling other functions, etc.          
        return true
end
 
function createCharacter2(params)        
                
        local myCharacter = display.newGroup()  
        -- add physics, set status, insert in groups, etc. 
 
        myCharacter.touch = myCharacterTouchHandler
        myCharacter:addEventListener( "touch", myCharacterTouchHandler )
        -- I notice this also works: myCharacter:addEventListener( "touch", myCharacter )
 
        myCharacter.collision = myCharacterCollisionHandler
        myCharacter:addEventListener( "collision", myCharacterCollisionHandler)
        
        return myCharacter
 
end
 
 
local d = createCharacter2()
local e = createCharacter2()
local f = createCharacter2()
 
print( "\nVersion 2:" )
print (d.touch)
print (e.touch)
print (f.touch)

Thanks for the detailed reply - especially the bit about understanding the code before using it. There's a lot of stuff out there that "works", but I'm always a bit suspicious if I don't know HOW it works.

I'm going to read up on lua closures, seems like a powerful feature.

And I did try the code - I had no idea each function had an actual ID, learned something else today too!

Well, functions are first-class values in Lua. Meaning they behave like any other value. Creating a function using the standard syntax:

1
2
local function myFunc()
end
views:1708 update:2011/10/3 8:06:12
corona forums © 2003-2011