@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
144 lines (110 loc) • 3.93 kB
JavaScript
import { assert } from "../../../../core/assert.js";
import { Behavior } from "../Behavior.js";
import { BehaviorStatus } from "../BehaviorStatus.js";
import { CompositeBehavior } from "./CompositeBehavior.js";
/**
* Executes all contained behaviors one after another in a sequence, next behaviour in the sequence will not be started until the previous one signal success
* If any of the contained behaviours fail - the whole sequence fails
*
* @author Alex Goldring
* @copyright Company Named Limited (c) 2025
*/
export class SequenceBehavior extends CompositeBehavior {
constructor() {
super();
/**
*
* @type {number}
* @protected
*/
this.__currentBehaviourIndex = -1;
/**
*
* @type {BehaviorStatus|number}
* @private
*/
this.__currentBehaviourState = BehaviorStatus.Initial;
/**
*
* @type {Behavior}
* @protected
*/
this.__currentBehaviour = undefined;
}
initialize(context) {
// console.log('+ SequenceBehavior');
this.__currentBehaviourIndex = 0;
this.__currentBehaviour = this.__children[0];
// allow for empty sequence
if (this.__currentBehaviour !== undefined) {
//initialize first behaviour
this.__currentBehaviour.initialize(context);
}
this.__currentBehaviourState = BehaviorStatus.Running;
super.initialize(context);
}
/**
*
* @param {number} timeDelta
* @returns {BehaviorStatus}
*/
tick(timeDelta) {
assert.isNonNegativeInteger(this.__currentBehaviourIndex, 'child index');
const currentBehaviour = this.__currentBehaviour;
if (currentBehaviour === undefined) {
// either un-initialized, or an empty sequence
this.__currentBehaviourState = BehaviorStatus.Succeeded;
return BehaviorStatus.Succeeded;
}
const s = currentBehaviour.tick(timeDelta);
this.__currentBehaviourState = s;
if (s !== BehaviorStatus.Succeeded) {
return s;
}
//current behaviour succeeded, move onto the next one
currentBehaviour.finalize();
this.__currentBehaviourState = BehaviorStatus.Initial;
this.__currentBehaviourIndex++;
if (this.__currentBehaviourIndex < this.__children.length) {
this.__currentBehaviour = this.__children[this.__currentBehaviourIndex];
this.__currentBehaviour.initialize(this.context);
this.__currentBehaviourState = BehaviorStatus.Running;
return BehaviorStatus.Running;
} else {
//all behaviours completed
return BehaviorStatus.Succeeded;
}
}
finalize() {
const child_count = this.__children.length;
if (this.__currentBehaviourIndex !== child_count) {
//sequence has not been finished
if (
this.__currentBehaviour !== undefined
&& this.__currentBehaviourState !== BehaviorStatus.Initial
) {
this.__currentBehaviour.finalize();
}
}
this.__currentBehaviour = undefined;
this.__currentBehaviourIndex = child_count;
// console.warn('- SequenceBehavior');
super.finalize();
}
/**
*
* @param {Behavior[]} children
* @return {SequenceBehavior}
*/
static from(children) {
const r = new SequenceBehavior();
r.addChildren(children);
return r;
}
}
/**
* @readonly
* @type {boolean}
*/
SequenceBehavior.prototype.isSequenceBehavior = true;
SequenceBehavior.typeName = "SequenceBehavior";