Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/excaliburjs/Excalibur. 🎮 Your friendly TypeScript 2D game engine for the web 🗡️ excaliburjs.com
excalibur excaliburjs game-development game-engine game-framework gamedev games html5-canvas typescript
Something went wrong. Try again.
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848import { isScreenElement, ScreenElement } from './screen-element';import type { ActivateEvent, DeactivateEvent, PauseEvent, ResumeEvent } from './events';import { InitializeEvent, PreUpdateEvent, PostUpdateEvent, PreDrawEvent, PostDrawEvent, PreDebugDrawEvent, PostDebugDrawEvent} from './events';import { Logger } from './util/log';import { Timer } from './timer';import type { Engine } from './engine';import { TileMap } from './tile-map';import { Camera } from './camera';import { Actor } from './actor';import type { CanInitialize, CanActivate, CanDeactivate, CanUpdate, CanDraw, SceneActivationContext } from './interfaces/lifecycle-events';import * as Util from './util/util';import { Trigger } from './trigger';import { SystemType } from './entity-component-system/system';import { World } from './entity-component-system/world';import { MotionSystem } from './collision/motion-system';import { CollisionSystem } from './collision/collision-system';import { Entity } from './entity-component-system/entity';import { GraphicsSystem } from './graphics/graphics-system';import { DebugSystem } from './debug/debug-system';import { PointerSystem } from './input/pointer-system';import { ActionsSystem } from './actions/actions-system';import { IsometricEntitySystem } from './tile-map/isometric-entity-system';import { OffscreenSystem } from './graphics/offscreen-system';import type { ExcaliburGraphicsContext } from './graphics';import { PhysicsWorld } from './collision/physics-world';import type { EventKey, Handler, Subscription } from './event-emitter';import { EventEmitter } from './event-emitter';import type { Color } from './color';import type { DefaultLoader } from './director/default-loader';import type { Transition } from './director';import { InputHost } from './input/input-host';import { PointerScope } from './input/pointer-scope';import { getDefaultPhysicsConfig } from './collision/physics-config';import { PauseSystem } from './util/pause-system';import { FlickerSystem } from './lighting/flicker-system';import { LightingSystem } from './lighting/lighting-system';
export class PreLoadEvent { loader!: DefaultLoader;}
export interface SceneEvents { initialize: InitializeEvent<Scene>; activate: ActivateEvent; deactivate: DeactivateEvent; preupdate: PreUpdateEvent; postupdate: PostUpdateEvent; predraw: PreDrawEvent; postdraw: PostDrawEvent; predebugdraw: PreDebugDrawEvent; postdebugdraw: PostDebugDrawEvent; preload: PreLoadEvent; transitionstart: Transition; transitionend: Transition; pause: PauseEvent; resume: ResumeEvent;}
export const SceneEvents = { Initialize: 'initialize', Activate: 'activate', Deactivate: 'deactivate', PreUpdate: 'preupdate', PostUpdate: 'postupdate', PreDraw: 'predraw', PostDraw: 'postdraw', PreDebugDraw: 'predebugdraw', PostDebugDraw: 'postdebugdraw', PreLoad: 'preload', TransitionStart: 'transitionstart', TransitionEnd: 'transitionend', Pause: 'pause', Resume: 'resume'} as const;
export type SceneConstructor = new (...args: any[]) => Scene;/** * */export function isSceneConstructor(x: any): x is SceneConstructor { return !!x?.prototype && !!x?.prototype?.constructor?.name;}
/** * {@apilink Actor | `Actors`} are composed together into groupings called Scenes in * Excalibur. The metaphor models the same idea behind real world * actors in a scene. Only actors in scenes will be updated and drawn. * * Typical usages of a scene include: levels, menus, loading screens, etc. * * Scenes go through the following lifecycle * 1. onPreLoad - called once * 2. onInitialize - called once * 3. onActivate - called the first frame the scene is current * 4. onPreUpdate - called every update * 5. onPostUpdate - called every update * 6. onPreDraw - called every draw * 7. onPostDraw - called every draw * 8. onDeactivate - called the first frame the scene is no longer current * * Each lifecycle stage also fires corresponding {@apilink Plugin} hooks: * `onScenePreInitialize`/`onScenePostInitialize`, * `onScenePreActivate`/`onScenePostActivate`, * `onScenePreDeactivate`/`onScenePostDeactivate`. */export class Scene<TActivationData = unknown> implements CanInitialize, CanActivate<TActivationData>, CanDeactivate, CanUpdate, CanDraw { private _logger: Logger = Logger.getInstance(); public events = new EventEmitter<SceneEvents>();
/** * Gets or sets the current camera for the scene */ public camera: Camera = new Camera();
/** * Scene specific background color */ public backgroundColor?: Color;
/** * The ECS world for the scene */ public world: World = new World(this);
/** * The Excalibur physics world for the scene. Used to interact * with colliders included in the scene. * * Can be used to perform scene ray casts, track colliders, broadphase, and narrowphase. */ public physics = new PhysicsWorld(getDefaultPhysicsConfig());
/** * The actors in the current scene */ public get actors(): readonly Actor[] { return this.world.entityManager.entities.filter((e: Entity<any>) => { return e instanceof Actor; }) as Actor[]; }
/** * The entities in the current scene */ public get entities(): readonly Entity[] { return this.world.entityManager.entities; }
/** * The triggers in the current scene */ public get triggers(): readonly Trigger[] { return this.world.entityManager.entities.filter((e: Entity<any>) => { return e instanceof Trigger; }) as Trigger[]; }
/** * The {@apilink TileMap}s in the scene, if any */ public get tileMaps(): readonly TileMap[] { return this.world.entityManager.entities.filter((e: Entity<any>) => { return e instanceof TileMap; }) as TileMap[]; }
/** * Access to the Excalibur engine */ public engine!: Engine;
/** * Access scene specific input, handlers on this only fire when this scene is active. */ public input!: InputHost;
private _isInitialized: boolean = false; private _lastLightingEnabled: boolean = false; private _timers: Timer[] = []; public get timers(): readonly Timer[] { return this._timers; } private _cancelQueue: Timer[] = [];
constructor() { // Initialize systems
// Update this.world.add(ActionsSystem); this.world.add(new MotionSystem(this.world, this.physics)); this.world.add(new CollisionSystem(this.world, this.physics)); this.world.add(PointerSystem); this.world.add(IsometricEntitySystem); // Draw this.world.add(OffscreenSystem); this.world.add(GraphicsSystem); this.world.add(DebugSystem); this.world.add(new PauseSystem(this)); }
public emit<TEventName extends EventKey<SceneEvents>>(eventName: TEventName, event: SceneEvents[TEventName]): void; public emit(eventName: string, event?: any): void; public emit<TEventName extends EventKey<SceneEvents> | string>(eventName: TEventName, event?: any): void { this.events.emit(eventName, event); }
public on<TEventName extends EventKey<SceneEvents>>(eventName: TEventName, handler: Handler<SceneEvents[TEventName]>): Subscription; public on(eventName: string, handler: Handler<unknown>): Subscription; public on<TEventName extends EventKey<SceneEvents> | string>(eventName: TEventName, handler: Handler<any>): Subscription { return this.events.on(eventName, handler); }
public once<TEventName extends EventKey<SceneEvents>>(eventName: TEventName, handler: Handler<SceneEvents[TEventName]>): Subscription; public once(eventName: string, handler: Handler<unknown>): Subscription; public once<TEventName extends EventKey<SceneEvents> | string>(eventName: TEventName, handler: Handler<any>): Subscription { return this.events.once(eventName, handler); }
public off<TEventName extends EventKey<SceneEvents>>(eventName: TEventName, handler: Handler<SceneEvents[TEventName]>): void; public off(eventName: string, handler: Handler<unknown>): void; public off(eventName: string): void; public off<TEventName extends EventKey<SceneEvents> | string>(eventName: TEventName, handler?: Handler<any>): void { this.events.off(eventName, handler as any); }
/** * Event hook to provide Scenes a way of loading scene specific resources. * * This is called before the Scene.onInitialize during scene transition. It will only ever fire once for a scene. * @param loader */ public onPreLoad(loader: DefaultLoader) { // will be overridden }
/** * Event hook fired directly before transition, either "in" or "out" of the scene * * This overrides the Engine scene definition. However transitions specified in goToScene take highest precedence * * ```typescript * // Overrides all * Engine.goToScene('scene', { destinationIn: ..., sourceOut: ... }); * ``` * * This can be used to configure custom transitions for a scene dynamically */ public onTransition(direction: 'in' | 'out'): Transition | null { // will be overridden return null; }
/** * This is called before the first update of the {@apilink Scene}. Initializes scene members like the camera. This method is meant to be * overridden. This is where initialization of child actors should take place. */ public onInitialize(engine: Engine): void { // will be overridden }
/** * This is called when the scene is made active and started. It is meant to be overridden, * this is where you should setup any DOM UI or event handlers needed for the scene. */ public onActivate(context: SceneActivationContext<TActivationData>): void { // will be overridden }
/** * This is called when the scene is made transitioned away from and stopped. It is meant to be overridden, * this is where you should cleanup any DOM UI or event handlers needed for the scene. * @returns Either data to pass to the next scene activation context as `previousSceneData` or nothing */ public onDeactivate(context: SceneActivationContext): any | void { // will be overridden }
/** * Safe to override onPreUpdate lifecycle event handler. Synonymous with `.on('preupdate', (evt) =>{...})` * * `onPreUpdate` is called directly before a scene is updated. * @param engine reference to the engine * @param elapsed Number of milliseconds elapsed since the last draw. */ public onPreUpdate(engine: Engine, elapsed: number): void { // will be overridden }
/** * Safe to override onPostUpdate lifecycle event handler. Synonymous with `.on('postupdate', (evt) =>{...})` * * `onPostUpdate` is called directly after a scene is updated. * @param engine reference to the engine * @param elapsed Number of milliseconds elapsed since the last draw. */ public onPostUpdate(engine: Engine, elapsed: number): void { // will be overridden }
/** * Safe to override onPreDraw lifecycle event handler. Synonymous with `.on('predraw', (evt) =>{...})` * * `onPreDraw` is called directly before a scene is drawn. * */ public onPreDraw(ctx: ExcaliburGraphicsContext, elapsed: number): void { // will be overridden }
/** * Safe to override onPostDraw lifecycle event handler. Synonymous with `.on('postdraw', (evt) =>{...})` * * `onPostDraw` is called directly after a scene is drawn. * */ public onPostDraw(ctx: ExcaliburGraphicsContext, elapsed: number): void { // will be overridden }
/** * Initializes actors in the scene */ private _initializeChildren() { for (const child of this.entities) { child._initialize(this.engine); } }
/** * Gets whether or not the {@apilink Scene} has been initialized */ public get isInitialized(): boolean { return this._isInitialized; }
/** * It is not recommended that internal excalibur methods be overridden, do so at your own risk. * * Initializes the scene before the first update, meant to be called by engine not by users of * Excalibur * @internal */ public async _initialize(engine: Engine) { if (!this.isInitialized) { try { this.engine = engine; // PhysicsWorld config is watched so things will automagically update this.physics.config = this.engine.physics; this.input = new InputHost({ global: engine.global, pointerTarget: engine.pointerScope === PointerScope.Canvas ? engine.canvas : document, grabWindowFocus: engine.grabWindowFocus, engine }); // Initialize camera first this.camera._initialize(engine);
// Lighting is opt-in, skip provisioning the systems entirely when disabled this._lastLightingEnabled = this.engine.lighting.enabled; if (this._lastLightingEnabled) { if (!this.world.systemManager.get(FlickerSystem)) { this.world.add(new FlickerSystem()); } if (!this.world.systemManager.get(LightingSystem)) { this.world.add(new LightingSystem()); } }
this.world.systemManager.initialize();
for (const plugin of engine.plugins) { plugin.onScenePreInitialize?.(this); }
// This order is important! we want to be sure any custom init that add actors // fire before the actor init await this.onInitialize(engine); this._initializeChildren();
for (const plugin of engine.plugins) { plugin.onScenePostInitialize?.(this); }
this._logger.debug('Scene.onInitialize', this, engine); this.events.emit('initialize', new InitializeEvent(engine, this)); } catch (e) { this._logger.error(`Error during scene initialization for scene ${engine.director?.getSceneName(this)}!`); throw e; } this._isInitialized = true; } }
/** * It is not recommended that internal excalibur methods be overridden, do so at your own risk. * * Activates the scene with the base behavior, then calls the overridable `onActivate` implementation. * @internal */ public async _activate(context: SceneActivationContext<TActivationData>) { try { this._logger.debug('Scene.onActivate', this); this.input.toggleEnabled(true);
for (const plugin of this.engine.plugins) { plugin.onScenePreActivate?.(this); }
await this.onActivate(context);
for (const plugin of this.engine.plugins) { plugin.onScenePostActivate?.(this); } } catch (e) { this._logger.error(`Error during scene activation for scene ${this.engine?.director?.getSceneName(this)}!`); throw e; } }
/** * It is not recommended that internal excalibur methods be overridden, do so at your own risk. * * Deactivates the scene with the base behavior, then calls the overridable `onDeactivate` implementation. * @internal */ public async _deactivate(context: SceneActivationContext<never>): Promise<any> { this._logger.debug('Scene.onDeactivate', this);
for (const plugin of this.engine.plugins) { plugin.onScenePreDeactivate?.(this); }
this.input.toggleEnabled(false); const result = await this.onDeactivate(context);
for (const plugin of this.engine.plugins) { plugin.onScenePostDeactivate?.(this); }
return result; }
/** * It is not recommended that internal excalibur methods be overridden, do so at your own risk. * * Internal _preupdate handler for {@apilink onPreUpdate} lifecycle event * @internal */ public _preupdate(engine: Engine, elapsed: number): void { this.emit('preupdate', new PreUpdateEvent(engine, elapsed, this)); this.onPreUpdate(engine, elapsed); }
/** * It is not recommended that internal excalibur methods be overridden, do so at your own risk. * * Internal _preupdate handler for {@apilink onPostUpdate} lifecycle event * @internal */ public _postupdate(engine: Engine, elapsed: number): void { this.emit('postupdate', new PostUpdateEvent(engine, elapsed, this)); this.onPostUpdate(engine, elapsed); }
/** * It is not recommended that internal excalibur methods be overridden, do so at your own risk. * * Internal _predraw handler for {@apilink onPreDraw} lifecycle event * @internal */ public _predraw(ctx: ExcaliburGraphicsContext, elapsed: number): void { this.emit('predraw', new PreDrawEvent(ctx, elapsed, this)); this.onPreDraw(ctx, elapsed); }
/** * It is not recommended that internal excalibur methods be overridden, do so at your own risk. * * Internal _postdraw handler for {@apilink onPostDraw} lifecycle event * @internal */ public _postdraw(ctx: ExcaliburGraphicsContext, elapsed: number): void { this.emit('postdraw', new PostDrawEvent(ctx, elapsed, this)); this.onPostDraw(ctx, elapsed); }
private _checkEnableDisableSystems(): void { if (this.engine.lighting.enabled !== this._lastLightingEnabled) { this._lastLightingEnabled = this.engine.lighting.enabled; if (this._lastLightingEnabled) { if (!this.world.systemManager.get(FlickerSystem)) { this.world.add(new FlickerSystem()); } if (!this.world.systemManager.get(LightingSystem)) { this.world.add(new LightingSystem()); } } else { const flicker = this.world.systemManager.get(FlickerSystem); if (flicker) { this.world.remove(flicker); } const lighting = this.world.systemManager.get(LightingSystem); if (lighting) { this.world.remove(lighting); } } } }
/** * Updates all the actors and timers in the scene. Called by the {@apilink Engine}. * @param engine Reference to the current Engine * @param elapsed The number of milliseconds since the last update */ public update(engine: Engine, elapsed: number) { if (!this.isInitialized) { this._logger.warnOnce(`Scene update called before initialize for scene ${engine.director?.getSceneName(this)}!`); return; } this._preupdate(engine, elapsed);
// TODO differed entity removal for timers let i: number, len: number; // Remove timers in the cancel queue before updating them for (i = 0, len = this._cancelQueue.length; i < len; i++) { this.removeTimer(this._cancelQueue[i]); } this._cancelQueue.length = 0;
// Cycle through timers updating timers for (const timer of this._timers) { timer.update(elapsed); }
this._checkEnableDisableSystems();
this.world.update(SystemType.Update, elapsed);
// Camera last keeps renders smooth that are based on entity/actor if (this.camera) { this.camera.update(engine, elapsed); }
this._collectActorStats(engine);
this._postupdate(engine, elapsed);
this.input.update(); }
/** * Draws all the actors in the Scene. Called by the {@apilink Engine}. * @param ctx The current rendering context * @param elapsed The number of milliseconds since the last draw */ public draw(ctx: ExcaliburGraphicsContext, elapsed: number) { if (!this.isInitialized) { this._logger.warnOnce(`Scene draw called before initialize!`); return; } this._predraw(ctx, elapsed);
this.world.update(SystemType.Draw, elapsed);
if (this.engine?.isDebug) { this.debugDraw(ctx); } this._postdraw(ctx, elapsed); }
/** * Draws all the actors' debug information in the Scene. Called by the {@apilink Engine}. * @param ctx The current rendering context */ /* istanbul ignore next */ public debugDraw(ctx: ExcaliburGraphicsContext) { this.emit('predebugdraw', new PreDebugDrawEvent(ctx, this)); // pass this.emit('postdebugdraw', new PostDebugDrawEvent(ctx, this)); }
/** * Checks whether an actor is contained in this scene or not */ public contains(actor: Actor): boolean { return this.actors.indexOf(actor) > -1; }
/** * Adds a {@apilink Timer} to the current {@apilink Scene}. * @param timer The timer to add to the current {@apilink Scene}. */ public add(timer: Timer): void;
/** * Adds a {@apilink TileMap} to the {@apilink Scene}, once this is done the {@apilink TileMap} will be drawn and updated. */ public add(tileMap: TileMap): void;
/** * Adds a {@apilink Trigger} to the {@apilink Scene}, once this is done the {@apilink Trigger} will listen for interactions with other actors. * @param trigger */ public add(trigger: Trigger): void;
/** * Adds an actor to the scene, once this is done the {@apilink Actor} will be drawn and updated. * @param actor The actor to add to the current scene */ public add(actor: Actor): void;
/** * Adds an {@apilink Entity} to the scene, once this is done the {@apilink Actor} will be drawn and updated. * @param entity The entity to add to the current scene */ public add(entity: Entity): void;
/** * Adds a {@apilink ScreenElement} to the scene. * @param screenElement The ScreenElement to add to the current scene */ public add(screenElement: ScreenElement): void; public add(entity: any): void { this.emit('entityadded', { target: entity } as any); if (entity instanceof Timer) { if (!Util.contains(this._timers, entity)) { this.addTimer(entity); } return; } this.world.add(entity); entity.scene = this; }
/** * Removes a {@apilink Timer} from it's current scene * and adds it to this scene. * * Useful if you want to have an object be present in only 1 scene at a time. * @param timer The Timer to transfer to the current scene */ public transfer(timer: Timer): void;
/** * Removes a {@apilink TileMap} from it's current scene * and adds it to this scene. * * Useful if you want to have an object be present in only 1 scene at a time. * @param tileMap The TileMap to transfer to the current scene */ public transfer(tileMap: TileMap): void;
/** * Removes a {@apilink Trigger} from it's current scene * and adds it to this scene. * * Useful if you want to have an object be present in only 1 scene at a time. * @param trigger The Trigger to transfer to the current scene */ public transfer(trigger: Trigger): void;
/** * Removes an {@apilink Actor} from it's current scene * and adds it to this scene. * * Useful if you want to have an object be present in only 1 scene at a time. * @param actor The Actor to transfer to the current scene */ public transfer(actor: Actor): void;
/** * Removes an {@apilink Entity} from it's current scene * and adds it to this scene. * * Useful if you want to have an object be present in only 1 scene at a time. * @param entity The Entity to transfer to the current scene */ public transfer(entity: Entity): void;
/** * Removes a {@apilink ScreenElement} from it's current scene * and adds it to this scene. * * Useful if you want to have an object be present in only 1 scene at a time. * @param screenElement The ScreenElement to transfer to the current scene */ public transfer(screenElement: ScreenElement): void;
/** * Removes an {@apilink Entity} (Actor, TileMap, Trigger, etc) or {@apilink Timer} from it's current scene * and adds it to this scene. * * Useful if you want to have an object be present in only 1 scene at a time. * @param entity */ public transfer(entity: any): void { let scene: Scene | null = null; if (entity instanceof Entity && entity.scene && entity.scene !== this) { scene = entity.scene; entity.scene.world.remove(entity, false); } if (entity instanceof Timer && entity.scene) { scene = entity.scene; entity.scene.removeTimer(entity); }
if (scene) { scene.emit('entityremoved', { target: entity } as any); } this.add(entity); }
/** * Removes a {@apilink Timer} from the current scene, it will no longer be updated. * @param timer The timer to remove to the current scene. */ public remove(timer: Timer): void;
/** * Removes a {@apilink TileMap} from the scene, it will no longer be drawn or updated. * @param tileMap {TileMap} */ public remove(tileMap: TileMap): void;
/** * Removes an actor from the scene, it will no longer be drawn or updated. * @param actor The actor to remove from the current scene. */ public remove(actor: Actor): void;
public remove(entity: Entity): void;
/** * Removes a {@apilink ScreenElement} to the scene, it will no longer be drawn or updated * @param screenElement The ScreenElement to remove from the current scene */ public remove(screenElement: ScreenElement): void; public remove(entity: any): void { this.emit('entityremoved', { target: entity } as any); if (entity instanceof Entity) { if (entity.isActive) { entity.kill(); } this.world.remove(entity); } if (entity instanceof Timer) { this.removeTimer(entity); } }
/** * Removes all entities and timers from the scene, optionally indicate whether deferred should or shouldn't be used. * * By default entities use deferred removal * @param deferred */ public clear(deferred: boolean = true): void { for (let i = this.entities.length - 1; i >= 0; i--) { this.world.remove(this.entities[i], deferred); } for (let i = this.timers.length - 1; i >= 0; i--) { this.removeTimer(this.timers[i]); } }
/** * Adds a {@apilink Timer} to the scene * @param timer The timer to add */ public addTimer(timer: Timer): Timer { this._timers.push(timer); timer.scene = this; return timer; }
/** * Removes a {@apilink Timer} from the scene. * @warning Can be dangerous, use {@apilink cancelTimer} instead * @param timer The timer to remove */ public removeTimer(timer: Timer): Timer { const i = this._timers.indexOf(timer); if (i !== -1) { this._timers.splice(i, 1); } return timer; }
/** * Cancels a {@apilink Timer}, removing it from the scene nicely * @param timer The timer to cancel */ public cancelTimer(timer: Timer): Timer { this._cancelQueue.push(timer); return timer; }
/** * Tests whether a {@apilink Timer} is active in the scene */ public isTimerActive(timer: Timer): boolean { return this._timers.indexOf(timer) > -1 && !timer.complete; }
public isCurrentScene(): boolean { if (this.engine) { return this.engine.currentScene === this; } return false; }
private _collectActorStats(engine: Engine) { const actors = this.actors; for (let i = 0; i < actors.length; i++) { const actor = actors[i]; if (actor instanceof ScreenElement) { engine.stats.currFrame.actors.ui++; } engine.stats.currFrame.actors.alive++; for (let j = 0; j < actor.children.length; j++) { const child = actor.children[j]; if (isScreenElement(child as Actor)) { // TODO not true engine.stats.currFrame.actors.ui++; } else { engine.stats.currFrame.actors.alive++; } } } }
public pause() { this.events.emit('pause'); }
public resume() { this.events.emit('resume'); }}