@inglorious/engine 2.1.0 → 2.1.1
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 +1 -1
- package/package.json +5 -5
- package/src/behaviors/input/mouse.js +12 -42
- package/src/behaviors/input/touch.js +66 -72
package/README.md
CHANGED
|
@@ -80,7 +80,7 @@ Here is a complete example showing how to set up and run a game using the engine
|
|
|
80
80
|
<script type="importmap">
|
|
81
81
|
{
|
|
82
82
|
"imports": {
|
|
83
|
-
"
|
|
83
|
+
"mutative": "https://unpkg.com/mutative@latest/dist/mutative.esm.mjs",
|
|
84
84
|
"@inglorious/utils/": "https://unpkg.com/@inglorious%2Futils@latest/src/",
|
|
85
85
|
"@inglorious/store/": "https://unpkg.com/@inglorious%2Fstore@latest/src/",
|
|
86
86
|
"@inglorious/engine/": "https://unpkg.com/@inglorious%2Fengine@latest/src/",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inglorious/engine",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.1",
|
|
4
4
|
"description": "A JavaScript game engine written with global state, immutability, and pure functions in mind. Have fun(ctional programming) with it!",
|
|
5
5
|
"author": "IceOnFire <antony.mistretta@gmail.com> (https://ingloriouscoderz.it)",
|
|
6
6
|
"license": "MIT",
|
|
@@ -30,12 +30,12 @@
|
|
|
30
30
|
"access": "public"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@inglorious/store": "4.0.
|
|
34
|
-
"@inglorious/utils": "3.5.
|
|
33
|
+
"@inglorious/store": "4.0.3",
|
|
34
|
+
"@inglorious/utils": "3.5.1"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
|
-
"@inglorious/store": "4.0.
|
|
38
|
-
"@inglorious/utils": "3.5.
|
|
37
|
+
"@inglorious/store": "4.0.3",
|
|
38
|
+
"@inglorious/utils": "3.5.1"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"prettier": "^3.5.3",
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import { findCollision } from "@inglorious/engine/collision/detection.js"
|
|
2
2
|
import { clampToBounds } from "@inglorious/engine/physics/bounds.js"
|
|
3
3
|
import { zero } from "@inglorious/utils/math/vector.js"
|
|
4
|
-
import { v } from "@inglorious/utils/v.js"
|
|
5
|
-
|
|
6
|
-
const NO_Y = 0
|
|
7
|
-
const HALF = 2
|
|
8
4
|
|
|
9
5
|
export function mouse() {
|
|
10
6
|
return {
|
|
@@ -35,10 +31,15 @@ export function mouse() {
|
|
|
35
31
|
}
|
|
36
32
|
}
|
|
37
33
|
|
|
38
|
-
export function trackMouse(parent, api) {
|
|
39
|
-
const handleMouseMove = createHandler(
|
|
40
|
-
|
|
41
|
-
|
|
34
|
+
export function trackMouse(parent, api, toGamePosition) {
|
|
35
|
+
const handleMouseMove = createHandler(
|
|
36
|
+
"mouseMove",
|
|
37
|
+
parent,
|
|
38
|
+
api,
|
|
39
|
+
toGamePosition,
|
|
40
|
+
)
|
|
41
|
+
const handleClick = createHandler("mouseClick", parent, api, toGamePosition)
|
|
42
|
+
const handleWheel = createHandler("mouseWheel", parent, api, toGamePosition)
|
|
42
43
|
|
|
43
44
|
return {
|
|
44
45
|
onMouseMove: handleMouseMove,
|
|
@@ -56,7 +57,7 @@ export function createMouse(overrides = {}) {
|
|
|
56
57
|
}
|
|
57
58
|
}
|
|
58
59
|
|
|
59
|
-
function createHandler(type, parent, api) {
|
|
60
|
+
function createHandler(type, parent, api, toGamePosition) {
|
|
60
61
|
return (event) => {
|
|
61
62
|
event.preventDefault()
|
|
62
63
|
event.stopPropagation()
|
|
@@ -70,38 +71,7 @@ function createHandler(type, parent, api) {
|
|
|
70
71
|
return
|
|
71
72
|
}
|
|
72
73
|
|
|
73
|
-
const
|
|
74
|
-
api.notify(type,
|
|
74
|
+
const position = toGamePosition(event.clientX, event.clientY)
|
|
75
|
+
api.notify(type, position)
|
|
75
76
|
}
|
|
76
77
|
}
|
|
77
|
-
|
|
78
|
-
function calculatePosition(event, parent, api) {
|
|
79
|
-
const { clientX, clientY } = event
|
|
80
|
-
const {
|
|
81
|
-
left,
|
|
82
|
-
bottom,
|
|
83
|
-
width: canvasWidth,
|
|
84
|
-
height: canvasHeight,
|
|
85
|
-
} = parent.getBoundingClientRect()
|
|
86
|
-
|
|
87
|
-
const x = clientX - left
|
|
88
|
-
const y = bottom - clientY
|
|
89
|
-
|
|
90
|
-
const game = api.getEntity("game")
|
|
91
|
-
const [gameWidth, gameHeight] = game.size
|
|
92
|
-
|
|
93
|
-
const scaleX = canvasWidth / gameWidth
|
|
94
|
-
const scaleY = canvasHeight / gameHeight
|
|
95
|
-
const scale = Math.min(scaleX, scaleY)
|
|
96
|
-
|
|
97
|
-
const scaledGameWidth = gameWidth * scale
|
|
98
|
-
const scaledGameHeight = gameHeight * scale
|
|
99
|
-
|
|
100
|
-
const offsetX = (canvasWidth - scaledGameWidth) / HALF
|
|
101
|
-
const offsetY = (canvasHeight - scaledGameHeight) / HALF
|
|
102
|
-
|
|
103
|
-
const gameX = (x - offsetX) / scale
|
|
104
|
-
const gameY = (y - offsetY) / scale
|
|
105
|
-
|
|
106
|
-
return v(gameX, NO_Y, gameY)
|
|
107
|
-
}
|
|
@@ -1,81 +1,105 @@
|
|
|
1
1
|
import { findCollision } from "@inglorious/engine/collision/detection.js"
|
|
2
2
|
import { clampToBounds } from "@inglorious/engine/physics/bounds.js"
|
|
3
|
-
import { magnitude
|
|
3
|
+
import { magnitude } from "@inglorious/utils/math/vector.js"
|
|
4
4
|
import { subtract } from "@inglorious/utils/math/vectors.js"
|
|
5
5
|
import { v } from "@inglorious/utils/v.js"
|
|
6
6
|
|
|
7
|
-
const NO_Y = 0
|
|
8
7
|
const MOVEMENT_THRESHOLD = 5
|
|
9
|
-
const HALF = 2
|
|
10
8
|
|
|
11
9
|
export function touch() {
|
|
12
10
|
return {
|
|
13
|
-
|
|
14
|
-
if (entityId !== entity.id) return
|
|
15
|
-
|
|
16
|
-
entity.collisions ??= {}
|
|
17
|
-
entity.collisions.bounds ??= { shape: "point" }
|
|
18
|
-
},
|
|
19
|
-
|
|
20
|
-
touchStart(entity, position) {
|
|
11
|
+
touchStart(entity, { index, position }, api) {
|
|
21
12
|
entity.isSwiping = false
|
|
22
|
-
entity.
|
|
23
|
-
},
|
|
13
|
+
entity.positions[index] = position
|
|
24
14
|
|
|
25
|
-
|
|
26
|
-
const
|
|
15
|
+
const entities = api.getEntities()
|
|
16
|
+
const touchedEntity = findCollision(
|
|
17
|
+
{ ...entity, position: entity.positions[index] },
|
|
18
|
+
entities,
|
|
19
|
+
"touch",
|
|
20
|
+
)
|
|
21
|
+
if (touchedEntity) {
|
|
22
|
+
entity.targetIds[index] = touchedEntity.id
|
|
23
|
+
api.notify("entityTouchStart", entity.targetIds[index])
|
|
24
|
+
} else {
|
|
25
|
+
api.notify("sceneTouchStart", v(...entity.positions[index]))
|
|
26
|
+
}
|
|
27
|
+
},
|
|
27
28
|
|
|
28
|
-
|
|
29
|
+
touchMove(entity, { index, position }, api) {
|
|
30
|
+
const delta = subtract(position, entity.positions[index])
|
|
29
31
|
|
|
30
32
|
if (magnitude(delta) > MOVEMENT_THRESHOLD) {
|
|
31
33
|
entity.isSwiping = true
|
|
32
34
|
}
|
|
33
35
|
|
|
34
|
-
entity.
|
|
36
|
+
entity.positions[index] = position
|
|
37
|
+
const game = api.getEntity("game")
|
|
38
|
+
clampToBounds({ ...entity, position: entity.positions[index] }, game.size)
|
|
35
39
|
|
|
36
|
-
|
|
40
|
+
if (entity.targetIds[index]) {
|
|
41
|
+
api.notify("entityTouchMove", {
|
|
42
|
+
targetId: entity.targetIds[index],
|
|
43
|
+
position: v(...entity.positions[index]),
|
|
44
|
+
})
|
|
45
|
+
}
|
|
37
46
|
},
|
|
38
47
|
|
|
39
|
-
touchEnd(entity,
|
|
48
|
+
touchEnd(entity, { index }, api) {
|
|
40
49
|
if (entity.isSwiping) {
|
|
41
|
-
api.notify("swipe", v(...entity.position))
|
|
42
50
|
entity.isSwiping = false
|
|
43
|
-
return
|
|
44
51
|
}
|
|
45
52
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
53
|
+
if (entity.targetIds[index]) {
|
|
54
|
+
api.notify("entityTouchEnd", {
|
|
55
|
+
targetId: entity.targetIds[index],
|
|
56
|
+
position: v(...entity.positions[index]),
|
|
57
|
+
})
|
|
58
|
+
entity.targetIds[index] = undefined
|
|
50
59
|
} else {
|
|
51
|
-
api.notify("
|
|
60
|
+
api.notify("sceneTouchEnd", v(...entity.positions[index]))
|
|
52
61
|
}
|
|
53
62
|
},
|
|
54
63
|
}
|
|
55
64
|
}
|
|
56
65
|
|
|
57
|
-
export function trackTouch(parent, api) {
|
|
58
|
-
const handleTouchStart = createHandler(
|
|
59
|
-
|
|
60
|
-
|
|
66
|
+
export function trackTouch(parent, api, toGamePosition) {
|
|
67
|
+
const handleTouchStart = createHandler(
|
|
68
|
+
"touchStart",
|
|
69
|
+
parent,
|
|
70
|
+
api,
|
|
71
|
+
toGamePosition,
|
|
72
|
+
)
|
|
73
|
+
const handleTouchMove = createHandler(
|
|
74
|
+
"touchMove",
|
|
75
|
+
parent,
|
|
76
|
+
api,
|
|
77
|
+
toGamePosition,
|
|
78
|
+
)
|
|
79
|
+
const handleTouchEnd = createHandler("touchEnd", parent, api, toGamePosition)
|
|
61
80
|
|
|
62
81
|
return {
|
|
63
82
|
onTouchStart: handleTouchStart,
|
|
64
83
|
onTouchMove: handleTouchMove,
|
|
84
|
+
onTouchCancel: handleTouchEnd,
|
|
65
85
|
onTouchEnd: handleTouchEnd,
|
|
66
86
|
}
|
|
67
87
|
}
|
|
68
88
|
|
|
69
|
-
export function createTouch(
|
|
89
|
+
export function createTouch() {
|
|
70
90
|
return {
|
|
71
91
|
type: "touch",
|
|
72
92
|
layer: 999, // A high layer value to ensure it's always rendered on top
|
|
73
|
-
|
|
74
|
-
|
|
93
|
+
positions: [],
|
|
94
|
+
collisions: {
|
|
95
|
+
bounds: { shape: "point" },
|
|
96
|
+
touch: { shape: "circle", radius: 44 },
|
|
97
|
+
},
|
|
98
|
+
targetIds: [],
|
|
75
99
|
}
|
|
76
100
|
}
|
|
77
101
|
|
|
78
|
-
function createHandler(type, parent, api) {
|
|
102
|
+
function createHandler(type, parent, api, toGamePosition) {
|
|
79
103
|
return (event) => {
|
|
80
104
|
event.preventDefault()
|
|
81
105
|
event.stopPropagation()
|
|
@@ -84,44 +108,14 @@ function createHandler(type, parent, api) {
|
|
|
84
108
|
return
|
|
85
109
|
}
|
|
86
110
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
return
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const payload = calculatePosition(event, parent, api)
|
|
93
|
-
api.notify(type, payload)
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
function calculatePosition(event, parent, api) {
|
|
98
|
-
const [touch] = event.touches
|
|
99
|
-
const { clientX, clientY } = touch
|
|
100
|
-
const {
|
|
101
|
-
left,
|
|
102
|
-
bottom,
|
|
103
|
-
width: canvasWidth,
|
|
104
|
-
height: canvasHeight,
|
|
105
|
-
} = parent.getBoundingClientRect()
|
|
111
|
+
// touchend doesn't have touches anymore, but it has changedTouches
|
|
112
|
+
const touches = event.touches.length ? event.touches : event.changedTouches
|
|
106
113
|
|
|
107
|
-
|
|
108
|
-
|
|
114
|
+
Array.from(touches).forEach((touch, index) => {
|
|
115
|
+
const { clientX, clientY } = touch
|
|
109
116
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
const scaleY = canvasHeight / gameHeight
|
|
115
|
-
const scale = Math.min(scaleX, scaleY)
|
|
116
|
-
|
|
117
|
-
const scaledGameWidth = gameWidth * scale
|
|
118
|
-
const scaledGameHeight = gameHeight * scale
|
|
119
|
-
|
|
120
|
-
const offsetX = (canvasWidth - scaledGameWidth) / HALF
|
|
121
|
-
const offsetY = (canvasHeight - scaledGameHeight) / HALF
|
|
122
|
-
|
|
123
|
-
const gameX = (x - offsetX) / scale
|
|
124
|
-
const gameY = (y - offsetY) / scale
|
|
125
|
-
|
|
126
|
-
return v(gameX, NO_Y, gameY)
|
|
117
|
+
const position = toGamePosition(clientX, clientY)
|
|
118
|
+
api.notify(type, { index, position })
|
|
119
|
+
})
|
|
120
|
+
}
|
|
127
121
|
}
|