@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
218 lines (158 loc) • 7.23 kB
JavaScript
import { EngineHarness } from "../../src/engine/EngineHarness.js";
import RenderSystem from "../../src/engine/ecs/systems/RenderSystem.js";
import { Camera } from "../../src/engine/graphics/ecs/camera/Camera.js";
import TopDownCameraController from "../../src/engine/graphics/ecs/camera/topdown/TopDownCameraController.js";
import Vector3 from "../../src/core/geom/Vector3.js";
import { TopDownCameraLander } from "../../src/engine/graphics/ecs/camera/topdown/TopDownCameraLander.js";
import Terrain from "../../src/engine/ecs/terrain/ecs/Terrain.js";
import { TerrainFlags } from "../../src/engine/ecs/terrain/ecs/TerrainFlags.js";
import Water from "../../src/engine/graphics/ecs/water/Water.js";
import GridObstacle from "../../src/engine/grid/obstacle/GridObstacle.js";
import Entity from "../../src/engine/ecs/Entity.js";
import GridPosition from "../../src/engine/grid/position/GridPosition.js";
import { Transform } from "../../src/engine/ecs/transform/Transform.js";
import { GridData } from "../../src/generation/grid/GridData.js";
import { computeStringHash } from "../../src/core/primitives/strings/computeStringHash.js";
import { ThemeEngine } from "../../src/generation/theme/ThemeEngine.js";
import { AreaTheme } from "../../src/generation/theme/AreaTheme.js";
import TaskGroup from "../../src/core/process/task/TaskGroup.js";
import { generateTerrainPreview } from "../../../../generator/generator/generateTerrainPreview.js";
import { SampleTheme0 } from "./themes/SampleTheme0.js";
import { SampleGenerator0 } from "./SampleGenerator0.js";
import { configureMirGrid } from "./grid/configureMirGrid.js";
import { EngineConfiguration } from "../../src/engine/EngineConfiguration.js";
import TerrainSystem from "../../src/engine/ecs/terrain/ecs/TerrainSystem.js";
import WaterSystem from "../../src/engine/graphics/ecs/water/WaterSystem.js";
import { MeshSystem } from "../../src/engine/graphics/ecs/mesh/MeshSystem.js";
import TopDownCameraControllerSystem
from "../../src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.js";
import { TopDownCameraLanderSystem } from "../../src/engine/graphics/ecs/camera/topdown/TopDownCameraLanderSystem.js";
import LightSystem from "../../src/engine/graphics/ecs/light/LightSystem.js";
import { TaskLoadingScreen } from "../../src/view/task/TaskLoadingScreen.js";
import { actionTask } from "../../src/core/process/task/util/actionTask.js";
function makeEngineConfig(engine) {
const config = new EngineConfiguration();
const graphics = engine.graphics;
config.addSystem(new RenderSystem(graphics));
config.addSystem(new TerrainSystem(graphics, engine.assetManager));
config.addSystem(new WaterSystem(graphics));
config.addSystem(new MeshSystem(engine));
config.addSystem(new TopDownCameraControllerSystem());
config.addSystem(new TopDownCameraLanderSystem());
config.addSystem(new LightSystem(engine))
return config;
}
/**
*
* @param {EngineHarness} harness
* @return {Promise<void>}
*/
async function init(harness) {
const engine = harness.engine;
await makeEngineConfig(engine).apply(engine);
await harness.initialize();
main(engine);
}
function prepare_gen_task({
SIZE_X = 64,
SIZE_Y = 64,
ecd
}) {
const camera = EngineHarness.buildCamera({
engine,
target: new Vector3(15, 0, 16),
// pitch: -PI_HALF,
pitch: 1.1,
yaw: 3.14,
distance: 13,
ecd,
distanceMin: 5,
distanceMax: 30
});
camera.add(new TopDownCameraLander());
// build lights
EngineHarness.buildLights({ engine })
// build terrain
const terrain = new Terrain();
terrain.resolution = 4;
terrain.size.set(SIZE_X, SIZE_Y);
terrain.samplerHeight.resize(SIZE_X, SIZE_Y);
terrain.splat.resize(SIZE_X * 4, SIZE_Y * 4, 0);
terrain.layers.resolution.set(512, 512);
terrain.clearFlag(TerrainFlags.Built);
terrain.build(engine.assetManager);
const water = new Water();
water.color.setRGB(0.2, 0.0, 0.5);
water.shoreColor.setRGB(0.3, 0.3, 1);
water.shoreDepthTransition.set(0.16, 0.5);
water.waveFrequency.set(1.3);
water.waveAmplitude.set(0.15);
water.waveSpeed.set(1.2);
water.scattering.set(1.2);
water.level.set(-0.3);
const obstacle = new GridObstacle();
obstacle.resize(terrain.size.x, terrain.size.y);
const terrainBuilder = new Entity();
terrainBuilder
.add(terrain)
.add(water)
.add(obstacle)
.add(new GridPosition())
.add(new Transform())
.build(ecd);
const gridData = new GridData();
configureMirGrid(gridData);
gridData.resize(terrain.size.x, terrain.size.y);
gridData.computeScale(1);
const generator = SampleGenerator0;
const tGenerationTask = generator.generate(ecd, gridData, computeStringHash('alexx855'));
const themeEngine = new ThemeEngine();
themeEngine.assetManager = engine.assetManager;
const theme0 = new AreaTheme();
const width = gridData.width;
const height = gridData.height;
theme0.mask.resize(width, height);
theme0.mask.mask.fill(0, 0, width, height, [1]);
theme0.theme = SampleTheme0;
themeEngine.add(theme0);
themeEngine.random.setCurrentSeed(1);
const tTheme = themeEngine.apply(gridData, ecd);
tTheme.addDependency(tGenerationTask);
const tBuildLevel = new TaskGroup([tGenerationTask, tTheme]);
const tAddGameplayElements = actionTask(() => {
// prepare gameplay-specific things on top of the generated level
//build minimap
const terrainPreview = generateTerrainPreview(terrainBuilder.id, ecd);
terrain.preview.copy(terrainPreview);
});
tAddGameplayElements.addDependency(tBuildLevel);
return new TaskGroup([tBuildLevel, tAddGameplayElements]);
}
/**
*
* @param {Engine} engine
*/
function main(engine) {
const ecd = engine.entityManager.dataset;
const tBuildLevel = prepare_gen_task({ ecd });
TaskLoadingScreen.load(engine, tBuildLevel);
engine.executor.runGroup(tBuildLevel);
tBuildLevel.promise().then(() => {
console.log('Generation took ', tBuildLevel.getExecutedCpuTime(), 'ms');
const camera = ecd.getAnyComponent(Camera);
EngineHarness.buildOrbitalCameraController({
cameraEntity: camera.entity,
engine
});
// tweak camera for prototyping
const ctrl = ecd.getComponent(camera.entity, TopDownCameraController);
if (ctrl !== undefined) {
ctrl.distanceMax = 200;
}
});
// Resume audio context
engine.devices.pointer.on.down.addOne(engine.sound.resumeContext, engine.sound);
engine.devices.pointer.on.wheel.addOne(engine.sound.resumeContext, engine.sound);
}
const engineHarness = new EngineHarness();
init(engineHarness);