Physics
Physics simulation can make games much more engaging and realistic. Easel makes this easy with its built-in physics engine.
pub tangible category Category:Ship
pub game fn World.Main() {
SpawnEachPlayer owner {
Subspawn ship {
use body=ship, radius=1, shape=Equilateral(numPoints=3)
Body(pos=20*RandomVector)
PolygonCollider(category=Category:Ship)
PolygonSprite(color=#0f0)
}
on BeforeCollide that {
Print { "Hero collided!" }
}
}
}
Bodies
A body represents a physical object that has a position and velocity, amongst other properties. Give your entity a body with the Body function:
Subspawn ship {
Body(pos=20*RandomVector)
}
You can now get or set various physical properties on the body:
- Pos is the body's position in the world.
- Heading is the body's orientation.
- Velocity is the body's velocity.
- TurnRate is the body's rate of rotation.
Subspawn ship {
use body=ship
Body(pos=@(10,10))
Velocity = @(20,20)
}
It is very common to write use body=ship or similar at the top of your blocks.
Many functions in Easel require a body parameter, and this is a convenient way to avoid having to specify it every time.
Colliders
By itself, a body does nothing. You need to attach a collider to it to make it interact with the world, using the PolygonCollider function. A collider gives the body a physical shape and mass. This allows the physics engine to calculate when two bodies collide with each other, and how their velocities should change as a result of the collision.
Subspawn ship {
use body=ship
Body(pos=20*RandomVector)
PolygonCollider(category=Category:Ship, shape=Equilateral(radius=1, numPoints=3))
}
A PolygonCollider requires a few parameters to be specified:
bodyspecifies which Body the collider is attached to.categoryspecifies which Category the collider belongs to. This is used for collision filtering and querying.shapespecifies the shape of the collider, for example a Circle. See Polygons for all the different shapes you can use.
Other body attachments
A body can have many attachments other than just colliders. For example:
- Graphical attachments like a PolygonSprite or Camera. See Graphics for more details.
- Sound attachments like Sing or Hear. See Audio for more details.
Subspawn ship {
use body=ship, radius=1, shape=Equilateral(numPoints=3)
Body(pos=20*RandomVector)
PolygonCollider(category=Category:Ship)
PolygonSprite(color=#0f0)
Hear(@ship-launch.esfx)
on Paint {
Spark(color=#f80)
}
}
Detecting collisions
The physics engine can report when two colliders collide with each other.
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
}
}
See Detecting Collisions for more information about collision detection.
Parent-child Collisions
There is a common issue where child colliders should not collide with their parents. For example, when a ship spawns a plasma bolt, the plasma bolt should not collide with the ship that spawned it, at least not for the first few moments after it is spawned. Otherwise, the plasma bolt might damage its own ship.
The parent parameter of the PolygonCollider
function can be used to specify a parent body for the collider.
The collider will keep ignoring collisions with the parent until it has been separated from the parent.
It will also ignore collisions with any other colliders that have the same parent until separated from them.
This is useful, for example, if you are firing multiple projectiles at once from the same ship.
Decay and friction
All bodies exist in a frictionless world where they will keep moving forever unless acted on by a force. This can mean that, after a collision, a body might keep sliding forever or keep spinning forever.
One way to solve this is to give colliders some friction.
The PolygonCollider function has a friction parameter
that you can set to a value between 0 and 1.
This works well if you are making a game with Gravity,
and your players generally walk on land,
Give the ground collider some friction and they will slow down naturally when they walk on it.
If you are making a top-down game, then the DecaySpeed and DecayTurnRate functions can be used to make bodies slow down over time even when they are not in contact with any other bodies.
Timescale
Normally, the physics simulation moves forward at the same rate as the game ticks,
but you can change this using the PhysicsTimescale property
to create various effects.
A value of 1 is normal speed, 0.5 for half speed, 2 for double speed,
and 0 to pause the physics simulation entirely.