Collision and Response
Collision and Response
Collision detection
- Using a space partitioning algorithm to dispatch all the Scene
Entity
list into some space cell, according to a limited number of nodes per cell, and a limited level of depth into the partition tree. The selected pattern is a Quadtree. - Detect collision between
STATIC
andDYNAMIC
PhysicType’s Entity (NONE
are excluded). - On collision process response by calling the
Behavior#onCollide(CollisionEvent)
method for each concernedEntity
.
Entity update
The Entity
class is updated with some new attributes :
-
collisions
: a list of CollisionEvent.
public static class Entity {
//...
private final Collection<CollisionEvent> collisions = new ArrayList<>();
public Entity add(CollisionEvent ce) {
collisions.add(ce);
return this;
}
public Collection<CollisionEvent> getCollisions() {
return collisions;
}
//...
}
Behavior update
The existing Behavior interface is updated with a new event;: onCollide(CollisionEvent):
public interface Behavior<Entity> {
//...
default void onCollision(CollisionEvent ce) {
}
}
CollisionEvent
We need a new object to define a collision: the CollisionEvent
containing src and target of the collision, the
collision normal, the depth of penetration factor and a collision side:
public static class CollisionEvent {
private final Entity srcCollision;
private final Entity dstCollision;
private Vector2D collisionNormal;
private double penetrationDepth;
private CollisionSide side;
// getters and setters.
}
Collision Detection
On each detected collision, a CollisionEvent
is created and dispatch to concerned Entity
’s.
public class KaraPlatform {
//...
public void update(long d) {
Collection<Entity> entities = sceneManager.getCurrent().getEntities();
// <1>
cullingProcess(this, d);
entities.stream()
.filter(Entity::isActive)
.forEach(e -> {
if (!e.getPhysicType().equals(PhysicType.NONE)) {
// compute physic on the Entity (velocity & position)
applyPhysics(world, e, d);
// <2> detect collision and apply response
detectCollision(world, e, d);
//...
}
});
//...
}
//...
public synchronized void cullingProcess(KarmaPlatform game, double d) {
spacePartition.clear();
sceneManager.getCurrent().getEntities().stream()
.filter(Entity::isActive)
.forEach(e -> {
spacePartition.insert(e);
});
}
}
- Modify the
KarmaPlatform#update
method to manage the Space partitioning -
Let’s detect possible collision
- And the detection process itself by checking only the concerned space partition and the contained Entities :
private void detectCollision(World w, Entity e, double d) {
Collection<Entity> entities = sceneManager.getCurrent().getEntities();
List<Entity> collisionList = new CopyOnWriteArrayList<>();
// <3>
spacePartition.find(collisionList, e);
collisionCounter = 0;
e.clearCollisions();
collisionList.forEach(o -> {
if (e.isActive() && !o.equals(e) && o.isActive()
&& !o.getPhysicType().equals(PhysicType.NONE)) {
collisionCounter++;
handleCollision(e, o);
}
});
}
The handling of the resulting collision is processed into the handleCollision
method.
Collision Response
TODO
- capture and process event
- update Entity position