UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

144 lines (114 loc) 3.57 kB
import Clock from "../../../Clock.js"; import { System } from "../../../ecs/System.js"; import { BehaviorStatus } from "../BehaviorStatus.js"; import { BehaviorComponent } from "./BehaviorComponent.js"; import { BehaviorComponentFlag } from "./BehaviorComponentFlag.js"; import { ClockChannelType } from "./ClockChannelType.js"; /** * * @param {Behavior} behavior * @param {number} timeDelta * @returns {BehaviorStatus} */ function updateBehavior(behavior, timeDelta) { try { return behavior.tick(timeDelta); } catch (e) { console.error('Behavior threw an exception', e); // Transition behavior into failed state return BehaviorStatus.Failed; } } /** * @extends System<BehaviorComponent> * * @author Alex Goldring * @copyright Company Named Limited (c) 2025 */ export class BehaviorSystem extends System { /** * * @param {Engine} engine */ constructor(engine) { super(); this.dependencies = [BehaviorComponent]; this.systemClock = new Clock(); /** * * @type {Engine} */ this.engine = engine; } async startup(entityManager) { this.systemClock.start(); this.entityManager = entityManager; } async shutdown(entityManager) { this.systemClock.stop(); } /** * * @param {BehaviorComponent} component * @param {number} entity */ link(component, entity) { const behavior = component.behavior; component.clearFlag(BehaviorComponentFlag.Resolved); if (behavior !== null) { // initialize behavior const dataset = this.entityManager.dataset; try { behavior.initialize({ entity, ecd: dataset, engine: this.engine }); } catch (e) { console.warn('Behavior initialization failed:', e); } } } /** * * @param {BehaviorComponent} component * @param {number} entity */ unlink(component, entity) { const behavior = component.behavior; if (behavior !== null) { // finalize behavior behavior.finalize(); } } update(timeDelta) { const systemDelta = this.systemClock.getDelta(); const dataset = this.entityManager.dataset; if (dataset === null) { //no data return; } /** * * @param {BehaviorComponent} b * @param {number} entity */ function visitBehavior(b, entity) { if (b.getFlag(BehaviorComponentFlag.Resolved)) { return; } let td; if (b.clock === ClockChannelType.Simulation) { //use simulation time td = timeDelta; } else if (b.clock === ClockChannelType.System) { //use system clock time delta td = systemDelta; } const behavior = b.behavior; if (behavior !== null) { const state = updateBehavior(behavior, td); if (state === BehaviorStatus.Failed || state === BehaviorStatus.Succeeded) { b.setFlag(BehaviorComponentFlag.Resolved); } } } dataset.traverseComponents(BehaviorComponent, visitBehavior); } }