TwoDee provides a simple collision detection system. By default all scene nodes are excluded from this collision detection to maximize the rendering performance. To enable the collision detection you must give each scene node which can be part of a collision a collision type and each scene node which should be checked for collisions must have a collision mask which tells the node with which other collision types it can collide. Events are fired when objects begin to collide and when they no longer collide.
Sounds complicated? Ok, lets do this step by step.
First of all we need a nice scene. We start with an asteroid at a fixed position (and we make it a little bit smaller):
image = new Image(); image.src = "asteroid.png"; var asteroid = new twodee.ImageNode(image); rootNode.appendChild(asteroid); asteroid.getTransform().translate(-100, 0).scale(0.5);
We also apply a spin to it (just because it looks good):
var physics = new twodee.Physics(); asteroid.setPhysics(physics); physics.setSpin(0.5);
Now we want to create a spaceship which flies in a circle and collides with the asteroid. Simplest method is creating an invisible scene node with a spin and adding the spaceship somewhere on the right side of this rotator scene node. Because child nodes of scene nodes are also affected by their tranformation matrix the spaceship now smoothly flies in a circle:
var rotator = new twodee.SceneNode(); rootNode.appendChild(rotator); physics = new twodee.Physics(); rotator.setPhysics(physics); physics.setSpin(-1); var image = new Image(); image.src = "spaceship.png"; var ship = new twodee.ImageNode(image); rotator.appendChild(ship); ship.getTransform().translate(100, 0);
Now we have a good-looking scene with two colliding objects but the collision isn't detected yet. Let's change this.
First each object in the scene which shall be able to collide with something needs a collision type. This is a number which you can define on your own. Only rule is that is must be a power of two. So you can use 1, 2, 4, 8, 16, 32, and so on. In our example we use 1 for the asteroid and 2 for the spaceship:
asteroid.setCollisionType(1); ship.setCollisionType(2);
Now both objects can be part of a collision detection but still nothing happens because both objects are set to collide with nothing by default. This can be changed by setting the collision mask. We want to check if the ship collides with the asteroid so we give it a collision mask of 1. When you define more collision types (Maybe you have a UFO with collision type 4) then you can add the collision types to build the collision mask. Asteroid (1) plus UFO (4) results in a collision mask of 5 for example. But we have no UFO here so 1 is sufficient:
ship.setCollisionMask(1);
Time to connect the event handlers so we can actually do something when the objects collide. This is done with the connect() method of the scene node:
ship.connect("collisionStarted", function(ship, something)
{
...Do something when the ship collides with something...
});
ship.connect("collisionStopped", function(ship, something)
{
...Do something when the ship no longer collides with something...
});
The two objects involved in the collision are passed as arguments to the handler function. When you want to remove an event handler from a scene node then you can use the disconnect() method for this.
Ok, we already did a lot of stuff to enable collision detection but it still doesn't work. Well, that's because TwoDee can't know which parts of an image can collide. When you use polygon nodes then the collision detection works out of the box because the polygon itself also defines the collision bounds. But for image nodes you must specify such bounds in form of a polygon:
asteroid.setBounds(new twodee.Polygon([
new twodee.Vector(-32, -10),
new twodee.Vector(-15, -32),
new twodee.Vector(8, -32),
new twodee.Vector(30, -14),
new twodee.Vector(30, 4),
new twodee.Vector(12, 30),
new twodee.Vector(-10, 30),
new twodee.Vector(-24, 22),
new twodee.Vector(-32, -4)
]));
ship.setBounds(new twodee.Polygon([
new twodee.Vector(-11, 8),
new twodee.Vector( 0, -18),
new twodee.Vector( 11, 8),
new twodee.Vector( 11, 13),
new twodee.Vector( 4, 17),
new twodee.Vector( -4, 17),
new twodee.Vector(-11, 13)
]));
It's important to know that the collision bounds polygon always must be defined in clockwise order and must define a convex polygon. Concave polygons won't work.