@inglorious/engine 7.0.0 → 8.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.
@@ -21,126 +21,123 @@ const NO_PENETRAION = 0
21
21
  export function jumpable(params) {
22
22
  params = extend(DEFAULT_PARAMS, params)
23
23
 
24
- return (type) =>
25
- extend(type, {
26
- create(entity, entityId, api) {
27
- type.create?.(entity, entityId, api)
24
+ return (type) => ({
25
+ create(entity, entityId, api) {
26
+ type.create?.(entity, entityId, api)
28
27
 
29
- if (entityId !== entity.id) return
28
+ if (entityId !== entity.id) return
30
29
 
31
- defaults(entity, params)
32
- entity.jumpsLeft ??= entity.maxJumps
30
+ defaults(entity, params)
31
+ entity.jumpsLeft ??= entity.maxJumps
33
32
 
34
- entity.velocity ??= zero()
35
- entity.vy ??= 0
36
- },
33
+ entity.velocity ??= zero()
34
+ entity.vy ??= 0
35
+ },
37
36
 
38
- jump(entity, entityId, api) {
39
- type.jump?.(entity, entityId, api)
37
+ jump(entity, entityId, api) {
38
+ type.jump?.(entity, entityId, api)
40
39
 
41
- if (entityId === entity.id && entity.jumpsLeft) {
42
- entity.vy = jump(entity)
43
- entity.groundObject = undefined
44
- entity.jumpsLeft--
45
- }
46
- },
47
-
48
- update(entity, dt, api) {
49
- type.update?.(entity, dt, api)
50
-
51
- const entities = api.getEntities()
52
-
53
- entity.collisions ??= {}
54
- entity.collisions.platform ??= {}
55
- entity.collisions.platform.shape ??= "rectangle"
56
-
57
- let width, height
58
- if (entity.collisions.platform.shape === "circle") {
59
- width = entity.collisions.platform.radius * DOUBLE
60
- height = entity.collisions.platform.radius * DOUBLE
61
- } else {
62
- ;[width, height] = entity.size
40
+ if (entityId === entity.id && entity.jumpsLeft) {
41
+ entity.vy = jump(entity)
42
+ entity.groundObject = undefined
43
+ entity.jumpsLeft--
44
+ }
45
+ },
46
+
47
+ update(entity, dt, api) {
48
+ type.update?.(entity, dt, api)
49
+
50
+ const entities = api.getEntities()
51
+
52
+ entity.collisions ??= {}
53
+ entity.collisions.platform ??= {}
54
+ entity.collisions.platform.shape ??= "rectangle"
55
+
56
+ let width, height
57
+ if (entity.collisions.platform.shape === "circle") {
58
+ width = entity.collisions.platform.radius * DOUBLE
59
+ height = entity.collisions.platform.radius * DOUBLE
60
+ } else {
61
+ ;[width, height] = entity.size
62
+ }
63
+ const [prevX, prevY] = [...entity.position]
64
+
65
+ // 1. HORIZONTAL MOVEMENT & RESOLUTION
66
+ entity.position[X] += entity.velocity[X] * dt
67
+ const entityLeft = entity.position[X] - width / HALF
68
+ const entityRight = entity.position[X] + width / HALF
69
+
70
+ const collisionX = findCollision(entity, entities, "platform")
71
+ if (collisionX) {
72
+ const vx = entity.velocity[X]
73
+
74
+ // Check if moving right and crossing the platform's left edge
75
+ const prevRight = prevX + width / HALF
76
+ const platformLeft = collisionX.position[X] - collisionX.size[X] / HALF
77
+ if (vx > NO_VELOCITY && prevRight <= platformLeft) {
78
+ const penetration = entityRight - platformLeft
79
+ if (penetration > NO_PENETRAION) entity.position[X] -= penetration
80
+ entity.velocity[X] = 0
63
81
  }
64
- const [prevX, prevY] = [...entity.position]
65
-
66
- // 1. HORIZONTAL MOVEMENT & RESOLUTION
67
- entity.position[X] += entity.velocity[X] * dt
68
- const entityLeft = entity.position[X] - width / HALF
69
- const entityRight = entity.position[X] + width / HALF
70
-
71
- const collisionX = findCollision(entity, entities, "platform")
72
- if (collisionX) {
73
- const vx = entity.velocity[X]
74
-
75
- // Check if moving right and crossing the platform's left edge
76
- const prevRight = prevX + width / HALF
77
- const platformLeft =
78
- collisionX.position[X] - collisionX.size[X] / HALF
79
- if (vx > NO_VELOCITY && prevRight <= platformLeft) {
80
- const penetration = entityRight - platformLeft
81
- if (penetration > NO_PENETRAION) entity.position[X] -= penetration
82
- entity.velocity[X] = 0
83
- }
84
82
 
85
- // Check if moving left and crossing the platform's right edge
86
- const prevLeft = prevX - width / HALF
87
- const platformRight =
88
- collisionX.position[X] + collisionX.size[X] / HALF
89
- if (vx < NO_VELOCITY && prevLeft >= platformRight) {
90
- const penetration = platformRight - entityLeft
91
- if (penetration > NO_PENETRAION) entity.position[X] += penetration
92
- entity.velocity[X] = 0
93
- }
83
+ // Check if moving left and crossing the platform's right edge
84
+ const prevLeft = prevX - width / HALF
85
+ const platformRight = collisionX.position[X] + collisionX.size[X] / HALF
86
+ if (vx < NO_VELOCITY && prevLeft >= platformRight) {
87
+ const penetration = platformRight - entityLeft
88
+ if (penetration > NO_PENETRAION) entity.position[X] += penetration
89
+ entity.velocity[X] = 0
94
90
  }
95
-
96
- // 2. VERTICAL MOVEMENT & RESOLUTION
97
- const wasOnGround = entity.groundObject
98
- entity.groundObject = undefined
99
-
100
- const { vy, position: nextGravityPosition } = applyGravity(entity, dt)
101
- entity.vy = vy
102
- entity.position[Y] = nextGravityPosition[Y]
103
-
104
- const collisionY = findCollision(entity, entities, "platform")
105
- if (collisionY) {
106
- const prevBottom = prevY - height / HALF
107
- const platformTop = collisionY.position[Y] + collisionY.size[Y] / HALF
108
-
109
- // Landing on top of a platform (one-way platform logic)
110
- if (entity.vy <= NO_VELOCITY && prevBottom >= platformTop) {
111
- const entityBottom = entity.position[Y] - height / HALF
112
- const penetration = platformTop - entityBottom
113
- if (penetration > NO_PENETRAION) entity.position[Y] += penetration
114
- entity.vy = 0
115
- entity.groundObject = collisionY
116
- entity.jumpsLeft = entity.maxJumps
117
-
118
- // Only notify on the frame we actually land, not every frame we're on the ground.
119
- if (!wasOnGround) {
120
- api.notify("land", {
121
- entityId: entity.id,
122
- targetId: collisionY.id,
123
- })
124
- }
91
+ }
92
+
93
+ // 2. VERTICAL MOVEMENT & RESOLUTION
94
+ const wasOnGround = entity.groundObject
95
+ entity.groundObject = undefined
96
+
97
+ const { vy, position: nextGravityPosition } = applyGravity(entity, dt)
98
+ entity.vy = vy
99
+ entity.position[Y] = nextGravityPosition[Y]
100
+
101
+ const collisionY = findCollision(entity, entities, "platform")
102
+ if (collisionY) {
103
+ const prevBottom = prevY - height / HALF
104
+ const platformTop = collisionY.position[Y] + collisionY.size[Y] / HALF
105
+
106
+ // Landing on top of a platform (one-way platform logic)
107
+ if (entity.vy <= NO_VELOCITY && prevBottom >= platformTop) {
108
+ const entityBottom = entity.position[Y] - height / HALF
109
+ const penetration = platformTop - entityBottom
110
+ if (penetration > NO_PENETRAION) entity.position[Y] += penetration
111
+ entity.vy = 0
112
+ entity.groundObject = collisionY
113
+ entity.jumpsLeft = entity.maxJumps
114
+
115
+ // Only notify on the frame we actually land, not every frame we're on the ground.
116
+ if (!wasOnGround) {
117
+ api.notify("land", {
118
+ entityId: entity.id,
119
+ targetId: collisionY.id,
120
+ })
125
121
  }
126
-
127
- // Hitting head on bottom of a platform
128
- // else if (entity.vy > 0) {
129
- // const prevTop = prevY + height / HALF
130
- // const platformBottom =
131
- // collisionY.position[Y] - collisionY.size[Y] / HALF
132
- // if (prevTop <= platformBottom) {
133
- // const entityTop = entity.position[Y] + height / HALF
134
- // const penetration = entityTop - platformBottom
135
- // if (penetration > 0) entity.position[Y] -= penetration
136
- // entity.vy = 0
137
- // }
138
- // }
139
122
  }
140
123
 
141
- entity.orientation = magnitude(entity.velocity)
142
- ? angle(entity.velocity)
143
- : entity.orientation
144
- },
145
- })
124
+ // Hitting head on bottom of a platform
125
+ // else if (entity.vy > 0) {
126
+ // const prevTop = prevY + height / HALF
127
+ // const platformBottom =
128
+ // collisionY.position[Y] - collisionY.size[Y] / HALF
129
+ // if (prevTop <= platformBottom) {
130
+ // const entityTop = entity.position[Y] + height / HALF
131
+ // const penetration = entityTop - platformBottom
132
+ // if (penetration > 0) entity.position[Y] -= penetration
133
+ // entity.vy = 0
134
+ // }
135
+ // }
136
+ }
137
+
138
+ entity.orientation = magnitude(entity.velocity)
139
+ ? angle(entity.velocity)
140
+ : entity.orientation
141
+ },
142
+ })
146
143
  }
@@ -1,6 +1,7 @@
1
1
  import { audio } from "@inglorious/engine/behaviors/audio.js"
2
2
  import { game } from "@inglorious/engine/behaviors/game.js"
3
3
  import { images } from "@inglorious/engine/behaviors/images.js"
4
+ import { createApi } from "@inglorious/store/api.js"
4
5
  import {
5
6
  connectDevTools,
6
7
  disconnectDevTools,
@@ -69,7 +70,6 @@ export class Engine {
69
70
  }
70
71
 
71
72
  this._store = createStore({ ...this._config, middlewares, mode: "batched" })
72
- this._api = this._store.getApi()
73
73
  this._loop = new Loop[this._config.loop.type]()
74
74
 
75
75
  if (this._devMode) {
@@ -78,11 +78,12 @@ export class Engine {
78
78
  }
79
79
 
80
80
  async init() {
81
+ const api = createApi(this._store)
81
82
  return Promise.all(
82
83
  Object.values(this._config.entities).map((entity) => {
83
84
  const originalType = this._config.types[entity.type]
84
85
  const type = augmentType(originalType)
85
- return type.init?.(entity, null, this._api)
86
+ return type.init?.(entity, null, api)
86
87
  }),
87
88
  )
88
89
  }
@@ -91,7 +92,7 @@ export class Engine {
91
92
  * Starts the game engine, initializing the loop and notifying the store.
92
93
  */
93
94
  start() {
94
- this._api.notify("start")
95
+ this._store.notify("start")
95
96
  this._loop.start(this, ONE_SECOND / this._config.loop.fps)
96
97
  }
97
98
 
@@ -99,7 +100,7 @@ export class Engine {
99
100
  * Stops the game engine, halting the loop and notifying the store.
100
101
  */
101
102
  stop() {
102
- this._api.notify("stop")
103
+ this._store.notify("stop")
103
104
  this._store.update()
104
105
  this._loop.stop()
105
106
  }
@@ -109,7 +110,7 @@ export class Engine {
109
110
  * @param {number} dt - Delta time since the last update in milliseconds.
110
111
  */
111
112
  update(dt) {
112
- this._api.notify("update", dt)
113
+ this._store.notify("update", dt)
113
114
  const processedEvents = this._store.update()
114
115
  const entities = this._store.getState()
115
116
 
@@ -1,20 +1,24 @@
1
+ import { createApi } from "@inglorious/store/api.js"
1
2
  import { EventMap } from "@inglorious/store/event-map.js"
2
3
 
3
4
  import { EntityPools } from "./entity-pools"
4
5
 
5
6
  export function entityPoolMiddleware() {
6
- return (store, api) => {
7
+ return (store) => {
7
8
  const pools = new EntityPools()
8
- const types = api.getTypes()
9
+ const types = store.getTypes()
9
10
  const eventMap = new EventMap()
10
11
 
11
- api.getAllActivePoolEntities = () => pools.getAllActiveEntities()
12
+ store.extras ??= {}
13
+ store.extras.getAllActivePoolEntities = () => pools.getAllActiveEntities()
12
14
 
13
- const game = api.getEntity("game")
15
+ const game = store.getState().game
14
16
  if (game.devMode) {
15
- api.getEntityPoolsStats = () => pools.getStats()
17
+ store.extras.getEntityPoolsStats = () => pools.getStats()
16
18
  }
17
19
 
20
+ const api = createApi(store)
21
+
18
22
  return (next) => (event) => {
19
23
  switch (event.type) {
20
24
  case "spawn": {