Skip to main content

Physics

Physics simulation can make games much more engaging and realistic. Easel makes this easy with its built-in physics engine.

Simply give the entity a body and one or more colliders, and the physics engine will handle the rest.

pub also body = projectile
pub tangible category Category:Projectile

pub fn hero.LaunchProjectile() {
Spawn projectile {
use categories = Category:Projectile
use speed=48, radius=0.24, density=30, restitution=1, bullet=true

Body(
parent=hero,
pos=hero.Pos,
heading=hero.Heading,
speed=Direction(heading) * speed,
)

PolygonCollider(Circle)

once AfterCollide {
Expire
}

// ...
}
}

Detecting collisions

BeforeCollide is triggered when a collider is begins contact with another collider, and AfterCollide is triggered when a collider ends contact with another collider. You would typically use an on block to listen for these events.

on BeforeCollide that {
if that.Category.Overlaps(Category.Unit) {
that.Health -= 10
}
}

Isolating collisions

By default, BeforeCollide and AfterCollide receive collision events for every collider on the entity. Sometimes you may want to create a collider that should not trigger normal collision handling. For example, you might want to detect when a hero gets close to an obstacle. For this you can create a new proximity sensor collider with the isolate parameter of PolygonCollider set to true. Being close to an obstacle should not be treated the same as touching an obstacle, and so isolate=true is used to keep the collision handling separate.

Once a collider has been isolated, you must use BeforeCollide<Id> and AfterCollide<Id> to listen for its events, as its collision events will no longer be sent to the usual BeforeCollide and AfterCollide handlers anymore. This allows you to separate the handling of normal collisions from the handling of isolated collisions.

PolygonCollider<proximitySensor>(shape=Circle(10), category=Category:Proximity, isolate=true, isSensor=true)
on BeforeCollide<proximitySensor> that {
// Do something we sense something within 10 units of this entity
}

Stepping

Call the ForcefulStep to move the body to another position by applying a one-off force during the next physics simulation. Similarly, call ForcefulTurn to change the body's heading by applying a one-off torque during the next physics simulation.

This differs from just modifying Pos or Heading directly because that would simply teleport the body to its new position, whereas this applies a one-off force which can be transferred to other bodies if a collision occurs.

This technique makes a body realistically push other bodies when it is walking into them, for example a hero pushing into a boulder or into another hero.

Querying

Querying searches all colliders in the physics engine for the ones that meet certain conditions:

Note that the querying is performed on colliders not bodies. That means if a body has multiple colliders, it will be returned multiple times in the results.

Querying is done using a spatial index which is only calculated on demand and cached. The cached spatial index is deleted when the physics simulation is performed, and at the end of every tick. That means if a query is performed, and then body positions are changed manually, the next query will run on a stale spatial index and so results might not be accurate. You can force the spatial index to be recalculated by calling ResetSpatialQueryIndex.