@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
145 lines (107 loc) • 4.27 kB
JavaScript
import { assert } from "../../core/assert.js";
import { noop } from "../../core/function/noop.js";
import Task from "../../core/process/task/Task.js";
import TaskGroup from "../../core/process/task/TaskGroup.js";
import TaskState from "../../core/process/task/TaskState.js";
import { actionTask } from "../../core/process/task/util/actionTask.js";
import { delayTask } from "../../core/process/task/util/delayTask.js";
import { ignoreFailureTask } from "../../core/process/task/util/ignoreFailureTask.js";
import { TaskLoadingScreen } from "../../view/task/TaskLoadingScreen.js";
import { loadVisibleTerrainTiles } from "../ecs/terrain/util/loadVisibleTerrainTiles.js";
import { compileAllMaterials } from "../graphics/ecs/compileAllMaterials.js";
import { createTaskWaitForMeshesToLoad } from "../graphics/ecs/mesh/createTaskWaitForMeshesToLoad.js";
/**
*
* @param {Task[]} [tasks]
* @param {Scene} scene
* @param {Engine} engine
* @param {string} [name]
* @return {Promise}
*/
export function transitionToScene({
tasks = [],
scene,
engine,
name
}) {
assert.defined(engine, 'engine');
assert.defined(scene, 'scene');
assert.isArray(tasks, 'tasks');
if (name === undefined) {
if (tasks.length > 0) {
//assume name of the first task
name = tasks[0].name;
} else {
name = `Loading ${scene.name} Scene`;
}
}
//wait for visible terrain tiles to be loaded
const tWaitForVisibleTerrainTiles = ignoreFailureTask(loadVisibleTerrainTiles({
em: engine.entityManager,
ecd: scene.dataset
}));
tWaitForVisibleTerrainTiles.name = "Waiting for visible terrain tiles";
tWaitForVisibleTerrainTiles.addDependencies(tasks);
const tWaitForMeshes = ignoreFailureTask(createTaskWaitForMeshesToLoad(scene.dataset, engine, 7000));
tWaitForMeshes.addDependencies(tasks);
/**
*
* @type {GraphicsEngine}
*/
const graphics = engine.graphics;
const tCompileMaterials = compileAllMaterials({ graphics });
tCompileMaterials.addDependency(tWaitForVisibleTerrainTiles);
tCompileMaterials.addDependency(tWaitForMeshes);
//hide all render layers during load
const renderLayerState = graphics.layers.pushState();
graphics.layers.hideAll();
function cleanup() {
graphics.layers.popState();
}
//render a frame
const tRender = actionTask(() => {
// push new state
graphics.layers.pushState();
// restore original state
renderLayerState.write(graphics.layers);
// tick simulation
engine.entityManager.simulate(0);
// update effects
// engine.effects.update(0); // TODO move this to effects plugin if possible or add "update" to plugin manager
// render current scene
graphics.needDraw = true;
graphics.render();
// restore previous sate
graphics.layers.popState();
}, 'Render 1 frame of the game');
tRender.addDependency(tCompileMaterials);
tRender.addDependency(tWaitForMeshes);
tRender.addDependencies(tasks);
const tDelay = delayTask(15, 'delay');
tDelay.addDependency(tRender);
const extraTasks = [
tWaitForMeshes,
tWaitForVisibleTerrainTiles,
tCompileMaterials,
tRender,
tDelay
];
const allTasks = tasks.concat(extraTasks);
const taskGroup = new TaskGroup(allTasks, name);
Task.joinAll(allTasks,
() => {
taskGroup.state.set(TaskState.SUCCEEDED);
taskGroup.on.completed.send0();
},
() => {
taskGroup.state.set(TaskState.FAILED);
taskGroup.on.failed.send0();
}
);
const promise = TaskLoadingScreen.load(engine, taskGroup);
Task.joinAll(tasks, () => {
engine.executor.runMany(extraTasks);
}, noop);
promise.finally(cleanup);
return promise;
}