Wednesday, December 19, 2012

When Entities Collide

I implemented an event that fires when an entity collides with another entity. When setting up a demo for this event, I quickly realized I'd need to set up a system of conditional collisions--known as collision categories--to produce the desired behavior.

This is best demonstrated with a simple example. I have a brazier that can spawn moving fireballs. I want the fireballs to be destroyed when they touch a wall. But I also want the fireballs to pass over other braziers (and the brazier that it comes out of, if it spawns directly in the middle!)

Refer to the following video when reading the rest of this post, as it's much easier to explain in video format.



The first brazier has the following script:


local entity = section:CreateEntity(t);
entity:SetModel("Solid");
entity:Attach("selfCollideEntity", function() entity:Destroy() end)

This ends up creating an entity that passes through everything. Why? Because the entity has no collision targets. To fix this, we need to add the following script, which is on the second brazier:

entity:AddCollisionTarget("wall");

(Note that by default, all 'walls' are tagged with the collision category 'wall'. It's a special collision category which has the property of blocking the player's movement when the player collides. Setting a model to 'Solid' in the editor automatically adds the collision category 'wall'.)

Now the entity is destroyed at a wall. Unfortunately, the brazier is also tagged with 'wall', so that's where the fireball disappears. Our third brazier has the same script, but the brazier next to it has its 'wall' tag removed. In the video, you can see that the fireballs pass through the brazier, but so does the player.

The solution: tag the brazier as 'wall' and 'brazier'...




... and add the following to the fireball creation script:

entity:AddCollisionExclude("brazier");

In summary, this means the fireball collides with anything marked 'wall', as long as that thing isn't marked 'brazier'.

That's all for now!

2 comments:

  1. It seems like the true collision problem is one of height. The fireball is spawned above the brazier and travels until it hits an object that is at it's height. I know is a dimension of extreme complexity in a 2D world, but would it make sense to give entities a height?

    ReplyDelete
  2. Good observation, height does indeed model this problem correctly. It wouldn't even be that hard to implement--you'd just give every model an arbitrary number for height (or even a range--lower and upper) and the logic from then on is as simple as detecting an overlap of heights.

    However, game logic is often not realistic at all. For example, you might have types of enemies that absolutely do not collide with eachother, but collide with the player and walls. Come to think of it, even the fireballs problem has this problem: what if I don't want two fireballs to disappear when they collide? Setting up categories, while slightly more complex, solves these problems without too much trouble.

    ReplyDelete