dacha 0.14.4 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. package/build/contrib/components/behaviors/index.d.ts +14 -0
  2. package/build/contrib/components/behaviors/index.js +15 -0
  3. package/build/contrib/components/index.d.ts +2 -2
  4. package/build/contrib/components/index.js +1 -1
  5. package/build/contrib/events/index.d.ts +12 -15
  6. package/build/contrib/events/index.js +0 -1
  7. package/build/contrib/systems/animator/condition-controllers/condition-controller.d.ts +1 -0
  8. package/build/contrib/systems/animator/condition-controllers/event-condition-controller.d.ts +4 -0
  9. package/build/contrib/systems/animator/condition-controllers/event-condition-controller.js +15 -9
  10. package/build/contrib/systems/animator/index.d.ts +5 -6
  11. package/build/contrib/systems/animator/index.js +10 -5
  12. package/build/contrib/systems/audio-system/index.d.ts +14 -10
  13. package/build/contrib/systems/audio-system/index.js +85 -51
  14. package/build/contrib/systems/audio-system/utils.d.ts +3 -0
  15. package/build/contrib/systems/audio-system/utils.js +19 -0
  16. package/build/contrib/systems/behavior-system/index.d.ts +3 -0
  17. package/build/contrib/systems/behavior-system/index.js +2 -0
  18. package/build/contrib/systems/behavior-system/system.d.ts +16 -0
  19. package/build/contrib/systems/behavior-system/system.js +69 -0
  20. package/build/contrib/systems/{script-system → behavior-system}/types.d.ts +7 -5
  21. package/build/contrib/systems/behavior-system/types.js +3 -0
  22. package/build/contrib/systems/camera-system/service.d.ts +5 -5
  23. package/build/contrib/systems/camera-system/service.js +5 -12
  24. package/build/contrib/systems/camera-system/system.d.ts +11 -12
  25. package/build/contrib/systems/camera-system/system.js +31 -34
  26. package/build/contrib/systems/game-stats-meter/index.d.ts +9 -6
  27. package/build/contrib/systems/game-stats-meter/index.js +13 -8
  28. package/build/contrib/systems/index.d.ts +4 -4
  29. package/build/contrib/systems/index.js +2 -2
  30. package/build/contrib/systems/keyboard-control-system/index.d.ts +10 -8
  31. package/build/contrib/systems/keyboard-control-system/index.js +15 -14
  32. package/build/contrib/systems/keyboard-input-system/index.d.ts +6 -7
  33. package/build/contrib/systems/keyboard-input-system/index.js +7 -9
  34. package/build/contrib/systems/mouse-control-system/index.d.ts +10 -8
  35. package/build/contrib/systems/mouse-control-system/index.js +14 -13
  36. package/build/contrib/systems/mouse-input-system/index.d.ts +5 -6
  37. package/build/contrib/systems/mouse-input-system/index.js +5 -9
  38. package/build/contrib/systems/mouse-input-system/subsystems/coordinates-projector/index.d.ts +4 -5
  39. package/build/contrib/systems/mouse-input-system/subsystems/coordinates-projector/index.js +7 -9
  40. package/build/contrib/systems/mouse-input-system/subsystems/input-subsystem/index.d.ts +4 -5
  41. package/build/contrib/systems/mouse-input-system/subsystems/input-subsystem/index.js +5 -7
  42. package/build/contrib/systems/physics-system/index.d.ts +5 -6
  43. package/build/contrib/systems/physics-system/index.js +8 -15
  44. package/build/contrib/systems/physics-system/subsystems/collision-broadcast/index.d.ts +3 -4
  45. package/build/contrib/systems/physics-system/subsystems/collision-broadcast/index.js +1 -3
  46. package/build/contrib/systems/physics-system/subsystems/collision-detection/index.d.ts +3 -4
  47. package/build/contrib/systems/physics-system/subsystems/collision-detection/index.js +1 -3
  48. package/build/contrib/systems/physics-system/subsystems/collision-solver/index.d.ts +3 -4
  49. package/build/contrib/systems/physics-system/subsystems/collision-solver/index.js +1 -3
  50. package/build/contrib/systems/physics-system/subsystems/constraint-solver/index.d.ts +3 -4
  51. package/build/contrib/systems/physics-system/subsystems/constraint-solver/index.js +1 -3
  52. package/build/contrib/systems/physics-system/subsystems/physics/index.d.ts +3 -4
  53. package/build/contrib/systems/physics-system/subsystems/physics/index.js +1 -3
  54. package/build/contrib/systems/physics-system/types.d.ts +2 -2
  55. package/build/contrib/systems/sprite-renderer/light-subsystem/index.d.ts +7 -7
  56. package/build/contrib/systems/sprite-renderer/light-subsystem/index.js +28 -17
  57. package/build/contrib/systems/sprite-renderer/renderer.d.ts +16 -12
  58. package/build/contrib/systems/sprite-renderer/renderer.js +127 -93
  59. package/build/contrib/systems/sprite-renderer/sprite-cropper.js +1 -1
  60. package/build/contrib/systems/sprite-renderer/utils.d.ts +4 -4
  61. package/build/contrib/systems/sprite-renderer/utils.js +13 -7
  62. package/build/contrib/systems/ui-bridge/index.d.ts +21 -33
  63. package/build/contrib/systems/ui-bridge/index.js +26 -51
  64. package/build/engine/actor/actor.d.ts +3 -2
  65. package/build/engine/actor/actor.js +7 -4
  66. package/build/engine/data-lib/cache-store.d.ts +11 -0
  67. package/build/engine/data-lib/cache-store.js +40 -0
  68. package/build/engine/data-lib/index.d.ts +1 -0
  69. package/build/engine/data-lib/index.js +1 -0
  70. package/build/engine/engine.d.ts +1 -1
  71. package/build/engine/engine.js +19 -33
  72. package/build/engine/entity/entity.d.ts +3 -2
  73. package/build/engine/entity/entity.js +8 -5
  74. package/build/engine/entity/index.d.ts +1 -1
  75. package/build/engine/entity/index.js +1 -1
  76. package/build/engine/entity/utils.d.ts +1 -1
  77. package/build/engine/entity/utils.js +7 -8
  78. package/build/engine/events/index.d.ts +46 -7
  79. package/build/engine/events/index.js +7 -1
  80. package/build/engine/game-loop.d.ts +3 -5
  81. package/build/engine/game-loop.js +6 -11
  82. package/build/engine/scene/index.d.ts +1 -2
  83. package/build/engine/scene/index.js +1 -1
  84. package/build/engine/scene/scene-manager.d.ts +43 -0
  85. package/build/engine/scene/scene-manager.js +190 -0
  86. package/build/engine/scene/scene.d.ts +5 -20
  87. package/build/engine/scene/scene.js +7 -59
  88. package/build/engine/system/index.d.ts +2 -2
  89. package/build/engine/system/index.js +1 -1
  90. package/build/engine/system/system.d.ts +21 -5
  91. package/build/engine/system/system.js +4 -0
  92. package/build/engine/template/template.d.ts +3 -2
  93. package/build/engine/template/template.js +7 -4
  94. package/build/engine/types/config.d.ts +2 -10
  95. package/build/engine/world/index.d.ts +28 -0
  96. package/build/engine/world/index.js +49 -0
  97. package/build/events/index.d.ts +4 -4
  98. package/build/events/index.js +2 -2
  99. package/build/index.d.ts +3 -2
  100. package/build/index.js +1 -1
  101. package/build/types/events.d.ts +4 -0
  102. package/package.json +1 -1
  103. package/build/contrib/components/script-bundle/index.d.ts +0 -14
  104. package/build/contrib/components/script-bundle/index.js +0 -15
  105. package/build/contrib/systems/audio-system/audio-loader.d.ts +0 -7
  106. package/build/contrib/systems/audio-system/audio-loader.js +0 -16
  107. package/build/contrib/systems/script-system/index.d.ts +0 -19
  108. package/build/contrib/systems/script-system/index.js +0 -71
  109. package/build/contrib/systems/script-system/types.js +0 -3
  110. package/build/contrib/systems/ui-bridge/observer/index.d.ts +0 -1
  111. package/build/contrib/systems/ui-bridge/observer/index.js +0 -1
  112. package/build/contrib/systems/ui-bridge/observer/observer.d.ts +0 -8
  113. package/build/contrib/systems/ui-bridge/observer/observer.js +0 -21
  114. package/build/contrib/systems/webgl-render-system/color/color-reader/color-reader.d.ts +0 -3
  115. package/build/contrib/systems/webgl-render-system/color/color-reader/color-reader.js +0 -1
  116. package/build/contrib/systems/webgl-render-system/color/color-reader/consts.d.ts +0 -3
  117. package/build/contrib/systems/webgl-render-system/color/color-reader/consts.js +0 -10
  118. package/build/contrib/systems/webgl-render-system/color/color-reader/hex-color-reader.d.ts +0 -4
  119. package/build/contrib/systems/webgl-render-system/color/color-reader/hex-color-reader.js +0 -14
  120. package/build/contrib/systems/webgl-render-system/color/color-reader/index.d.ts +0 -6
  121. package/build/contrib/systems/webgl-render-system/color/color-reader/index.js +0 -6
  122. package/build/contrib/systems/webgl-render-system/color/color-reader/short-hex-color-reader.d.ts +0 -4
  123. package/build/contrib/systems/webgl-render-system/color/color-reader/short-hex-color-reader.js +0 -11
  124. package/build/contrib/systems/webgl-render-system/color/index.d.ts +0 -7
  125. package/build/contrib/systems/webgl-render-system/color/index.js +0 -41
  126. package/build/contrib/systems/webgl-render-system/consts.d.ts +0 -9
  127. package/build/contrib/systems/webgl-render-system/consts.js +0 -9
  128. package/build/contrib/systems/webgl-render-system/geometry/rectangle.d.ts +0 -6
  129. package/build/contrib/systems/webgl-render-system/geometry/rectangle.js +0 -22
  130. package/build/contrib/systems/webgl-render-system/index.d.ts +0 -66
  131. package/build/contrib/systems/webgl-render-system/index.js +0 -405
  132. package/build/contrib/systems/webgl-render-system/matrix-transformer/index.d.ts +0 -20
  133. package/build/contrib/systems/webgl-render-system/matrix-transformer/index.js +0 -55
  134. package/build/contrib/systems/webgl-render-system/shader-builder/fragment-shader.d.ts +0 -1
  135. package/build/contrib/systems/webgl-render-system/shader-builder/fragment-shader.js +0 -29
  136. package/build/contrib/systems/webgl-render-system/shader-builder/index.d.ts +0 -11
  137. package/build/contrib/systems/webgl-render-system/shader-builder/index.js +0 -39
  138. package/build/contrib/systems/webgl-render-system/shader-builder/shader-provider.d.ts +0 -10
  139. package/build/contrib/systems/webgl-render-system/shader-builder/shader-provider.js +0 -34
  140. package/build/contrib/systems/webgl-render-system/shader-builder/vertex-shader.d.ts +0 -1
  141. package/build/contrib/systems/webgl-render-system/shader-builder/vertex-shader.js +0 -16
  142. package/build/contrib/systems/webgl-render-system/texture-handlers/index.d.ts +0 -7
  143. package/build/contrib/systems/webgl-render-system/texture-handlers/index.js +0 -6
  144. package/build/contrib/systems/webgl-render-system/texture-handlers/sprite-texture-handler.d.ts +0 -10
  145. package/build/contrib/systems/webgl-render-system/texture-handlers/sprite-texture-handler.js +0 -16
  146. package/build/contrib/systems/webgl-render-system/texture-handlers/static-texture-handler.d.ts +0 -9
  147. package/build/contrib/systems/webgl-render-system/texture-handlers/static-texture-handler.js +0 -10
  148. package/build/contrib/systems/webgl-render-system/texture-handlers/texture-handler.d.ts +0 -10
  149. package/build/contrib/systems/webgl-render-system/texture-handlers/texture-handler.js +0 -1
  150. package/build/contrib/systems/webgl-render-system/utils/index.d.ts +0 -1
  151. package/build/contrib/systems/webgl-render-system/utils/index.js +0 -1
  152. package/build/contrib/systems/webgl-render-system/utils/split-to-batch.d.ts +0 -3
  153. package/build/contrib/systems/webgl-render-system/utils/split-to-batch.js +0 -19
  154. package/build/engine/controllers/controller.d.ts +0 -7
  155. package/build/engine/controllers/controller.js +0 -1
  156. package/build/engine/controllers/index.d.ts +0 -2
  157. package/build/engine/controllers/index.js +0 -1
  158. package/build/engine/controllers/scene-controller.d.ts +0 -11
  159. package/build/engine/controllers/scene-controller.js +0 -50
  160. package/build/engine/scene/scene-provider.d.ts +0 -50
  161. package/build/engine/scene/scene-provider.js +0 -148
@@ -0,0 +1,14 @@
1
+ import { Component } from '../../../engine/component';
2
+ interface BehaviorConfig {
3
+ name: string;
4
+ options: Record<string, unknown>;
5
+ }
6
+ export interface BehaviorsConfig {
7
+ list: BehaviorConfig[];
8
+ }
9
+ export declare class Behaviors extends Component {
10
+ list: BehaviorConfig[];
11
+ constructor(config: BehaviorsConfig);
12
+ clone(): Behaviors;
13
+ }
14
+ export {};
@@ -0,0 +1,15 @@
1
+ import { Component } from '../../../engine/component';
2
+ export class Behaviors extends Component {
3
+ list;
4
+ constructor(config) {
5
+ super();
6
+ const { list } = config;
7
+ this.list = list;
8
+ }
9
+ clone() {
10
+ return new Behaviors({
11
+ list: this.list.map(({ name, options }) => ({ name, options: { ...options } })),
12
+ });
13
+ }
14
+ }
15
+ Behaviors.componentName = 'Behaviors';
@@ -14,8 +14,8 @@ export { Transform } from './transform';
14
14
  export type { TransformConfig } from './transform';
15
15
  export { MouseControl } from './mouse-control';
16
16
  export type { MouseControlConfig } from './mouse-control';
17
- export { ScriptBundle } from './script-bundle';
18
- export type { ScriptBundleConfig } from './script-bundle';
17
+ export { Behaviors } from './behaviors';
18
+ export type { BehaviorsConfig } from './behaviors';
19
19
  export { Light } from './light';
20
20
  export type { LightConfig } from './light';
21
21
  export { AudioSource } from './audio-source';
@@ -6,6 +6,6 @@ export { Animatable } from './animatable';
6
6
  export { Sprite } from './sprite';
7
7
  export { Transform } from './transform';
8
8
  export { MouseControl } from './mouse-control';
9
- export { ScriptBundle } from './script-bundle';
9
+ export { Behaviors } from './behaviors';
10
10
  export { Light } from './light';
11
11
  export { AudioSource } from './audio-source';
@@ -1,8 +1,7 @@
1
1
  import type { Actor } from '../../engine/actor';
2
2
  import type { Vector2 } from '../../engine/math-lib';
3
3
  import type { CustomMouseEvent, CustomKeyboardEvent } from '../types/input-events';
4
- import type { ActorEvent, SceneEvent } from '../../types/events';
5
- export declare const SetCamera = "SetCamera";
4
+ import type { ActorEvent, SceneEvent, WorldEvent } from '../../types/events';
6
5
  export declare const GameStatsUpdate = "GameStatsUpdate";
7
6
  export declare const Collision = "Collision";
8
7
  export declare const KeyboardInput = "KeyboardInput";
@@ -16,25 +15,22 @@ export declare const StopMovement = "StopMovement";
16
15
  export declare const PlayAudio = "PlayAudio";
17
16
  export declare const StopAudio = "StopAudio";
18
17
  export declare const SetAudioVolume = "SetAudioVolume";
19
- export type MouseInputEvent = SceneEvent<CustomMouseEvent>;
20
- export type KeyboardInputEvent = SceneEvent<CustomKeyboardEvent>;
21
- export type SetCameraEvent = SceneEvent<{
22
- actorId: string;
23
- }>;
24
- export type GameStatsUpdateEvent = SceneEvent<{
18
+ export type MouseInputEvent = WorldEvent<CustomMouseEvent>;
19
+ export type KeyboardInputEvent = WorldEvent<CustomKeyboardEvent>;
20
+ export type GameStatsUpdateEvent = WorldEvent<{
25
21
  fps: number;
26
22
  actorsCount: number;
27
23
  }>;
24
+ export type SetAudioGroupVolumeEvent = WorldEvent<{
25
+ group: string;
26
+ value: number;
27
+ }>;
28
28
  export type CollisionEvent = SceneEvent<{
29
29
  actor1: Actor;
30
30
  actor2: Actor;
31
31
  mtv1: Vector2;
32
32
  mtv2: Vector2;
33
33
  }>;
34
- export type SetAudioGroupVolumeEvent = SceneEvent<{
35
- group: string;
36
- value: number;
37
- }>;
38
34
  export type MouseControlEvent<T = Record<string, never>> = ActorEvent<Pick<CustomMouseEvent, 'x' | 'y' | 'screenX' | 'screenY' | 'nativeEvent'>> & T;
39
35
  export type KeyboardControlEvent<T = Record<string, never>> = ActorEvent<T>;
40
36
  type CollisionStateEvent = ActorEvent<{
@@ -54,14 +50,15 @@ export type SetAudioSourceVolumeEvent = ActorEvent<{
54
50
  value: number;
55
51
  }>;
56
52
  declare module '../../types/events' {
57
- interface SceneEventMap {
53
+ interface WorldEventMap {
58
54
  [MouseInput]: MouseInputEvent;
59
55
  [KeyboardInput]: KeyboardInputEvent;
60
- [SetCamera]: SetCameraEvent;
61
56
  [GameStatsUpdate]: GameStatsUpdateEvent;
62
- [Collision]: CollisionEvent;
63
57
  [SetAudioVolume]: SetAudioGroupVolumeEvent;
64
58
  }
59
+ interface SceneEventMap {
60
+ [Collision]: CollisionEvent;
61
+ }
65
62
  interface ActorEventMap {
66
63
  [CollisionEnter]: CollisionEnterEvent;
67
64
  [CollisionStay]: CollisionStayEvent;
@@ -1,4 +1,3 @@
1
- export const SetCamera = 'SetCamera';
2
1
  export const GameStatsUpdate = 'GameStatsUpdate';
3
2
  export const Collision = 'Collision';
4
3
  export const KeyboardInput = 'KeyboardInput';
@@ -1,3 +1,4 @@
1
1
  export interface ConditionController {
2
+ destroy?(): void;
2
3
  check(): boolean;
3
4
  }
@@ -2,7 +2,11 @@ import type { Actor } from '../../../../engine/actor';
2
2
  import type { EventConditionProps } from '../../../components/animatable/event-condition-props';
3
3
  import { ConditionController } from './condition-controller';
4
4
  export declare class EventConditionController implements ConditionController {
5
+ private actor;
6
+ private eventType;
5
7
  private isEventFired;
6
8
  constructor(props: EventConditionProps, actor: Actor);
9
+ destroy(): void;
10
+ private handleEvent;
7
11
  check(): boolean;
8
12
  }
@@ -1,17 +1,23 @@
1
1
  export class EventConditionController {
2
+ actor;
3
+ eventType;
2
4
  isEventFired;
3
5
  constructor(props, actor) {
6
+ this.actor = actor;
7
+ this.eventType = props.eventType;
4
8
  this.isEventFired = false;
5
- const { eventType } = props;
6
- const handleEvent = (event) => {
7
- if (event.target !== actor) {
8
- return;
9
- }
10
- this.isEventFired = true;
11
- actor.removeEventListener(eventType, handleEvent);
12
- };
13
- actor.addEventListener(eventType, handleEvent);
9
+ this.actor.addEventListener(this.eventType, this.handleEvent);
14
10
  }
11
+ destroy() {
12
+ this.actor.removeEventListener(this.eventType, this.handleEvent);
13
+ }
14
+ handleEvent = (event) => {
15
+ if (event.target !== this.actor) {
16
+ return;
17
+ }
18
+ this.isEventFired = true;
19
+ this.actor.removeEventListener(this.eventType, this.handleEvent);
20
+ };
15
21
  check() {
16
22
  return this.isEventFired;
17
23
  }
@@ -1,12 +1,11 @@
1
- import { System } from '../../../engine/system';
2
- import type { SystemOptions, UpdateOptions } from '../../../engine/system';
3
- export declare class Animator extends System {
1
+ import { SceneSystem } from '../../../engine/system';
2
+ import type { UpdateOptions, SceneSystemOptions } from '../../../engine/system';
3
+ export declare class Animator extends SceneSystem {
4
4
  private actorCollection;
5
5
  private substatePickers;
6
6
  private actorConditions;
7
- constructor(options: SystemOptions);
8
- mount(): void;
9
- unmount(): void;
7
+ constructor(options: SceneSystemOptions);
8
+ onSceneDestroy(): void;
10
9
  private handleActorRemove;
11
10
  private setUpConditionControllers;
12
11
  private updateFrame;
@@ -1,4 +1,4 @@
1
- import { System } from '../../../engine/system';
1
+ import { SceneSystem } from '../../../engine/system';
2
2
  import { ActorCollection } from '../../../engine/actor';
3
3
  import { Animatable } from '../../components/animatable';
4
4
  import { RemoveActor } from '../../../engine/events';
@@ -6,7 +6,7 @@ import { conditionControllers } from './condition-controllers';
6
6
  import { substatePickers } from './substate-pickers';
7
7
  import { setValue } from './utils';
8
8
  const FRAME_RATE = 100;
9
- export class Animator extends System {
9
+ export class Animator extends SceneSystem {
10
10
  actorCollection;
11
11
  substatePickers;
12
12
  actorConditions;
@@ -22,12 +22,17 @@ export class Animator extends System {
22
22
  return storage;
23
23
  }, {});
24
24
  this.actorConditions = {};
25
- }
26
- mount() {
27
25
  this.actorCollection.addEventListener(RemoveActor, this.handleActorRemove);
28
26
  }
29
- unmount() {
27
+ onSceneDestroy() {
30
28
  this.actorCollection.removeEventListener(RemoveActor, this.handleActorRemove);
29
+ Object.values(this.actorConditions).forEach((transitions) => {
30
+ Object.values(transitions).forEach((conditions) => {
31
+ Object.values(conditions).forEach((controller) => {
32
+ controller.destroy?.();
33
+ });
34
+ });
35
+ });
31
36
  }
32
37
  handleActorRemove = (event) => {
33
38
  delete this.actorConditions[event.actor.id];
@@ -1,18 +1,22 @@
1
- import { System } from '../../../engine/system';
2
- import type { SystemOptions } from '../../../engine/system';
3
- export declare class AudioSystem extends System {
1
+ import { WorldSystem } from '../../../engine/system';
2
+ import type { Scene } from '../../../engine/scene';
3
+ import type { WorldSystemOptions } from '../../../engine/system';
4
+ export declare class AudioSystem extends WorldSystem {
4
5
  private templateCollection;
5
- private actorCollection;
6
- private scene;
6
+ private world;
7
+ private scene?;
7
8
  private audioContext;
8
9
  private audioGroups;
9
- private audioCache;
10
+ private audioStore;
10
11
  private audioState;
11
- constructor(options: SystemOptions);
12
- load(): Promise<void>;
12
+ private actorCollections;
13
+ constructor(options: WorldSystemOptions);
14
+ onSceneLoad(scene: Scene): Promise<void>;
15
+ onSceneEnter(scene: Scene): void;
16
+ onSceneExit(scene: Scene): void;
17
+ onSceneDestroy(scene: Scene): void;
18
+ onWorldDestroy(): void;
13
19
  private loadAudio;
14
- mount(): void;
15
- unmount(): void;
16
20
  private handleActorAdd;
17
21
  private handleActorRemove;
18
22
  private handlePlayAudio;
@@ -1,27 +1,26 @@
1
- import { System } from '../../../engine/system';
1
+ import { WorldSystem } from '../../../engine/system';
2
2
  import { Actor, ActorCollection } from '../../../engine/actor';
3
3
  import { AddActor, RemoveActor } from '../../../engine/events';
4
+ import { CacheStore } from '../../../engine/data-lib';
4
5
  import { AudioSource } from '../../components';
5
6
  import { PlayAudio, StopAudio, SetAudioVolume, } from '../../../events';
6
- import { audioLoader } from './audio-loader';
7
+ import { getAllTemplateSources, loadAudio } from './utils';
7
8
  const MASTER_GROUP = 'master';
8
9
  const VOLUME_TOLERANCE = 0.001;
9
- export class AudioSystem extends System {
10
+ export class AudioSystem extends WorldSystem {
10
11
  templateCollection;
11
- actorCollection;
12
+ world;
12
13
  scene;
13
14
  audioContext;
14
15
  audioGroups;
15
- audioCache;
16
+ audioStore;
16
17
  audioState;
18
+ actorCollections;
17
19
  constructor(options) {
18
20
  super();
19
- const { scene, globalOptions, templateCollection } = options;
21
+ const { world, globalOptions, templateCollection } = options;
20
22
  this.templateCollection = templateCollection;
21
- this.actorCollection = new ActorCollection(scene, {
22
- components: [AudioSource],
23
- });
24
- this.scene = scene;
23
+ this.world = world;
25
24
  this.audioContext = new AudioContext();
26
25
  const masterAudioGroup = new GainNode(this.audioContext);
27
26
  masterAudioGroup.connect(this.audioContext.destination);
@@ -37,60 +36,92 @@ export class AudioSystem extends System {
37
36
  acc[groupSettings.name] = gainNode;
38
37
  return acc;
39
38
  }, { [MASTER_GROUP]: masterAudioGroup });
40
- this.audioCache = new Map();
39
+ this.audioStore = new CacheStore();
41
40
  this.audioState = new Map();
42
- }
43
- async load() {
44
- const templateSources = this.templateCollection.getAll()
45
- .filter((template) => template.getComponent(AudioSource))
46
- .map((template) => template.getComponent(AudioSource).src);
47
- const sources = this.actorCollection.map((actor) => actor.getComponent(AudioSource).src);
48
- const uniqueSources = [...new Set([...templateSources, ...sources])];
49
- await Promise.all(uniqueSources.map((src) => this.loadAudio(src)));
50
- }
51
- async loadAudio(audioSourcePath) {
52
- if (this.audioCache.has(audioSourcePath)) {
53
- return;
54
- }
55
- try {
56
- const arrayBuffer = await audioLoader.load(audioSourcePath);
57
- const audioBuffer = await this.audioContext.decodeAudioData(arrayBuffer);
58
- this.audioCache.set(audioSourcePath, audioBuffer);
59
- }
60
- catch (error) {
61
- console.error(`An error occurred during audio source loading: ${audioSourcePath}`, error);
62
- }
63
- }
64
- mount() {
65
- this.actorCollection.forEach((actor) => this.initAudio(actor));
66
- this.actorCollection.addEventListener(AddActor, this.handleActorAdd);
67
- this.actorCollection.addEventListener(RemoveActor, this.handleActorRemove);
68
- this.scene.addEventListener(PlayAudio, this.handlePlayAudio);
69
- this.scene.addEventListener(StopAudio, this.handleStopAudio);
70
- this.scene.addEventListener(SetAudioVolume, this.handleSetAudioVolume);
41
+ this.actorCollections = {};
42
+ this.world.addEventListener(PlayAudio, this.handlePlayAudio);
43
+ this.world.addEventListener(StopAudio, this.handleStopAudio);
44
+ this.world.addEventListener(SetAudioVolume, this.handleSetAudioVolume);
71
45
  window.addEventListener('click', this.resumeIfSuspended, { once: true });
72
46
  window.addEventListener('keydown', this.resumeIfSuspended, { once: true });
73
47
  window.addEventListener('touchstart', this.resumeIfSuspended, { once: true });
74
48
  }
75
- unmount() {
49
+ async onSceneLoad(scene) {
50
+ this.actorCollections[scene.id] = new ActorCollection(scene, {
51
+ components: [AudioSource],
52
+ });
53
+ const allSources = [
54
+ ...getAllTemplateSources(this.templateCollection),
55
+ ...this.actorCollections[scene.id].map((actor) => actor.getComponent(AudioSource).src),
56
+ ];
57
+ const uniqueSources = [...new Set(allSources)];
58
+ const audioBuffers = await Promise.all(uniqueSources.map((src) => {
59
+ return !this.audioStore.has(src) ? this.loadAudio(src) : undefined;
60
+ }));
61
+ uniqueSources.forEach((src, index) => {
62
+ if (audioBuffers[index]) {
63
+ this.audioStore.add(src, audioBuffers[index]);
64
+ }
65
+ });
66
+ allSources.forEach((src) => this.audioStore.retain(src));
67
+ }
68
+ onSceneEnter(scene) {
69
+ this.scene = scene;
70
+ this.actorCollections[scene.id]?.forEach((actor) => this.initAudio(actor));
71
+ this.actorCollections[scene.id]?.addEventListener(AddActor, this.handleActorAdd);
72
+ this.actorCollections[scene.id]?.addEventListener(RemoveActor, this.handleActorRemove);
73
+ }
74
+ onSceneExit(scene) {
76
75
  this.audioState.forEach((audioState) => {
77
76
  audioState.sourceNode.stop();
78
77
  });
78
+ this.actorCollections[scene.id]?.removeEventListener(AddActor, this.handleActorAdd);
79
+ this.actorCollections[scene.id]?.removeEventListener(RemoveActor, this.handleActorRemove);
80
+ this.scene = undefined;
81
+ }
82
+ onSceneDestroy(scene) {
83
+ const allSources = [
84
+ ...getAllTemplateSources(this.templateCollection),
85
+ ...this.actorCollections[scene.id].map((actor) => actor.getComponent(AudioSource).src),
86
+ ];
87
+ allSources.forEach((src) => this.audioStore.release(src));
88
+ this.audioStore.cleanReleased();
89
+ delete this.actorCollections[scene.id];
90
+ }
91
+ onWorldDestroy() {
79
92
  void this.audioContext.close();
80
- this.actorCollection.removeEventListener(AddActor, this.handleActorAdd);
81
- this.actorCollection.removeEventListener(RemoveActor, this.handleActorRemove);
82
- this.scene.removeEventListener(PlayAudio, this.handlePlayAudio);
83
- this.scene.removeEventListener(StopAudio, this.handleStopAudio);
84
- this.scene.removeEventListener(SetAudioVolume, this.handleSetAudioVolume);
93
+ this.world.removeEventListener(PlayAudio, this.handlePlayAudio);
94
+ this.world.removeEventListener(StopAudio, this.handleStopAudio);
95
+ this.world.removeEventListener(SetAudioVolume, this.handleSetAudioVolume);
85
96
  window.removeEventListener('click', this.resumeIfSuspended);
86
97
  window.removeEventListener('keydown', this.resumeIfSuspended);
87
98
  window.removeEventListener('touchstart', this.resumeIfSuspended);
88
99
  }
100
+ async loadAudio(src) {
101
+ if (!src) {
102
+ return undefined;
103
+ }
104
+ try {
105
+ const arrayBuffer = await loadAudio(src);
106
+ const audioBuffer = await this.audioContext.decodeAudioData(arrayBuffer);
107
+ return audioBuffer;
108
+ }
109
+ catch (error) {
110
+ console.error(`An error occurred during audio source loading: ${src}`, error);
111
+ return undefined;
112
+ }
113
+ }
89
114
  handleActorAdd = (event) => {
90
- this.initAudio(event.actor);
115
+ const { actor } = event;
116
+ const { src } = actor.getComponent(AudioSource);
117
+ this.audioStore.retain(src);
118
+ this.initAudio(actor);
91
119
  };
92
120
  handleActorRemove = (event) => {
93
- this.stopAudio(event.actor);
121
+ const { actor } = event;
122
+ const { src } = actor.getComponent(AudioSource);
123
+ this.audioStore.release(src);
124
+ this.stopAudio(actor);
94
125
  };
95
126
  handlePlayAudio = (event) => {
96
127
  this.playAudio(event.target);
@@ -136,7 +167,7 @@ export class AudioSystem extends System {
136
167
  }
137
168
  const { src, group, volume, looped, playing, } = audioSource;
138
169
  const audioGroupNode = this.audioGroups[group];
139
- if (!audioGroupNode || !this.audioCache.has(src)) {
170
+ if (!audioGroupNode || !this.audioStore.has(src)) {
140
171
  return;
141
172
  }
142
173
  if (playing && this.audioState.has(actor.id)) {
@@ -146,7 +177,7 @@ export class AudioSystem extends System {
146
177
  prevAudio.gainNode.disconnect();
147
178
  }
148
179
  const sourceNode = new AudioBufferSourceNode(this.audioContext, {
149
- buffer: this.audioCache.get(src),
180
+ buffer: this.audioStore.get(src),
150
181
  loop: looped,
151
182
  });
152
183
  const gainNode = new GainNode(this.audioContext, {
@@ -184,7 +215,10 @@ export class AudioSystem extends System {
184
215
  }
185
216
  }
186
217
  update() {
187
- this.actorCollection.forEach((actor) => {
218
+ if (!this.scene) {
219
+ return;
220
+ }
221
+ this.actorCollections[this.scene.id]?.forEach((actor) => {
188
222
  const audioSource = actor.getComponent(AudioSource);
189
223
  const audioState = this.audioState.get(actor.id);
190
224
  if (audioSource.playing && audioState) {
@@ -0,0 +1,3 @@
1
+ import type { TemplateCollection } from '../../../engine/template';
2
+ export declare const getAllTemplateSources: (templateCollection: TemplateCollection) => string[];
3
+ export declare const loadAudio: (url: string) => Promise<ArrayBuffer>;
@@ -0,0 +1,19 @@
1
+ import { AudioSource } from '../../components';
2
+ import { traverseEntity } from '../../../engine/entity';
3
+ export const getAllTemplateSources = (templateCollection) => {
4
+ const templateSources = [];
5
+ templateCollection.getAll().forEach((template) => {
6
+ traverseEntity(template, (entity) => {
7
+ const audioSource = entity.getComponent(AudioSource);
8
+ if (audioSource?.src) {
9
+ templateSources.push(audioSource.src);
10
+ }
11
+ });
12
+ });
13
+ return templateSources;
14
+ };
15
+ export const loadAudio = async (url) => {
16
+ const response = await fetch(url);
17
+ const arrayBuffer = await response.arrayBuffer();
18
+ return arrayBuffer;
19
+ };
@@ -0,0 +1,3 @@
1
+ export { BehaviorSystem } from './system';
2
+ export { Behavior } from './types';
3
+ export type { BehaviorOptions, BehaviorConstructor } from './types';
@@ -0,0 +1,2 @@
1
+ export { BehaviorSystem } from './system';
2
+ export { Behavior } from './types';
@@ -0,0 +1,16 @@
1
+ import { SceneSystem } from '../../../engine/system';
2
+ import type { SceneSystemOptions, UpdateOptions } from '../../../engine/system';
3
+ export declare class BehaviorSystem extends SceneSystem {
4
+ private behaviorCollection;
5
+ private actorSpawner;
6
+ private globalOptions;
7
+ private behaviors;
8
+ private world;
9
+ private scene;
10
+ private activeBehaviors;
11
+ constructor(options: SceneSystemOptions);
12
+ onSceneDestroy(): void;
13
+ private handleActorRemove;
14
+ private setUpBehavior;
15
+ update(options: UpdateOptions): void;
16
+ }
@@ -0,0 +1,69 @@
1
+ import { SceneSystem } from '../../../engine/system';
2
+ import { ActorCollection } from '../../../engine/actor';
3
+ import { Behaviors } from '../../components';
4
+ import { RemoveActor } from '../../../engine/events';
5
+ export class BehaviorSystem extends SceneSystem {
6
+ behaviorCollection;
7
+ actorSpawner;
8
+ globalOptions;
9
+ behaviors;
10
+ world;
11
+ scene;
12
+ activeBehaviors;
13
+ constructor(options) {
14
+ super();
15
+ const { actorSpawner, world, scene, globalOptions, resources = {}, } = options;
16
+ this.world = world;
17
+ this.scene = scene;
18
+ this.behaviorCollection = new ActorCollection(scene, {
19
+ components: [Behaviors],
20
+ });
21
+ this.actorSpawner = actorSpawner;
22
+ this.globalOptions = globalOptions;
23
+ this.behaviors = resources.reduce((acc, behavior) => {
24
+ if (behavior.behaviorName === undefined) {
25
+ throw new Error(`Missing behaviorName field for ${behavior.name} behavior.`);
26
+ }
27
+ acc[behavior.behaviorName] = behavior;
28
+ return acc;
29
+ }, {});
30
+ this.activeBehaviors = {};
31
+ this.behaviorCollection.addEventListener(RemoveActor, this.handleActorRemove);
32
+ }
33
+ onSceneDestroy() {
34
+ this.behaviorCollection.removeEventListener(RemoveActor, this.handleActorRemove);
35
+ this.behaviorCollection.forEach((actor) => {
36
+ this.activeBehaviors[actor.id].forEach((behavior) => behavior.destroy?.());
37
+ delete this.activeBehaviors[actor.id];
38
+ });
39
+ }
40
+ handleActorRemove = (event) => {
41
+ const { actor } = event;
42
+ this.activeBehaviors[actor.id].forEach((behavior) => behavior.destroy?.());
43
+ delete this.activeBehaviors[actor.id];
44
+ };
45
+ setUpBehavior(actor) {
46
+ const { list } = actor.getComponent(Behaviors);
47
+ this.activeBehaviors[actor.id] = list.map((config) => {
48
+ const options = {
49
+ ...config.options,
50
+ actor,
51
+ actorSpawner: this.actorSpawner,
52
+ world: this.world,
53
+ scene: this.scene,
54
+ globalOptions: this.globalOptions,
55
+ };
56
+ const BehaviorClass = this.behaviors[config.name];
57
+ return new BehaviorClass(options);
58
+ });
59
+ }
60
+ update(options) {
61
+ this.behaviorCollection.forEach((actor) => {
62
+ if (!this.activeBehaviors[actor.id]) {
63
+ this.setUpBehavior(actor);
64
+ }
65
+ this.activeBehaviors[actor.id].forEach((behavior) => behavior.update?.(options));
66
+ });
67
+ }
68
+ }
69
+ BehaviorSystem.systemName = 'BehaviorSystem';
@@ -1,7 +1,9 @@
1
1
  import type { Actor, ActorSpawner } from '../../../engine/actor';
2
+ import type { World } from '../../../engine/world';
2
3
  import type { Scene } from '../../../engine/scene';
3
4
  import type { Constructor } from '../../../types/utils';
4
- export interface ScriptOptions {
5
+ export interface BehaviorOptions {
6
+ world: World;
5
7
  scene: Scene;
6
8
  actor: Actor;
7
9
  actorSpawner: ActorSpawner;
@@ -10,12 +12,12 @@ export interface ScriptOptions {
10
12
  interface UpdateOptions {
11
13
  deltaTime: number;
12
14
  }
13
- export declare abstract class Script {
14
- static scriptName: string;
15
+ export declare abstract class Behavior {
16
+ static behaviorName: string;
15
17
  destroy?(): void;
16
18
  update?(options: UpdateOptions): void;
17
19
  }
18
- export type ScriptConstructor = Constructor<Script> & {
19
- scriptName: string;
20
+ export type BehaviorConstructor = Constructor<Behavior> & {
21
+ behaviorName: string;
20
22
  };
21
23
  export {};
@@ -0,0 +1,3 @@
1
+ export class Behavior {
2
+ static behaviorName;
3
+ }
@@ -1,12 +1,12 @@
1
- import type { Actor, ActorCollection } from '../../../engine/actor';
1
+ import type { Actor } from '../../../engine/actor';
2
2
  interface CameraServiceOptions {
3
- cameraCollection: ActorCollection;
4
- onCameraUpdate: () => void;
3
+ onCameraUpdate: (actor: Actor) => void;
4
+ findCurrentCamera: () => Actor | undefined;
5
5
  }
6
6
  export declare class CameraService {
7
- private cameraCollection;
8
7
  private onCameraUpdate;
9
- constructor({ cameraCollection, onCameraUpdate }: CameraServiceOptions);
8
+ private findCurrentCamera;
9
+ constructor({ onCameraUpdate, findCurrentCamera }: CameraServiceOptions);
10
10
  setCurrentCamera(actor: Actor): void;
11
11
  getCurrentCamera(): Actor | undefined;
12
12
  }