Physics
Bare has two optional physics engines. Neither is included in your build unless you import it.
Arcade physics
Simple rectangle and circle collisions, good for platformers and top-down games. Import from bare-engine/arcade and register it in your scene:
import { ArcadeObject, ArcadePhysicsController } from 'bare-engine/arcade';
export class Game extends Scene
{
OnAwake()
{
bare.AddClass(ArcadeObject);
bare.AddClass(ArcadePhysicsController);
}
}Then give your prefabs "baseClass": "ArcadeObject":
{
"name": "player",
"baseClass": "ArcadeObject",
"texture": "player"
},
{
"name": "block",
"baseClass": "ArcadeObject",
"texture": "block",
"static": true
}Set gravity at the top level of settingsData.json:
{
"gravity": 5000
}Example: the Platformer registers arcade physics, sets gravity, and makes its prefabs ArcadeObjects.
ArcadeObject
| Property | Default | Description |
|---|---|---|
velocity | { x: 0, y: 0 } | Speed in units per second (Vec2). |
static | false | Doesn't move; other objects collide with it. |
collide | true | Takes part in collisions. |
sensor | false | Reports collisions but doesn't block, and ignores stayInBounds. Use it for triggers, like coins or checkpoints. |
drag | 0 | Fraction of the velocity lost every 1/60 second, from 0 to 1. |
restitution | 0 | Bounciness, from 0 to 1. Two objects bounce with the lower value of the two. |
stayInBounds | true | Keep the object inside the level. |
removeOnOutOfBounds | false | Remove the object when it's fully outside the level. |
hitbox | the image | Rectangle as { x1, y1, x2, y2 }. Values between 0 and 1 are a fraction of the image size, larger ones are pixels. "FULL" covers the whole image. |
hitboxType / hitboxRadius | "Rectangle" | "Rectangle" or "Circle", and the circle's radius. |
A child ArcadeObject always acts as a sensor, so it reports collisions without pushing anything.
| Method | Description |
|---|---|
SetVelocity(vec) / SetVelocityXY(x, y) / ResetVelocity() | Change velocity. |
IsGrounded() | Standing on something. Same as IsBlocked(BlockedState.Down). |
IsBlocked(direction) | Blocked in a direction: BlockedState.Up, Down, Left or Right. |
IsMoving() | Has velocity. |
Examples: the Platformer's player moves with velocity and checks IsGrounded, and RPG enemies roam with SetVelocity. The Showcase has an arcade physics demo.
Collisions
Handle collisions in a component:
export class CoinComponent extends Component<ArcadeObject>
{
OnCollisionStart(other: GameObject)
{
if (other.name == 'player')
this.go.Remove();
}
}OnCollisionUpdate runs every frame during contact, and OnCollisionEnd when it ends.
Examples: Platformer coins are collected on collision, and Shmup ships take damage from bullets.
Collision layers
By default, every object collides with every other object.
WARNING
That default only holds when your layers list includes "objects". If it doesn't, the engine adds an objects layer itself, and only objects on that layer collide, with each other. Add "objects" to layers, or use collidesWith.
To choose which layers collide, give them collidesWith in layersInfo:
"layers": ["enemies", "bulletsEnemy", "bulletsPlayer", "player"],
"layersInfo": {
"bulletsPlayer": {
"collidesWith": ["enemies"]
},
"bulletsEnemy": {
"collidesWith": ["player"]
},
"enemies": {
"collidesWith": ["player"]
}
}Now your bullets hit enemies, enemy bullets and enemies hit you, and nothing else collides. Bullets don't hit each other, and enemies don't push each other around.
- A pair collides when either layer lists the other, so you only need to write it once.
- As soon as one layer has
collidesWith, layers without it don't collide with anything. List every pair that should collide, including a layer with itself if needed, like"collidesWith": ["objects"]forobjects. - Children count as being on their root object's layer.
Example: this is the Shmup's layersInfo.
Realistic physics
Rigid-body physics with rotation, friction, mass and joints, based on Sopiro/Physics. Use it when objects should tumble, stack, swing or roll. It works, but it isn't as well supported as arcade physics yet.
Import it from bare-engine/sopiro and register the controller. That also registers all its body and joint classes:
import { SopiroPhysicsController } from 'bare-engine/sopiro';
export class Game extends Scene
{
OnAwake()
{
bare.AddClass(SopiroPhysicsController);
}
}Gravity is read from gravity in settingsData.json, like arcade physics. Without it, realistic physics uses a gravity of 1200.
Bodies
Set one of these as a prefab's baseClass:
| Class | Shape |
|---|---|
Box | A rectangle, the size of the object. |
Circle | A circle. |
Polygon | Any convex shape, from polygonVertices: a flat list of points, [x1, y1, x2, y2, …]. |
{
"name": "crate",
"baseClass": "Box",
"texture": "crate",
"restitution": 0.5
},
{
"name": "ground",
"baseClass": "Box",
"texture": "ground",
"static": true
}| Property | Description |
|---|---|
static | Doesn't move; other bodies collide with it. |
mass / density | How heavy the body is. Set one, the other follows from its size. |
restitution | Bounciness, from 0 to 1. |
friction | How much it grips other bodies. |
surfaceSpeed | Moves whatever touches it along its surface, like a conveyor belt. |
linearVelocity / angularVelocity | Current movement and spin. |
You can also create bodies in code. They're GameObjects, so add them like any other:
import { Circle, Type } from 'bare-engine/sopiro';
const ball = new Circle(this, 36, Type.Dynamic);
ball.restitution = 0.8;
this.AddGameObject(ball);
ball.SetPosition(x, y);Collisions fire the collision_start, collision_update and collision_end events.
Joints
Joints connect two bodies. Place a joint object in the level editor where two bodies overlap, and it connects them. Placed on a single body, it pins that body to the spot instead. Joints are invisible in the game.
| Class | What it does |
|---|---|
RevoluteJointObject | A hinge: the bodies rotate freely around the point, like a wheel or a door. |
WeldJointObject | Glues the bodies together. |
AngleJointObject | Keeps the angle between the bodies, but lets them move. |
DistanceJointObject | Keeps the bodies at a distance, like a rope or spring. Set mode to Pull for a rope that can go slack, and distance for its length. It draws a line in lineColor and lineWidth. |
LineJointObject | Lets a body slide along a line, like a piston. lockRotation stops it from rotating. |
MotorJointObject | Drives a body: set angularSpeed to spin it, or linearOffset and angularOffset to move it, with maxForce and maxTorque as limits. |
Every joint also has frequency and dampingRatio, to make it stiff or springy, and jointMass. They're inspector fields, so you can tweak them in the Chrome extension while the game runs.
To use a joint, make a prefab for it:
{
"name": "hinge",
"baseClass": "RevoluteJointObject",
"texture": "PIXEL",
"scale": {
"x": 32,
"y": 32
},
"pivot": "CENTER"
}Example: the Showcase's realistic physics demo has a prefab for every body and joint, and creates a ball wherever you click.