Collision of bodies detection

\_W = display.viewableContentWidth \_H = display.viewableContentHeight local physics = require("physics") physics.start () physics.setDrawMode("hybrid") local xOfGravity local yOfGravity --local jump = false local ballinair = true local tapping = false local sheetInfo = require("ball") local ballSheet = graphics.newImageSheet( "ball.png", sheetInfo:getSheet() ) local background = display.newRect (0,0, \_W, \_H) local ground = display.newRect (0, (\_H - 80), \_W, (\_W - 80)) ground:setFillColor (255,0,0) local leftwall = display.newRect (0, 0, 80, \_H) leftwall:setFillColor (255,0,0) local rightwall = display.newRect ((\_W - 80), 0 , 80, \_H) rightwall:setFillColor (255,0,0) local ball = display.newImage (ballSheet, sheetInfo:getFrameIndex("ball")) ball.x = 400 ball.y = 400 physics.addBody(ground, "static",{friction = 0.5, bounce = 0.1}) physics.addBody(leftwall, "static",{friction = 0.5, bounce = 0.2}) physics.addBody(rightwall, "static",{friction = 0.5, bounce = 0.2}) physics.addBody(ball, {friction = 0.5, bounce = 0.1}) -- function accelerometer:accelerometer(event.xGravity) -- xOfGravity = event.xGravity -- ball.x = (xOfGravity/2) + ball.x --end function onCollision(q) print ("rg") if (q.phase == "began") then print ("collision") if (q.object1.myName == "ball" and q.object2.myName == "ground") then ballinair = false if (tapping == true and ballinair == false) then ballinair = true ball:setLinearVelocity( 0, -200 ) --jump end print ("touching ground") elseif (q.object1.myName == "ball" and q.object2.myName == "leftwall") then if (q.object1.myName == "ball" and q.object2.myName == "ground") then ballinair = false else ballinair = true end elseif (q.object1.myName == "ball" and q.object2.myName == "rightwall") then if (q.object1.myName == "ball" and q.object2.myName == "ground") then ballinair = false else ballinair = true end end end end function tap (q) tapping = true print ("gg") end Runtime:addEventListener("tap", tap) Runtime:addEventListener( "collision", onCollision ) --Runtime:addEventListener("accelerometer", accelerometer)

What is wrong, guys? The tap isn’t detected.

Where are you tapping? I see no reason why a finger tap on the screen would not be detected, though you should return true at the end of the tap function.

Your code does not run because you have not included the ball.lua file.

horacebury,

The tapping is global. And I created the sprite using TexturePacker, and the ball is shown and it does fall on the ground, but doesn’t jump…

Thanks for replying man.

The ball doesn’t show in the code snippet you provided because the ball library code is not there. But no matter…

It looks like you’re recording that the user tapped the screen and checking that when a collision occurs.

Seeing as you’re attaching the listener to the Runtime object, what happens if the .object1 is the wall and the .object2 is the ball?

well, I was saving it for later for the advanced coding, but I’m still stuck. Right now, its just to determine if the ball is still in air.

What I’m hinting at, is that the ball may not be the object1, it might be object2, in which case your IF statements will not make it bounce.

So, what should I do? I tried putting this but it still doesnt work.

.....or q.object1.myName == "ground" and q.object2.myName == "ball"...  

Try this:

-- tap to bounce -- hide status bar display.setStatusBar( display.HiddenStatusBar ) -- enable physics  require( "physics" ) physics.start() physics.setGravity(0,10) physics.setDrawMode( "hybrid" ) -- walls physics.addBody( display.newRect( -5, 0, 10, display.contentHeight ), "static" ) physics.addBody( display.newRect( display.contentWidth-5, 0, 10, display.contentHeight ), "static" ) physics.addBody( display.newRect( 0, -5, display.contentWidth, 10 ), "static" ) physics.addBody( display.newRect( 0, display.contentHeight-5, display.contentWidth, 10 ), "static" ) -- ball local ball = display.newCircle( display.contentCenterX, display.contentCenterY, 40 ) physics.addBody( ball, "dynamic", { density=1, bounce=.8, friction=.5, radius=40 } ) -- tap handling didTap = false function tap(e)     didTap = true     return true end Runtime:addEventListener("tap", tap) -- bounce handling function ball:collision(e)     if (didTap and e.phase == "began") then         ball:applyLinearImpulse( 0, 40, ball.x, ball.y )     end     didTap = false     return true end ball:addEventListener("collision", ball)  

Yup - it did work, but when the ball stops and rests, it stops bouncing - I think it’ll be better if the if clause is skipped altogether, huh? And what about detection of collision with other objects? Shall I use the object1.myName clause inside the function ball:collision(e) clause?  

I’m trying to infer your requirements from your original code - remember that your first question was about the tap not being detected.

What do you actually want to happen?

It sounds, so far, that you want to detect a user’s tap and then make the ball bounce the next time it collides with another object. My code above does just that. If the ball comes to rest on another object (ie: there is no ended phase to the collision) you will not be able to make it bounce.

If you want to be able to make the ball bounce whenever it is in contact with another object OR (not XOR) the NEXT time it is in contact you need to modify the logic. Your code is just checking when the collision happens, which won’t do it because collisions are not fired between began and ended phases. Try this:

-- tap to bounce -- hide status bar display.setStatusBar( display.HiddenStatusBar ) -- enable physics require( "physics" ) physics.start() physics.setGravity(0,10) physics.setDrawMode( "hybrid" ) -- walls physics.addBody( display.newRect( -5, 0, 10, display.contentHeight ), "static" ) physics.addBody( display.newRect( display.contentWidth-5, 0, 10, display.contentHeight ), "static" ) physics.addBody( display.newRect( 0, -5, display.contentWidth, 10 ), "static" ) physics.addBody( display.newRect( 0, display.contentHeight-5, display.contentWidth, 10 ), "static" ) -- ball local ball = display.newCircle( display.contentCenterX, display.contentCenterY, 40 ) physics.addBody( ball, "dynamic", { density=1, bounce=.8, friction=.5, radius=40 } ) ball.didTap = false ball.collidePhase = "ended" -- tap handling function tap(e) if (ball.collidePhase == "began") then ball:doBounce() elseif (ball.collidePhase == "ended") then ball.didTap = true end return true end Runtime:addEventListener("tap", tap) -- collision handling function ball:collision(e) ball.collidePhase = e.phase if (ball.didTap and e.phase == "began") then ball:doBounce() end return true end ball:addEventListener("collision", ball) -- bounce handling function ball:doBounce() ball:applyLinearImpulse( 0, 40, ball.x, ball.y ) ball.didTap = false end

Horace, that is genius. Thanks man. But if I want it to collide with some object (eg. color changer) that makes the ball do something else, like change color? Shall I add Collide.phase to the color changer stating that if any collision happens, the color should change? or use the precollision to detect and change options so to refine the bounce?

Objects should handle their own state, don’t pass it off to other objects or things will get complicated real quick.

I would say that if you want one type of object to change the ball’s colour, you should have the colour as a property on that object. When the ball collides with that object you can check the property and the ball can change it’s own colour.

Like this…

-- tap to bounce -- hide status bar display.setStatusBar( display.HiddenStatusBar ) -- enable physics require( "physics" ) physics.start() physics.setGravity(0,10) --physics.setDrawMode( "hybrid" ) -- groups walls, toys = display.newGroup(), display.newGroup() -- walls physics.addBody( display.newRect( walls, -5, 0, 10, display.contentHeight ), "static" ) physics.addBody( display.newRect( walls, display.contentWidth-5, 0, 10, display.contentHeight ), "static" ) physics.addBody( display.newRect( walls, 0, -5, display.contentWidth, 10 ), "static" ) physics.addBody( display.newRect( walls, 0, display.contentHeight-5, display.contentWidth, 10 ), "static" ) -- wall colours walls[1].colour = {255,0,0} walls[2].colour = {0,255,0} walls[3].colour = {0,0,255} walls[4].colour = {255,255,255} -- ball local ball = display.newCircle( toys, display.contentCenterX, display.contentCenterY, 40 ) physics.addBody( ball, "dynamic", { density=1, bounce=.8, friction=.5, radius=40 } ) ball.didTap = false ball.collidePhase = "ended" -- tap handling function tap(e) if (ball.collidePhase == "began") then ball:doBounce() elseif (ball.collidePhase == "ended") then ball.didTap = true end return true end Runtime:addEventListener("tap", tap) -- collision handling function ball:collision(e) ball.collidePhase = e.phase if (e.phase == "began") then local colour = e.other.colour ball:setFillColor( colour[1], colour[2], colour[3] ) if (ball.didTap) then ball:doBounce() end end return true end ball:addEventListener("collision", ball) -- bounce handling function ball:doBounce() ball:applyLinearImpulse( math.random(-100,100), 40, ball.x, ball.y ) ball.didTap = false end

Thanks. :) You have cleared all my difficulties. But, if I want to contact you, can you please Private message me your email?

tbh, best way is on here.

Where are you tapping? I see no reason why a finger tap on the screen would not be detected, though you should return true at the end of the tap function.

Your code does not run because you have not included the ball.lua file.

horacebury,

The tapping is global. And I created the sprite using TexturePacker, and the ball is shown and it does fall on the ground, but doesn’t jump…

Thanks for replying man.

The ball doesn’t show in the code snippet you provided because the ball library code is not there. But no matter…

It looks like you’re recording that the user tapped the screen and checking that when a collision occurs.

Seeing as you’re attaching the listener to the Runtime object, what happens if the .object1 is the wall and the .object2 is the ball?

well, I was saving it for later for the advanced coding, but I’m still stuck. Right now, its just to determine if the ball is still in air.

What I’m hinting at, is that the ball may not be the object1, it might be object2, in which case your IF statements will not make it bounce.