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):

[code]
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) [import]uid: 82408 topic_id: 17519 reply_id: 317519[/import]

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,

?:slight_smile: [import]uid: 3826 topic_id: 17519 reply_id: 66570[/import]

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 :wink: [import]uid: 82408 topic_id: 17519 reply_id: 66578[/import]

Try adding [lua]if event.phase == “began”[/lua] or [lua]if event.phase == “ended”[/lua] 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 :slight_smile: [import]uid: 52491 topic_id: 17519 reply_id: 66621[/import]

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:

[code]
– 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) [import]uid: 82408 topic_id: 17519 reply_id: 66788[/import]

Try modifying your collision function to this;

[lua]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[/lua]

It’s a little cobbled together but I believe this achieves the result you want. Weight is added only when the object first drops, not continually - and it is added regardless of what the object collides with. (So it can be on top of other objects and not hit the bridge at all, but still have its weight counted.)

Peach :slight_smile: [import]uid: 52491 topic_id: 17519 reply_id: 66874[/import]

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! :wink: [import]uid: 82408 topic_id: 17519 reply_id: 67056[/import]

Very happy to hear it!

I enjoyed the wording, too :slight_smile:

Peach :slight_smile: [import]uid: 52491 topic_id: 17519 reply_id: 67107[/import]