Collision Problems, Filters, Dynamic, Kinematic, OH my!

So, I’m at my wits end… (yet again, my wit tends to end quite quickly)

I have a game with a world that has gravity. I have a floor. I have monsters that both walk and fly… but I have a problem now. (Yes, I’ve set up filters properly and both the walking and flying monster have the same filter)

The monsters that walk are bodyType = “dynamic.” This allows them to move along the floor with no problem. It also allows collisions with weapons and player and explosions to work properly.

But the monsters that fly… now that I’m baffled with.

If I set the monsters that fly to “dynamic” they fall straight into the floor. Ok, obviously, that makes sense and that’s NOT what I want (unless you can show me how to make dynamic objects that don’t fall with gravity), so I tried “static” but what I didn’t realize is that “static” objects don’t interact with other static objects and have rather limited set of things they interact with. Problem. So then I switched to “kinematic” thinking that would solve my problems.

It doesn’t.

So kinematic gets me oh so close… my flying enemies look like they are flying, and they respond to weapons and they hit the player… so far so good.

Problem. How do I handle explosions? How I’ve been doing it, and what works wonderfully with the dynamic ground walking enemies is I spawn an invisible circle of type “static” that has “.isSensor = true.” I then destroy it after a moment and deal the damage to the monsters and set their force vectors.

But these .isSensor explosions don’t seem to interact with the kinematic objects! So I tried turning them “dynamic” or “kinematic”… but it doesn’t matter… the isSensor flag makes it so that the explosion simply will not interact with the “kinematic” flying enemies.

If I remove the .isSensor, then all kinds of nastiness happens as the ground monsters end up getting pushed around by the invisible explosion object.

HELP! [import]uid: 37122 topic_id: 18497 reply_id: 318497[/import]

Would it perhaps be an idea to use a preCollision listener to change the body type then? (I may be picturing your game all wrong but how I imagine it this could help.)

Peach :slight_smile: [import]uid: 52491 topic_id: 18497 reply_id: 70942[/import]

Ok, rewind. I have no idea what you’re trying to tell me.

Sooo… the flying things, they should be kinematic then? And the explosion, that should be an isSensor?

Basically I fire missiles, and when the missile collides I want it to explode. It works great with the ground enemies (dynamic bodies) but the flying ones (kinematic) the missile hits (because it’s dynamic) and then I create the explosion (big invisible circle .isSensor = true) and listen for collisions. The sensor picks up collisions with the dynamic bodies but nothing happens with the kinematic ones so the missile explosion never does any damage to the flying enemies.

What exactly would the preCollision listener listen for? Which object am I changing the body type of? Sooo confused. I would love to use preCollisions if I even had a remote idea of what I’m listening for and understood why I need to change the body type?

Or am I doing this all completely wrong.

I suppose clear questions might help:

For an object that’s flying, am I correct in using a body type that’s “kinematic?” If not, how do I keep a flying object in the air?

For an explosion, is it correct to be using something like .isSensor to detect the collision? Is there a better way to be able to hit many different objects at once and send them in all directions without causing the physics engine to “push” things around because it’s a kinematic or dynamic object hitting another kinematic or dynamic object?

Basically imagine angry birds and the black bird. When the black bird explodes, it applies a force to all objects within a certain range of the black bird. I assume this is using some sort of collision and not a loop that iterates through all of the objects, measures the distance between them and the bird, and applies a force if it’s in range?

The problem is, imagine if there was a mix of objects that were affected by gravity and a bunch that were not. Now what?

BTW, thanks sooo much for the help and apologies for being so daft. [import]uid: 37122 topic_id: 18497 reply_id: 70960[/import]

are u applying force to your body to get expolosion if yes kinematic body can not affected by forces only on dynamic body can be affect by force

may be you should try applying very high dumping to your dynamic body and or change your kinematic body to dynamic on precollition
also use timer.performwithdelay when you goes to applyforce after changing bodytype or damping
:slight_smile:
be my friend

http://www.facebook.com/hgvyas123 [import]uid: 12482 topic_id: 18497 reply_id: 70966[/import]

Not really, I’m not even concerned with the force, I’m more concerned about the damage.

Right now the explosion.isSensor = true does not make ANY contact at all with the kinematic body. Since it doesn’t, I can’t reduce Monster.hp since neither the monster nor the sensor ever detect that the two have hit each other. Will preCollision detect something that a regular collision listener doesn’t detect?

I’ll give it a try tomorrow, but I don’t think preCollision will detect the collision between the sensor and the kinematic body since a regular listener won’t even detect it, but who knows, maybe I’ll be surprised.

Here is some pseudo code to try to explain

local createBaconBomb = function()  
  
 local onExplosionCollision = function(self, event)  
 if event.phase == "began" then  
 if event.other.myName == "monster" then  
 event.other.isHit = true  
 event.other.hp = event.other.hp - bombDamage  
 end  
 end  
 end  
  
  
 local onBombCollision = function(self,event)  
 if event.phase == "began" and (event.other.myName == "ground" or event.other.myName == "player" or event.other.myName == "monster") then --added test for ground  
 if self.isHit == false then  
 local bombDisappear = function()  
 self:setLinearVelocity( 0, 0 )  
 self.isVisible = false  
 self.isBodyActive = false  
 self.inAir = false  
 self.rotation = 0  
  
 local removeBomb = function()  
 gameGroup:remove(self)  
 end  
 timer.performWithDelay(10,removeBomb)  
 end  
 self.isHit = true  
  
 local moveSensor = function()  
 explosionSensor.x = self.x; explosionSensor.y = self.y  
 explosionSensor.isBodyActive = true  
 end  
  
 local killSensor = function()  
 explosionSensor:setLinearVelocity( 0, 0 )  
 explosionSensor.bodyType = "static"  
 explosionSensor.isVisible = false  
 explosionSensor.isBodyActive = false  
 explosionSensor.inAir = false  
 explosionSensor.rotation = 0  
  
 local removeSensor = function()  
 gameGroup:remove(explosionSensor)  
 end  
 timer.performWithDelay(10,removeSensor)  
 end  
  
 timer.performWithDelay(10,moveSensor)  
 timer.performWithDelay(50,bombDisappear)  
 timer.performWithDelay(200,killSensor)  
  
 elseif self.isHit then  
 return true  
 end  
 end  
 end  
  
 local sheet1 = sprite.newSpriteSheet("bomb.png", 64, 124)  
 local spriteSet2 = sprite.newSpriteSet(sheet1, 1, 2)  
 sprite.add( spriteSet2, "theBomb", 1, 2, 300, 0 )   
  
  
 bomb = sprite.newSprite(spriteSet2)  
 bomb.xScale = .25  
 bomb.yScale = .25  
 bomb.x = 250; bomb.y = 0  
 bomb.isVisible = true  
  
 bomb:prepare("theBomb")  
 bomb:play()  
  
 bomb.inAir = true  
 bomb.isHit = false  
 bomb.isBullet = true  
 bomb.myName = "theBomb"  
  
 bomb.radius = 3.5  
 physics.addBody(bomb,"dynamic",{density=30.0, bounce=0.1, friction=0.15, radius=bomb.radius,filter = weaponCollisionFilter})  
 bomb.rotation = 0  
 bomb.angularVelocity = 200  
  
 bomb.collision = onBombCollision  
 bomb:addEventListener("collision",bomb)  
  
 bomb.isBodyActive = true  
  
 gameGroup:insert(bomb)  
 bomb:toFront()  
  
 local explosionSensorRadius = 50  
  
 explosionSensor = display.newCircle(bomb.x,bomb.y,explosionSensorRadius)  
 explosionSensor.isVisible = false  
 explosionSensor.myName = "explosionSensor"  
  
  
 physics.addBody(explosionSensor,"static",{radius=explosionSensorRadius,filter = weaponCollisionFilter})  
 explosionSensor.rotation = 0  
 explosionSensor.isBodyActive = false  
 explosionSensor.isSensor = true  
 explosionSensor.isHit = false  
  
 explosionSensor.collision = onExplosionCollision  
 explosionSensor:addEventListener("collision",explosionSensor)  
  
 gameGroup:insert(explosionSensor)  
 end  
  

Note, this isn’t actual working code, again, it’s pseudo but loosely based on what I’ve done.

Make a note that onExplosionCollision NEVER fires if the object it hits is kinematic but it has no problems with dynamic.

The bomb will hit a monster and all bomb code will properly execute, moving the sensor to where it is, at this point I expect the sensor to detect a collision with any and all monsters around it, but it will only register collisions for the dynamic ones.

I still don’t understand how preCollision will help =/

How else might I go about doing this? (Not even sure the code helps) [import]uid: 37122 topic_id: 18497 reply_id: 70969[/import]

there is no collision possible between static and kinematic body

static and kinematic body can only collide with dynamic body

so change this line,

physics.addBody(explosionSensor,“static”,{radius=explosionSensorRadius,filter = weaponCollisionFilter})

:slight_smile:

be my friend

http://www.facebook.com/hgvyas123 [import]uid: 12482 topic_id: 18497 reply_id: 70972[/import]

also if your physics objects are in different group there are some problems with collision :frowning:

but luckily it is not case over here .

:slight_smile:
be my friend

http://www.facebook.com/hgvyas123 [import]uid: 12482 topic_id: 18497 reply_id: 70975[/import]

OMG. I can’t believe I didn’t try that.

/facepalm.

I was just about to reply and say “I already tried that” and then I went and did it, and what do you know… it worked.

Thanks a million! Feel like an idiot, but you guys helped much! [import]uid: 37122 topic_id: 18497 reply_id: 70992[/import]

Sorry I didn’t get a chance to help more - I started writing a little sample but lost it due to a power cut >.
Great to come back and see all solved :slight_smile:

hgvyas - sorry, I don’t like telling people off, but please stop posting that at the end of every post you make; http://developer.anscamobile.com/forum/2011/05/05/forum-rules-and-guidelines (Last point under advertising/spam.)

If you want to post it sometimes that’s OK - just make sure it’s appropriate and not every post :wink:

Peach :slight_smile: [import]uid: 52491 topic_id: 18497 reply_id: 71007[/import]

hi peach,

i had already read those rules long time ago and i thought it was ok to ask for friendship anyway as it is against rule i will not do now forgive me plz.
:slight_smile: [import]uid: 12482 topic_id: 18497 reply_id: 71015[/import]

I’m having problems with this too.

Right now my actor collides with the static items and the pickup items and that’s working fine.

At the end of the level, I go into a mode of where I shoot bullets at the level boss and I detect a collision with my actor which I should not and I don’t get collisions with the level boss (though if my actor runs into the level boss, that is detected.

local staticCollisionFilter = { categoryBits = 1, maskBits = 6 }  
local actorCollisionFilter = { categoryBits = 2, maskBits = 1 }   
local bulletCollisionFilter = { categoryBits = 4, maskBits = 1}  
  
...  
  
local blockerBaseShape = { -25,40, 25,40, 25,0, -25,0 }  
local blockerPhysics = { density = 10.0, friction = 1.0, bounce = 0.2, shape=blockerBaseShape, filter=staticCollisionFilter }  
  
...  
-- this is my level boss  
  
physics.addBody( objects[1], "kinematic", { density=1.5, friction=0.5, bounce=0.8, filter=staticCollisionFilter } )  
  
-- this is my end goal object  
  
physics.addBody( objects[2], "kinematic", { density=1.5, friction=0.5, bounce=0.3, filter=staticCollisionFilter } )  
objects[2].isSensor = true  
  
-- these are static things that stop the actor  
  
physics.addBody( objects[i], "static", blockerPhysics )  
  
-- these are my pickup items  
  
physics.addBody( objects[i], "static", { density=1.0, friction=0.5, bounce=0.3, filter=staticCollisionFilter})  
objects[i].isSensor = true  
  
-- everything is inserted into my camera group.  
  
...  
  
-- this is my actor  
local actorBaseShape = { -25,40, 25,40, 25,0, -25,0 }  
  
physics.addBody(actor, "dynamic", { density=1.0, friction=0.5, bounce=0.3, shape=actorBaseShape, filter=actorCollisionFilter})  
actor.isBullet = true  
actor.isSensor = true  
  
...  
  
-- Here are my bullet creation bits  
  
physics.addBody(b, "dynamic", { density=1.0, bounce=0.0, friction=0.1, filter= bulletCollisionFilter})  
b.isBullet = true  
  
Runtime:addEventListener( "collision", onCollision )  

The collision handler

local function onCollision(event)  
 --print\_r(event)  
 print(event.phase .. " " .. event.object1.name .. " is colliding with " .. event.object2.name)  
 local hit = event.object1  
 if event.phase == "began" then  
 if hit.isPickup then  
 timer.performWithDelay(10, function() pickUp(hit) end)  
 elseif hit.killsPlayer then  
 killPlayer(hit)  
 end  
 end  
 return true  
end  

here is what I get in my console log:

began actor is colliding with bullet  
ended actor is colliding with bullet  

I should get messages when my bullets collide with objects[1] and objects[2]

any ideas?
[import]uid: 19626 topic_id: 18497 reply_id: 71147[/import]

i think we clearly need more advanced physics handling, more options, not just dynamic, static and kinematic) it would be great to not apply gravity to particular object or something like that [import]uid: 16142 topic_id: 18497 reply_id: 71151[/import]

Hey, Rob, have you tried adding a type or id to each object being hit and filter the collision event based on what type/id the object is?

I haven’t really carefully looked at the code you posted, but the idea is something like:

[lua]-- give type to each object when the object is created in your code
actor.type = “actor”
boss.type = “boss”[/lua]

And a function that a bullet may trigger when hitting something may look like:
[lua]local function onBulletHit(event)
local target = event.other
if event.phase == “began” then
if (target.type == “actor”) then
– do this
elseif (target.type == “boss”) then
– do this
end
end
end [/lua]

I use this approach when I have dynamic objects collide with sensor objects (and when I want to have different effect/action triggered by each specific type of object). I’m not sure if this would work with dynamic objects colliding with other dynamic objects (because I haven’t used it that way) – but maybe it’s worth a try?

Naomi
[import]uid: 67217 topic_id: 18497 reply_id: 71156[/import]

Its not even triggering the collision so my event handler never gets called…
[import]uid: 19626 topic_id: 18497 reply_id: 71172[/import]

Hey Rob, just a thought… have you checked the physics body difference between the actor and the boss? If actor is getting the hit but not the boss, maybe how you set up the boss’ physics body is the problem?

Naomi [import]uid: 67217 topic_id: 18497 reply_id: 71175[/import]

What do you mean? I have it set to display in hybrid mode so I can see the collision boxes and I see them pass through each other and I don’t see my event handler getting hit, since the print is the first thing in the funtion.

[import]uid: 19626 topic_id: 18497 reply_id: 71176[/import]

Arrgh. So clearly this physics engine is the BANE of my existence.

I agree that we need more advanced controls. The inability to have objects that behave like dynamic ones but are not affected by gravity… would help enormously.

I am in the process of changing my control scheme and now I’ve hit another wall.

Lets say you want to launch a projectile from coordinates:

x=10, y = 200

and you want to be able to tap anywhere on the screen and have the projectile pass through the point where your finger touched.

So you touch

x= 200, y = 10

It would be cake to calculate if there was no gravity. In fact I did it with a kinematic object and sweet, it worked great (pseudo):

local onTouch = function( event )  
 local x = event.x - weapon.x  
 local y = event.y - weapon.y  
  
 local angle = math.atan(y/x)  
  
 local xComponent = velocity\*math.cos(angle)  
 local yComponent = velocity\*math.sin(angle)  
  
 weapon:setLinearVelocity( xComponent, yComponent)  
end  

Beautiful… EXCEPT the stupid weapons, being kinematic, pass right through all of the walls of the stage. NOT good.

So I set them to dynamic. But now of course, being affected by gravity as they now are, are NEARLY IMPOSSIBLE to get to pass through where my finger touches. And I’m about to take my keyboard and snap it in half.

This is my new code, which simply will NOT work. It gets close, but simply doesn’t work, and I’m hoping someone here, with greater math skills than I have (or who can figure out how to make kinematic objects hit static ones or make dynamic ones that have no gravity)

(pseudo)

local onTouch = function( event )  
 local angle  
 local x = event.x - weapon.x  
 local y = event.y - weapon.y  
  
 local velocity = 200  
 local gravity = 5  
 local temp = math.pow(velocity,4) - gravity \* (gravity\*math.pow(x,2)+2\*y\*math.pow(velocity,2))  
  
  
 if x==0 then  
 angle = -1\*math.pi/2  
 else  
 angle = math.atan((math.pow(velocity,2)-math.sqrt(temp)) / (gravity \* x))  
 end  
  
 local xComponent = velocity\*math.cos(angle)  
 local yComponent = velocity\*math.sin(angle)  
  
 weapon.bodyType = "dynamic"  
 weapon:applyForce( xComponent, yComponent, weapon.x, weapon.y )  
end  

As you can see, the formula is wildly more complex, and yet, it doesn’t make the object pass through my finger. The farther I am from the point of origin, the more effect gravity has, despite the formula accounting for gravity. The problem that remains I believe is that instead of specifying velocity, I’m applying a force, and forces take mass into account, which I’m not dealing with here at all.

F=1/2mv^2 but no matter what I do, I’m not getting something right. (Especially since this thing has me specifying mass by specifying density and size…WTf?) [import]uid: 37122 topic_id: 18497 reply_id: 71180[/import]

Gigaflop - would it be possible to use transition.to() for your projectile? You could use easing if you don’t like the initial effect, perhaps?

Just a thought.

Peach :slight_smile: [import]uid: 52491 topic_id: 18497 reply_id: 71184[/import]

My understand that kinematic is just like dynamic except it’s not affected by gravity.

Static objects don’t interact with other static objects, but kinematic should interact with static.

Of course you could set a dynamic body to a density of 0.0 and it should “float”.

Is this not the case?

It also doesn’t figure out why my things aren’t colliding…
As for isSensor, if I understand correctly isSensor makes the object not react to physics but is supposed to generate collisions. If you don’t want your explosion affecting other objects, why not just play an animation using a sprite or a movie clip where you want it and not have it be a physics object? Hide the missile, show the explosion and hide the target.
[import]uid: 19626 topic_id: 18497 reply_id: 71187[/import]

@rob

Kinematic most definitely does not interact with static. I’ve tested it a hundred times. Switching to dynamic generates collisions, kinematic does not.

Also tried density of 0.0. Still fell.

As for your question about isSensor, I want to control the force applied to the objects when they interact with the “explosion.” I DO want every object touched by the explosion to be affected by it, but not the way the physics engine treats it. If you don’t use isSensor, the objects touching it act like they are being pushed around by some big invisible wall, instead of acting like an explosive force sent them flying in different directions.

@Peach

Gonna try the transition.to. Didn’t realize that physics objects could be moved with it… and wondering what will happen when I destroy the object upon collision before transition.to is finished with it… Guess I’ll find out. [import]uid: 37122 topic_id: 18497 reply_id: 71196[/import]