Wednesday, December 30, 2015

collision detection - How do I make good guy attacks only hit bad guys and vice versa?


My game has many different type of good guys and many different type of bad guys. They will all be firing projectiles at each other but I don't want any accidental collateral damage to occur for either alignment. So bad guys should not be able to hit/damage other bad guys and good guys should not be able to hit/damage other good guys.


The way I'm thinking of solving this is by making it so that the Unit instance (this is javascript, btw), has an alignment property that can be either good or bad. And I'll only let collision happen if the


class Attack

boolean didAttackCollideWithTarget(target)
return attack.source.alignment != target.alignment and collisionDetected(attack.source, target)


This is pseudo-code, of course.


But I'm asking this question because I get the sense that there might be a much more elegant way to design this besides adding yet another property to my Unit class.



Answer



Collision Filtering


A more robust situation that scales into many layers is to use filtering, which is not the same thing as grouping.


This works best by giving every object 2 bitmasks.


Category
Mask

And only trigger a collision if the below is true.



(filterA.maskBits & filterB.categoryBits) != 0 &&
(filterA.categoryBits & filterB.maskBits) != 0;

Its easiest to default the Mask to 0xFFFF which results in it colliding with everything. And default the Category to 0x0001. objects collide with the categories in the others mask will there be a collision.


Another way to think of it is each object has a type and a list of all the types it can collide with. Only when two objects both collide with the types of each other is there a collision. You could have the same behavior having a list of enums instead of a mask but a mask in an order of magnitude faster.


Scenario you describe


I like to take advantage of enums in this situation.


So say we have.


enum Categories {
GoodGuy = 0x0001,

BadGuy = 0x0002,
Bullet = 0x0004,
GlassWall = 0x0008,
Lazer = 0x0010,
All = 0xFFFF
};

Bullet shot by a good guy


 Category = Bullet
Mask = BadGuy | GlassWall


Good Guys


 Category = GoodGuy
Mask = All

Bad Guys


 Category = BadGuy
Mask = All

Which results in the below when a Bullet shot by a good guy hits another good guy.



(All & GoodGuy) != 0 && <-- Passes
(GoodGuy & (BadGuy | GlassWall)) != 0; <-- This would fail

But it will hit bad guys.


(All & BadGuy) != 0 && <- Passes
(BadGuy & (BadGuy | GlassWall)) != 0; <-- Passes

No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...