@inglorious/engine 0.1.0 → 0.2.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 (292) hide show
  1. package/README.md +39 -36
  2. package/package.json +20 -33
  3. package/src/engine/ai/movement/dynamic/align.js +63 -63
  4. package/src/engine/ai/movement/dynamic/arrive.js +42 -43
  5. package/src/engine/ai/movement/dynamic/evade.js +38 -38
  6. package/src/engine/ai/movement/dynamic/face.js +19 -20
  7. package/src/engine/ai/movement/dynamic/flee.js +45 -45
  8. package/src/engine/ai/movement/dynamic/look-where-youre-going.js +16 -17
  9. package/src/engine/ai/movement/dynamic/match-velocity.js +51 -50
  10. package/src/engine/ai/movement/dynamic/pursue.js +38 -38
  11. package/src/engine/ai/movement/dynamic/seek.js +44 -44
  12. package/src/engine/ai/movement/dynamic/wander.js +31 -32
  13. package/src/engine/ai/movement/kinematic/align.js +37 -37
  14. package/src/engine/ai/movement/kinematic/arrive.js +42 -42
  15. package/src/engine/ai/movement/kinematic/face.js +19 -20
  16. package/src/engine/ai/movement/kinematic/flee.js +26 -26
  17. package/src/engine/ai/movement/kinematic/seek.js +26 -26
  18. package/src/engine/ai/movement/kinematic/seek.test.js +42 -42
  19. package/src/engine/ai/movement/kinematic/wander-as-seek.js +31 -31
  20. package/src/engine/ai/movement/kinematic/wander.js +27 -27
  21. package/src/engine/animation/sprite.js +101 -0
  22. package/src/engine/animation/ticker.js +38 -0
  23. package/src/engine/behaviors/camera.js +68 -0
  24. package/src/engine/behaviors/controls/dynamic/modern.js +76 -0
  25. package/src/engine/behaviors/controls/dynamic/shooter.js +84 -0
  26. package/src/engine/behaviors/controls/dynamic/tank.js +69 -0
  27. package/src/engine/behaviors/controls/event-handlers.js +17 -0
  28. package/src/engine/behaviors/controls/kinematic/modern.js +76 -0
  29. package/src/engine/behaviors/controls/kinematic/shooter.js +82 -0
  30. package/src/engine/behaviors/controls/kinematic/tank.js +67 -0
  31. package/src/engine/behaviors/debug/collision.js +35 -0
  32. package/src/engine/behaviors/fps.js +29 -0
  33. package/src/engine/behaviors/fsm.js +33 -0
  34. package/src/{game/decorators → engine/behaviors}/fsm.test.js +49 -56
  35. package/src/engine/behaviors/game.js +15 -0
  36. package/src/engine/behaviors/input/controls.js +37 -0
  37. package/src/engine/behaviors/input/gamepad.js +114 -0
  38. package/src/engine/behaviors/input/input.js +48 -0
  39. package/src/engine/behaviors/input/keyboard.js +64 -0
  40. package/src/engine/behaviors/input/mouse.js +91 -0
  41. package/src/engine/behaviors/physics/bouncy.js +25 -0
  42. package/src/engine/behaviors/physics/clamped.js +36 -0
  43. package/src/{game/decorators/collisions.js → engine/behaviors/physics/collidable.js} +20 -24
  44. package/src/engine/behaviors/physics/jumpable.js +145 -0
  45. package/src/engine/behaviors/ui/button.js +17 -0
  46. package/src/engine/collision/detection.js +110 -115
  47. package/src/engine/core/api.js +34 -0
  48. package/src/engine/core/dev-tools.js +135 -0
  49. package/src/engine/core/engine.js +119 -0
  50. package/src/engine/core/loop.js +15 -0
  51. package/src/engine/{loop → core/loops}/animation-frame.js +25 -26
  52. package/src/engine/{loop → core/loops}/elapsed.js +22 -23
  53. package/src/engine/{loop → core/loops}/fixed.js +27 -28
  54. package/src/engine/{loop → core/loops}/flash.js +13 -14
  55. package/src/engine/{loop → core/loops}/lag.js +26 -27
  56. package/src/engine/core/select.js +26 -0
  57. package/src/engine/core/store.js +178 -0
  58. package/src/engine/core/store.test.js +110 -0
  59. package/src/engine/movement/dynamic/modern.js +21 -24
  60. package/src/engine/movement/dynamic/tank.js +43 -43
  61. package/src/engine/movement/kinematic/modern.js +16 -16
  62. package/src/engine/movement/kinematic/modern.test.js +27 -27
  63. package/src/engine/movement/kinematic/tank.js +27 -27
  64. package/src/engine/physics/bounds.js +138 -0
  65. package/src/engine/physics/position.js +43 -0
  66. package/src/engine/physics/position.test.js +80 -0
  67. package/src/engine/systems/sprite-animation.js +27 -0
  68. package/src/main.js +10 -5
  69. package/src/renderers/canvas/absolute-position.js +18 -0
  70. package/src/renderers/canvas/camera.js +13 -0
  71. package/src/renderers/canvas/canvas-renderer.js +68 -0
  72. package/src/{ui → renderers}/canvas/character.js +38 -35
  73. package/src/{ui → renderers}/canvas/form/button.js +25 -25
  74. package/src/{ui → renderers}/canvas/fps.js +18 -18
  75. package/src/renderers/canvas/image/hitmask.js +51 -0
  76. package/src/{ui → renderers}/canvas/image/image.js +34 -37
  77. package/src/{ui → renderers}/canvas/image/sprite.js +49 -49
  78. package/src/{ui → renderers}/canvas/image/tilemap.js +66 -64
  79. package/src/{ui → renderers}/canvas/mouse.js +37 -37
  80. package/src/renderers/canvas/rendering-system.js +79 -0
  81. package/src/{ui → renderers}/canvas/shapes/circle.js +29 -31
  82. package/src/{ui → renderers}/canvas/shapes/rectangle.js +27 -31
  83. package/src/renderers/react/game/character/index.jsx +20 -0
  84. package/src/{ui → renderers}/react/game/cursor/index.jsx +20 -20
  85. package/src/{ui → renderers}/react/game/form/fields/field/index.jsx +56 -56
  86. package/src/{ui → renderers}/react/game/form/fields/index.jsx +12 -12
  87. package/src/{ui → renderers}/react/game/form/index.jsx +22 -22
  88. package/src/{ui → renderers}/react/game/fps/index.jsx +16 -16
  89. package/src/{ui → renderers}/react/game/game.jsx +72 -71
  90. package/src/{ui → renderers}/react/game/index.jsx +29 -29
  91. package/src/{ui → renderers}/react/game/platform/index.jsx +30 -30
  92. package/src/{ui → renderers}/react/game/scene/index.jsx +27 -25
  93. package/src/{ui → renderers}/react/game/sprite/index.jsx +60 -58
  94. package/src/{ui → renderers}/react/game/stats/index.jsx +22 -22
  95. package/src/{ui → renderers}/react/hocs/with-absolute-position/index.jsx +20 -20
  96. package/src/{ui → renderers}/react/index.jsx +9 -9
  97. package/src/utils/algorithms/decision-tree.js +24 -24
  98. package/src/utils/algorithms/decision-tree.test.js +153 -102
  99. package/src/utils/algorithms/path-finding.js +155 -155
  100. package/src/utils/algorithms/path-finding.test.js +151 -151
  101. package/src/utils/data-structures/array.js +83 -83
  102. package/src/utils/data-structures/array.test.js +173 -173
  103. package/src/utils/data-structures/board.js +159 -159
  104. package/src/utils/data-structures/board.test.js +242 -242
  105. package/src/utils/data-structures/boolean.js +9 -9
  106. package/src/utils/data-structures/heap.js +164 -164
  107. package/src/utils/data-structures/heap.test.js +103 -103
  108. package/src/utils/data-structures/object.js +138 -102
  109. package/src/utils/data-structures/object.test.js +218 -121
  110. package/src/utils/data-structures/objects.js +66 -48
  111. package/src/utils/data-structures/objects.test.js +99 -99
  112. package/src/utils/data-structures/tree.js +36 -36
  113. package/src/utils/data-structures/tree.test.js +33 -33
  114. package/src/utils/functions/functions.js +19 -19
  115. package/src/utils/functions/functions.test.js +23 -23
  116. package/src/utils/math/geometry/circle.js +70 -117
  117. package/src/utils/math/geometry/circle.test.js +97 -97
  118. package/src/utils/math/geometry/hitmask.js +70 -39
  119. package/src/utils/math/geometry/hitmask.test.js +155 -84
  120. package/src/utils/math/geometry/line.js +35 -35
  121. package/src/utils/math/geometry/line.test.js +49 -49
  122. package/src/utils/math/geometry/point.js +78 -71
  123. package/src/utils/math/geometry/point.test.js +81 -81
  124. package/src/utils/math/geometry/rectangle.js +76 -45
  125. package/src/utils/math/geometry/rectangle.test.js +42 -42
  126. package/src/utils/math/geometry/segment.js +80 -80
  127. package/src/utils/math/geometry/segment.test.js +183 -183
  128. package/src/utils/math/geometry/triangle.js +15 -15
  129. package/src/utils/math/geometry/triangle.test.js +11 -11
  130. package/src/utils/math/linear-algebra/2d.js +28 -28
  131. package/src/utils/math/linear-algebra/2d.test.js +17 -17
  132. package/src/utils/math/linear-algebra/quaternion.js +22 -22
  133. package/src/utils/math/linear-algebra/quaternion.test.js +25 -25
  134. package/src/utils/math/linear-algebra/quaternions.js +20 -20
  135. package/src/utils/math/linear-algebra/quaternions.test.js +29 -29
  136. package/src/utils/math/linear-algebra/vector.js +327 -302
  137. package/src/utils/math/linear-algebra/vector.test.js +265 -257
  138. package/src/utils/math/linear-algebra/vectors.js +122 -122
  139. package/src/utils/math/linear-algebra/vectors.test.js +65 -65
  140. package/src/utils/math/linear-interpolation.js +9 -0
  141. package/src/utils/math/numbers.js +90 -90
  142. package/src/utils/math/numbers.test.js +137 -137
  143. package/src/utils/math/rng.js +44 -44
  144. package/src/utils/math/rng.test.js +39 -39
  145. package/src/utils/math/statistics.js +43 -43
  146. package/src/utils/math/statistics.test.js +47 -47
  147. package/src/utils/math/trigonometry.js +89 -89
  148. package/src/utils/math/trigonometry.test.js +52 -52
  149. package/src/utils/physics/acceleration.js +61 -63
  150. package/src/utils/physics/friction.js +28 -30
  151. package/src/utils/physics/friction.test.js +42 -44
  152. package/src/utils/physics/gravity.js +69 -71
  153. package/src/utils/physics/gravity.test.js +77 -80
  154. package/src/utils/physics/jump.js +31 -41
  155. package/src/utils/physics/velocity.js +36 -38
  156. package/src/docs/ai/movement/dynamic/align.js +0 -131
  157. package/src/docs/ai/movement/dynamic/arrive.js +0 -88
  158. package/src/docs/ai/movement/dynamic/dynamic.mdx +0 -99
  159. package/src/docs/ai/movement/dynamic/dynamic.stories.js +0 -58
  160. package/src/docs/ai/movement/dynamic/evade.js +0 -72
  161. package/src/docs/ai/movement/dynamic/face.js +0 -90
  162. package/src/docs/ai/movement/dynamic/flee.js +0 -38
  163. package/src/docs/ai/movement/dynamic/look-where-youre-going.js +0 -114
  164. package/src/docs/ai/movement/dynamic/match-velocity.js +0 -92
  165. package/src/docs/ai/movement/dynamic/pursue.js +0 -72
  166. package/src/docs/ai/movement/dynamic/seek.js +0 -37
  167. package/src/docs/ai/movement/dynamic/wander.js +0 -71
  168. package/src/docs/ai/movement/kinematic/align.js +0 -122
  169. package/src/docs/ai/movement/kinematic/arrive.js +0 -78
  170. package/src/docs/ai/movement/kinematic/face.js +0 -82
  171. package/src/docs/ai/movement/kinematic/flee.js +0 -36
  172. package/src/docs/ai/movement/kinematic/kinematic.mdx +0 -67
  173. package/src/docs/ai/movement/kinematic/kinematic.stories.js +0 -42
  174. package/src/docs/ai/movement/kinematic/seek.js +0 -34
  175. package/src/docs/ai/movement/kinematic/wander-as-seek.js +0 -62
  176. package/src/docs/ai/movement/kinematic/wander.js +0 -28
  177. package/src/docs/bounds.js +0 -7
  178. package/src/docs/code-reuse.js +0 -35
  179. package/src/docs/collision/circles.js +0 -58
  180. package/src/docs/collision/collision.mdx +0 -27
  181. package/src/docs/collision/collision.stories.js +0 -22
  182. package/src/docs/collision/platform.js +0 -76
  183. package/src/docs/collision/tilemap.js +0 -181
  184. package/src/docs/empty.js +0 -1
  185. package/src/docs/engine.mdx +0 -81
  186. package/src/docs/engine.stories.js +0 -37
  187. package/src/docs/event-handlers.js +0 -68
  188. package/src/docs/framerate.js +0 -37
  189. package/src/docs/game.jsx +0 -15
  190. package/src/docs/image/image.js +0 -19
  191. package/src/docs/image/image.stories.js +0 -22
  192. package/src/docs/image/sprite.js +0 -39
  193. package/src/docs/image/tilemap.js +0 -84
  194. package/src/docs/input/controls.js +0 -67
  195. package/src/docs/input/gamepad.js +0 -67
  196. package/src/docs/input/input.mdx +0 -55
  197. package/src/docs/input/input.stories.js +0 -27
  198. package/src/docs/input/keyboard.js +0 -58
  199. package/src/docs/input/mouse.js +0 -32
  200. package/src/docs/instances.js +0 -49
  201. package/src/docs/player/dynamic/double-jump.js +0 -90
  202. package/src/docs/player/dynamic/dynamic.stories.js +0 -32
  203. package/src/docs/player/dynamic/jump.js +0 -83
  204. package/src/docs/player/dynamic/modern-controls.js +0 -57
  205. package/src/docs/player/dynamic/shooter-controls.js +0 -51
  206. package/src/docs/player/dynamic/tank-controls.js +0 -44
  207. package/src/docs/player/kinematic/double-jump.js +0 -90
  208. package/src/docs/player/kinematic/jump.js +0 -82
  209. package/src/docs/player/kinematic/kinematic.stories.js +0 -32
  210. package/src/docs/player/kinematic/modern-controls.js +0 -56
  211. package/src/docs/player/kinematic/shooter-controls.js +0 -48
  212. package/src/docs/player/kinematic/tank-controls.js +0 -42
  213. package/src/docs/quick-start/first-game.js +0 -49
  214. package/src/docs/quick-start/hello-world.js +0 -1
  215. package/src/docs/quick-start.mdx +0 -127
  216. package/src/docs/quick-start.stories.js +0 -17
  217. package/src/docs/recipes/add-and-remove.js +0 -71
  218. package/src/docs/recipes/add-instance.js +0 -42
  219. package/src/docs/recipes/decision-tree.js +0 -169
  220. package/src/docs/recipes/random-instances.js +0 -25
  221. package/src/docs/recipes/recipes.mdx +0 -81
  222. package/src/docs/recipes/recipes.stories.js +0 -37
  223. package/src/docs/recipes/remove-instance.js +0 -52
  224. package/src/docs/recipes/states.js +0 -64
  225. package/src/docs/ui/button.js +0 -28
  226. package/src/docs/ui/form.stories.js +0 -55
  227. package/src/docs/ui-chooser.jsx +0 -6
  228. package/src/docs/utils/data-structures/object.mdx +0 -47
  229. package/src/docs/utils/data-structures/objects.mdx +0 -30
  230. package/src/docs/utils/functions/functions.mdx +0 -34
  231. package/src/docs/utils/math/geometry/circle.mdx +0 -55
  232. package/src/docs/utils/math/geometry/point.mdx +0 -38
  233. package/src/docs/utils/math/geometry/rectangle.mdx +0 -24
  234. package/src/docs/utils/math/geometry/segment.mdx +0 -55
  235. package/src/docs/utils/math/geometry/triangle.mdx +0 -22
  236. package/src/docs/utils/math/linear-algebra/2d.mdx +0 -22
  237. package/src/docs/utils/math/linear-algebra/quaternion.mdx +0 -21
  238. package/src/docs/utils/math/linear-algebra/quaternions.mdx +0 -22
  239. package/src/docs/utils/math/linear-algebra/vector.mdx +0 -177
  240. package/src/docs/utils/math/linear-algebra/vectors.mdx +0 -58
  241. package/src/docs/utils/math/numbers.mdx +0 -76
  242. package/src/docs/utils/math/random.mdx +0 -35
  243. package/src/docs/utils/math/statistics.mdx +0 -38
  244. package/src/docs/utils/math/trigonometry.mdx +0 -85
  245. package/src/docs/utils/physics/friction.mdx +0 -20
  246. package/src/docs/utils/physics/gravity.mdx +0 -28
  247. package/src/engine/loop.js +0 -15
  248. package/src/engine/store.js +0 -174
  249. package/src/engine/store.test.js +0 -256
  250. package/src/engine.js +0 -74
  251. package/src/game/animation.js +0 -26
  252. package/src/game/bounds.js +0 -66
  253. package/src/game/decorators/character.js +0 -5
  254. package/src/game/decorators/clamp-to-bounds.js +0 -15
  255. package/src/game/decorators/controls/dynamic/modern.js +0 -48
  256. package/src/game/decorators/controls/dynamic/shooter.js +0 -47
  257. package/src/game/decorators/controls/dynamic/tank.js +0 -55
  258. package/src/game/decorators/controls/kinematic/modern.js +0 -49
  259. package/src/game/decorators/controls/kinematic/shooter.js +0 -45
  260. package/src/game/decorators/controls/kinematic/tank.js +0 -52
  261. package/src/game/decorators/debug/collisions.js +0 -32
  262. package/src/game/decorators/double-jump.js +0 -70
  263. package/src/game/decorators/fps.js +0 -30
  264. package/src/game/decorators/fsm.js +0 -27
  265. package/src/game/decorators/game.js +0 -11
  266. package/src/game/decorators/image/image.js +0 -5
  267. package/src/game/decorators/image/sprite.js +0 -5
  268. package/src/game/decorators/image/tilemap.js +0 -5
  269. package/src/game/decorators/input/controls.js +0 -27
  270. package/src/game/decorators/input/gamepad.js +0 -74
  271. package/src/game/decorators/input/input.js +0 -41
  272. package/src/game/decorators/input/keyboard.js +0 -49
  273. package/src/game/decorators/input/mouse.js +0 -65
  274. package/src/game/decorators/jump.js +0 -72
  275. package/src/game/decorators/platform.js +0 -5
  276. package/src/game/decorators/ui/button.js +0 -21
  277. package/src/game/sprite.js +0 -119
  278. package/src/ui/canvas/absolute-position.js +0 -17
  279. package/src/ui/canvas/image/hitmask.js +0 -37
  280. package/src/ui/canvas.js +0 -81
  281. package/src/ui/react/game/character/index.jsx +0 -30
  282. package/src/utils/math/geometry/platform.js +0 -42
  283. package/src/utils/math/geometry/platform.test.js +0 -133
  284. /package/src/{ui → renderers}/react/game/character/character.module.scss +0 -0
  285. /package/src/{ui → renderers}/react/game/cursor/cursor.module.scss +0 -0
  286. /package/src/{ui → renderers}/react/game/form/fields/field/field.module.scss +0 -0
  287. /package/src/{ui → renderers}/react/game/form/fields/fields.module.scss +0 -0
  288. /package/src/{ui → renderers}/react/game/form/form.module.scss +0 -0
  289. /package/src/{ui → renderers}/react/game/platform/platform.module.scss +0 -0
  290. /package/src/{ui → renderers}/react/game/scene/scene.module.scss +0 -0
  291. /package/src/{ui → renderers}/react/game/sprite/sprite.module.css +0 -0
  292. /package/src/{ui → renderers}/react/hocs/with-absolute-position/with-absolute-position.module.scss +0 -0
@@ -1,35 +0,0 @@
1
- import { Meta } from '@storybook/blocks'
2
-
3
- import { random, randomBinomial } from '@inglorious/utils/math/rng'
4
-
5
- <Meta title="Utils/Math/Rng" />
6
-
7
- # Rng
8
-
9
- Random number generators.
10
-
11
- ## Random
12
-
13
- Generates a random number with optional parameters that specify range and step.
14
-
15
- No parameters will generate a random number in the range `[0, 1)` (zero included, one excluded).
16
-
17
- <code>random() == {random()}</code>&nbsp;
18
-
19
- A parameter `n` means the random number will be an integer in the range `[0, n]` (zero and `n` included).
20
-
21
- <code>random(6) == {random(6)}</code>&nbsp;
22
-
23
- Two parameters `n` and `m` means the random number will be an integer in the range `[n, m]` (both numbers included).
24
-
25
- <code>random(1, 6) == {random(1, 6)}</code>&nbsp;
26
-
27
- A third parameter allows to specify the step.
28
-
29
- <code>random(2, 6, 2) == {random(2, 6, 2)}</code>&nbsp;
30
-
31
- ## Random Binomial
32
-
33
- Generates a random number in the range `(-1, 1)` (minus one excluded, one excluded), with probability following the [Binomial Distribution](https://en.wikipedia.org/wiki/Binomial_distribution).
34
-
35
- <code>randomBinomial() == {randomBinomial()}</code>&nbsp;
@@ -1,38 +0,0 @@
1
- import { Meta } from '@storybook/blocks'
2
-
3
- import { mean, median, mode } from '@inglorious/utils/math/statistics'
4
- import { toString } from '@inglorious/utils/data-structures/object'
5
-
6
- <Meta title="Utils/Math/Statistics" />
7
-
8
- # Statistics
9
-
10
- Basic statistics functions.
11
-
12
- ## Average
13
-
14
- Alias of `mean`.
15
-
16
- ## Mean
17
-
18
- Returns the mathematical mean of a list of numbers.
19
-
20
- <code>mean(1, 3, 2) == {mean(1, 3, 2)}</code>&nbsp;
21
-
22
- ## Median
23
-
24
- Returns the median value from a list of numbers.
25
-
26
- When the list has odd length, the median is whatever value sits in between:
27
-
28
- <code>median(1, 3, 2) == {median(1, 3, 2)}</code>&nbsp;
29
-
30
- When the list has an even length, the median is the average of its two values in between (in this case, 2 and 3):
31
-
32
- <code>median(1, 3, 2, 4) == {median(1, 3, 2, 4)}</code>&nbsp;
33
-
34
- ## Mode
35
-
36
- Returns the most frequent item in a list of values.
37
-
38
- <code>mode("rarely", "sometimes", "sometimes", "always") == {toString(mode("rarely", "sometimes", "sometimes", "always"))}</code>&nbsp;
@@ -1,85 +0,0 @@
1
- import { Meta } from '@storybook/blocks'
2
-
3
- import { atan2, cos, cosine, pi, sin, sine, toDegrees, toRadians, toRange } from '@inglorious/utils/math/trigonometry'
4
-
5
- <Meta title="Utils/Math/Trigonometry" />
6
-
7
- # Trigonometry
8
-
9
- Basic trigonometry functions.
10
-
11
- ## Atan2
12
-
13
- Returns the atan2 of y and x.
14
-
15
- <code>atan2(0, 0) == {atan2(0, 0)}</code>&nbsp;
16
-
17
-
18
- <code>atan2(0, pi() / 2) == {atan2(0, pi() / 2)}</code>&nbsp;
19
-
20
-
21
- <code>atan2(pi() / 2, 0) == {atan2(pi() / 2, 0)}</code>&nbsp;
22
-
23
-
24
- <code>atan2(pi() / 2, pi() / 2) == {atan2(pi() / 2, pi() / 2)}</code>&nbsp;
25
-
26
- ## Cos
27
-
28
- Returns the cosine of an angle in radians (alias `cosine`).
29
-
30
- <code>cos(0) == {cos(0)}</code>&nbsp;
31
-
32
- <code>cos(pi() / 4) == {cos(pi() / 4).toFixed(3)}</code>&nbsp;
33
-
34
- <code>cos(pi() / 2) == {cos(pi() / 2)}</code> (&asymp;0)
35
-
36
- ## Cosine
37
-
38
- Alias of `cos`.
39
-
40
- ## Pi
41
-
42
- Returns an approximation of &pi;.
43
-
44
- <code>pi() == {pi()}</code> (&asymp;&pi;)
45
-
46
- ## Sin
47
-
48
- Return the sine of an angle in degrees (alias `sine`).
49
-
50
-
51
- <code>sin(0) == {sin(0)}</code>&nbsp;
52
-
53
- <code>sin(pi() / 4) == {sin(pi() / 4).toFixed(3)}</code>&nbsp;
54
-
55
- <code>sin(pi() / 2) == {sin(pi() / 2)}</code>&nbsp;
56
-
57
- ## Sine
58
-
59
- Alias of `sin`.
60
-
61
- ## To Degrees
62
-
63
- Converts radians into degrees.
64
-
65
- <code>toDegrees(pi() / 4) == {toDegrees(pi() / 4)}</code>&nbsp;
66
-
67
- ## To Radians
68
-
69
- Converts degrees into radians.
70
-
71
- <code>toRadians(45) == {toRadians(45)}</code> (&asymp;&pi;/4)
72
-
73
- ## To Range
74
-
75
- Clamps any angle into the range [-&pi;, &pi;].
76
-
77
- <code>toRange(5 / 4 * pi()) == {toRange((5 / 4) * pi())}</code> (&asymp;-3/4&pi;)
78
-
79
- <code>toRange(13 / 4 * pi()) == {toRange((13 / 4) * pi())}</code> (&asymp;-3/4&pi;)
80
-
81
- <code>toRange(-5 / 4 * pi()) == {toRange((-5 / 4) * pi())}</code> (&asymp;3/4&pi;)
82
-
83
- <code>toRange(-13 / 4 * pi()) == {toRange((-13 / 4) * pi())}</code> (&asymp;3/4&pi;)
84
-
85
- <code>toRange(3 / 4 * pi()) == {toRange((3 / 4) * pi())}</code> (&asymp;3/4&pi;)
@@ -1,20 +0,0 @@
1
- import { Meta } from '@storybook/blocks'
2
-
3
- import { applyFriction } from '@inglorious/utils/physics/friction'
4
- import { toString } from '@inglorious/utils/math/linear-algebra/vector'
5
-
6
- <Meta title="Utils/Physics/Friction" />
7
-
8
- # Friction
9
-
10
- Friction is a force that resists movement. It is directly related to the body's momentum, which is mass times velocity, but for our purposes we can safely ignore mass and apply it directly to velocity.
11
-
12
- A friction that is equal to the velocity's magnitude will eventually stop the body after some time.
13
-
14
- <code>applyFriction(\{ velocity: [8, 0, 6], friction: 5 \}, \{ dt: 1 \}) == {toString(applyFriction({ velocity: [8, 0, 6], friction: 5 }, { dt: 1 }))}</code>&nbsp;
15
-
16
- <code>applyFriction(\{ velocity: [8, 0, 6], friction: 5 \}, \{ dt: 2 \}) == {toString(applyFriction({ velocity: [8, 0, 6], friction: 5 }, { dt: 2 }))}</code>&nbsp;
17
-
18
- When the body is still then no friction will be applied:
19
-
20
- <code>applyFriction(\{ velocity: [0, 0, 0], friction: 5 \}, \{ dt: 1 \}) == {toString(applyFriction({ velocity: [0, 0, 0], friction: 5 }, { dt: 1 }))}</code>&nbsp;
@@ -1,28 +0,0 @@
1
- import { Meta } from '@storybook/blocks'
2
-
3
- import { applyGravity } from '@inglorious/utils/physics/gravity'
4
- import { toString } from '@inglorious/utils/data-structures/object'
5
-
6
- <Meta title="Utils/Physics/Gravity" />
7
-
8
- # Gravity
9
-
10
- We can consider gravity as a constant acceleration downards. [This video](https://youtu.be/hG9SzQxaCm8) shows how to calculate this acceleration based on the curve that we want our character to draw when jumping. Also, it rightfully warns to keep jump parameters separate from our world coordinates. That's why we need a specific acceleration and velocity to model our jumps, while directly integrating into the position vector.
11
-
12
- - `maxJump` is the maximum height that we want to achieve;
13
- - `maxLeap` is the maximum distance we want to cover with a jump;
14
- - `maxSpeed` is the maximum horizontal speed when running;
15
- - `vy` is the current jump velocity;
16
- - `position[Y]` is the current world height.
17
-
18
- <code>applyGravity(\{ maxJump: 10, maxLeap: 10, maxSpeed: 10, vy: 10, position: [0,10,0] \}, \{ dt: 1 \}) == {toString(applyGravity({ maxJump: 10, maxLeap: 10, maxSpeed: 10, vy: 10, position: [0,10,0] }, { dt: 1 }))}</code>&nbsp;
19
-
20
- Not specifying `maxJump` and `maxSpeed` will result in no gravity being applied:
21
-
22
- <code>applyGravity(\{ maxLeap: 10, maxSpeed: 10, vy: 10, position: [0,10,0] \}, \{ dt: 1 \}) == {toString(applyGravity({ maxLeap: 10, maxSpeed: 10, vy: 10, position: [0,10,0] }, { dt: 1 }))}</code>&nbsp;
23
-
24
- <code>applyGravity(\{ maxJump: 10, maxSpeed: 10, vy: 10, position: [0,10,0] \}, \{ dt: 1 \}) == {toString(applyGravity({ maxJump: 10, maxLeap: 10, vy: 10, position: [0,10,0] }, { dt: 1 }))}</code>&nbsp;
25
-
26
- While not specifying `maxLeap` will result in an error, since we have to divide by this quantity:
27
-
28
- <code>applyGravity(\{ maxJump: 10, maxSpeed: 10, vy: 10, position: [0,10,0] \}, \{ dt: 1 \}) == Error(['maxLeap'])</code>&nbsp;
@@ -1,15 +0,0 @@
1
- import AnimationFrameLoop from "./loop/animation-frame.js"
2
- import ElapsedLoop from "./loop/elapsed.js"
3
- import FixedLoop from "./loop/fixed.js"
4
- import FlashLoop from "./loop/flash.js"
5
- import LagLoop from "./loop/lag.js"
6
-
7
- // @see https://gameprogrammingpatterns.com/game-loop.html
8
-
9
- export default {
10
- flash: FlashLoop,
11
- fixed: FixedLoop,
12
- elapsed: ElapsedLoop,
13
- lag: LagLoop,
14
- animationFrame: AnimationFrameLoop,
15
- }
@@ -1,174 +0,0 @@
1
- import { enableGame } from "@inglorious/game/decorators/game.js"
2
- import { map } from "@inglorious/utils/data-structures/object.js"
3
- import { extend } from "@inglorious/utils/data-structures/objects.js"
4
- import { pipe } from "@inglorious/utils/functions/functions.js"
5
- import { produce } from "immer"
6
-
7
- const DEFAULT_TYPES = {
8
- game: [enableGame()],
9
- }
10
-
11
- const DEFAULT_INSTANCES = {
12
- // eslint-disable-next-line no-magic-numbers
13
- game: { type: "game", bounds: [0, 0, 800, 600] }, // Default game instance with bounds.
14
- }
15
-
16
- const DEFAULT_LAYER = 0
17
-
18
- /**
19
- * Creates a store to manage state and events.
20
- * @param {Object} options - Configuration options for the store.
21
- * @param {Object} options.instances - Initial instances to include in the store.
22
- * @param {Object} options.originalConfig - Additional configuration for the store.
23
- * @returns {Object} The store with methods to interact with state and events.
24
- */
25
- export function createStore({
26
- types: originalTypes,
27
- instances: originalInstances,
28
- }) {
29
- const listeners = new Set()
30
- let incomingEvents = []
31
-
32
- let types = extend(DEFAULT_TYPES, originalTypes)
33
- types = augmentTypes(types)
34
-
35
- let instances = extend(DEFAULT_INSTANCES, originalInstances)
36
- instances = augmentInstances(instances)
37
-
38
- let state = { events: [], instances }
39
-
40
- return {
41
- subscribe,
42
- update,
43
- notify,
44
- dispatch: notify, // needed for react-redux
45
- getTypes,
46
- getState,
47
- }
48
-
49
- /**
50
- * Subscribes a listener to state updates.
51
- * @param {Function} listener - The listener function to call on updates.
52
- * @returns {Function} A function to unsubscribe the listener.
53
- */
54
- function subscribe(listener) {
55
- listeners.add(listener)
56
-
57
- return function unsubscribe() {
58
- listeners.delete(listener)
59
- }
60
- }
61
-
62
- /**
63
- * Updates the state based on elapsed time and processes events.
64
- * @param {number} dt - The delta time since the last update.
65
- */
66
- function update(dt) {
67
- state = { ...state }
68
-
69
- state.events.push(...incomingEvents, { id: "game:update" })
70
- incomingEvents = []
71
-
72
- while (state.events.length) {
73
- const event = state.events.shift()
74
-
75
- if (event.id === "instance:add") {
76
- add(event.payload.id, event.payload)
77
- }
78
-
79
- state.instances = map(state.instances, (_, instance, instances) => {
80
- const type = types[instance.type]
81
- const handle = type[event.id]
82
- return (
83
- handle?.(instance, event, {
84
- dt,
85
- type: originalTypes[instance.type],
86
- instances,
87
- notify,
88
- }) ?? instance
89
- )
90
- })
91
-
92
- if (event.id === "instance:remove") {
93
- remove(event.payload)
94
- }
95
- }
96
-
97
- listeners.forEach((onUpdate) => onUpdate())
98
- }
99
-
100
- /**
101
- * Adds a new instance to the state.
102
- * @param {string} id - The ID of the instance to add.
103
- * @param {Object} instance - The instance object to add.
104
- */
105
- function add(id, instance) {
106
- state = { ...state }
107
- state.instances[id] = augmentInstance(id, instance)
108
- }
109
-
110
- /**
111
- * Removes an instance from the state.
112
- * @param {string} id - The ID of the instance to remove.
113
- */
114
- function remove(id) {
115
- state = { ...state }
116
- delete state.instances[id]
117
- }
118
-
119
- /**
120
- * Notifies the store of a new event.
121
- * @param {Object} event - The event object to notify.
122
- */
123
- function notify(event) {
124
- incomingEvents.push(event)
125
- }
126
-
127
- /**
128
- * Retrieves the types configuration.
129
- * @returns {Object} The types configuration.
130
- */
131
- function getTypes() {
132
- return types
133
- }
134
-
135
- /**
136
- * Retrieves the current state.
137
- * @returns {Object} The current state.
138
- */
139
- function getState() {
140
- return state
141
- }
142
- }
143
-
144
- function augmentTypes(types) {
145
- return pipe(applyDecorators, enableMutability)(types)
146
- }
147
-
148
- function applyDecorators(types) {
149
- return map(types, (_, type) => {
150
- if (!Array.isArray(type)) {
151
- return type
152
- }
153
-
154
- const decorators = type.map((fn) =>
155
- typeof fn !== "function" ? (type) => extend(type, fn) : fn,
156
- )
157
- return pipe(...decorators)({})
158
- })
159
- }
160
-
161
- function enableMutability(types) {
162
- return map(types, (_, { draw, ...events }) => ({
163
- draw,
164
- ...map(events, (_, event) => produce(event)),
165
- }))
166
- }
167
-
168
- function augmentInstances(instances) {
169
- return map(instances, augmentInstance)
170
- }
171
-
172
- function augmentInstance(id, instance) {
173
- return { ...instance, layer: instance.layer ?? DEFAULT_LAYER, id }
174
- }
@@ -1,256 +0,0 @@
1
- import { expect, test } from "vitest"
2
-
3
- import { createStore } from "./store.js"
4
-
5
- test("it should add an event to the event queue", () => {
6
- const event = { id: "something:happened" }
7
- const config = {
8
- types: {
9
- kitty: {
10
- [event.id](instance) {
11
- return { ...instance, wasNotified: true }
12
- },
13
- },
14
- },
15
- instances: {
16
- instance1: { type: "kitty" },
17
- },
18
- }
19
- const store = createStore(config)
20
- const afterState = {
21
- events: [],
22
- instances: {
23
- game: {
24
- id: "game",
25
- type: "game",
26
- layer: 0,
27
- bounds: [0, 0, 800, 600],
28
- },
29
- instance1: {
30
- id: "instance1",
31
- type: "kitty",
32
- layer: 0,
33
- wasNotified: true,
34
- },
35
- },
36
- }
37
-
38
- store.notify(event)
39
- store.update()
40
-
41
- const state = store.getState()
42
- expect(state).toStrictEqual(afterState)
43
- })
44
-
45
- test("it should process the event queue", () => {
46
- const event = { id: "something:happened" }
47
- const config = {
48
- types: {
49
- kitty: {
50
- "game:update"(instance) {
51
- return { ...instance, wasUpdated: true }
52
- },
53
-
54
- [event.id](instance) {
55
- return { ...instance, wasNotified: true }
56
- },
57
- },
58
- },
59
- instances: {
60
- instance1: { type: "kitty" },
61
- },
62
- }
63
- const store = createStore(config)
64
- store.notify(event)
65
- const afterState = {
66
- events: [],
67
- instances: {
68
- game: {
69
- id: "game",
70
- type: "game",
71
- layer: 0,
72
- bounds: [0, 0, 800, 600],
73
- },
74
- instance1: {
75
- id: "instance1",
76
- type: "kitty",
77
- layer: 0,
78
- wasNotified: true,
79
- wasUpdated: true,
80
- },
81
- },
82
- }
83
-
84
- store.update()
85
-
86
- const state = store.getState()
87
- expect(state).toStrictEqual(afterState)
88
- })
89
-
90
- test("it should send an event from an instance", () => {
91
- const event = {
92
- id: "doge:message",
93
- payload: { id: "inu", message: "Woof!" },
94
- }
95
- const config = {
96
- types: {
97
- doge: {
98
- "game:update"(instance, event, { instances, notify }) {
99
- if (instances.instance2.position === "near") {
100
- notify(event)
101
- }
102
- },
103
- },
104
- kitty: {
105
- [event.id](instance) {
106
- if (event.payload.id === "inu" && event.payload.message === "Woof!") {
107
- instance.position = "far"
108
- }
109
- },
110
- },
111
- },
112
-
113
- instances: {
114
- instance1: {
115
- type: "doge",
116
- },
117
- instance2: {
118
- type: "kitty",
119
- position: "near",
120
- },
121
- },
122
- }
123
- const store = createStore(config)
124
- const afterState = {
125
- events: [],
126
- instances: {
127
- game: {
128
- id: "game",
129
- type: "game",
130
- layer: 0,
131
- bounds: [0, 0, 800, 600],
132
- },
133
- instance1: {
134
- id: "instance1",
135
- type: "doge",
136
- layer: 0,
137
- },
138
- instance2: {
139
- id: "instance2",
140
- type: "kitty",
141
- layer: 0,
142
- position: "near", // should do nothing at first
143
- },
144
- },
145
- }
146
-
147
- store.update()
148
-
149
- const state = store.getState()
150
- expect(state).toStrictEqual(afterState)
151
- })
152
-
153
- test("it should receive an event from an instance", () => {
154
- const event = {
155
- id: "doge:message",
156
- payload: { id: "inu", message: "Woof!" },
157
- }
158
- const config = {
159
- types: {
160
- doge: {
161
- "game:update"(instance, event, { instances, notify }) {
162
- if (instances.instance2.position === "near") {
163
- notify(event)
164
- }
165
- },
166
- },
167
- kitty: {
168
- [event.id](instance, event) {
169
- if (event.payload.id === "inu" && event.payload.message === "Woof!") {
170
- instance.position = "far"
171
- }
172
- },
173
- },
174
- },
175
-
176
- instances: {
177
- instance1: {
178
- type: "doge",
179
- },
180
- instance2: {
181
- type: "kitty",
182
- position: "near",
183
- },
184
- },
185
- }
186
- const store = createStore(config)
187
- store.notify(event)
188
- const afterState = {
189
- events: [],
190
- instances: {
191
- game: {
192
- id: "game",
193
- type: "game",
194
- layer: 0,
195
- bounds: [0, 0, 800, 600],
196
- },
197
- instance1: {
198
- id: "instance1",
199
- type: "doge",
200
- layer: 0,
201
- },
202
- instance2: {
203
- id: "instance2",
204
- type: "kitty",
205
- layer: 0,
206
- position: "far", // position changed
207
- },
208
- },
209
- }
210
-
211
- store.update()
212
-
213
- const state = store.getState()
214
- expect(state).toStrictEqual(afterState)
215
- })
216
-
217
- test("it should mutate state in an immutable way", () => {
218
- const config = {
219
- types: {
220
- kitty: {
221
- "game:update"(instance) {
222
- instance.wasUpdated = true
223
- },
224
- },
225
- },
226
-
227
- instances: {
228
- instance1: {
229
- type: "kitty",
230
- },
231
- },
232
- }
233
- const store = createStore(config)
234
- const afterState = {
235
- events: [],
236
- instances: {
237
- game: {
238
- id: "game",
239
- type: "game",
240
- layer: 0,
241
- bounds: [0, 0, 800, 600],
242
- },
243
- instance1: {
244
- id: "instance1",
245
- type: "kitty",
246
- layer: 0,
247
- wasUpdated: true,
248
- },
249
- },
250
- }
251
-
252
- store.update()
253
-
254
- const state = store.getState()
255
- expect(state).toStrictEqual(afterState)
256
- })