Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

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.

share|improve this question
4  
Filtering is the typical approach here. Essentially that's what you've described. There's also layers. Two layers, bad layer and good layer. Bad guys projectiles are fired into the good layer and vise versa. –  Byte56 Jun 20 '13 at 22:41
    
@Byte56 Can you elaborate on this "layer" concept? Or at least link to something about it? I've never heard of that before. –  Daniel Kaplan Jun 20 '13 at 23:00
    
Essentially they're different "worlds". All the objects in a layer interact with each other, but don't interact with any other layer. This can be done with tags (like filtering), or by totally different datasets for each layer. –  Byte56 Jun 20 '13 at 23:06
3  
In a word, it's grouping. Group good bullets and only check for collision against bad guys. Flixel has a concept like this. –  ashes999 Jun 20 '13 at 23:42
2  
One nitpicky design note: do you want 'friendly-fire' shots to hit but do no damage, or do you want them to completely ignore allies, possibly passing through them to strike enemies instead? –  Steven Stadnicki Jun 21 '13 at 6:21

2 Answers 2

up vote 6 down vote accepted

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
share|improve this answer
    
Would you mind explaining this conceptually instead of explaining it at a low level detail of bit arithmetic? –  Daniel Kaplan Jun 26 '13 at 20:15
    
@tieTYT sure check again in 5 mins –  ClassicThunder Jul 2 '13 at 17:39

I had the same problem at my current project (in Java). After a couple tries is solved it by creating four lists. This solution is created in Java and for a 2D Game but should also work, in a similar way, in JavaScript

public static main (String [] args)
{
    private List<Bullets> bullets_GoodGuys = new LinkedList <Bullet>(); //List of all bullets fired by good guys
    private List<Bullets> bullets_BadGuys  = new LinkedList <Bullet>(); //List of all bullets fired by bad guys
    private List<Guys> goodGuys  = new LinkedList <Guys>(); //List of all good guys
    private List<Guys> badGuys  = new LinkedList <Guys>();  //List of all good guys

    init();
    ...
    while(game_is_running)
    {
        ... 
        for(int i=0;i>=goodGuys.length;i++)
        {
            for(int j=0;j>=bullets_BadGuys.length;i++)
            {
                if(goodGuys.get(i).getBounding().interacts(bullets_BadGuys.get(i).getBounding()))
                {// If a good guy was hit by a bullet from a bad guy
                    goodGuys.get(i).getDamage();
                    bullets_BadGuys.remove((bullets_BadGuys.get(i));
         }   }   }
       for(...) //same for the bad guys
       {...}
}

pseudo-code

class Guys
{
   private float xkoordinate;
   private float ykoordinate;
   private BufferedImage look;
   private Rectangle bounding = new Rectangle(xkoordinate,ykoordinate,look.getWith(),look.getHight())
   ...
}

pseudo-code, same for the class Bullets

This might not be the best or fastest solution but it will help you in the moment. I’m sorry that I cannot give you a solution in JavaScript but I hope I could help you

By the way my English isn’t the best but I hope you could follow my explanation

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.