@inglorious/engine 0.10.0 → 1.0.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 (38) hide show
  1. package/package.json +3 -3
  2. package/src/ai/movement/dynamic/arrive.js +2 -5
  3. package/src/ai/movement/dynamic/evade.js +2 -6
  4. package/src/ai/movement/dynamic/face.js +2 -5
  5. package/src/ai/movement/dynamic/flee.js +2 -2
  6. package/src/ai/movement/dynamic/look-where-youre-going.js +1 -5
  7. package/src/ai/movement/dynamic/match-velocity.js +2 -2
  8. package/src/ai/movement/dynamic/pursue.js +2 -6
  9. package/src/ai/movement/dynamic/seek.js +2 -2
  10. package/src/ai/movement/dynamic/wander.js +2 -2
  11. package/src/ai/movement/kinematic/arrive.js +2 -2
  12. package/src/ai/movement/kinematic/face.js +2 -5
  13. package/src/ai/movement/kinematic/flee.js +2 -2
  14. package/src/ai/movement/kinematic/seek.js +2 -2
  15. package/src/ai/movement/kinematic/seek.test.js +13 -12
  16. package/src/ai/movement/kinematic/wander-as-seek.js +2 -5
  17. package/src/ai/movement/kinematic/wander.js +2 -6
  18. package/src/behaviors/controls/dynamic/modern.js +1 -1
  19. package/src/behaviors/controls/dynamic/shooter.js +1 -1
  20. package/src/behaviors/controls/dynamic/tank.js +1 -1
  21. package/src/behaviors/controls/kinematic/modern.js +1 -1
  22. package/src/behaviors/controls/kinematic/shooter.js +1 -1
  23. package/src/behaviors/controls/kinematic/tank.js +1 -1
  24. package/src/behaviors/input/mouse.js +1 -1
  25. package/src/behaviors/physics/jumpable.js +1 -5
  26. package/src/collision/detection.js +8 -8
  27. package/src/core/engine.js +16 -33
  28. package/src/core/loops/{loops.js → index.js} +1 -1
  29. package/src/core/middlewares/entity-pool/entity-pool-middleware.js +13 -3
  30. package/src/core/middlewares/multiplayer-middleware.js +7 -7
  31. package/src/movement/dynamic/modern.js +1 -4
  32. package/src/movement/dynamic/tank.js +2 -7
  33. package/src/movement/kinematic/modern.js +1 -4
  34. package/src/movement/kinematic/modern.test.js +7 -6
  35. package/src/movement/kinematic/tank.js +2 -7
  36. package/src/physics/bounds.js +3 -3
  37. package/src/physics/position.test.js +10 -9
  38. package/src/core/middlewares/middlewares.js +0 -32
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inglorious/engine",
3
- "version": "0.10.0",
3
+ "version": "1.0.0",
4
4
  "description": "A JavaScript game engine written with global state, immutability, and pure functions in mind. Have fun(ctional programming) with it!",
5
5
  "author": "IceOnFire <antony.mistretta@gmail.com> (https://ingloriouscoderz.it)",
6
6
  "license": "MIT",
@@ -30,8 +30,8 @@
30
30
  "access": "public"
31
31
  },
32
32
  "dependencies": {
33
- "@inglorious/utils": "2.2.0",
34
- "@inglorious/store": "3.0.0"
33
+ "@inglorious/store": "4.0.0",
34
+ "@inglorious/utils": "3.1.0"
35
35
  },
36
36
  "devDependencies": {
37
37
  "prettier": "^3.5.3",
@@ -1,9 +1,6 @@
1
1
  import { matchVelocity } from "@inglorious/engine/ai/movement/dynamic/match-velocity.js"
2
- import {
3
- magnitude,
4
- setMagnitude,
5
- } from "@inglorious/utils/math/linear-algebra/vector.js"
6
- import { subtract } from "@inglorious/utils/math/linear-algebra/vectors.js"
2
+ import { magnitude, setMagnitude } from "@inglorious/utils/math/vector.js"
3
+ import { subtract } from "@inglorious/utils/math/vectors.js"
7
4
 
8
5
  export const DEFAULT_TARGET_RADIUS = 1
9
6
  export const DEFAULT_SLOW_RADIUS = 100
@@ -1,10 +1,6 @@
1
1
  import { flee } from "@inglorious/engine/ai/movement/dynamic/flee.js"
2
- import {
3
- magnitude,
4
- multiply,
5
- zero,
6
- } from "@inglorious/utils/math/linear-algebra/vector.js"
7
- import { subtract, sum } from "@inglorious/utils/math/linear-algebra/vectors.js"
2
+ import { magnitude, multiply, zero } from "@inglorious/utils/math/vector.js"
3
+ import { subtract, sum } from "@inglorious/utils/math/vectors.js"
8
4
 
9
5
  export const DEFAULT_MAX_PREDICTION = 10
10
6
 
@@ -1,9 +1,6 @@
1
1
  import { align } from "@inglorious/engine/ai/movement/dynamic/align.js"
2
- import {
3
- angle,
4
- magnitude,
5
- } from "@inglorious/utils/math/linear-algebra/vector.js"
6
- import { subtract } from "@inglorious/utils/math/linear-algebra/vectors.js"
2
+ import { angle, magnitude } from "@inglorious/utils/math/vector.js"
3
+ import { subtract } from "@inglorious/utils/math/vectors.js"
7
4
 
8
5
  export function face(entity, target, dt, options) {
9
6
  const direction = subtract(target.position, entity.position)
@@ -5,8 +5,8 @@ import {
5
5
  multiply,
6
6
  setMagnitude,
7
7
  zero,
8
- } from "@inglorious/utils/math/linear-algebra/vector.js"
9
- import { subtract, sum } from "@inglorious/utils/math/linear-algebra/vectors.js"
8
+ } from "@inglorious/utils/math/vector.js"
9
+ import { subtract, sum } from "@inglorious/utils/math/vectors.js"
10
10
 
11
11
  const DEFAULT_MAX_ACCELERATION = 0
12
12
  const DEFAULT_MAX_SPEED = 0
@@ -1,9 +1,5 @@
1
1
  import { align } from "@inglorious/engine/ai/movement/dynamic/align.js"
2
- import {
3
- angle,
4
- magnitude,
5
- zero,
6
- } from "@inglorious/utils/math/linear-algebra/vector.js"
2
+ import { angle, magnitude, zero } from "@inglorious/utils/math/vector.js"
7
3
 
8
4
  export function lookWhereYoureGoing(entity, dt, options) {
9
5
  const velocity = entity.velocity ?? zero()
@@ -5,8 +5,8 @@ import {
5
5
  magnitude,
6
6
  multiply,
7
7
  zero,
8
- } from "@inglorious/utils/math/linear-algebra/vector.js"
9
- import { subtract, sum } from "@inglorious/utils/math/linear-algebra/vectors.js"
8
+ } from "@inglorious/utils/math/vector.js"
9
+ import { subtract, sum } from "@inglorious/utils/math/vectors.js"
10
10
 
11
11
  export const DEFAULT_TIME_TO_TARGET = 0.1
12
12
 
@@ -1,10 +1,6 @@
1
1
  import { seek } from "@inglorious/engine/ai/movement/dynamic/seek.js"
2
- import {
3
- magnitude,
4
- multiply,
5
- zero,
6
- } from "@inglorious/utils/math/linear-algebra/vector.js"
7
- import { subtract, sum } from "@inglorious/utils/math/linear-algebra/vectors.js"
2
+ import { magnitude, multiply, zero } from "@inglorious/utils/math/vector.js"
3
+ import { subtract, sum } from "@inglorious/utils/math/vectors.js"
8
4
 
9
5
  export const DEFAULT_MAX_PREDICTION = 10
10
6
 
@@ -5,8 +5,8 @@ import {
5
5
  multiply,
6
6
  setMagnitude,
7
7
  zero,
8
- } from "@inglorious/utils/math/linear-algebra/vector.js"
9
- import { subtract, sum } from "@inglorious/utils/math/linear-algebra/vectors.js"
8
+ } from "@inglorious/utils/math/vector.js"
9
+ import { subtract, sum } from "@inglorious/utils/math/vectors.js"
10
10
 
11
11
  const DEFAULT_MAX_ACCELERATION = 0
12
12
  const DEFAULT_MAX_SPEED = 0
@@ -1,7 +1,7 @@
1
1
  import { seek } from "@inglorious/engine/ai/movement/dynamic/seek.js"
2
- import { createVector } from "@inglorious/utils/math/linear-algebra/vector.js"
3
- import { sum } from "@inglorious/utils/math/linear-algebra/vectors.js"
4
2
  import { randomBinomial } from "@inglorious/utils/math/rng.js"
3
+ import { createVector } from "@inglorious/utils/math/vector.js"
4
+ import { sum } from "@inglorious/utils/math/vectors.js"
5
5
 
6
6
  export const DEFAULT_WANDER_OFFSET = 100
7
7
  export const DEFAULT_WANDER_RADIUS = 100
@@ -4,8 +4,8 @@ import {
4
4
  divide,
5
5
  magnitude,
6
6
  multiply,
7
- } from "@inglorious/utils/math/linear-algebra/vector.js"
8
- import { subtract, sum } from "@inglorious/utils/math/linear-algebra/vectors.js"
7
+ } from "@inglorious/utils/math/vector.js"
8
+ import { subtract, sum } from "@inglorious/utils/math/vectors.js"
9
9
 
10
10
  export const DEFAULT_TARGET_RADIUS = 1
11
11
  export const DEFAULT_TIME_TO_TARGET = 0.1
@@ -1,9 +1,6 @@
1
1
  import { align } from "@inglorious/engine/ai/movement/kinematic/align.js"
2
- import {
3
- angle,
4
- magnitude,
5
- } from "@inglorious/utils/math/linear-algebra/vector.js"
6
- import { subtract } from "@inglorious/utils/math/linear-algebra/vectors.js"
2
+ import { angle, magnitude } from "@inglorious/utils/math/vector.js"
3
+ import { subtract } from "@inglorious/utils/math/vectors.js"
7
4
 
8
5
  export function face(entity, target, dt, options) {
9
6
  const direction = subtract(target.position, entity.position)
@@ -3,8 +3,8 @@ import {
3
3
  magnitude,
4
4
  multiply,
5
5
  setMagnitude,
6
- } from "@inglorious/utils/math/linear-algebra/vector.js"
7
- import { subtract, sum } from "@inglorious/utils/math/linear-algebra/vectors.js"
6
+ } from "@inglorious/utils/math/vector.js"
7
+ import { subtract, sum } from "@inglorious/utils/math/vectors.js"
8
8
 
9
9
  const DEFAULT_MAX_SPEED = 0
10
10
 
@@ -3,8 +3,8 @@ import {
3
3
  magnitude,
4
4
  multiply,
5
5
  setMagnitude,
6
- } from "@inglorious/utils/math/linear-algebra/vector.js"
7
- import { subtract, sum } from "@inglorious/utils/math/linear-algebra/vectors.js"
6
+ } from "@inglorious/utils/math/vector.js"
7
+ import { subtract, sum } from "@inglorious/utils/math/vectors.js"
8
8
 
9
9
  const DEFAULT_MAX_SPEED = 0
10
10
 
@@ -1,14 +1,15 @@
1
+ import { v } from "@inglorious/utils/v.js"
1
2
  import { expect, test } from "vitest"
2
3
 
3
4
  import { seek } from "./seek.js"
4
5
 
5
6
  test("it should move toward the target", () => {
6
- const entity = { maxSpeed: 1, position: [0, 0, 0] }
7
- const target = { position: [2, 0, 0] }
7
+ const entity = { maxSpeed: 1, position: v(0, 0, 0) }
8
+ const target = { position: v(2, 0, 0) }
8
9
  const dt = 1
9
10
  const expectedResult = {
10
- position: [1, 0, 0],
11
- velocity: [1, 0, 0],
11
+ position: v(1, 0, 0),
12
+ velocity: v(1, 0, 0),
12
13
  orientation: 0,
13
14
  }
14
15
 
@@ -16,12 +17,12 @@ test("it should move toward the target", () => {
16
17
  })
17
18
 
18
19
  test("it should eventually reach the target", () => {
19
- const entity = { maxSpeed: 1, position: [0, 0, 0] }
20
- const target = { position: [2, 0, 0] }
20
+ const entity = { maxSpeed: 1, position: v(0, 0, 0) }
21
+ const target = { position: v(2, 0, 0) }
21
22
  const dt = 2
22
23
  const expectedResult = {
23
- position: [2, 0, 0],
24
- velocity: [1, 0, 0],
24
+ position: v(2, 0, 0),
25
+ velocity: v(1, 0, 0),
25
26
  orientation: 0,
26
27
  }
27
28
 
@@ -29,12 +30,12 @@ test("it should eventually reach the target", () => {
29
30
  })
30
31
 
31
32
  test("it should overshoot when speed is too high", () => {
32
- const entity = { maxSpeed: 10, position: [0, 0, 0] }
33
- const target = { position: [2, 0, 0] }
33
+ const entity = { maxSpeed: 10, position: v(0, 0, 0) }
34
+ const target = { position: v(2, 0, 0) }
34
35
  const dt = 1
35
36
  const expectedResult = {
36
- position: [10, 0, 0],
37
- velocity: [10, 0, 0],
37
+ position: v(10, 0, 0),
38
+ velocity: v(10, 0, 0),
38
39
  orientation: 0,
39
40
  }
40
41
 
@@ -1,10 +1,7 @@
1
1
  import { seek } from "@inglorious/engine/ai/movement/kinematic/seek.js"
2
- import {
3
- fromAngle,
4
- multiply,
5
- } from "@inglorious/utils/math/linear-algebra/vector.js"
6
- import { sum } from "@inglorious/utils/math/linear-algebra/vectors.js"
7
2
  import { randomBinomial } from "@inglorious/utils/math/rng.js"
3
+ import { fromAngle, multiply } from "@inglorious/utils/math/vector.js"
4
+ import { sum } from "@inglorious/utils/math/vectors.js"
8
5
 
9
6
  export const DEFAULT_WANDER_RADIUS = 10
10
7
 
@@ -1,10 +1,6 @@
1
- import {
2
- angle,
3
- createVector,
4
- multiply,
5
- } from "@inglorious/utils/math/linear-algebra/vector.js"
6
- import { sum } from "@inglorious/utils/math/linear-algebra/vectors.js"
7
1
  import { randomBinomial } from "@inglorious/utils/math/rng.js"
2
+ import { angle, createVector, multiply } from "@inglorious/utils/math/vector.js"
3
+ import { sum } from "@inglorious/utils/math/vectors.js"
8
4
 
9
5
  const DEFAULT_MAX_SPEED = 0
10
6
  const DEFAULT_MAX_ANGULAR_SPEED = 0
@@ -1,6 +1,6 @@
1
1
  import { modernMove } from "@inglorious/engine/movement/dynamic/modern.js"
2
2
  import { extend, merge } from "@inglorious/utils/data-structures/objects.js"
3
- import { zero } from "@inglorious/utils/math/linear-algebra/vector.js"
3
+ import { zero } from "@inglorious/utils/math/vector.js"
4
4
 
5
5
  import { createMovementEventHandlers } from "../event-handlers.js"
6
6
 
@@ -1,8 +1,8 @@
1
1
  import { face } from "@inglorious/engine/ai/movement/dynamic/face.js"
2
2
  import { tankMove } from "@inglorious/engine/movement/dynamic/tank.js"
3
3
  import { extend, merge } from "@inglorious/utils/data-structures/objects.js"
4
- import { zero } from "@inglorious/utils/math/linear-algebra/vector.js"
5
4
  import { pi } from "@inglorious/utils/math/trigonometry.js"
5
+ import { zero } from "@inglorious/utils/math/vector.js"
6
6
 
7
7
  import { createMovementEventHandlers } from "../event-handlers.js"
8
8
 
@@ -1,6 +1,6 @@
1
1
  import { tankMove } from "@inglorious/engine/movement/dynamic/tank.js"
2
2
  import { extend, merge } from "@inglorious/utils/data-structures/objects.js"
3
- import { zero } from "@inglorious/utils/math/linear-algebra/vector.js"
3
+ import { zero } from "@inglorious/utils/math/vector.js"
4
4
 
5
5
  import { createMovementEventHandlers } from "../event-handlers.js"
6
6
 
@@ -1,6 +1,6 @@
1
1
  import { modernMove } from "@inglorious/engine/movement/kinematic/modern.js"
2
2
  import { extend, merge } from "@inglorious/utils/data-structures/objects.js"
3
- import { zero } from "@inglorious/utils/math/linear-algebra/vector.js"
3
+ import { zero } from "@inglorious/utils/math/vector.js"
4
4
 
5
5
  import { createMovementEventHandlers } from "../event-handlers.js"
6
6
 
@@ -1,8 +1,8 @@
1
1
  import { face } from "@inglorious/engine/ai/movement/kinematic/face.js"
2
2
  import { tankMove } from "@inglorious/engine/movement/kinematic/tank.js"
3
3
  import { extend, merge } from "@inglorious/utils/data-structures/objects.js"
4
- import { zero } from "@inglorious/utils/math/linear-algebra/vector.js"
5
4
  import { pi } from "@inglorious/utils/math/trigonometry.js"
5
+ import { zero } from "@inglorious/utils/math/vector.js"
6
6
 
7
7
  import { createMovementEventHandlers } from "../event-handlers.js"
8
8
 
@@ -1,6 +1,6 @@
1
1
  import { tankMove } from "@inglorious/engine/movement/kinematic/tank.js"
2
2
  import { extend, merge } from "@inglorious/utils/data-structures/objects.js"
3
- import { zero } from "@inglorious/utils/math/linear-algebra/vector.js"
3
+ import { zero } from "@inglorious/utils/math/vector.js"
4
4
 
5
5
  import { createMovementEventHandlers } from "../event-handlers.js"
6
6
 
@@ -1,6 +1,6 @@
1
1
  import { findCollision } from "@inglorious/engine/collision/detection.js"
2
2
  import { clampToBounds } from "@inglorious/engine/physics/bounds.js"
3
- import { zero } from "@inglorious/utils/math/linear-algebra/vector.js"
3
+ import { zero } from "@inglorious/utils/math/vector.js"
4
4
 
5
5
  const DEFAULT_PARAMS = {
6
6
  name: "mouse",
@@ -1,10 +1,6 @@
1
1
  import { findCollision } from "@inglorious/engine/collision/detection.js"
2
2
  import { defaults, extend } from "@inglorious/utils/data-structures/objects.js"
3
- import {
4
- angle,
5
- magnitude,
6
- zero,
7
- } from "@inglorious/utils/math/linear-algebra/vector.js"
3
+ import { angle, magnitude, zero } from "@inglorious/utils/math/vector.js"
8
4
  import { applyGravity } from "@inglorious/utils/physics/gravity.js"
9
5
  import { jump } from "@inglorious/utils/physics/jump.js"
10
6
 
@@ -1,12 +1,12 @@
1
1
  import { filter } from "@inglorious/utils/data-structures/object.js"
2
- import * as circle from "@inglorious/utils/math/geometry/circle.js"
3
- import * as hitmask from "@inglorious/utils/math/geometry/hitmask.js"
4
- import * as line from "@inglorious/utils/math/geometry/line.js"
5
- import * as point from "@inglorious/utils/math/geometry/point.js"
6
- import * as rectangle from "@inglorious/utils/math/geometry/rectangle.js"
7
- import * as segment from "@inglorious/utils/math/geometry/segment.js"
8
- import { zero } from "@inglorious/utils/math/linear-algebra/vector.js"
9
- import { add } from "@inglorious/utils/math/linear-algebra/vectors.js"
2
+ import * as circle from "@inglorious/utils/math/circle.js"
3
+ import * as hitmask from "@inglorious/utils/math/hitmask.js"
4
+ import * as line from "@inglorious/utils/math/line.js"
5
+ import * as point from "@inglorious/utils/math/point.js"
6
+ import * as rectangle from "@inglorious/utils/math/rectangle.js"
7
+ import * as segment from "@inglorious/utils/math/segment.js"
8
+ import { zero } from "@inglorious/utils/math/vector.js"
9
+ import { add } from "@inglorious/utils/math/vectors.js"
10
10
 
11
11
  const Z = 2 // Z-axis index.
12
12
 
@@ -1,18 +1,16 @@
1
1
  import { audio } from "@inglorious/engine/behaviors/audio.js"
2
2
  import { game } from "@inglorious/engine/behaviors/game.js"
3
- import { createApi } from "@inglorious/store/api.js"
4
3
  import { createStore } from "@inglorious/store/store.js"
5
4
  import { augmentType } from "@inglorious/store/types.js"
6
5
  import { isArray } from "@inglorious/utils/data-structures/array.js"
7
6
  import { extendWith } from "@inglorious/utils/data-structures/objects.js"
8
- import { isVector } from "@inglorious/utils/math/linear-algebra/vector.js"
7
+ import { isVector } from "@inglorious/utils/math/vector.js"
8
+ import { v } from "@inglorious/utils/v.js"
9
9
 
10
10
  import { coreEvents } from "./core-events.js"
11
11
  import { disconnectDevTools, initDevTools, sendAction } from "./dev-tools.js"
12
- import { Loops } from "./loops/loops.js"
12
+ import { Loop } from "./loops/index.js"
13
13
  import { entityPoolMiddleware } from "./middlewares/entity-pool/entity-pool-middleware.js"
14
- import { EntityPools } from "./middlewares/entity-pool/entity-pools.js"
15
- import { applyMiddlewares } from "./middlewares/middlewares.js"
16
14
  import { multiplayerMiddleware } from "./middlewares/multiplayer-middleware.js"
17
15
 
18
16
  // Default game configuration
@@ -29,7 +27,7 @@ const DEFAULT_GAME_CONFIG = {
29
27
 
30
28
  entities: {
31
29
  // eslint-disable-next-line no-magic-numbers
32
- game: { type: "game", size: [800, 600] },
30
+ game: { type: "game", size: v(800, 600) },
33
31
  audio: { type: "audio", sounds: {} },
34
32
  },
35
33
  }
@@ -41,44 +39,29 @@ const ONE_SECOND = 1000 // Number of milliseconds in one second.
41
39
  */
42
40
  export class Engine {
43
41
  /**
44
- * @param {Object} [gameConfig] - Game-specific configuration.
45
- * @param {Object} [renderer] - UI entity responsible for rendering. It must have a `render` method.
42
+ * @param {...Object} gameConfigs - Game-specific configurations.
46
43
  */
47
44
  constructor(...gameConfigs) {
48
45
  this._config = extendWith(merger, DEFAULT_GAME_CONFIG, ...gameConfigs)
49
46
 
50
- // Determine devMode from the entities config.
47
+ // Determine devMode from the entities config
51
48
  const devMode = this._config.entities.game?.devMode
52
49
  this._devMode = devMode
53
50
 
54
- // Add user-defined systems
55
- const systems = [...(this._config.systems ?? [])]
51
+ const middlewares = []
56
52
 
57
- this._store = createStore({ ...this._config, systems })
53
+ // Always add entity pool middleware
54
+ middlewares.push(entityPoolMiddleware())
58
55
 
59
- // Create API layer, with optional methods for debugging
60
- this._api = createApi(this._store)
61
-
62
- this._entityPools = new EntityPools()
63
- this._api = applyMiddlewares(entityPoolMiddleware(this._entityPools))(
64
- this._api,
65
- )
66
- this._api.getAllActivePoolEntities = () =>
67
- this._entityPools.getAllActiveEntities()
68
-
69
- if (this._devMode) {
70
- this._api.getEntityPoolsStats = () => this._entityPools.getStats()
71
- }
72
-
73
- // Apply multiplayer if specified.
56
+ // Add multiplayer middleware if needed
74
57
  const multiplayer = this._config.entities.game?.multiplayer
75
58
  if (multiplayer) {
76
- this._api = applyMiddlewares(multiplayerMiddleware(multiplayer))(
77
- this._api,
78
- )
59
+ middlewares.push(multiplayerMiddleware(multiplayer))
79
60
  }
80
61
 
81
- this._loop = new Loops[this._config.loop.type]()
62
+ this._store = createStore({ ...this._config, middlewares })
63
+ this._api = this._store.getApi()
64
+ this._loop = new Loop[this._config.loop.type]()
82
65
 
83
66
  if (this._devMode) {
84
67
  initDevTools(this._store)
@@ -108,7 +91,7 @@ export class Engine {
108
91
  */
109
92
  stop() {
110
93
  this._api.notify("stop")
111
- this._store.update(this._api)
94
+ this._store.update()
112
95
  this._loop.stop()
113
96
  }
114
97
 
@@ -118,7 +101,7 @@ export class Engine {
118
101
  */
119
102
  update(dt) {
120
103
  this._api.notify("update", dt)
121
- const processedEvents = this._store.update(this._api)
104
+ const processedEvents = this._store.update()
122
105
  const state = this._store.getState()
123
106
 
124
107
  // Check for devMode changes and connect/disconnect dev tools accordingly.
@@ -6,7 +6,7 @@ import { LagLoop } from "./lag.js"
6
6
 
7
7
  // @see https://gameprogrammingpatterns.com/game-loop.html
8
8
 
9
- export const Loops = {
9
+ export const Loop = {
10
10
  flash: FlashLoop,
11
11
  fixed: FixedLoop,
12
12
  elapsed: ElapsedLoop,
@@ -1,10 +1,20 @@
1
- import { EventMap } from "@inglorious/store/event-map"
1
+ import { EventMap } from "@inglorious/store/event-map.js"
2
2
 
3
- export function entityPoolMiddleware(pools) {
4
- return (api) => {
3
+ import { EntityPools } from "./entity-pools"
4
+
5
+ export function entityPoolMiddleware() {
6
+ return (store, api) => {
7
+ const pools = new EntityPools()
5
8
  const types = api.getTypes()
6
9
  const eventMap = new EventMap()
7
10
 
11
+ api.getAllActivePoolEntities = () => pools.getAllActiveEntities()
12
+
13
+ const game = api.getEntity("game")
14
+ if (game.devMode) {
15
+ api.getEntityPoolsStats = () => pools.getStats()
16
+ }
17
+
8
18
  return (next) => (event) => {
9
19
  switch (event.type) {
10
20
  case "spawn": {
@@ -19,14 +19,14 @@ export function multiplayerMiddleware(config = {}) {
19
19
  const localQueue = []
20
20
 
21
21
  // The middleware function that will be applied to the store.
22
- return (api) => (next) => (event) => {
22
+ return (store) => (next) => (event) => {
23
23
  if (coreEvents.includes(event.type)) {
24
24
  return next(event)
25
25
  }
26
26
 
27
27
  // Establish the connection on the first event.
28
28
  if (!ws) {
29
- establishConnection(api)
29
+ establishConnection(store)
30
30
  }
31
31
 
32
32
  // Only send the event to the server if it didn't come from the server.
@@ -48,7 +48,7 @@ export function multiplayerMiddleware(config = {}) {
48
48
  /**
49
49
  * Attempts to establish a WebSocket connection to the server.
50
50
  */
51
- function establishConnection(api) {
51
+ function establishConnection(store) {
52
52
  // If a connection already exists, close it first.
53
53
  if (ws) {
54
54
  ws.close()
@@ -71,17 +71,17 @@ export function multiplayerMiddleware(config = {}) {
71
71
 
72
72
  if (serverEvent.type === "initialState") {
73
73
  // Merge the server's initial state with the client's local state.
74
- const nextState = extend(api.getState(), serverEvent.payload)
75
- api.setState(nextState)
74
+ const nextState = extend(store.getState(), serverEvent.payload)
75
+ store.setState(nextState)
76
76
  } else {
77
77
  // Dispatch the event to the local store to update the client's state.
78
- api.dispatch({ ...serverEvent, fromServer: true })
78
+ store.dispatch({ ...serverEvent, fromServer: true })
79
79
  }
80
80
  }
81
81
 
82
82
  ws.onclose = () => {
83
83
  // Attempt to reconnect after a short delay.
84
- setTimeout(() => establishConnection(api), reconnectionDelay)
84
+ setTimeout(() => establishConnection(store), reconnectionDelay)
85
85
  }
86
86
 
87
87
  ws.onerror = () => {
@@ -1,7 +1,4 @@
1
- import {
2
- angle,
3
- magnitude,
4
- } from "@inglorious/utils/math/linear-algebra/vector.js"
1
+ import { angle, magnitude } from "@inglorious/utils/math/vector.js"
5
2
  import { applyAcceleration } from "@inglorious/utils/physics/acceleration.js"
6
3
 
7
4
  const DEFAULT_ORIENTATION = 0
@@ -1,11 +1,6 @@
1
- import {
2
- clamp,
3
- multiply,
4
- rotate,
5
- zero,
6
- } from "@inglorious/utils/math/linear-algebra/vector.js"
7
- import { sum } from "@inglorious/utils/math/linear-algebra/vectors.js"
8
1
  import { toRange } from "@inglorious/utils/math/trigonometry.js"
2
+ import { clamp, multiply, rotate, zero } from "@inglorious/utils/math/vector.js"
3
+ import { sum } from "@inglorious/utils/math/vectors.js"
9
4
  import { applyFriction } from "@inglorious/utils/physics/friction.js"
10
5
 
11
6
  const DEFAULT_MAX_ACCELERATION = 0
@@ -1,7 +1,4 @@
1
- import {
2
- angle,
3
- magnitude,
4
- } from "@inglorious/utils/math/linear-algebra/vector.js"
1
+ import { angle, magnitude } from "@inglorious/utils/math/vector.js"
5
2
  import { applyVelocity } from "@inglorious/utils/physics/velocity.js"
6
3
 
7
4
  const DEFAULT_ORIENTATION = 0
@@ -1,13 +1,14 @@
1
+ import { v } from "@inglorious/utils/v.js"
1
2
  import { expect, test } from "vitest"
2
3
 
3
4
  import { modernMove } from "./modern.js"
4
5
 
5
6
  test("it should move following its velocity", () => {
6
- const entity = { maxSpeed: 1, velocity: [1, 0, 0], position: [0, 0, 0] }
7
+ const entity = { maxSpeed: 1, velocity: v(1, 0, 0), position: v(0, 0, 0) }
7
8
  const dt = 1
8
9
  const expectedResult = {
9
- velocity: [1, 0, 0],
10
- position: [1, 0, 0],
10
+ velocity: v(1, 0, 0),
11
+ position: v(1, 0, 0),
11
12
  orientation: 0,
12
13
  }
13
14
 
@@ -15,11 +16,11 @@ test("it should move following its velocity", () => {
15
16
  })
16
17
 
17
18
  test("it should limit the velocity to the max speed", () => {
18
- const entity = { maxSpeed: 1, velocity: [10, 0, 0], position: [0, 0, 0] }
19
+ const entity = { maxSpeed: 1, velocity: v(10, 0, 0), position: v(0, 0, 0) }
19
20
  const dt = 1
20
21
  const expectedResult = {
21
- velocity: [1, 0, 0],
22
- position: [1, 0, 0],
22
+ velocity: v(1, 0, 0),
23
+ position: v(1, 0, 0),
23
24
  orientation: 0,
24
25
  }
25
26
 
@@ -1,11 +1,6 @@
1
- import {
2
- clamp,
3
- multiply,
4
- rotate,
5
- zero,
6
- } from "@inglorious/utils/math/linear-algebra/vector.js"
7
- import { sum } from "@inglorious/utils/math/linear-algebra/vectors.js"
8
1
  import { toRange } from "@inglorious/utils/math/trigonometry.js"
2
+ import { clamp, multiply, rotate, zero } from "@inglorious/utils/math/vector.js"
3
+ import { sum } from "@inglorious/utils/math/vectors.js"
9
4
 
10
5
  const DEFAULT_MAX_SPEED = 0
11
6
 
@@ -1,3 +1,4 @@
1
+ import { abs } from "@inglorious/utils/math/numbers.js"
1
2
  import {
2
3
  angle,
3
4
  clamp,
@@ -5,9 +6,8 @@ import {
5
6
  fromAngle,
6
7
  multiply,
7
8
  zero,
8
- } from "@inglorious/utils/math/linear-algebra/vector.js"
9
- import { sum } from "@inglorious/utils/math/linear-algebra/vectors.js"
10
- import { abs } from "@inglorious/utils/math/numbers.js"
9
+ } from "@inglorious/utils/math/vector.js"
10
+ import { sum } from "@inglorious/utils/math/vectors.js"
11
11
 
12
12
  const ORIGIN = 0
13
13
  const DOUBLE = 2
@@ -1,3 +1,4 @@
1
+ import { v } from "@inglorious/utils/v.js"
1
2
  import { expect, test } from "vitest"
2
3
 
3
4
  import { calculateLandingPosition } from "./position.js"
@@ -9,9 +10,9 @@ test("it should calculate the landing position for a point entity on a platform"
9
10
  },
10
11
  }
11
12
  const target = {
12
- position: [0, 0, 0],
13
+ position: v(0, 0, 0),
13
14
  collisions: {
14
- platform: { size: [20, 10, 0] },
15
+ platform: { size: v(20, 10, 0) },
15
16
  },
16
17
  }
17
18
  const collisionGroup = "platform"
@@ -28,9 +29,9 @@ test("it should calculate the landing position for a circular entity on a platfo
28
29
  },
29
30
  }
30
31
  const target = {
31
- position: [0, 0, 0],
32
+ position: v(0, 0, 0),
32
33
  collisions: {
33
- platform: { size: [20, 10, 0] },
34
+ platform: { size: v(20, 10, 0) },
34
35
  },
35
36
  }
36
37
  const collisionGroup = "platform"
@@ -42,15 +43,15 @@ test("it should calculate the landing position for a circular entity on a platfo
42
43
 
43
44
  test("it should calculate the landing position for a rectangular entity on a platform", () => {
44
45
  const entity = {
45
- size: [10, 10, 0],
46
+ size: v(10, 10, 0),
46
47
  collisions: {
47
48
  platform: { shape: "rectangle" },
48
49
  },
49
50
  }
50
51
  const target = {
51
- position: [0, 0, 0],
52
+ position: v(0, 0, 0),
52
53
  collisions: {
53
- platform: { size: [20, 10, 0] },
54
+ platform: { size: v(20, 10, 0) },
54
55
  },
55
56
  }
56
57
  const collisionGroup = "platform"
@@ -67,9 +68,9 @@ test("it should fallback to a rectangular calculation for an unknown entity shap
67
68
  },
68
69
  }
69
70
  const target = {
70
- position: [0, 0, 0],
71
+ position: v(0, 0, 0),
71
72
  collisions: {
72
- platform: { size: [20, 10, 0] },
73
+ platform: { size: v(20, 10, 0) },
73
74
  },
74
75
  }
75
76
  const collisionGroup = "platform"
@@ -1,32 +0,0 @@
1
- import { compose } from "@inglorious/utils/functions/functions.js"
2
-
3
- /**
4
- * Applies a list of middleware functions to a store's dispatch method.
5
- *
6
- * @param {...Function} middlewares The middleware functions to apply.
7
- * @returns {Function} A store enhancer function.
8
- */
9
- export function applyMiddlewares(...middlewares) {
10
- return (store) => {
11
- let dispatch = () => {
12
- throw new Error(
13
- "Dispatching while constructing your middleware is not allowed.",
14
- )
15
- }
16
-
17
- // The middleware API that can be passed to each middleware function.
18
- const api = {
19
- ...store,
20
- dispatch: (...args) => dispatch(...args),
21
- notify: (type, payload) => dispatch({ type, payload }),
22
- }
23
-
24
- // Create a chain of middleware functions.
25
- const chain = middlewares.map((middleware) => middleware(api))
26
-
27
- // Compose the middleware chain to create the final dispatch function.
28
- dispatch = compose(...chain)(store.dispatch)
29
-
30
- return api
31
- }
32
- }