Entity - rogerscg/era-engine GitHub Wiki
An entity is any object within the scene, and probably the most important piece of the ERA engine. An entity extends THREE.Object3D, giving it important properties such as position, rotation, and scale, as well as allowing for additional entities to be attached to it.
The Entity class also comes with a few features that ease development.
Building - Meshes and Physics Bodies
When creating an entity, you will need to define mesh and physics body generation functions that are eventually called by the build
function. Let's say we want to create a Box
entity for our scene. We'd start with:
const box = new Box().withPhysics().build();
The build
function calls both generateMesh
and generatePhysicsBody
functions and should not be modified (unless super.build
is called).
generateMesh()
- Builds and returns the mesh (or root Object3D) that represents the entity visually.
generatePhysicsBody()
- Builds and returns the physics body for the entity.
In our file box.js
, we'd create the class to extend Entity
and override the generateMesh
and generatePhysicsBody
base functions:
class Box extends Entity {
/** @override */
generateMesh() {
// Define and return your THREE.Mesh here.
}
/** @override */
generatePhysicsBody() {
// Define and return your preferred physics engine body here.
}
}
If you have a custom model loaded into ERA model storage (see the Models section), you can simply set the modelName
property in the Box
constructor and it will retrieve and set the mesh automatically.
class Box extends Entity {
constructor() {
super();
this.modelName = 'cardboard-box';
}
}
Updating - Listening to Engine ticks
Now that we've defined our Entity's appearance and physics behavior, we can give it life with the update
method. In the base Entity
class, the update
method copies the mesh position and rotation to match the physics object. Once the super method is called, it's up to the developer to update the entity state, listen for user input, etc.
class Box extends Entity {
...
/** @override */
update() {
// Push the box. We're using the Ammo physics engine in this example.
this.physicsBody.applyCentralImpulse(new Ammo.btVector3(1, 0, 0));
}
}
Controls
Controlling an entity is another critical part of the ERA engine. This section is tied heavily to the Controls and Bindings section of the wiki, so be sure to read up on that as well.
Within our Box
class, we can defined Bindings
and Actions
from an object. Actions
are labels for things that an entity can do, such as FORWARD
, BACKWARD
, FIRE
, ROLL
, etc. Each Action
has a set of input types and keys:
const BOX_BINDINGS = {
BACKWARD: {
keys: {
keyboard: 83,
controller: '+axes1',
}
},
FORWARD: {
keys: {
keyboard: 87,
controller: '-axes1',
}
},
ROLL: {
keys: {
keyboard: 32,
controller: 'button0',
}
},
};
We'll also need to define a CONTROLS_ID
constant for use by the Controls
plugin.
const BOX_CONTROLS_ID = 'box';
Now that our bindings are defined, we can register them to the Controls
plugin. Be sure to override the static GetBindings
function as well as the getControlsId
function. Also note the line at the bottom that actually registers the bindings to Controls
.
class Box extends Entity {
...
/** @override */
static GetBindings() {
return new Bindings(BOX_CONTROLS_ID).load(BOX_BINDINGS);
}
/** @override */
getControlsId() {
return BOX_CONTROLS_ID;
}
/** @override */
update() {
super.update();
// Use the Entity method "getActionValue" to read user input.
if (this.getActionValue(this.bindings.FORWARD)) {
this.physicsBody.applyCentralImpulse(new Ammo.btVector3(1, 0, 0));
}
}
}
// Register the entity bindings to the Controls plugin.
Controls.get().registerBindings(Box);
Notes
You can merge bindings together to create your own form of controls "inheritance". For instance, let's say you have an Animal
base entity and a Horse
entity that extends it. You can have the basic bindings of an Animal
in animal.js
, then in Horse.GetBindings()
, you would define it as:
static GetBindings() {
return new Bindings(HORSE_CONTROLS_ID)
.load(HORSE_BINDINGS)
.merge(Animal.GetBindings());
}
You can view the Gamepad spec here
To see how you can let your users/players customize bindings, see Controls and Bindings.