-
Notifications
You must be signed in to change notification settings - Fork 8
Things.Controllable
A controllable thing is one which a Controller can attach to. Any thing which can be controlled by a player, AI, or via the network should inherit from elation.engine.things.controllable
When defining a controllable thing, you first tell the engine what commands a thing exposes. Examples of common commands would be "move_forward", "turn_left", "fire", "jump", etc. These commands tell the engine what any instances of this type of thing is capable of doing, and if a controller is attached it can use these commands to manipulate the state of the object in response to input, AI, or network events.
A controller turns input-based decisions from the player, logic-based decisions from AI, and remote decisions received via the network into actions to control a thing.
- PlayerController
- AIController
- NetworkController
The PlayerController represents a player physically sitting at the system which the engine is running on, providing input via keyboard, mouse, touchscreen, gamepad, etc. In most gaming contexts there is only ever one PlayerController per system; NPC characters are provided for by AIControllers, while other remote players are provided for by NetworkControllers. One scenario where multiple PlayerControllers might be used is if there are several gamepads connected to the same system.
The AIController is a base class which allows you to attach behavioral scripts to a thing. Generally you would use the AIController class as a base for your specific AI, for example AIControllerTurret, AIControllerCar, AIControllerCreeper, etc.
The AI system is currently a simple finite state machine. When defining an AIController, you first define the various states your AI supports (eg: "idle", "acquire_target", "track_and_fire", "retreat", etc). These behavioral scripts can send commands to the controllable thing, making decisions based on the state of the thing and the world around it.
Upon creation, the AIController should set its default behavioral state. This registers the controller with the AI system, and it will start receiving thing_think events. Each AIController can independently set its current active behavior, and the time at which the next think event should occur. This allows your AI to adapt its responsiveness to fit the needs of its current state. For instance, while in the default acquire_target behavior, a turret might only need to think once every 2 seconds. When a target is acquired, it switches to the track_and_fire behavior and sets its think interval to 20 times per second. After the target has been destroyed or is out of range, the AI returns to the acquire_target behavior at 2 second intervals.
elation.component.add('engine.controllers.AIControllerTurret', function() {
this.thing = this.args.thing;
this.initController = function() {
this.addBehavior("acquire_target", this.acquireTarget, 2000); // every 2 seconds
this.addBehavior("track_and_fire", this.trackAndFire, 50); // every 50ms = 20 times per second
this.setBehavior("acquire_target");
}
this.acquireTarget = function(args) {
var target = engine.systems.world.getNearbyObjects(this.thing.position, this.thing.range);
if (target) {
this.target = target;
this.setBehavior("track_and_fire");
}
}
this.trackAndFire = function(args) {
if (this.target && this.target.exists && thing.position.distanceTo(this.target.position) < this.thing.range) {
var solution = this.thing.getFiringSolution(this.target.position, this.target.velocity);
var turn_left = solution.angle.yaw < -deadzone,
turn_right = solution.angle.yaw > deadzone,
pitch_up = solution.angle.pitch < -deadzone,
pitch_down = solution.angle.pitch > deadzone,
fire = !(turn_left || turn_right || pitch_up || pitch_down);
this.thing.setAction('turn_left', turn_left);
this.thing.setAction('turn_right', turn_right);
this.thing.setAction('pitch_up', pitch_up);
this.thing.setAction('pitch_down', pitch_down);
this.thing.setAction('fire', fire);
} else {
this.target = false;
this.setBehavior("acquire_target");
}
}
}, elation.engine.controllers.AIController);