Excalibur comes built in with two physics simulations.
Arcade physics simulation is on by default, but can be enabled explicitly at any time with ex.Physics.useArcadePhysics()
Physics.useArcadePhysics();
const game = new Engine({...});
Realistic physics are not on by default, but can be enabled explicitly at any time with ex.Physics.useRealisticPhysics()
Physics.useRealisticPhysics();
const game = new Engine({...});
ex.Physics.useRealisticPhysics();
ex.Physics.acc = ex.vec(0, 300);
const game = new ex.Engine({
width: 600,
height: 400,
displayMode: ex.DisplayMode.FitScreen
});
const box = new ex.Actor({
pos: ex.vec(game.halfDrawWidth, -100),
width: 50,
height: 50,
rotation: Math.PI / 3,
color: ex.Color.Red,
collisionType: ex.CollisionType.Active
});
const trianglePoints = [ex.vec(-20, 20), ex.vec(0, -20), ex.vec(20, 20)];
const triangle = new ex.Actor({
pos: ex.vec(game.halfDrawWidth, 100),
rotation: Math.PI / 3,
collider: new ex.PolygonCollider({points: trianglePoints}),
collisionType: ex.CollisionType.Active
});
const triangleGraphic = new ex.Polygon({points: trianglePoints, color: ex.Color.Green});
triangle.graphics.use(triangleGraphic);
const circle = new ex.Actor({
pos: ex.vec(game.halfDrawWidth + 20, -200),
radius: 30,
color: ex.Color.Yellow,
collisionType: ex.CollisionType.Active
});
const ground = new ex.Actor({
pos: ex.vec(game.halfDrawWidth, game.drawHeight),
width: game.drawWidth,
height: 100,
color: ex.Color.DarkGray,
collisionType: ex.CollisionType.Fixed
});
// start-snippet{collision}
game.start().then(() => {
game.currentScene.add(box);
game.currentScene.add(circle);
game.currentScene.add(triangle);
game.currentScene.add(ground);
game.currentScene.camera.pos = ex.vec(game.halfDrawWidth, game.halfDrawHeight);
});
See Physics documentation for more
ex.Physics.enabled = false
ex.Physics.acc = ex.vec(0, 100)
ex.Physics.checkForFastBodies = true
ex.Physics.positionIterations = 3
ex.Physics.velocityIterations = 8
The physics simulation has 2 major pieces for actors
Actors come out of the box with both of these components, an implicitly created BodyComponent and a ColliderComponent
of a box that matches the specified width
and height
, or a circle
const actor = new ex.Actor({
pos: ex.vec(200, 200),
width: 100,
height: 100,
collisionType: ex.CollisionType.Active,
})
const builtInBox = actor.collider.get()
Reminder entities don't have anything pre-built, all Actors are Entities, but with the common built in features included.
const entity = new ex.Entity([
new TransformComponent(),
new BodyComponent(),
new ColliderComponent(),
])
const tx = entity.get(TransformComponent)
const body = entity.get(BodyComponent)
const collider = entity.get(ColliderComponent)
// setup game
const game = new ex.Engine({
width: 600,
height: 400
});
// use rigid body
ex.Physics.collisionResolutionStrategy = ex.CollisionResolutionStrategy.RigidBody;
// set global acceleration simulating gravity pointing down
ex.Physics.acc.setTo(0, 700);
const block = new ex.Actor({
pos: new ex.Vector(300, 0),
width: 20,
height: 20,
color: ex.Color.Blue
});
block.body.useBoxCollider(); // useBoxCollision is the default, technically optional
block.body.collider.type = ex.CollisionType.Active;
game.add(block);
// or
const block = new ex.Actor({
pos: new ex.Vector(300, 0),
color: ex.Color.Blue,
body: new ex.Body({
collider: new ex.Collider({
type: ex.CollisionType.Active,
shape: ex.Shape.Box(20, 20)
})
})
});
const circle = new ex.Actor({
x: 301,
y: 100,
width: 20,
height: 20,
color: ex.Color.Red
});
circle.body.useCircleCollider(10);
circle.body.collider.type = ex.CollisionType.Active;
game.add(circle);
// or
const circle = new ex.Actor({
pos: new ex.Vector(301, 100),
color: ex.Color.Red,
body: new ex.Body({
collider: new ex.Collider({
shape: ex.Shape.Circle(10),
type: ex.CollisionType.Active
})
})
});
const ground = new ex.Actor({
x: 300,
y: 380,
width: 600,
height: 10,
color: ex.Color.Black;
});
ground.body.useBoxCollider(); // optional
ground.body.collider.type = ex.CollisionType.Fixed;
game.add(ground);
// start the game
game.start();