@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
127 lines (93 loc) • 3.52 kB
JavaScript
import TopDownCameraControllerSystem from "../../../graphics/ecs/camera/topdown/TopDownCameraControllerSystem.js";
import { Camera } from "../../../graphics/ecs/camera/Camera.js";
import { obtainTerrain } from "./obtainTerrain.js";
import { assert } from "../../../../core/assert.js";
import TerrainSystem from "../ecs/TerrainSystem.js";
import Task from "../../../../core/process/task/Task.js";
import { TaskSignal } from "../../../../core/process/task/TaskSignal.js";
import { max2 } from "../../../../core/math/max2.js";
import { clamp01 } from "../../../../core/math/clamp01.js";
/**
*
* @param {EntityManager} em
* @param {EntityComponentDataset} ecd
* @param {number} [timeout] in seconds
* @returns {Task}
*/
export function loadVisibleTerrainTiles({
em,
ecd,
timeout = 10
}) {
let totalTiles = 0;
let loadedTiles = 0;
let failedTiles = 0;
let attempt = 0;
let failureFlag = false;
const timeout_milliseconds = timeout * 1000;
let start_time = 0;
function init() {
start_time = Date.now();
const attemptId = attempt;
//force update by camera controller, to ensure correct focus is set
em.getSystem(TopDownCameraControllerSystem).update(0);
ecd.traverseComponents(Camera, function (c) {
c.updateMatrices();
});
const tiles = [];
const terrain = obtainTerrain(ecd);
assert.notEqual(terrain, null, 'terrain not found');
TerrainSystem.traverseVisibleTiles(ecd, terrain, function (tile) {
tiles.push(tile);
});
totalTiles = tiles.length;
const tileManager = terrain.__tiles;
function handleObtainedTile(t) {
if (attemptId !== attempt) {
return;
}
loadedTiles++;
}
function handleFailedTile(t) {
if (attemptId !== attempt) {
return;
}
attempt++;
failedTiles++;
if (attempt < 10) {
init();
} else {
failureFlag = true;
}
}
if (totalTiles !== 0) {
tiles.forEach(function (tile) {
tileManager.obtain(tile.gridPosition.x, tile.gridPosition.y).then(handleObtainedTile, handleFailedTile);
});
}
}
const task = new Task({
name: "Building visible terrain tiles",
initializer: init,
cycleFunction() {
if (Date.now() > start_time + timeout_milliseconds) {
// timed out
return TaskSignal.EndFailure;
}
if (failureFlag) {
return TaskSignal.EndFailure;
}
if (loadedTiles >= totalTiles) {
return TaskSignal.EndSuccess;
} else {
return TaskSignal.Yield;
}
},
computeProgress() {
const loaded_fraction = totalTiles === 0 ? 0 : loadedTiles / totalTiles;
const timeout_fraction = (Date.now() - start_time) / timeout_milliseconds;
return clamp01(max2(loaded_fraction, timeout_fraction));
}
});
return task;
}