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