UNPKG

noa-engine

Version:

Experimental voxel game engine

260 lines (259 loc) 9.04 kB
/** * Main engine class. * Takes an object full of optional settings as a parameter. * * ```js * import { Engine } from 'noa-engine' * var noa = new Engine({ * debug: false, * }) * ``` * * Note that the options object is also passed to noa's * child modules ({@link Rendering}, {@link Container}, etc). * See docs for each module for their options. * */ export class Engine extends EventEmitter { /** * The core Engine constructor uses the following options: * * ```js * var defaultOptions = { * debug: false, * silent: false, * playerHeight: 1.8, * playerWidth: 0.6, * playerStart: [0, 10, 0], * playerAutoStep: false, * playerShadowComponent: true, * tickRate: 30, // ticks per second * maxRenderRate: 0, // max FPS, 0 for uncapped * blockTestDistance: 10, * stickyPointerLock: true, * dragCameraOutsidePointerLock: true, * stickyFullscreen: false, * skipDefaultHighlighting: false, * originRebaseDistance: 25, * } * ``` * * **Events:** * + `tick => (dt)` * Tick update, `dt` is (fixed) tick duration in ms * + `beforeRender => (dt)` * `dt` is the time (in ms) since the most recent tick * + `afterRender => (dt)` * `dt` is the time (in ms) since the most recent tick * + `targetBlockChanged => (blockInfo)` * Emitted each time the user's targeted world block changes * + `addingTerrainMesh => (mesh)` * Alerts client about a terrain mesh being added to the scene * + `removingTerrainMesh => (mesh)` * Alerts client before a terrain mesh is removed. */ constructor(opts?: {}); /** Version string, e.g. `"0.25.4"` */ version: string; /** @internal */ _paused: boolean; /** @internal */ _originRebaseDistance: any; /** @internal */ worldOriginOffset: number[]; /** @internal */ positionInCurrentTick: number; /** * String identifier for the current world. * It's safe to ignore this if your game has only one level/world. */ worldName: string; /** * Multiplier for how fast time moves. Setting this to a value other than * `1` will make the game speed up or slow down. This can significantly * affect how core systems behave (particularly physics!). */ timeScale: number; /** Child module for managing the game's container, canvas, etc. */ container: Container; /** The game's tick rate (number of ticks per second) * @type {number} * @readonly */ readonly tickRate: number; /** The game's max framerate (use `0` for uncapped) * @type {number} */ maxRenderRate: number; /** Manages key and mouse input bindings */ inputs: Inputs; /** A registry where voxel/material properties are managed */ registry: Registry; /** Manages the world, chunks, and all voxel data */ world: World; /** Rendering manager */ rendering: Rendering; /** Physics engine - solves collisions, properties, etc. */ physics: Physics; /** Entity manager / Entity Component System (ECS) */ entities: Entities; /** Alias to `noa.entities` */ ents: Entities; /** Entity id for the player entity */ playerEntity: number; /** Manages the game's camera, view angle, sensitivity, etc. */ camera: Camera; /** How far to check for a solid voxel the player is currently looking at * @type {number} */ blockTestDistance: number; /** * Callback to determine which voxels can be targeted. * Defaults to a solidity check, but can be overridden with arbitrary logic. * @type {(blockID: number) => boolean} */ blockTargetIdCheck: (blockID: number) => boolean; /** * Dynamically updated object describing the currently targeted block. * @type {null | { * blockID:number, * position: number[], * normal: number[], * adjacent: number[], * }} */ targetedBlock: { blockID: number; position: number[]; normal: number[]; adjacent: number[]; }; defaultBlockHighlightFunction: (tgt: any) => void; /** @internal */ _terrainMesher: TerrainMesher; /** @internal */ _objectMesher: ObjectMesher; /** @internal */ _targetedBlockDat: { blockID: number; position: any; normal: any; adjacent: any; }; /** @internal */ _prevTargetHash: number; /** @internal */ _pickPos: any; /** @internal */ _pickResult: { _localPosition: any; position: number[]; normal: number[]; }; /** @internal */ vec3: typeof vec3; /** @internal */ ndarray: any; /** * Tick function, called by container module at a fixed timestep. * Clients should not normally need to call this manually. * @internal */ tick(dt: any): void; /** * Render function, called every animation frame. Emits #beforeRender(dt), #afterRender(dt) * where dt is the time in ms *since the last tick*. * Clients should not normally need to call this manually. * @internal */ render(dt: any, framePart: any): void; /** Pausing the engine will also stop render/tick events, etc. */ setPaused(paused?: boolean): void; /** * Get the voxel ID at the specified position */ getBlock(x: any, y?: number, z?: number): any; /** * Sets the voxel ID at the specified position. * Does not check whether any entities are in the way! */ setBlock(id: any, x: any, y?: number, z?: number): void; /** * Adds a block, unless there's an entity in the way. */ addBlock(id: any, x: any, y?: number, z?: number): any; /** * Precisely converts a world position to the current internal * local frame of reference. * * See `/docs/positions.md` for more info. * * Params: * * `global`: input position in global coords * * `globalPrecise`: (optional) sub-voxel offset to the global position * * `local`: output array which will receive the result */ globalToLocal(global: any, globalPrecise: any, local: any): any; /** * Precisely converts a world position to the current internal * local frame of reference. * * See `/docs/positions.md` for more info. * * Params: * * `local`: input array of local coords * * `global`: output array which receives the result * * `globalPrecise`: (optional) sub-voxel offset to the output global position * * If both output arrays are passed in, `global` will get int values and * `globalPrecise` will get fractional parts. If only one array is passed in, * `global` will get the whole output position. */ localToGlobal(local: any, global: any, globalPrecise?: any): any; /** * Raycast through the world, returning a result object for any non-air block * * See `/docs/positions.md` for info on working with precise positions. * * @param {number[]} pos where to pick from (default: player's eye pos) * @param {number[]} dir direction to pick along (default: camera vector) * @param {number} dist pick distance (default: `noa.blockTestDistance`) * @param {(id:number) => boolean} blockTestFunction which voxel IDs can be picked (default: any solid voxel) */ pick(pos?: number[], dir?: number[], dist?: number, blockTestFunction?: (id: number) => boolean): { position: number[]; normal: number[]; _localPosition: number[]; }; /** * @internal * Do a raycast in local coords. * See `/docs/positions.md` for more info. * @param {number[]} pos where to pick from (default: player's eye pos) * @param {number[]} dir direction to pick along (default: camera vector) * @param {number} dist pick distance (default: `noa.blockTestDistance`) * @param {(id:number) => boolean} blockTestFunction which voxel IDs can be picked (default: any solid voxel) * @returns { null | { * position: number[], * normal: number[], * _localPosition: number[], * }} */ _localPick(pos?: number[], dir?: number[], dist?: number, blockTestFunction?: (id: number) => boolean): null | { position: number[]; normal: number[]; _localPosition: number[]; }; } import { EventEmitter } from 'events'; import { Container } from './lib/container'; import { Inputs } from './lib/inputs'; import { Registry } from './lib/registry'; import { World } from './lib/world'; import { Rendering } from './lib/rendering'; import { Physics } from './lib/physics'; import { Entities } from './lib/entities'; import { Camera } from './lib/camera'; import { TerrainMesher } from './lib/terrainMesher'; import { ObjectMesher } from './lib/objectMesher'; import vec3 from 'gl-vec3';