@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
147 lines (105 loc) • 4.01 kB
JavaScript
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];
}
}