@inglorious/engine 0.1.1 → 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 (201) hide show
  1. package/README.md +39 -36
  2. package/package.json +10 -22
  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/engine/loop.js +0 -15
  157. package/src/engine/store.js +0 -174
  158. package/src/engine/store.test.js +0 -256
  159. package/src/engine.js +0 -74
  160. package/src/game/animation.js +0 -26
  161. package/src/game/bounds.js +0 -66
  162. package/src/game/decorators/character.js +0 -5
  163. package/src/game/decorators/clamp-to-bounds.js +0 -15
  164. package/src/game/decorators/controls/dynamic/modern.js +0 -48
  165. package/src/game/decorators/controls/dynamic/shooter.js +0 -47
  166. package/src/game/decorators/controls/dynamic/tank.js +0 -55
  167. package/src/game/decorators/controls/kinematic/modern.js +0 -49
  168. package/src/game/decorators/controls/kinematic/shooter.js +0 -45
  169. package/src/game/decorators/controls/kinematic/tank.js +0 -52
  170. package/src/game/decorators/debug/collisions.js +0 -32
  171. package/src/game/decorators/double-jump.js +0 -70
  172. package/src/game/decorators/fps.js +0 -30
  173. package/src/game/decorators/fsm.js +0 -27
  174. package/src/game/decorators/game.js +0 -11
  175. package/src/game/decorators/image/image.js +0 -5
  176. package/src/game/decorators/image/sprite.js +0 -5
  177. package/src/game/decorators/image/tilemap.js +0 -5
  178. package/src/game/decorators/input/controls.js +0 -27
  179. package/src/game/decorators/input/gamepad.js +0 -74
  180. package/src/game/decorators/input/input.js +0 -41
  181. package/src/game/decorators/input/keyboard.js +0 -49
  182. package/src/game/decorators/input/mouse.js +0 -65
  183. package/src/game/decorators/jump.js +0 -72
  184. package/src/game/decorators/platform.js +0 -5
  185. package/src/game/decorators/ui/button.js +0 -21
  186. package/src/game/sprite.js +0 -119
  187. package/src/ui/canvas/absolute-position.js +0 -17
  188. package/src/ui/canvas/image/hitmask.js +0 -37
  189. package/src/ui/canvas.js +0 -81
  190. package/src/ui/react/game/character/index.jsx +0 -30
  191. package/src/utils/math/geometry/platform.js +0 -42
  192. package/src/utils/math/geometry/platform.test.js +0 -133
  193. /package/src/{ui → renderers}/react/game/character/character.module.scss +0 -0
  194. /package/src/{ui → renderers}/react/game/cursor/cursor.module.scss +0 -0
  195. /package/src/{ui → renderers}/react/game/form/fields/field/field.module.scss +0 -0
  196. /package/src/{ui → renderers}/react/game/form/fields/fields.module.scss +0 -0
  197. /package/src/{ui → renderers}/react/game/form/form.module.scss +0 -0
  198. /package/src/{ui → renderers}/react/game/platform/platform.module.scss +0 -0
  199. /package/src/{ui → renderers}/react/game/scene/scene.module.scss +0 -0
  200. /package/src/{ui → renderers}/react/game/sprite/sprite.module.css +0 -0
  201. /package/src/{ui → renderers}/react/hocs/with-absolute-position/with-absolute-position.module.scss +0 -0
@@ -1,52 +0,0 @@
1
- import tankMove from "@inglorious/engine/movement/kinematic/tank.js"
2
- import { extend, merge } from "@inglorious/utils/data-structures/objects.js"
3
- import { zero } from "@inglorious/utils/math/linear-algebra/vector.js"
4
-
5
- const DEFAULT_PARAMS = {
6
- maxAngularSpeed: 10,
7
- maxSpeed: 250,
8
- }
9
- const X = 0
10
- const Z = 2
11
-
12
- export function enableTankControls(params) {
13
- params = extend(DEFAULT_PARAMS, params)
14
-
15
- return (type) =>
16
- extend(type, {
17
- "game:update"(instance, event, options) {
18
- instance.maxAngularSpeed =
19
- instance.maxAngularSpeed ?? params.maxAngularSpeed
20
- instance.maxSpeed = instance.maxSpeed ?? params.maxSpeed
21
-
22
- const { input0 } = options.instances
23
- instance.velocity = zero()
24
-
25
- if (input0.left) {
26
- instance.orientation += 0.1
27
- }
28
- if (input0.down) {
29
- instance.velocity[X] = -instance.maxSpeed
30
- }
31
- if (input0.right) {
32
- instance.orientation -= 0.1
33
- }
34
- if (input0.up) {
35
- instance.velocity[X] = instance.maxSpeed
36
- }
37
-
38
- if (input0.leftRight != null) {
39
- instance.orientation +=
40
- -input0.leftRight * instance.maxAngularSpeed * options.dt
41
- }
42
- if (input0.upDown != null) {
43
- instance.velocity[X] += -input0.upDown * instance.maxSpeed
44
- }
45
- if (input0.strafe != null) {
46
- instance.velocity[Z] += input0.strafe * instance.maxSpeed
47
- }
48
-
49
- merge(instance, tankMove(instance, options))
50
- },
51
- })
52
- }
@@ -1,32 +0,0 @@
1
- import drawHitmask from "@inglorious/ui/canvas/image/hitmask.js"
2
- import drawCircle from "@inglorious/ui/canvas/shapes/circle.js"
3
- import drawRectangle from "@inglorious/ui/canvas/shapes/rectangle.js"
4
- import { extend } from "@inglorious/utils/data-structures/objects.js"
5
-
6
- const Shape = {
7
- circle: drawCircle,
8
- rectangle: drawRectangle,
9
- hitmask: drawHitmask,
10
- }
11
-
12
- export function enableCollisionsDebug() {
13
- return (type) =>
14
- extend(type, {
15
- draw(ctx, instance, options) {
16
- type.draw(ctx, instance, options)
17
-
18
- if (!options.instances.game.debug) {
19
- return
20
- }
21
-
22
- ctx.save()
23
-
24
- Object.values(instance.collisions).forEach((collision) => {
25
- const draw = Shape[collision.shape]
26
- draw(ctx, { ...collision, color: "#00FF00" }, options)
27
- })
28
-
29
- ctx.restore()
30
- },
31
- })
32
- }
@@ -1,70 +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 enableDoubleJump(params) {
18
- params = extend(DEFAULT_PARAMS, params)
19
-
20
- const freeFall = createFreeFall(params)
21
-
22
- return enableFsm({
23
- jumping: {
24
- "input:press"(instance, event, options) {
25
- instance.onInput = instance.onInput ?? params.onInput
26
- instance.maxJump = instance.maxJump ?? params.maxJump
27
- instance.maxLeap = instance.maxLeap ?? params.maxLeap
28
- instance.maxSpeed = instance.maxSpeed ?? params.maxSpeed
29
-
30
- const { id, action } = event.payload
31
- if (id.endsWith(instance.onInput) && action === "jump") {
32
- instance.state = "doubleJumping"
33
- merge(instance, jump(instance, options))
34
- }
35
- },
36
- },
37
-
38
- doubleJumping: {
39
- "game:update"(instance, event, options) {
40
- freeFall(instance, event, options)
41
- },
42
- },
43
- })
44
- }
45
-
46
- // TODO: this is a copy-paste of jump.js. Can we reduce duplication?
47
- function createFreeFall(params) {
48
- return (instance, event, options) => {
49
- instance.maxLeap = instance.maxLeap ?? params.maxLeap
50
-
51
- merge(instance, applyGravity(instance, options))
52
-
53
- const { instances } = options
54
- const targets = Object.values(instances).filter(
55
- ({ type }) => type === "platform",
56
- )
57
-
58
- targets.forEach((target) => {
59
- if (instance.vy < FALLING && collidesWith(instance, target, "platform")) {
60
- instance.vy = 0
61
- const [x, , z] = instance.position
62
- const { radius } = instance.collisions.platform
63
- const [, targetY] = target.position
64
- const py = targetY + radius
65
- instance.position = [x, py, z]
66
- instance.state = params.onState
67
- }
68
- })
69
- }
70
- }
@@ -1,30 +0,0 @@
1
- import { Animation } from "@inglorious/game/animation.js"
2
- import draw from "@inglorious/ui/canvas/fps.js"
3
- import { extend } from "@inglorious/utils/data-structures/objects.js"
4
-
5
- const DEFAULT_PARAMS = {
6
- accuracy: 1,
7
- size: 16,
8
- speed: 1,
9
- defaultValue: 0.016666666666666666,
10
- }
11
-
12
- export function enableFps(params) {
13
- params = extend(DEFAULT_PARAMS, params)
14
-
15
- return {
16
- draw,
17
-
18
- "game:start"(instance) {
19
- instance.dt = instance.dt ?? params
20
- },
21
-
22
- "game:update"(instance, event, options) {
23
- Animation.play("dt", "default", instance, { ...options, onTick })
24
- },
25
- }
26
- }
27
-
28
- function onTick(instance, options) {
29
- instance.dt.value = options.dt
30
- }
@@ -1,27 +0,0 @@
1
- import { extend } from "@inglorious/utils/data-structures/objects.js"
2
-
3
- const DEFAULT_STATE = "default"
4
-
5
- export function enableFsm(states) {
6
- return (type) => {
7
- const uniqueEventNames = [
8
- ...new Set(Object.values(states).flatMap(Object.keys)),
9
- ]
10
-
11
- const newType = uniqueEventNames.reduce(
12
- (acc, eventName) => ({
13
- ...acc,
14
-
15
- [eventName](instance, event, options) {
16
- type[eventName]?.(instance, event, options)
17
-
18
- const state = states[instance.state ?? DEFAULT_STATE]
19
- state?.[eventName]?.(instance, event, options)
20
- },
21
- }),
22
- {},
23
- )
24
-
25
- return extend(type, newType)
26
- }
27
- }
@@ -1,11 +0,0 @@
1
- export function enableGame() {
2
- return {
3
- "keyboard:keyUp"(instance, event) {
4
- const code = event.payload
5
-
6
- if (code === "KeyC") {
7
- instance.debug = !instance.debug
8
- }
9
- },
10
- }
11
- }
@@ -1,5 +0,0 @@
1
- import draw from "@inglorious/ui/canvas/image/image.js"
2
-
3
- export function enableImage() {
4
- return { draw }
5
- }
@@ -1,5 +0,0 @@
1
- import draw from "@inglorious/ui/canvas/image/sprite.js"
2
-
3
- export function enableSprite() {
4
- return { draw }
5
- }
@@ -1,5 +0,0 @@
1
- import draw from "@inglorious/ui/canvas/image/tilemap.js"
2
-
3
- export function enableTilemap() {
4
- return { draw }
5
- }
@@ -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
- }