@inglorious/engine 0.2.0 → 0.3.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.
- package/README.md +75 -75
- package/package.json +13 -23
- package/src/{engine/ai → ai}/movement/dynamic/align.js +63 -63
- package/src/{engine/ai → ai}/movement/dynamic/arrive.js +42 -42
- package/src/{engine/ai → ai}/movement/dynamic/evade.js +38 -38
- package/src/{engine/ai → ai}/movement/dynamic/face.js +19 -19
- package/src/{engine/ai → ai}/movement/dynamic/flee.js +45 -45
- package/src/{engine/ai → ai}/movement/dynamic/look-where-youre-going.js +16 -16
- package/src/{engine/ai → ai}/movement/dynamic/match-velocity.js +51 -51
- package/src/{engine/ai → ai}/movement/dynamic/pursue.js +38 -38
- package/src/{engine/ai → ai}/movement/dynamic/seek.js +44 -44
- package/src/{engine/ai → ai}/movement/dynamic/wander.js +31 -31
- package/src/{engine/ai → ai}/movement/kinematic/align.js +37 -37
- package/src/{engine/ai → ai}/movement/kinematic/arrive.js +42 -42
- package/src/{engine/ai → ai}/movement/kinematic/face.js +19 -19
- package/src/{engine/ai → ai}/movement/kinematic/flee.js +26 -26
- package/src/{engine/ai → ai}/movement/kinematic/seek.js +26 -26
- package/src/{engine/ai → ai}/movement/kinematic/seek.test.js +42 -42
- package/src/{engine/ai → ai}/movement/kinematic/wander-as-seek.js +31 -31
- package/src/{engine/ai → ai}/movement/kinematic/wander.js +27 -27
- package/src/{engine/animation → animation}/sprite.js +101 -101
- package/src/{engine/animation → animation}/ticker.js +38 -38
- package/src/{engine/behaviors → behaviors}/camera.js +68 -68
- package/src/{engine/behaviors → behaviors}/controls/dynamic/modern.js +76 -76
- package/src/{engine/behaviors → behaviors}/controls/dynamic/shooter.js +84 -84
- package/src/{engine/behaviors → behaviors}/controls/dynamic/tank.js +69 -69
- package/src/{engine/behaviors → behaviors}/controls/event-handlers.js +17 -17
- package/src/{engine/behaviors → behaviors}/controls/kinematic/modern.js +76 -76
- package/src/{engine/behaviors → behaviors}/controls/kinematic/shooter.js +82 -82
- package/src/{engine/behaviors → behaviors}/controls/kinematic/tank.js +67 -67
- package/src/behaviors/debug/collision.js +29 -0
- package/src/{engine/behaviors → behaviors}/fps.js +29 -29
- package/src/{engine/behaviors → behaviors}/fsm.js +33 -33
- package/src/{engine/behaviors → behaviors}/fsm.test.js +49 -49
- package/src/{engine/behaviors → behaviors}/game.js +15 -15
- package/src/{engine/behaviors → behaviors}/input/controls.js +37 -37
- package/src/{engine/behaviors → behaviors}/input/gamepad.js +114 -114
- package/src/{engine/behaviors → behaviors}/input/input.js +48 -48
- package/src/{engine/behaviors → behaviors}/input/keyboard.js +64 -64
- package/src/{engine/behaviors → behaviors}/input/mouse.js +91 -91
- package/src/{engine/behaviors → behaviors}/physics/bouncy.js +25 -25
- package/src/{engine/behaviors → behaviors}/physics/clamped.js +36 -36
- package/src/{engine/behaviors → behaviors}/physics/collidable.js +20 -20
- package/src/{engine/behaviors → behaviors}/physics/jumpable.js +145 -145
- package/src/{engine/behaviors → behaviors}/ui/button.js +17 -17
- package/src/{engine/collision → collision}/detection.js +110 -110
- package/src/{engine/core → core}/api.js +34 -34
- package/src/{engine/core → core}/dev-tools.js +135 -135
- package/src/{engine/core → core}/engine.js +119 -119
- package/src/{engine/core → core}/loop.js +15 -15
- package/src/{engine/core → core}/loops/animation-frame.js +25 -25
- package/src/{engine/core → core}/loops/elapsed.js +22 -22
- package/src/{engine/core → core}/loops/fixed.js +27 -27
- package/src/{engine/core → core}/loops/flash.js +13 -13
- package/src/{engine/core → core}/loops/lag.js +26 -26
- package/src/{engine/core → core}/select.js +26 -26
- package/src/{engine/core → core}/store.js +178 -178
- package/src/{engine/core → core}/store.test.js +110 -110
- package/src/main.js +10 -10
- package/src/{engine/movement → movement}/dynamic/modern.js +21 -21
- package/src/{engine/movement → movement}/dynamic/tank.js +43 -43
- package/src/{engine/movement → movement}/kinematic/modern.js +16 -16
- package/src/{engine/movement → movement}/kinematic/modern.test.js +27 -27
- package/src/{engine/movement → movement}/kinematic/tank.js +27 -27
- package/src/{engine/physics → physics}/bounds.js +138 -138
- package/src/{engine/physics → physics}/position.js +43 -43
- package/src/{engine/physics → physics}/position.test.js +80 -80
- package/src/{engine/systems → systems}/sprite-animation.js +27 -27
- package/src/engine/behaviors/debug/collision.js +0 -35
- package/src/renderers/canvas/absolute-position.js +0 -18
- package/src/renderers/canvas/camera.js +0 -13
- package/src/renderers/canvas/canvas-renderer.js +0 -68
- package/src/renderers/canvas/character.js +0 -38
- package/src/renderers/canvas/form/button.js +0 -25
- package/src/renderers/canvas/fps.js +0 -18
- package/src/renderers/canvas/image/hitmask.js +0 -51
- package/src/renderers/canvas/image/image.js +0 -34
- package/src/renderers/canvas/image/sprite.js +0 -49
- package/src/renderers/canvas/image/tilemap.js +0 -66
- package/src/renderers/canvas/mouse.js +0 -37
- package/src/renderers/canvas/rendering-system.js +0 -79
- package/src/renderers/canvas/shapes/circle.js +0 -29
- package/src/renderers/canvas/shapes/rectangle.js +0 -27
- package/src/renderers/react/game/character/character.module.scss +0 -17
- package/src/renderers/react/game/character/index.jsx +0 -20
- package/src/renderers/react/game/cursor/cursor.module.scss +0 -47
- package/src/renderers/react/game/cursor/index.jsx +0 -20
- package/src/renderers/react/game/form/fields/field/field.module.scss +0 -5
- package/src/renderers/react/game/form/fields/field/index.jsx +0 -56
- package/src/renderers/react/game/form/fields/fields.module.scss +0 -48
- package/src/renderers/react/game/form/fields/index.jsx +0 -12
- package/src/renderers/react/game/form/form.module.scss +0 -18
- package/src/renderers/react/game/form/index.jsx +0 -22
- package/src/renderers/react/game/fps/index.jsx +0 -16
- package/src/renderers/react/game/game.jsx +0 -72
- package/src/renderers/react/game/index.jsx +0 -29
- package/src/renderers/react/game/platform/index.jsx +0 -30
- package/src/renderers/react/game/platform/platform.module.scss +0 -7
- package/src/renderers/react/game/scene/index.jsx +0 -27
- package/src/renderers/react/game/scene/scene.module.scss +0 -9
- package/src/renderers/react/game/sprite/index.jsx +0 -60
- package/src/renderers/react/game/sprite/sprite.module.css +0 -3
- package/src/renderers/react/game/stats/index.jsx +0 -22
- package/src/renderers/react/hocs/with-absolute-position/index.jsx +0 -20
- package/src/renderers/react/hocs/with-absolute-position/with-absolute-position.module.scss +0 -5
- package/src/renderers/react/index.jsx +0 -9
- package/src/utils/algorithms/decision-tree.js +0 -24
- package/src/utils/algorithms/decision-tree.test.js +0 -153
- package/src/utils/algorithms/path-finding.js +0 -155
- package/src/utils/algorithms/path-finding.test.js +0 -151
- package/src/utils/algorithms/types.d.ts +0 -28
- package/src/utils/data-structures/array.js +0 -83
- package/src/utils/data-structures/array.test.js +0 -173
- package/src/utils/data-structures/board.js +0 -159
- package/src/utils/data-structures/board.test.js +0 -242
- package/src/utils/data-structures/boolean.js +0 -9
- package/src/utils/data-structures/heap.js +0 -164
- package/src/utils/data-structures/heap.test.js +0 -103
- package/src/utils/data-structures/object.js +0 -138
- package/src/utils/data-structures/object.test.js +0 -218
- package/src/utils/data-structures/objects.js +0 -66
- package/src/utils/data-structures/objects.test.js +0 -99
- package/src/utils/data-structures/tree.js +0 -36
- package/src/utils/data-structures/tree.test.js +0 -33
- package/src/utils/data-structures/types.d.ts +0 -4
- package/src/utils/functions/functions.js +0 -19
- package/src/utils/functions/functions.test.js +0 -23
- package/src/utils/math/geometry/circle.js +0 -70
- package/src/utils/math/geometry/circle.test.js +0 -97
- package/src/utils/math/geometry/hitmask.js +0 -70
- package/src/utils/math/geometry/hitmask.test.js +0 -155
- package/src/utils/math/geometry/line.js +0 -35
- package/src/utils/math/geometry/line.test.js +0 -49
- package/src/utils/math/geometry/point.js +0 -78
- package/src/utils/math/geometry/point.test.js +0 -81
- package/src/utils/math/geometry/rectangle.js +0 -76
- package/src/utils/math/geometry/rectangle.test.js +0 -42
- package/src/utils/math/geometry/segment.js +0 -80
- package/src/utils/math/geometry/segment.test.js +0 -183
- package/src/utils/math/geometry/triangle.js +0 -15
- package/src/utils/math/geometry/triangle.test.js +0 -11
- package/src/utils/math/geometry/types.d.ts +0 -23
- package/src/utils/math/linear-algebra/2d.js +0 -28
- package/src/utils/math/linear-algebra/2d.test.js +0 -17
- package/src/utils/math/linear-algebra/quaternion.js +0 -22
- package/src/utils/math/linear-algebra/quaternion.test.js +0 -25
- package/src/utils/math/linear-algebra/quaternions.js +0 -20
- package/src/utils/math/linear-algebra/quaternions.test.js +0 -29
- package/src/utils/math/linear-algebra/types.d.ts +0 -4
- package/src/utils/math/linear-algebra/vector.js +0 -327
- package/src/utils/math/linear-algebra/vector.test.js +0 -265
- package/src/utils/math/linear-algebra/vectors.js +0 -122
- package/src/utils/math/linear-algebra/vectors.test.js +0 -65
- package/src/utils/math/linear-interpolation.js +0 -9
- package/src/utils/math/numbers.js +0 -90
- package/src/utils/math/numbers.test.js +0 -137
- package/src/utils/math/rng.js +0 -44
- package/src/utils/math/rng.test.js +0 -39
- package/src/utils/math/statistics.js +0 -43
- package/src/utils/math/statistics.test.js +0 -47
- package/src/utils/math/trigonometry.js +0 -89
- package/src/utils/math/trigonometry.test.js +0 -52
- package/src/utils/physics/acceleration.js +0 -61
- package/src/utils/physics/friction.js +0 -28
- package/src/utils/physics/friction.test.js +0 -42
- package/src/utils/physics/gravity.js +0 -69
- package/src/utils/physics/gravity.test.js +0 -77
- package/src/utils/physics/jump.js +0 -31
- package/src/utils/physics/velocity.js +0 -36
|
@@ -1,138 +1,138 @@
|
|
|
1
|
-
import {
|
|
2
|
-
angle,
|
|
3
|
-
clamp,
|
|
4
|
-
createVector,
|
|
5
|
-
fromAngle,
|
|
6
|
-
multiply,
|
|
7
|
-
zero,
|
|
8
|
-
} from "@inglorious/utils/math/linear-algebra/vector.js"
|
|
9
|
-
import { sum } from "@inglorious/utils/math/linear-algebra/vectors.js"
|
|
10
|
-
import { abs } from "@inglorious/utils/math/numbers.js"
|
|
11
|
-
|
|
12
|
-
const DOUBLE = 2
|
|
13
|
-
const HALF = 2
|
|
14
|
-
const X = 0
|
|
15
|
-
const Z = 2
|
|
16
|
-
|
|
17
|
-
export function bounce(entity, dt, [minX, minZ, maxX, maxZ]) {
|
|
18
|
-
const [x, , z] = entity.position
|
|
19
|
-
|
|
20
|
-
const velocity = createVector(entity.maxSpeed, entity.orientation)
|
|
21
|
-
if (x < minX || x >= maxX) {
|
|
22
|
-
velocity[X] = -velocity[X]
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (z < minZ || z >= maxZ) {
|
|
26
|
-
velocity[Z] = -velocity[Z]
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const position = sum(entity.position, multiply(velocity, dt))
|
|
30
|
-
const orientation = angle(velocity)
|
|
31
|
-
|
|
32
|
-
return { velocity, position, orientation }
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const ClampToBoundsByShape = {
|
|
36
|
-
rectangle(entity, [minX, minZ, maxX, maxZ], collisionGroup) {
|
|
37
|
-
const [width, height, depth] =
|
|
38
|
-
entity.collisions[collisionGroup].size ?? entity.size
|
|
39
|
-
|
|
40
|
-
const halfWidth = width / HALF
|
|
41
|
-
const halfHeight = height / HALF
|
|
42
|
-
const halfDepth = depth / HALF
|
|
43
|
-
|
|
44
|
-
return clamp(
|
|
45
|
-
entity.position,
|
|
46
|
-
[minX + halfWidth, minZ + halfHeight, minZ + halfDepth],
|
|
47
|
-
[maxX - halfWidth, maxZ - halfHeight, maxZ - halfDepth],
|
|
48
|
-
)
|
|
49
|
-
},
|
|
50
|
-
|
|
51
|
-
circle(entity, [minX, minY, maxX, maxY], collisionGroup, depthAxis = "y") {
|
|
52
|
-
const radius = entity.collisions[collisionGroup].radius ?? entity.radius
|
|
53
|
-
|
|
54
|
-
if (depthAxis === "z") {
|
|
55
|
-
return clamp(
|
|
56
|
-
entity.position,
|
|
57
|
-
[minX + radius, minY + radius, minY],
|
|
58
|
-
[maxX - radius, maxY - radius, maxY],
|
|
59
|
-
)
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
return clamp(
|
|
63
|
-
entity.position,
|
|
64
|
-
[minX + radius, minY, minY + radius],
|
|
65
|
-
[maxX - radius, maxY, maxY - radius],
|
|
66
|
-
)
|
|
67
|
-
},
|
|
68
|
-
|
|
69
|
-
point(entity, [minX, minZ, maxX, maxZ]) {
|
|
70
|
-
return clamp(entity.position, [minX, minZ, minZ], [maxX, maxZ, maxZ])
|
|
71
|
-
},
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export function clampToBounds(
|
|
75
|
-
entity,
|
|
76
|
-
bounds,
|
|
77
|
-
collisionGroup = "bounds",
|
|
78
|
-
depthAxis,
|
|
79
|
-
) {
|
|
80
|
-
const shape = entity.collisions[collisionGroup].shape || "rectangle"
|
|
81
|
-
const handler = ClampToBoundsByShape[shape] || ClampToBoundsByShape.point
|
|
82
|
-
return handler(entity, bounds, collisionGroup, depthAxis)
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export function flip(entity, [minX, minZ, maxX, maxZ]) {
|
|
86
|
-
const [x, , z] = entity.position
|
|
87
|
-
|
|
88
|
-
entity.collisions ??= {}
|
|
89
|
-
entity.collisions.bounds ??= {}
|
|
90
|
-
entity.collisions.bounds.shape ??= "rectangle"
|
|
91
|
-
|
|
92
|
-
let width, height, depth
|
|
93
|
-
if (entity.collisions.bounds.shape === "circle") {
|
|
94
|
-
width = entity.collisions.bounds.radius * DOUBLE
|
|
95
|
-
height = entity.collisions.bounds.radius * DOUBLE
|
|
96
|
-
depth = entity.collisions.bounds.radius * DOUBLE
|
|
97
|
-
} else {
|
|
98
|
-
;[width, height, depth] = entity.collisions.bounds.size ?? entity.size
|
|
99
|
-
}
|
|
100
|
-
const halfWidth = width / HALF
|
|
101
|
-
const halfHeight = height / HALF
|
|
102
|
-
const halfDepth = depth / HALF
|
|
103
|
-
|
|
104
|
-
const left = x - halfWidth
|
|
105
|
-
const right = x + halfWidth
|
|
106
|
-
const bottom = z - halfHeight
|
|
107
|
-
const top = z + halfHeight
|
|
108
|
-
const back = z - halfDepth
|
|
109
|
-
const front = z + halfDepth
|
|
110
|
-
|
|
111
|
-
const direction = fromAngle(entity.orientation)
|
|
112
|
-
|
|
113
|
-
if (
|
|
114
|
-
left < minX ||
|
|
115
|
-
right >= maxX ||
|
|
116
|
-
bottom < minZ ||
|
|
117
|
-
top >= maxZ ||
|
|
118
|
-
back < minZ ||
|
|
119
|
-
front >= maxZ
|
|
120
|
-
) {
|
|
121
|
-
if (left < minX) {
|
|
122
|
-
direction[X] = abs(direction[X])
|
|
123
|
-
} else if (right >= maxX) {
|
|
124
|
-
direction[X] = -abs(direction[X])
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
if (back < minZ) {
|
|
128
|
-
direction[Z] = abs(direction[Z])
|
|
129
|
-
} else if (front >= maxZ) {
|
|
130
|
-
direction[Z] = -abs(direction[Z])
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
entity.acceleration = zero()
|
|
134
|
-
entity.velocity = zero()
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
entity.orientation = angle(direction)
|
|
138
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
angle,
|
|
3
|
+
clamp,
|
|
4
|
+
createVector,
|
|
5
|
+
fromAngle,
|
|
6
|
+
multiply,
|
|
7
|
+
zero,
|
|
8
|
+
} from "@inglorious/utils/math/linear-algebra/vector.js"
|
|
9
|
+
import { sum } from "@inglorious/utils/math/linear-algebra/vectors.js"
|
|
10
|
+
import { abs } from "@inglorious/utils/math/numbers.js"
|
|
11
|
+
|
|
12
|
+
const DOUBLE = 2
|
|
13
|
+
const HALF = 2
|
|
14
|
+
const X = 0
|
|
15
|
+
const Z = 2
|
|
16
|
+
|
|
17
|
+
export function bounce(entity, dt, [minX, minZ, maxX, maxZ]) {
|
|
18
|
+
const [x, , z] = entity.position
|
|
19
|
+
|
|
20
|
+
const velocity = createVector(entity.maxSpeed, entity.orientation)
|
|
21
|
+
if (x < minX || x >= maxX) {
|
|
22
|
+
velocity[X] = -velocity[X]
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (z < minZ || z >= maxZ) {
|
|
26
|
+
velocity[Z] = -velocity[Z]
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const position = sum(entity.position, multiply(velocity, dt))
|
|
30
|
+
const orientation = angle(velocity)
|
|
31
|
+
|
|
32
|
+
return { velocity, position, orientation }
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const ClampToBoundsByShape = {
|
|
36
|
+
rectangle(entity, [minX, minZ, maxX, maxZ], collisionGroup) {
|
|
37
|
+
const [width, height, depth] =
|
|
38
|
+
entity.collisions[collisionGroup].size ?? entity.size
|
|
39
|
+
|
|
40
|
+
const halfWidth = width / HALF
|
|
41
|
+
const halfHeight = height / HALF
|
|
42
|
+
const halfDepth = depth / HALF
|
|
43
|
+
|
|
44
|
+
return clamp(
|
|
45
|
+
entity.position,
|
|
46
|
+
[minX + halfWidth, minZ + halfHeight, minZ + halfDepth],
|
|
47
|
+
[maxX - halfWidth, maxZ - halfHeight, maxZ - halfDepth],
|
|
48
|
+
)
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
circle(entity, [minX, minY, maxX, maxY], collisionGroup, depthAxis = "y") {
|
|
52
|
+
const radius = entity.collisions[collisionGroup].radius ?? entity.radius
|
|
53
|
+
|
|
54
|
+
if (depthAxis === "z") {
|
|
55
|
+
return clamp(
|
|
56
|
+
entity.position,
|
|
57
|
+
[minX + radius, minY + radius, minY],
|
|
58
|
+
[maxX - radius, maxY - radius, maxY],
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return clamp(
|
|
63
|
+
entity.position,
|
|
64
|
+
[minX + radius, minY, minY + radius],
|
|
65
|
+
[maxX - radius, maxY, maxY - radius],
|
|
66
|
+
)
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
point(entity, [minX, minZ, maxX, maxZ]) {
|
|
70
|
+
return clamp(entity.position, [minX, minZ, minZ], [maxX, maxZ, maxZ])
|
|
71
|
+
},
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function clampToBounds(
|
|
75
|
+
entity,
|
|
76
|
+
bounds,
|
|
77
|
+
collisionGroup = "bounds",
|
|
78
|
+
depthAxis,
|
|
79
|
+
) {
|
|
80
|
+
const shape = entity.collisions[collisionGroup].shape || "rectangle"
|
|
81
|
+
const handler = ClampToBoundsByShape[shape] || ClampToBoundsByShape.point
|
|
82
|
+
return handler(entity, bounds, collisionGroup, depthAxis)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function flip(entity, [minX, minZ, maxX, maxZ]) {
|
|
86
|
+
const [x, , z] = entity.position
|
|
87
|
+
|
|
88
|
+
entity.collisions ??= {}
|
|
89
|
+
entity.collisions.bounds ??= {}
|
|
90
|
+
entity.collisions.bounds.shape ??= "rectangle"
|
|
91
|
+
|
|
92
|
+
let width, height, depth
|
|
93
|
+
if (entity.collisions.bounds.shape === "circle") {
|
|
94
|
+
width = entity.collisions.bounds.radius * DOUBLE
|
|
95
|
+
height = entity.collisions.bounds.radius * DOUBLE
|
|
96
|
+
depth = entity.collisions.bounds.radius * DOUBLE
|
|
97
|
+
} else {
|
|
98
|
+
;[width, height, depth] = entity.collisions.bounds.size ?? entity.size
|
|
99
|
+
}
|
|
100
|
+
const halfWidth = width / HALF
|
|
101
|
+
const halfHeight = height / HALF
|
|
102
|
+
const halfDepth = depth / HALF
|
|
103
|
+
|
|
104
|
+
const left = x - halfWidth
|
|
105
|
+
const right = x + halfWidth
|
|
106
|
+
const bottom = z - halfHeight
|
|
107
|
+
const top = z + halfHeight
|
|
108
|
+
const back = z - halfDepth
|
|
109
|
+
const front = z + halfDepth
|
|
110
|
+
|
|
111
|
+
const direction = fromAngle(entity.orientation)
|
|
112
|
+
|
|
113
|
+
if (
|
|
114
|
+
left < minX ||
|
|
115
|
+
right >= maxX ||
|
|
116
|
+
bottom < minZ ||
|
|
117
|
+
top >= maxZ ||
|
|
118
|
+
back < minZ ||
|
|
119
|
+
front >= maxZ
|
|
120
|
+
) {
|
|
121
|
+
if (left < minX) {
|
|
122
|
+
direction[X] = abs(direction[X])
|
|
123
|
+
} else if (right >= maxX) {
|
|
124
|
+
direction[X] = -abs(direction[X])
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (back < minZ) {
|
|
128
|
+
direction[Z] = abs(direction[Z])
|
|
129
|
+
} else if (front >= maxZ) {
|
|
130
|
+
direction[Z] = -abs(direction[Z])
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
entity.acceleration = zero()
|
|
134
|
+
entity.velocity = zero()
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
entity.orientation = angle(direction)
|
|
138
|
+
}
|
|
@@ -1,43 +1,43 @@
|
|
|
1
|
-
const HALF = 2
|
|
2
|
-
|
|
3
|
-
export function calculateLandingPosition(
|
|
4
|
-
entity,
|
|
5
|
-
target,
|
|
6
|
-
collisionGroup = "platform",
|
|
7
|
-
) {
|
|
8
|
-
const entityShape = entity.collisions[collisionGroup]?.shape
|
|
9
|
-
|
|
10
|
-
if (CalculatePY[entityShape]) {
|
|
11
|
-
return CalculatePY[entityShape](entity, target, collisionGroup)
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
return calculatePYForPoint(entity, target, collisionGroup)
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function calculatePYForPoint(entity, target, collisionGroup) {
|
|
18
|
-
const [, targetY] = target.position
|
|
19
|
-
const [, targetHeight] = target.collisions[collisionGroup].size ?? target.size
|
|
20
|
-
return targetY + targetHeight / HALF
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function calculatePYForCircle(entity, target, collisionGroup) {
|
|
24
|
-
const entityRadius = entity.collisions[collisionGroup].radius ?? entity.radius
|
|
25
|
-
|
|
26
|
-
const [, targetY] = target.position
|
|
27
|
-
const [, targetHeight] = target.collisions[collisionGroup].size ?? target.size
|
|
28
|
-
return targetY + targetHeight / HALF + entityRadius
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function calculatePYForRectangle(entity, target, collisionGroup) {
|
|
32
|
-
const [, entityHeight] = entity.collisions[collisionGroup].size ?? entity.size
|
|
33
|
-
|
|
34
|
-
const [, targetY] = target.position
|
|
35
|
-
const [, targetHeight] = target.collisions[collisionGroup].size ?? target.size
|
|
36
|
-
return targetY + targetHeight / HALF + entityHeight / HALF
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const CalculatePY = {
|
|
40
|
-
point: calculatePYForPoint,
|
|
41
|
-
circle: calculatePYForCircle,
|
|
42
|
-
rectangle: calculatePYForRectangle,
|
|
43
|
-
}
|
|
1
|
+
const HALF = 2
|
|
2
|
+
|
|
3
|
+
export function calculateLandingPosition(
|
|
4
|
+
entity,
|
|
5
|
+
target,
|
|
6
|
+
collisionGroup = "platform",
|
|
7
|
+
) {
|
|
8
|
+
const entityShape = entity.collisions[collisionGroup]?.shape
|
|
9
|
+
|
|
10
|
+
if (CalculatePY[entityShape]) {
|
|
11
|
+
return CalculatePY[entityShape](entity, target, collisionGroup)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return calculatePYForPoint(entity, target, collisionGroup)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function calculatePYForPoint(entity, target, collisionGroup) {
|
|
18
|
+
const [, targetY] = target.position
|
|
19
|
+
const [, targetHeight] = target.collisions[collisionGroup].size ?? target.size
|
|
20
|
+
return targetY + targetHeight / HALF
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function calculatePYForCircle(entity, target, collisionGroup) {
|
|
24
|
+
const entityRadius = entity.collisions[collisionGroup].radius ?? entity.radius
|
|
25
|
+
|
|
26
|
+
const [, targetY] = target.position
|
|
27
|
+
const [, targetHeight] = target.collisions[collisionGroup].size ?? target.size
|
|
28
|
+
return targetY + targetHeight / HALF + entityRadius
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function calculatePYForRectangle(entity, target, collisionGroup) {
|
|
32
|
+
const [, entityHeight] = entity.collisions[collisionGroup].size ?? entity.size
|
|
33
|
+
|
|
34
|
+
const [, targetY] = target.position
|
|
35
|
+
const [, targetHeight] = target.collisions[collisionGroup].size ?? target.size
|
|
36
|
+
return targetY + targetHeight / HALF + entityHeight / HALF
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const CalculatePY = {
|
|
40
|
+
point: calculatePYForPoint,
|
|
41
|
+
circle: calculatePYForCircle,
|
|
42
|
+
rectangle: calculatePYForRectangle,
|
|
43
|
+
}
|
|
@@ -1,80 +1,80 @@
|
|
|
1
|
-
import { expect, test } from "vitest"
|
|
2
|
-
|
|
3
|
-
import { calculateLandingPosition } from "./position.js"
|
|
4
|
-
|
|
5
|
-
test("it should calculate the landing position for a point entity on a platform", () => {
|
|
6
|
-
const entity = {
|
|
7
|
-
collisions: {
|
|
8
|
-
platform: { shape: "point" },
|
|
9
|
-
},
|
|
10
|
-
}
|
|
11
|
-
const target = {
|
|
12
|
-
position: [0, 0, 0],
|
|
13
|
-
collisions: {
|
|
14
|
-
platform: { size: [20, 10, 0] },
|
|
15
|
-
},
|
|
16
|
-
}
|
|
17
|
-
const collisionGroup = "platform"
|
|
18
|
-
|
|
19
|
-
const py = calculateLandingPosition(entity, target, collisionGroup)
|
|
20
|
-
|
|
21
|
-
expect(py).toBe(5)
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
test("it should calculate the landing position for a circular entity on a platform", () => {
|
|
25
|
-
const entity = {
|
|
26
|
-
collisions: {
|
|
27
|
-
platform: { shape: "circle", radius: 5 },
|
|
28
|
-
},
|
|
29
|
-
}
|
|
30
|
-
const target = {
|
|
31
|
-
position: [0, 0, 0],
|
|
32
|
-
collisions: {
|
|
33
|
-
platform: { size: [20, 10, 0] },
|
|
34
|
-
},
|
|
35
|
-
}
|
|
36
|
-
const collisionGroup = "platform"
|
|
37
|
-
|
|
38
|
-
const py = calculateLandingPosition(entity, target, collisionGroup)
|
|
39
|
-
|
|
40
|
-
expect(py).toBe(10)
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
test("it should calculate the landing position for a rectangular entity on a platform", () => {
|
|
44
|
-
const entity = {
|
|
45
|
-
size: [10, 10, 0],
|
|
46
|
-
collisions: {
|
|
47
|
-
platform: { shape: "rectangle" },
|
|
48
|
-
},
|
|
49
|
-
}
|
|
50
|
-
const target = {
|
|
51
|
-
position: [0, 0, 0],
|
|
52
|
-
collisions: {
|
|
53
|
-
platform: { size: [20, 10, 0] },
|
|
54
|
-
},
|
|
55
|
-
}
|
|
56
|
-
const collisionGroup = "platform"
|
|
57
|
-
|
|
58
|
-
const py = calculateLandingPosition(entity, target, collisionGroup)
|
|
59
|
-
|
|
60
|
-
expect(py).toBe(10)
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
test("it should fallback to a rectangular calculation for an unknown entity shape", () => {
|
|
64
|
-
const entity = {
|
|
65
|
-
collisions: {
|
|
66
|
-
platform: { shape: "triangle" },
|
|
67
|
-
},
|
|
68
|
-
}
|
|
69
|
-
const target = {
|
|
70
|
-
position: [0, 0, 0],
|
|
71
|
-
collisions: {
|
|
72
|
-
platform: { size: [20, 10, 0] },
|
|
73
|
-
},
|
|
74
|
-
}
|
|
75
|
-
const collisionGroup = "platform"
|
|
76
|
-
|
|
77
|
-
const py = calculateLandingPosition(entity, target, collisionGroup)
|
|
78
|
-
|
|
79
|
-
expect(py).toBe(5)
|
|
80
|
-
})
|
|
1
|
+
import { expect, test } from "vitest"
|
|
2
|
+
|
|
3
|
+
import { calculateLandingPosition } from "./position.js"
|
|
4
|
+
|
|
5
|
+
test("it should calculate the landing position for a point entity on a platform", () => {
|
|
6
|
+
const entity = {
|
|
7
|
+
collisions: {
|
|
8
|
+
platform: { shape: "point" },
|
|
9
|
+
},
|
|
10
|
+
}
|
|
11
|
+
const target = {
|
|
12
|
+
position: [0, 0, 0],
|
|
13
|
+
collisions: {
|
|
14
|
+
platform: { size: [20, 10, 0] },
|
|
15
|
+
},
|
|
16
|
+
}
|
|
17
|
+
const collisionGroup = "platform"
|
|
18
|
+
|
|
19
|
+
const py = calculateLandingPosition(entity, target, collisionGroup)
|
|
20
|
+
|
|
21
|
+
expect(py).toBe(5)
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
test("it should calculate the landing position for a circular entity on a platform", () => {
|
|
25
|
+
const entity = {
|
|
26
|
+
collisions: {
|
|
27
|
+
platform: { shape: "circle", radius: 5 },
|
|
28
|
+
},
|
|
29
|
+
}
|
|
30
|
+
const target = {
|
|
31
|
+
position: [0, 0, 0],
|
|
32
|
+
collisions: {
|
|
33
|
+
platform: { size: [20, 10, 0] },
|
|
34
|
+
},
|
|
35
|
+
}
|
|
36
|
+
const collisionGroup = "platform"
|
|
37
|
+
|
|
38
|
+
const py = calculateLandingPosition(entity, target, collisionGroup)
|
|
39
|
+
|
|
40
|
+
expect(py).toBe(10)
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
test("it should calculate the landing position for a rectangular entity on a platform", () => {
|
|
44
|
+
const entity = {
|
|
45
|
+
size: [10, 10, 0],
|
|
46
|
+
collisions: {
|
|
47
|
+
platform: { shape: "rectangle" },
|
|
48
|
+
},
|
|
49
|
+
}
|
|
50
|
+
const target = {
|
|
51
|
+
position: [0, 0, 0],
|
|
52
|
+
collisions: {
|
|
53
|
+
platform: { size: [20, 10, 0] },
|
|
54
|
+
},
|
|
55
|
+
}
|
|
56
|
+
const collisionGroup = "platform"
|
|
57
|
+
|
|
58
|
+
const py = calculateLandingPosition(entity, target, collisionGroup)
|
|
59
|
+
|
|
60
|
+
expect(py).toBe(10)
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
test("it should fallback to a rectangular calculation for an unknown entity shape", () => {
|
|
64
|
+
const entity = {
|
|
65
|
+
collisions: {
|
|
66
|
+
platform: { shape: "triangle" },
|
|
67
|
+
},
|
|
68
|
+
}
|
|
69
|
+
const target = {
|
|
70
|
+
position: [0, 0, 0],
|
|
71
|
+
collisions: {
|
|
72
|
+
platform: { size: [20, 10, 0] },
|
|
73
|
+
},
|
|
74
|
+
}
|
|
75
|
+
const collisionGroup = "platform"
|
|
76
|
+
|
|
77
|
+
const py = calculateLandingPosition(entity, target, collisionGroup)
|
|
78
|
+
|
|
79
|
+
expect(py).toBe(5)
|
|
80
|
+
})
|
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
import { Sprite } from "@inglorious/engine/animation/sprite.js"
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Advances sprite animations for entities that have a sprite component
|
|
5
|
-
* with an active animation state.
|
|
6
|
-
*
|
|
7
|
-
* @param {Object} state - The game state, containing all entities.
|
|
8
|
-
* @param {Object<string, Object>} state.entities - A map of entity IDs to entity objects.
|
|
9
|
-
* @param {number} dt - The delta time since the last update.
|
|
10
|
-
* @param {Object} api - The game API.
|
|
11
|
-
* @param {Function} api.notify - A function to notify about events.
|
|
12
|
-
*/
|
|
13
|
-
export function spriteAnimationSystem() {
|
|
14
|
-
return {
|
|
15
|
-
update(state, dt, api) {
|
|
16
|
-
for (const id in state.entities) {
|
|
17
|
-
const entity = state.entities[id]
|
|
18
|
-
|
|
19
|
-
if (!entity.sprite || !entity.sprite.state) {
|
|
20
|
-
continue
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
Sprite.play(entity.sprite.state, { entity, dt, notify: api.notify })
|
|
24
|
-
}
|
|
25
|
-
},
|
|
26
|
-
}
|
|
27
|
-
}
|
|
1
|
+
import { Sprite } from "@inglorious/engine/animation/sprite.js"
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Advances sprite animations for entities that have a sprite component
|
|
5
|
+
* with an active animation state.
|
|
6
|
+
*
|
|
7
|
+
* @param {Object} state - The game state, containing all entities.
|
|
8
|
+
* @param {Object<string, Object>} state.entities - A map of entity IDs to entity objects.
|
|
9
|
+
* @param {number} dt - The delta time since the last update.
|
|
10
|
+
* @param {Object} api - The game API.
|
|
11
|
+
* @param {Function} api.notify - A function to notify about events.
|
|
12
|
+
*/
|
|
13
|
+
export function spriteAnimationSystem() {
|
|
14
|
+
return {
|
|
15
|
+
update(state, dt, api) {
|
|
16
|
+
for (const id in state.entities) {
|
|
17
|
+
const entity = state.entities[id]
|
|
18
|
+
|
|
19
|
+
if (!entity.sprite || !entity.sprite.state) {
|
|
20
|
+
continue
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
Sprite.play(entity.sprite.state, { entity, dt, notify: api.notify })
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { renderHitmask } from "@inglorious/renderers/canvas/image/hitmask.js"
|
|
2
|
-
import { renderCircle } from "@inglorious/renderers/canvas/shapes/circle.js"
|
|
3
|
-
import { renderRectangle } from "@inglorious/renderers/canvas/shapes/rectangle.js"
|
|
4
|
-
import { extend } from "@inglorious/utils/data-structures/objects.js"
|
|
5
|
-
|
|
6
|
-
const Shape = {
|
|
7
|
-
circle: renderCircle,
|
|
8
|
-
rectangle: renderRectangle,
|
|
9
|
-
platform: renderRectangle,
|
|
10
|
-
hitmask: renderHitmask,
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export function collisionGizmos() {
|
|
14
|
-
return (type) =>
|
|
15
|
-
extend(type, {
|
|
16
|
-
render(entity, ctx, api) {
|
|
17
|
-
type.render(entity, ctx, api)
|
|
18
|
-
|
|
19
|
-
const game = api.getEntity("game")
|
|
20
|
-
|
|
21
|
-
if (!game.debug) {
|
|
22
|
-
return
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
ctx.save()
|
|
26
|
-
|
|
27
|
-
Object.values(entity.collisions).forEach((collision) => {
|
|
28
|
-
const render = Shape[collision.shape]
|
|
29
|
-
render({ ...entity, ...collision, color: "#00FF00" }, ctx, api)
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
ctx.restore()
|
|
33
|
-
},
|
|
34
|
-
})
|
|
35
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { snap, zero } from "@inglorious/utils/math/linear-algebra/vector.js"
|
|
2
|
-
|
|
3
|
-
export function absolutePosition(render) {
|
|
4
|
-
return (entity, ctx, { api }) => {
|
|
5
|
-
const { position = zero() } = entity
|
|
6
|
-
const [x, y, z] = snap(position)
|
|
7
|
-
|
|
8
|
-
const game = api.getEntity("game")
|
|
9
|
-
const [, , , screenHeight] = game.bounds
|
|
10
|
-
|
|
11
|
-
ctx.save()
|
|
12
|
-
|
|
13
|
-
ctx.translate(x, screenHeight - y - z)
|
|
14
|
-
render(entity, ctx, api)
|
|
15
|
-
|
|
16
|
-
ctx.restore()
|
|
17
|
-
}
|
|
18
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { renderRectangle } from "./shapes/rectangle.js"
|
|
2
|
-
|
|
3
|
-
export function renderCamera(entity, ctx, api) {
|
|
4
|
-
const { devMode } = api.getEntity("game")
|
|
5
|
-
|
|
6
|
-
if (devMode) {
|
|
7
|
-
// In dev mode, we want to see the camera's viewport.
|
|
8
|
-
// We can reuse the rectangle renderer.
|
|
9
|
-
renderRectangle(entity, ctx)
|
|
10
|
-
}
|
|
11
|
-
// In non-dev mode, the camera itself is not rendered;
|
|
12
|
-
// its properties are used by the main CanvasRenderer to transform the scene.
|
|
13
|
-
}
|