@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,27 +0,0 @@
1
- import { extend } from "@inglorious/utils/data-structures/objects.js"
2
-
3
- import { createGamepad, enableGamepad } from "./gamepad.js"
4
- import { createInput, enableInput } from "./input.js"
5
- import { createKeyboard, enableKeyboard } from "./keyboard.js"
6
-
7
- const DEFAULT_PARAMS = {
8
- name: "input0",
9
- }
10
-
11
- export function enableControls(params) {
12
- params = extend(DEFAULT_PARAMS, params)
13
-
14
- return {
15
- keyboard: [enableKeyboard(params)],
16
- gamepad: [enableGamepad(params)],
17
- input: [enableInput(params)],
18
- }
19
- }
20
-
21
- export function createControls(name = DEFAULT_PARAMS.name, mapping = {}) {
22
- return {
23
- [`keyboard_${name}`]: createKeyboard(`keyboard_${name}`, mapping),
24
- [`gamepad_${name}`]: createGamepad(`gamepad_${name}`, mapping),
25
- [name]: createInput(name, mapping),
26
- }
27
- }
@@ -1,74 +0,0 @@
1
- const DEFAULT_PARAMS = {
2
- name: "gamepad0",
3
- }
4
-
5
- export function enableGamepad() {
6
- return {
7
- "game:update"(instance, event, { notify }) {
8
- navigator.getGamepads().forEach((gamepad) => {
9
- if (gamepad == null) {
10
- return
11
- }
12
-
13
- gamepad.axes.forEach((axis, index) => {
14
- notify({
15
- id: "gamepad:axis",
16
- payload: { id: gamepad.index, axis: `Axis${index}`, value: axis },
17
- })
18
- })
19
-
20
- gamepad.buttons.forEach((button, index) => {
21
- const id = button.pressed ? "gamepad:press" : "gamepad:release"
22
- notify({
23
- id,
24
- payload: { id: gamepad.index, button: `Btn${index}` },
25
- })
26
- })
27
- })
28
- },
29
-
30
- "gamepad:axis"(instance, event, { notify }) {
31
- const { id, axis, value } = event.payload
32
-
33
- if (instance.id !== `gamepad${id}`) {
34
- return
35
- }
36
-
37
- const action = instance.mapping[axis]
38
- instance[action] = value
39
- notify({ id: "input:axis", payload: { id, action, value } })
40
- },
41
-
42
- "gamepad:press"(instance, event, { notify }) {
43
- const { id, button } = event.payload
44
-
45
- if (instance.id !== `gamepad${id}`) {
46
- return
47
- }
48
-
49
- const action = instance.mapping[button]
50
- if (!instance[action]) {
51
- instance[action] = true
52
- notify({ id: "input:press", payload: { id, action } })
53
- }
54
- },
55
-
56
- "gamepad:release"(instance, event, { notify }) {
57
- const { id, button } = event.payload
58
-
59
- if (instance.id !== `gamepad${id}`) {
60
- return
61
- }
62
-
63
- const action = instance.mapping[button]
64
- if (instance[action]) {
65
- instance[action] = false
66
- notify({ id: "input:release", payload: { id, action } })
67
- }
68
- },
69
- }
70
- }
71
-
72
- export function createGamepad(name = DEFAULT_PARAMS.name, mapping = {}) {
73
- return { id: name, type: "gamepad", mapping }
74
- }
@@ -1,41 +0,0 @@
1
- const DEFAULT_PARAMS = {
2
- name: "input0",
3
- }
4
-
5
- export function enableInput() {
6
- return {
7
- "input:axis"(instance, event) {
8
- const { id, action, value } = event.payload
9
-
10
- if (!id.endsWith(instance.id)) {
11
- return
12
- }
13
-
14
- instance[action] = value
15
- },
16
-
17
- "input:press"(instance, event) {
18
- const { id, action } = event.payload
19
-
20
- if (!id.endsWith(instance.id)) {
21
- return
22
- }
23
-
24
- instance[action] = true
25
- },
26
-
27
- "input:release"(instance, event) {
28
- const { id, action } = event.payload
29
-
30
- if (!id.endsWith(instance.id)) {
31
- return
32
- }
33
-
34
- instance[action] = false
35
- },
36
- }
37
- }
38
-
39
- export function createInput(name = DEFAULT_PARAMS.name, mapping = {}) {
40
- return { id: name, type: "input", mapping }
41
- }
@@ -1,49 +0,0 @@
1
- const DEFAULT_PARAMS = {
2
- name: "keyboard0",
3
- }
4
-
5
- export function enableKeyboard() {
6
- let handleKeyDown, handleKeyUp
7
-
8
- return {
9
- "game:start"(instance, event, options) {
10
- handleKeyDown = createKeyboardHandler("keyboard:keyDown", options)
11
- handleKeyUp = createKeyboardHandler("keyboard:keyUp", options)
12
-
13
- document.addEventListener("keydown", handleKeyDown)
14
- document.addEventListener("keyup", handleKeyUp)
15
- },
16
-
17
- "game:stop"() {
18
- document.removeEventListener("keydown", handleKeyDown)
19
- document.removeEventListener("keyup", handleKeyUp)
20
- },
21
-
22
- "keyboard:keyDown"(instance, event, { notify }) {
23
- const action = instance.mapping[event.payload]
24
- if (!instance[action]) {
25
- instance[action] = true
26
- notify({ id: "input:press", payload: { id: instance.id, action } })
27
- }
28
- },
29
-
30
- "keyboard:keyUp"(instance, event, { notify }) {
31
- const action = instance.mapping[event.payload]
32
- if (instance[action]) {
33
- instance[action] = false
34
- notify({ id: "input:release", payload: { id: instance.id, action } })
35
- }
36
- },
37
- }
38
- }
39
-
40
- export function createKeyboard(name = DEFAULT_PARAMS.name, mapping = {}) {
41
- return { id: name, type: "keyboard", mapping }
42
- }
43
-
44
- function createKeyboardHandler(id, { notify }) {
45
- return (event) => {
46
- event.stopPropagation()
47
- notify({ id, payload: event.code })
48
- }
49
- }
@@ -1,65 +0,0 @@
1
- import { findCollision } from "@inglorious/engine/collision/detection.js"
2
- import { clampToBounds } from "@inglorious/game/bounds.js"
3
- import draw from "@inglorious/ui/canvas/mouse.js"
4
-
5
- const NO_Y = 0
6
-
7
- export function enableMouse() {
8
- return {
9
- draw,
10
-
11
- "mouse:move"(instance, event, { instances }) {
12
- instance.position = event.payload
13
-
14
- clampToBounds(instance, instances.game.bounds)
15
- },
16
-
17
- "mouse:click"(instance, event, options) {
18
- const { notify } = options
19
-
20
- const clickedInstance = findCollision(instance, options)
21
- if (clickedInstance) {
22
- notify({ id: "instance:click", payload: clickedInstance.id })
23
- } else {
24
- notify({ id: "scene:click", payload: event.payload })
25
- }
26
- },
27
- }
28
- }
29
-
30
- export function track(parent, options) {
31
- const handleMouseMove = createHandler("mouse:move", parent, options)
32
- const handleClick = createHandler("mouse:click", parent, options)
33
-
34
- return { onMouseMove: handleMouseMove, onClick: handleClick }
35
- }
36
-
37
- function createHandler(id, parent, { notify }) {
38
- return (event) => {
39
- event.stopPropagation()
40
-
41
- if (parent == null) {
42
- return
43
- }
44
-
45
- const payload = calculatePosition({
46
- clientX: event.clientX,
47
- clientY: event.clientY,
48
- parent,
49
- })
50
-
51
- notify({ id, payload })
52
- }
53
- }
54
-
55
- function calculatePosition({ clientX, clientY, parent }) {
56
- const bounds = parent.getBoundingClientRect()
57
-
58
- const scaleX = (parent.width || parent.clientWidth) / bounds.width
59
- const scaleY = (parent.height || parent.clientHeight) / bounds.height
60
-
61
- const x = (clientX - bounds.left) * scaleX
62
- const z = (bounds.bottom - clientY) * scaleY
63
-
64
- return [x, NO_Y, z]
65
- }
@@ -1,72 +0,0 @@
1
- import { collidesWith } from "@inglorious/engine/collision/detection.js"
2
- import { extend, merge } from "@inglorious/utils/data-structures/objects.js"
3
- import { applyGravity } from "@inglorious/utils/physics/gravity.js"
4
- import { jump } from "@inglorious/utils/physics/jump.js"
5
-
6
- import { enableFsm } from "./fsm.js"
7
-
8
- const DEFAULT_PARAMS = {
9
- onState: "default",
10
- onInput: "input0",
11
- maxSpeed: 250,
12
- maxJump: 100,
13
- maxLeap: 100,
14
- }
15
- const FALLING = 0
16
-
17
- export function enableJump(params) {
18
- params = extend(DEFAULT_PARAMS, params)
19
-
20
- const freeFall = createFreeFall(params)
21
-
22
- return enableFsm({
23
- [params.onState]: {
24
- "game:update"(instance, event, options) {
25
- freeFall(instance, event, options)
26
- },
27
-
28
- "input:press"(instance, event, options) {
29
- instance.onInput = instance.onInput ?? params.onInput
30
- instance.maxJump = instance.maxJump ?? params.maxJump
31
- instance.maxLeap = instance.maxLeap ?? params.maxLeap
32
- instance.maxSpeed = instance.maxSpeed ?? params.maxSpeed
33
-
34
- const { id, action } = event.payload
35
- if (id.endsWith(instance.onInput) && action === "jump") {
36
- instance.state = "jumping"
37
- merge(instance, jump(instance, options))
38
- }
39
- },
40
- },
41
-
42
- jumping: {
43
- "game:update"(instance, event, options) {
44
- freeFall(instance, event, options)
45
- },
46
- },
47
- })
48
- }
49
-
50
- function createFreeFall(params) {
51
- return (instance, event, options) => {
52
- instance.maxLeap = instance.maxLeap ?? params.maxLeap
53
-
54
- merge(instance, applyGravity(instance, options))
55
-
56
- const targets = Object.values(options.instances).filter(
57
- ({ type }) => type === "platform",
58
- )
59
-
60
- targets.forEach((target) => {
61
- if (instance.vy < FALLING && collidesWith(instance, target, "platform")) {
62
- instance.vy = 0
63
- const [x, , z] = instance.position
64
- const { radius } = instance.collisions.platform
65
- const [, targetY] = target.position
66
- const py = targetY + radius
67
- instance.position = [x, py, z]
68
- instance.state = params.onState
69
- }
70
- })
71
- }
72
- }
@@ -1,5 +0,0 @@
1
- import draw from "@inglorious/ui/canvas/shapes/rectangle.js"
2
-
3
- export function enablePlatform() {
4
- return { draw }
5
- }
@@ -1,21 +0,0 @@
1
- import draw from "@inglorious/ui/canvas/form/button.js"
2
-
3
- export function enableButton() {
4
- return {
5
- draw,
6
-
7
- states: {
8
- default: {
9
- "instance:click"(instance) {
10
- instance.state = "pressed"
11
- },
12
- },
13
-
14
- pressed: {
15
- "instance:release"(instance) {
16
- instance.state = "default"
17
- },
18
- },
19
- },
20
- }
21
- }
@@ -1,119 +0,0 @@
1
- /* eslint-disable no-magic-numbers */
2
- import { Animation } from "@inglorious/game/animation.js"
3
- import { mod } from "@inglorious/utils/math/numbers.js"
4
- import { pi, toRange } from "@inglorious/utils/math/trigonometry.js"
5
-
6
- const BEFORE = -1
7
- const AFTER = 1
8
-
9
- export const Sprite = {
10
- move2,
11
- move4,
12
- move6,
13
- move8,
14
- play,
15
- }
16
-
17
- function move2(instance) {
18
- const directions = 2
19
- const multiple = pi() / directions
20
- const theta = toRange(instance.orientation) / multiple
21
-
22
- if (theta > 0 + BEFORE && theta < 0 + AFTER) {
23
- return "right"
24
- } else if (theta < 0 + BEFORE || theta > 0 + AFTER) {
25
- return "left"
26
- }
27
-
28
- return instance.sprite.state ?? "right"
29
- }
30
-
31
- function move4(instance) {
32
- const directions = 4
33
- const multiple = pi() / directions
34
- const theta = toRange(instance.orientation) / multiple
35
-
36
- if (theta >= -2 + BEFORE && theta < -2 + AFTER) {
37
- return "down"
38
- } else if (theta >= 0 + BEFORE && theta < 0 + AFTER) {
39
- return "right"
40
- } else if (theta >= 2 + BEFORE && theta < 2 + AFTER) {
41
- return "up"
42
- } else if (theta < 0 + BEFORE || theta > 0 + AFTER) {
43
- return "left"
44
- }
45
-
46
- return instance.sprite.state ?? "down"
47
- }
48
-
49
- function move6(instance) {
50
- const directions = 6
51
- const multiple = pi() / directions
52
- const theta = toRange(instance.orientation) / multiple
53
-
54
- if (theta >= -6 + BEFORE && theta < -6 + AFTER) {
55
- return "leftDown"
56
- } else if (theta >= -4 + BEFORE && theta < -4 + AFTER) {
57
- return "down"
58
- } else if (theta >= -2 + BEFORE && theta < -2 + AFTER) {
59
- return "rightDown"
60
- } else if (theta >= 0 + BEFORE && theta < 0 + AFTER) {
61
- return "right"
62
- } else if (theta >= 2 + BEFORE && theta < 2 + AFTER) {
63
- return "rightUp"
64
- } else if (theta >= 4 + BEFORE && theta < 4 + AFTER) {
65
- return "up"
66
- } else if (theta >= 6 + BEFORE && theta < 6 + AFTER) {
67
- return "leftUp"
68
- } else if (theta < 0 + BEFORE || theta > 0 + AFTER) {
69
- return "left"
70
- }
71
-
72
- return instance.sprite.state ?? "down"
73
- }
74
-
75
- function move8(instance) {
76
- const directions = 8
77
- const multiple = pi() / directions
78
- const theta = toRange(instance.orientation) / multiple
79
-
80
- if (theta >= -6 + BEFORE && theta < -6 + AFTER) {
81
- return "leftDown"
82
- } else if (theta >= -4 + BEFORE && theta < -4 + AFTER) {
83
- return "down"
84
- } else if (theta >= -2 + BEFORE && theta < -2 + AFTER) {
85
- return "rightDown"
86
- } else if (theta >= 0 + BEFORE && theta < 0 + AFTER) {
87
- return "right"
88
- } else if (theta >= 2 + BEFORE && theta < 2 + AFTER) {
89
- return "rightUp"
90
- } else if (theta >= 4 + BEFORE && theta < 4 + AFTER) {
91
- return "up"
92
- } else if (theta >= 6 + BEFORE && theta < 6 + AFTER) {
93
- return "leftUp"
94
- } else if (theta < 0 + BEFORE || theta > 0 + AFTER) {
95
- return "left"
96
- }
97
-
98
- return instance.sprite.state ?? "down"
99
- }
100
-
101
- function play(spriteState, instance, options) {
102
- Animation.play("sprite", spriteState, instance, { ...options, onTick })
103
- }
104
-
105
- function onTick(instance, options) {
106
- const { notify } = options
107
-
108
- const { frames, state } = instance.sprite
109
-
110
- const framesLength = frames[state].length
111
-
112
- instance.sprite.value = mod(instance.sprite.value + 1, framesLength)
113
- if (instance.sprite.value === framesLength - 1) {
114
- notify({
115
- id: `sprite:animationEnd`,
116
- payload: { id: instance.id, spriteState: state },
117
- })
118
- }
119
- }
@@ -1,17 +0,0 @@
1
- import { snap, zero } from "@inglorious/utils/math/linear-algebra/vector.js"
2
-
3
- export function absolutePosition(draw) {
4
- return (ctx, instance, options = {}) => {
5
- const { position = zero() } = instance
6
- const { instances } = options
7
- const [, , , screenHeight] = instances.game.bounds
8
- const [x, y, z] = snap(position)
9
-
10
- ctx.save()
11
-
12
- ctx.translate(x, screenHeight - y - z)
13
- draw(ctx, instance, options)
14
-
15
- ctx.restore()
16
- }
17
- }
@@ -1,37 +0,0 @@
1
- import drawRectangle from "@inglorious/ui/canvas/shapes/rectangle.js"
2
- import { max } from "@inglorious/utils/data-structures/array.js"
3
-
4
- const NO_Y = 0
5
- const MAX_HUE = 255
6
-
7
- export default function draw(ctx, instance, options) {
8
- const { tileSize, columns, heights } = instance
9
-
10
- const [tileWidth, tileHeight] = tileSize
11
- const rows = Math.ceil(heights.length / columns)
12
- const height = rows * tileHeight
13
-
14
- const minH = 0
15
- const maxH = max(heights)
16
-
17
- heights.forEach((h, index) => {
18
- const x = (index % columns) * tileWidth
19
- const z = Math.floor(index / columns) * tileHeight - height
20
-
21
- ctx.save()
22
-
23
- const normalizedH = (h - minH) / (maxH - minH)
24
- const hue = MAX_HUE - normalizedH * MAX_HUE
25
-
26
- const instance = {
27
- offset: [x, NO_Y, z],
28
- size: [tileWidth, NO_Y, tileHeight],
29
- color: "transparent",
30
- backgroundColor: `hsla(${hue}, 100%, 50%, 0.2)`,
31
- }
32
-
33
- drawRectangle(ctx, instance, options)
34
-
35
- ctx.restore()
36
- })
37
- }
package/src/ui/canvas.js DELETED
@@ -1,81 +0,0 @@
1
- import Engine from "@inglorious/engine.js"
2
- import { track } from "@inglorious/game/decorators/input/mouse.js"
3
-
4
- import { absolutePosition } from "./canvas/absolute-position.js"
5
-
6
- const Y = 1
7
- const Z = 2
8
-
9
- export function start(config, canvas) {
10
- const ctx = canvas.getContext("2d")
11
- const engine = new Engine(config, { render: render(ctx) })
12
-
13
- const { game } = engine._store.getState().instances
14
- const [, , width, height] = game.bounds
15
-
16
- canvas.style.width = `${width}px`
17
- canvas.style.height = `${height}px`
18
- const dpi = window.devicePixelRatio
19
- canvas.width = Math.floor(width * dpi)
20
- canvas.height = Math.floor(height * dpi)
21
- ctx.scale(dpi, dpi)
22
-
23
- if (game.pixelated) {
24
- canvas.style.imageRendering = "pixelated"
25
- ctx.textRendering = "geometricPrecision"
26
- }
27
-
28
- document.addEventListener("keypress", (event) => {
29
- if (event.key === "p") {
30
- engine.isRunning ? engine.stop() : engine.start()
31
- }
32
- })
33
-
34
- const { onMouseMove, onClick } = track(canvas, {
35
- notify: engine.notify,
36
- })
37
-
38
- canvas.addEventListener("mousemove", onMouseMove)
39
- canvas.addEventListener("click", onClick)
40
-
41
- engine.start()
42
- }
43
-
44
- function render(ctx) {
45
- return (options) => {
46
- const { types, instances } = options
47
-
48
- const { game, mouse, ...rest } = instances
49
-
50
- const [x, y, width, height] = game.bounds
51
- ctx.fillStyle = "lightgrey"
52
- ctx.fillRect(x, y, width, height)
53
- if (game.pixelated) {
54
- ctx.imageSmoothingEnabled = false
55
- }
56
-
57
- Object.values(rest)
58
- .filter(({ position }) => position)
59
- .toSorted(
60
- (a, b) =>
61
- a.layer - b.layer ||
62
- a.position[Y] - b.position[Y] ||
63
- b.position[Z] - a.position[Z],
64
- )
65
- .forEach((instance) =>
66
- draw(ctx, instance, { ...options, type: types[instance.type] }),
67
- )
68
-
69
- if (mouse) {
70
- draw(ctx, mouse, { ...options, type: types[mouse.type] })
71
- }
72
- }
73
- }
74
-
75
- function draw(ctx, instance, options) {
76
- const draw = options.type.draw
77
-
78
- if (draw) {
79
- absolutePosition(draw)(ctx, instance, options)
80
- }
81
- }
@@ -1,30 +0,0 @@
1
- import { useDispatch } from "react-redux"
2
-
3
- import classes from "./character.module.scss"
4
-
5
- const DEFAULT_SIZE = 24
6
- const DEFAULT_ORIENTATION = 0
7
-
8
- export default function Character({ id, type, instance, className, style }) {
9
- const notify = useDispatch()
10
-
11
- const size = type.size ?? DEFAULT_SIZE
12
- const { orientation = DEFAULT_ORIENTATION } = instance
13
-
14
- const handleClick = (event) => {
15
- event.stopPropagation()
16
- notify({ id: "instance:click", payload: id })
17
- }
18
-
19
- return (
20
- <div
21
- className={`${classes.character} ${className}`}
22
- style={{
23
- ...style,
24
- "--size": `${size}px`,
25
- "--angle": `${-orientation}rad`,
26
- }}
27
- onClick={handleClick}
28
- />
29
- )
30
- }
@@ -1,42 +0,0 @@
1
- /**
2
- * Checks if a platform intersects with a circle in 3D space.
3
- * @param {Platform} platform - The platform to check.
4
- * @param {Circle} circle - The circle to check.
5
- * @returns {boolean} True if the platform intersects the circle, false otherwise.
6
- */
7
- export function intersectsCircle(platform, circle) {
8
- const [left, top, front] = platform.position
9
- const [extension, elevation, thickness] = platform.size
10
-
11
- const [x, y, z] = circle.position
12
-
13
- const lowestPoint = y - circle.radius
14
- const isAbove = lowestPoint <= top && lowestPoint >= top - elevation
15
-
16
- const isOverlappingX = x >= left && x <= left + extension
17
- const isOverlappingZ = z >= front && z <= front + thickness
18
-
19
- return isAbove && isOverlappingX && isOverlappingZ
20
- }
21
-
22
- /**
23
- * Determines whether platform intersects with a rectangle in 3D space.
24
- *
25
- * @param {Platform} platform - The platform defined by its position (top-left-front corner) and size (extension, elevation, thickness).
26
- * @param {Rectangle} rectangle - The rectangle defined by its position (top-left-front corner) and size (width, height, depth).
27
- * @returns {boolean} True if the platform intersects the rectangle, false otherwise.
28
- */
29
- export function intersectsRectangle(platform, rectangle) {
30
- const [left, top, front] = platform.position
31
- const [extension, elevation, thickness] = platform.size
32
-
33
- const [x, y, z] = rectangle.position
34
- const [width, , depth] = rectangle.size
35
-
36
- const isAbove = y >= top && y <= top + elevation
37
-
38
- const isOverlappingX = x + width >= left && x <= left + extension
39
- const isOverlappingZ = z + depth >= front && z <= front + thickness
40
-
41
- return isAbove && isOverlappingX && isOverlappingZ
42
- }