Hey Brent,
So basically, you get more flakes stopping outside/below the objects when their speed is increased, i.e. because of increased gravity?
It appears that it’s more prone to this when the speed is fast. I’m not too familiar how everything works “under the hood” so I can’t say with certainty, but my guess is that the step right before the “collision ended” is large. In other words, the sequence would go like this.
-
Flake is already colliding with the tree / land timer has started / flake is still traveling down
-
Due to high speed, the flake takes a large step to its next position, which in this circumstance, happens to be outside the tree’s physics body.
-
The land timer happens to complete, which stops the flake.
-
Collision end is triggered, which triggers the cancellation of the landTimer, which doesn’t do anything since the land timer has already completed.
Feel free to correct me if I’m wrong. And if I’m wrong, could you help me understand the situation a bit more?
I don’t think this is an issue with collision detection frequency, but you could try increasing the defaults and setting the flakes as “bullets” and see what happens:
http://docs.coronalabs.com/api/library/physics/setPositionIterations.html
http://docs.coronalabs.com/api/library/physics/setVelocityIterations.html
http://docs.coronalabs.com/api/type/Body/isBullet.html
I’ve tried all these options. As far as setPositionIterations and setVelocityIterations, I’ve tried an arguments of 1, 16 and even 50. Also, tried isBullet and setContinuous, but unfortunately I still get the issue (See attached image). Here’s a copy of your code, which I updated with these suggestions:
local physics = require( "physics" ) physics.start() physics.setGravity( 0,5 ) -- \<--------- GRAVITY AT physics.setDrawMode( "hybrid" ) physics.setContinuous( true ) -- \<----------- SET CONTINUOUS physics.setPositionIterations( 50 ) -- \<----------- SET POSITION ITERATIONS physics.setVelocityIterations( 50 ) -- \<----------- SET VELOCITY ITERATIONS local tail = {-117,12, -123,-46, -68,-13} local bodyBack = {-89,-26, -61,-39, -20,-46, 20,-49, 42,27, -12,28, -66,16, -94,0} local bodyFront = {20,-49, 71,-43, 107,-32, 121,-20, 126,-10, 108,5, 78,19, 43,27} local finBack = {-39,23, -11,29, -10,41, -32,50} local finFront = {-9,51, -11,28, 41,27, 15,42} local fishFilter = { categoryBits=1, maskBits=2 } local flakeFilter = { categoryBits=2, maskBits=1 } local fish1 = display.newRect( 0,0,250,50 ) fish1.alpha = 0 fish1.x, fish1.y = display.contentWidth/2, display.contentHeight/2-60 physics.addBody( fish1, "kinematic", { shape=tail, filter=fishFilter }, { shape=bodyBack, filter=fishFilter }, { shape=bodyFront, filter=fishFilter }, { shape=finBack, filter=fishFilter }, { shape=finFront, filter=fishFilter } ) local fish2 = display.newRect( 0,0,250,50 ) fish2.alpha = 0 fish2.x, fish2.y = display.contentWidth/2, display.contentHeight/2+50 physics.addBody( fish2, "kinematic", { shape=tail, filter=fishFilter }, { shape=bodyBack, filter=fishFilter }, { shape=bodyFront, filter=fishFilter }, { shape=finBack, filter=fishFilter }, { shape=finFront, filter=fishFilter } ) local function stopFlake( event ) local thisFlake = event.source.parent --this references the flake on which the timer is a property thisFlake:setFillColor( 1 ) thisFlake:setLinearVelocity( 0,0 ) physics.removeBody( thisFlake ) end local function flakeCollide( self, event ) if ( event.phase == "began" ) then if ( self.collCount == 0 ) then --this means that flake has NO contact with another element self:setFillColor( 1,0,0.2 ) --change flake color to red --print( "LAND TIMER STARTED" ) self.landTimer = timer.performWithDelay( math.random(1,1200), stopFlake ) self.landTimer.parent = self self.linearDamping = 2 --increase linear damping to make flake slow down end self.collCount = self.collCount+1 --increment self.collCount elseif ( event.phase == "ended" ) then self.collCount = self.collCount-1 --decrement self.collCount if ( self.collCount == 0 ) then --this means that the flake is currently touching NO other elements self:setFillColor( 0,0.8,0.4 ) --change flake color to green print( "LAND TIMER CANCELLED" ) timer.cancel( self.landTimer ) self.linearDamping = 0 --reset linear damping to make flake fall as normal end end end local function spawnFlake(x,y) local flake = display.newCircle( 0,0,4 ) flake.x = x flake.y = y flake:setFillColor( 0,0.8,0.4 ) --set flake color to green initially flake.collCount = 0 --flake has not collided with anything yet, so set to 0 flake.landTimer = nil physics.addBody( flake, { radius=1, isSensor=true, filter=flakeFilter } ) flake.isBullet = true -- \<------------------ IS BULLET flake.collision = flakeCollide flake:addEventListener( "collision", flake ) end --timer.performWithDelay( 200, spawnFlake, 80 ) local function onWorldTouch(e) spawnFlake(e.x,e.y) return true; end Runtime:addEventListener("touch", onWorldTouch)
Assuming there’s still nothing we can do (aside from my kill timer idea and offsetting the bottom of the physics body), maybe we can move on to the 2nd example? Do you have any suggestions for (or questions about) example 2?
On a side note, would you guys ever consider providing a “Polygon Contains Point” functionality? I feel like it would be extremely valuable.
Thank you for your time!