UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

145 lines (107 loc) 4.27 kB
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; }