Issues using globals in collision events

Hi, I'm eleven years old and a novice at Corona.

I'm having issues using globals with the "event." prefix in collision events. I have it set so that if an object involved in the collision has a .myName of "coconut", it will modify a variable called "weight". On the other hand, if its .myName is "rock", it will modify "weight" in a different manner.

The issue is that whenever I try calling a global using the "event." prefix (in this case, "event.object1.myName"), it will cause an error in the terminal. Not a crash, just an error. It says that the global "event" is nil, when in fact it isn't! Anybody know how to fix this? Here's all the code in it (adapted from the "Bridge" sample code):

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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
local physics = require("physics")
physics.start()
 
display.setStatusBar( display.HiddenStatusBar )
 
-- Create some variables to say how much weight is being applied to the bridge and if it can be broken
local weight = 0
local breakable = true
 
-- The final "true" parameter overrides Corona's auto-scaling of large images
local background = display.newImage( "jungle_bkg.png", 0, 0, true )
background.x = display.contentWidth / 2
background.y = display.contentHeight / 2
 
local pole1 = display.newImage( "bamboo.png" )
pole1.x = 50; pole1.y = 250; pole1.rotation = -12
physics.addBody( pole1, "static", { friction=0.5 } )
 
local pole2 = display.newImage( "bamboo.png" )
pole2.x = 430; pole2.y = 250; pole2.rotation = 12
physics.addBody( pole2, "static", { friction=0.5 } )
 
local instructionLabel = display.newText( "touch boards to break bridge, touch rocks to remove", 22, 20, native.systemFont, 17 )
instructionLabel:setTextColor( 190, 255, 131, 150 )
 
local board = {}
local joint = {}
 
-- A touch listener to "break" bridge joints
local breakJoint = function( event )
        local t = event.target
        local phase = event.phase
 
        if "began" == phase then
                if breakable == true then
                        local myIndex = t.myIndex
                        print( "breaking joint at board#" .. myIndex )
                        joint[myIndex]:removeSelf() -- destroy joint
                        breakable = false
                end
        end
 
        -- Stop further propagation of touch event
        return true
end
 
-- A touch listener to remove rocks
local removeBody = function( event )
        local t = event.target
        local phase = event.phase
 
        if "began" == phase then
                t:removeSelf() -- destroy object
        end
        
        if t.myName == "coconut" then
                weight = weight - 5
        else
                weight = weight - 10
        end
 
        -- Stop further propagation of touch event
        return true
end
 
 
for j = 1,16 do
        board[j] = display.newImage( "board.png" )
        board[j].x = 20 + (j*26)
        board[j].y = 150
        board[j].myIndex = j -- for touch handler above
        board[j]:addEventListener( "touch", breakJoint ) -- assign touch listener to board
        board[j].myName = "board"
        
        physics.addBody( board[j], { density=0.8, friction=0.3, bounce=0.3 } )
        
        -- damping the board motion increases the "tension" in the bridge
        board[j].angularDamping = 5000
        board[j].linearDamping = 0.7
 
        -- create joints between boards
        if (j > 1) then
                prevLink = board[j-1] -- each board is joined with the one before it
        else
                prevLink = pole1 -- first board is joined to left pole
        end
        joint[j] = physics.newJoint( "pivot", prevLink, board[j], 6+(j*26), 150 )
 
end
 
-- join final board to right pole
joint[#joint + 1] = physics.newJoint( "pivot", board[16], pole2, 6+(17*26), 150 )
 
-- A function for a collision to apply weight to the bridge
local function onCollision()
 
        if event.object1.myName == "coconut" then
                weight = weight + 5
        elseif event.object1.myName == "rock" then
                weight = weight + 10
                end
end
 
Runtime:addEventListener( "collision", onCollision )
 
local balls = {}
 
-- function to drop random coconuts and rocks
local randomBall = function()
 
        choice = math.random( 100 )
        local ball
        
        if ( choice < 80 ) then
                ball = display.newImage( "coconut.png" )
                ball.x = 40 + math.random( 380 ); ball.y = -40
                physics.addBody( ball, { density=0.6, friction=0.6, bounce=0.6, radius=19 } )
                ball.angularVelocity = math.random(800) - 400
                ball.isSleepingAllowed = false
                ball.myName = "coconut" 
        else
                ball = display.newImage( "rock.png" )
                ball.x = 40 + math.random( 380 ); ball.y = -40
                physics.addBody( ball, { density=2.0, friction=0.6, bounce=0.2, radius=33 } )
                ball.angularVelocity = math.random(600) - 300
                ball.myName = "rock"
        
        end
        
        ball:addEventListener( "touch", removeBody ) -- assign touch listener to rock
        balls[#balls + 1] = ball        
end
 
-- run the above function 14 times
timer.performWithDelay( 1500, randomBall, 14 )
 
-- A weight listener to "break" bridge joints
local weightBreakJoint = function( event )
        if breakable == true then
                if weight >= 75 then
                        print( "Weight has broken the bridge" )
                        joint[(math.random(2,15))]:removeSelf() -- destroy joint
                        breakable = false
                end
        end
end
 
Runtime:addEventListener("enterFrame", weightBreakJoint)

Eleven and you were allowed to watch Blood and Sand or the Gods of the Arena? Why would you have a nickname of Spartacus otherwise?

NEways, your problem can be resolved by rectifying the line 95 as

local function onCollision(event)

cheers,

?:)

Thanks for that. Now I see what the (event) thing is for. And no, I haven't watched those. I just like history.

Anyways, I still have one problem. It seems to register the collision multiple times even after the rock/coconut hits the bridge. Is there any way to neutralize this, or am I just stuck? Either way, thanks for the help.

Cheers ;)

Try adding if event.phase == "began" or if event.phase == "ended" to get the desired result. (Began is probably what you want to use, I imagine.)

Right now it would be firing when the collision began and when it ended.

Peach :)

Thanks. Actually, I found it was that the rocks/coconuts collide with eachother and set off the collision listener. Now, the simple technique of checking the other object's name won't work too well because objects that land ontop of one another would add weight to the bridge (albeit damped weight, but that would be tricky to pull off).

I'm gonna try to localize the listener to the rocks themselves (so I probably wouldn't need the "event.object1.myName" API) and have it so that once the collision ends, the collision listener is removed from the rock. That should make it work.

EDIT:
It isn't working. I've localized it to the rocks/coconuts that fall, but the event won't fire now. It's not that there's an error or a crash or anything, it just doesn't fire. I even set it to print something to show the current weight, but it won't print. Anybody know why? Here's the code:

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
-- A function for a collision to apply weight to the bridge
local function onLocalCollision( self, event )
 
        if self.myName == "coconut" then
                weight = weight + 5
                print( "Weight =" .. weight )
        elseif self.myName == "rock" then
                weight = weight + 10
                print( "Weight =" .. weight )
                end
end
 
local balls = {}
 
-- function to drop random coconuts and rocks
local randomBall = function()
 
        choice = math.random( 100 )
        local ball
        
        if ( choice < 80 ) then
                ball = display.newImage( "coconut.png" )
                ball.x = 40 + math.random( 380 ); ball.y = -40
                physics.addBody( ball, { density=0.6, friction=0.6, bounce=0.6, radius=19 } )
                ball.angularVelocity = math.random(800) - 400
                ball.isSleepingAllowed = false
                ball.myName = "coconut"
                ball.collision = onLocalCollision
                ball:addEventListener( "collision", onLocalCollision )
        else
                ball = display.newImage( "rock.png" )
                ball.x = 40 + math.random( 380 ); ball.y = -40
                physics.addBody( ball, { density=2.0, friction=0.6, bounce=0.2, radius=33 } )
                ball.angularVelocity = math.random(600) - 300
                ball.myName = "rock"
                ball.collision = onLocalCollision
                ball:addEventListener( "collision", onLocalCollision )
        
        end
        
        ball:addEventListener( "touch", removeBody ) -- assign touch listener to rock
        balls[#balls + 1] = ball        
end
 
-- run the above function 14 times
timer.performWithDelay( 1500, randomBall, 14 )
 
-- A weight listener to "break" bridge joints
local weightBreakJoint = function( event )
        if breakable == true then
                if weight >= 75 then
                        print( "Weight has broken the bridge" )
                        joint[(math.random(2,15))]:removeSelf() -- destroy joint
                        breakable = false
                end
        end
end
 
Runtime:addEventListener("enterFrame", weightBreakJoint)

Try modifying your collision function to this;

1
2
3
4
5
6
7
8
9
10
11
12
local function onLocalCollision( event )
 
        if event.target.myName == "coconut" then
                weight = weight + 5
                print( "Weight =" .. weight )
                                event.target:removeEventListener("collision", onLocalCollision)
        elseif event.target.myName == "rock" then
                weight = weight + 10
                print( "Weight =" .. weight )
                                event.target:removeEventListener("collision", onLocalCollision)
                end
end

Awesome! It works perfectly, printing and all! I get to see the weight changing in the terminal and wait for the weight (pardon the pun) to break the bridge. A simple thing that could be useful in certain games. Thanks for the help everyone! ;)

Very happy to hear it!

I enjoyed the wording, too :)

Peach :)

views:1986 update:2011/11/14 9:16:56
corona forums © 2003-2011