UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

144 lines (110 loc) 3.93 kB
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";