UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

147 lines (105 loc) 4.01 kB
import { System } from "../System.js"; import { FogOfWarRevealer } from "./FogOfWarRevealer.js"; import { SignalBinding } from "../../../core/events/signal/SignalBinding.js"; import { FogOfWar } from "./FogOfWar.js"; import Team from "../team/Team.js"; import { Transform } from "../transform/Transform.js"; import Vector2 from "../../../core/geom/Vector2.js"; import { obtainTerrain } from "../terrain/util/obtainTerrain.js"; import { ResourceAccessSpecification } from "../../../core/model/ResourceAccessSpecification.js"; import { ResourceAccessKind } from "../../../core/model/ResourceAccessKind.js"; const v2 = new Vector2(); export class FogOfWarRevealerSystem extends System { /** * * @param {number} team */ constructor(team) { super(); this.dependencies = [FogOfWarRevealer, Transform, Team]; this.components_used = [ ResourceAccessSpecification.from(FogOfWar, ResourceAccessKind.Write) ]; this.data = []; /** * * @type {number} */ this.team = team; } /** * * @param {FogOfWarRevealer} revealer * @param {Transform} transform * @param {Team} team * @param entity */ link(revealer, transform, team, entity) { const em = this.entityManager; const visibilityTeam = this.team; const position = transform.position; function update() { const dataset = em.dataset; if (dataset !== null) { const terrain = obtainTerrain(dataset); if (terrain !== null) { terrain.mapPointWorld2Grid(position, v2); dataset.traverseComponents(FogOfWar, function (fow) { fow.reveal(v2.x, v2.y, revealer.radius.getValue()); }); } } } const signalBindings = []; const positionWatcher = new SignalBinding(position.onChanged, update); signalBindings.push(positionWatcher); function attemptToWatch(team) { if (team === visibilityTeam) { positionWatcher.link(); update(); } else { positionWatcher.unlink(); } } attemptToWatch(team.getValue()); const teamWatcher = new SignalBinding(team.onChanged, attemptToWatch); signalBindings.push(teamWatcher); teamWatcher.link(); const radiusWatcher = new SignalBinding(revealer.radius.onChanged, update); signalBindings.push(radiusWatcher); radiusWatcher.link(); this.data[entity] = signalBindings; } forceUpdate() { const dataset = this.entityManager.dataset; if (dataset !== null) { const terrain = obtainTerrain(dataset); /** * * @type {FogOfWar[]} */ const fows = []; dataset.traverseComponents(FogOfWar, function (fow) { fows.push(fow); }); dataset.traverseEntities([FogOfWarRevealer, Transform, Team], (revealer, transform, team) => { if (team.getValue() !== this.team) { // wrong team return; } const position = transform.position; if (terrain !== null) { terrain.mapPointWorld2Grid(position, v2); fows.forEach(function (fow) { fow.reveal(v2.x, v2.y, revealer.radius.getValue()); }); } }); } } unlink(revealer, position, team, entity) { const bindings = this.data[entity]; bindings.forEach(b => b.unlink()); delete this.data[entity]; } }