emeraldengine 2.0.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 +968 -0
- package/dist/types/imports/BitmapText.d.ts +79 -0
- package/dist/types/imports/Color.d.ts +17 -0
- package/dist/types/imports/Drawable.d.ts +157 -0
- package/dist/types/imports/Emerald.d.ts +73 -0
- package/dist/types/imports/FPSCounter.d.ts +19 -0
- package/dist/types/imports/GLUtils.d.ts +6 -0
- package/dist/types/imports/Instance.d.ts +87 -0
- package/dist/types/imports/InstancedTexture.d.ts +230 -0
- package/dist/types/imports/Physics.d.ts +139 -0
- package/dist/types/imports/Scene.d.ts +39 -0
- package/dist/types/imports/Shaders.d.ts +4 -0
- package/dist/types/imports/Shapes.d.ts +25 -0
- package/dist/types/imports/Storage.d.ts +46 -0
- package/dist/types/imports/Texture.d.ts +19 -0
- package/dist/types/imports/Time.d.ts +22 -0
- package/dist/types/imports/Transform.d.ts +41 -0
- package/dist/types/imports/components/BoxCollider.d.ts +41 -0
- package/dist/types/imports/components/BoxColliderDebug.d.ts +19 -0
- package/dist/types/imports/components/CircleCollider.d.ts +39 -0
- package/dist/types/imports/components/CircleColliderDebug.d.ts +19 -0
- package/dist/types/imports/components/Collider.d.ts +53 -0
- package/dist/types/imports/components/GameObject.d.ts +72 -0
- package/dist/types/imports/components/RigidBody.d.ts +104 -0
- package/dist/types/imports/lights/DirectionalLight.d.ts +26 -0
- package/dist/types/imports/lights/PointLight.d.ts +18 -0
- package/dist/types/imports/managers/AudioManager.d.ts +60 -0
- package/dist/types/imports/managers/CameraManager.d.ts +35 -0
- package/dist/types/imports/managers/EventManager.d.ts +187 -0
- package/dist/types/imports/managers/GLManager.d.ts +47 -0
- package/dist/types/imports/managers/IDManager.d.ts +21 -0
- package/dist/types/imports/managers/SceneManager.d.ts +22 -0
- package/dist/types/imports/particlesystem/Particle.d.ts +42 -0
- package/dist/types/imports/particlesystem/ParticleSettings.d.ts +49 -0
- package/dist/types/imports/particlesystem/Particles.d.ts +71 -0
- package/dist/types/index.d.ts +32 -0
- package/imports/BitmapText.js +245 -0
- package/imports/Color.js +18 -0
- package/imports/Drawable.js +550 -0
- package/imports/Emerald.js +459 -0
- package/imports/FPSCounter.js +43 -0
- package/imports/GLUtils.js +67 -0
- package/imports/Instance.js +187 -0
- package/imports/InstancedTexture.js +856 -0
- package/imports/Physics.js +242 -0
- package/imports/Scene.js +79 -0
- package/imports/Shaders.js +165 -0
- package/imports/Shapes.js +129 -0
- package/imports/Storage.js +63 -0
- package/imports/Texture.js +67 -0
- package/imports/Time.js +28 -0
- package/imports/Transform.js +59 -0
- package/imports/components/BoxCollider.js +67 -0
- package/imports/components/BoxColliderDebug.js +38 -0
- package/imports/components/CircleCollider.js +67 -0
- package/imports/components/CircleColliderDebug.js +36 -0
- package/imports/components/Collider.js +51 -0
- package/imports/components/GameObject.js +160 -0
- package/imports/components/RigidBody.js +169 -0
- package/imports/lights/DirectionalLight.js +68 -0
- package/imports/lights/PointLight.js +17 -0
- package/imports/managers/AudioManager.js +146 -0
- package/imports/managers/CameraManager.js +60 -0
- package/imports/managers/EventManager.js +479 -0
- package/imports/managers/GLManager.js +65 -0
- package/imports/managers/IDManager.js +32 -0
- package/imports/managers/SceneManager.js +27 -0
- package/imports/managers/ShaderManager.js +133 -0
- package/imports/particlesystem/Particle.js +75 -0
- package/imports/particlesystem/ParticleSettings.js +49 -0
- package/imports/particlesystem/Particles.js +226 -0
- package/index.js +67 -0
- package/package.json +38 -0
|
@@ -0,0 +1,479 @@
|
|
|
1
|
+
import Scene from "../Scene.js";
|
|
2
|
+
import InstancedTexture from "../InstancedTexture.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @class EventManager
|
|
6
|
+
* @description Manages the events for the game
|
|
7
|
+
* @param {HTMLCanvasElement} canvas - The canvas element
|
|
8
|
+
* @param {Scene} scene - The scene
|
|
9
|
+
* @param {Camera} camera - The camera
|
|
10
|
+
*/
|
|
11
|
+
class EventManager {
|
|
12
|
+
constructor(canvas, scene, camera) {
|
|
13
|
+
this.scene = scene;
|
|
14
|
+
this.camera = camera;
|
|
15
|
+
this.canvas = canvas;
|
|
16
|
+
this.keyDownListeners = new Map();
|
|
17
|
+
this.keyUpListeners = new Map();
|
|
18
|
+
this.clickListeners = new Map();
|
|
19
|
+
this.canvasWidth = canvas.width;
|
|
20
|
+
this.canvasHeight = canvas.height;
|
|
21
|
+
this.hoverListeners = new Map();
|
|
22
|
+
this.lastHoveredObject = null;
|
|
23
|
+
this.lastHoveredInstance = null;
|
|
24
|
+
this.pressedKeys = new Map();
|
|
25
|
+
this.mousePosition = { x: 0, y: 0 };
|
|
26
|
+
this.boundHandleMouseMove = this.handleMouseMove.bind(this);
|
|
27
|
+
this.boundHandleKeyDown = this.handleKeyDown.bind(this);
|
|
28
|
+
this.boundHandleKeyUp = this.handleKeyUp.bind(this);
|
|
29
|
+
this.boundHandleClick = this.handleClick.bind(this);
|
|
30
|
+
|
|
31
|
+
this.boundHandleMouseDown = this.handleMouseDown.bind(this);
|
|
32
|
+
this.boundHandleMouseUp = this.handleMouseUp.bind(this);
|
|
33
|
+
|
|
34
|
+
// Camera dragging state
|
|
35
|
+
this.isDragging = false;
|
|
36
|
+
this.dragStartX = 0;
|
|
37
|
+
this.dragStartY = 0;
|
|
38
|
+
this.initialCameraX = this.camera.transform.position.x;
|
|
39
|
+
this.initialCameraY = this.camera.transform.position.y;
|
|
40
|
+
this.cameraWasMoved = false;
|
|
41
|
+
|
|
42
|
+
window.addEventListener("mousemove", this.boundHandleMouseMove);
|
|
43
|
+
window.addEventListener("keydown", this.boundHandleKeyDown);
|
|
44
|
+
window.addEventListener("keyup", this.boundHandleKeyUp);
|
|
45
|
+
window.addEventListener("click", this.boundHandleClick);
|
|
46
|
+
window.addEventListener("mousedown", this.boundHandleMouseDown);
|
|
47
|
+
window.addEventListener("mouseup", this.boundHandleMouseUp);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @method addKeyDown
|
|
52
|
+
* @description Adds a key down event listener
|
|
53
|
+
* @param {string} key - The key to listen for
|
|
54
|
+
* @param {function} func - The function to call when the key is pressed
|
|
55
|
+
*/
|
|
56
|
+
addKeyDown(key, func) {
|
|
57
|
+
if (!this.keyDownListeners.has(key.length <= 1 ? key.toLowerCase() : key)) {
|
|
58
|
+
this.keyDownListeners.set(
|
|
59
|
+
key.length <= 1 ? key.toLowerCase() : key,
|
|
60
|
+
new Set()
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
this.keyDownListeners
|
|
64
|
+
.get(key.length <= 1 ? key.toLowerCase() : key)
|
|
65
|
+
.add(func);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @method addKeyUp
|
|
70
|
+
* @description Adds a key up event listener
|
|
71
|
+
* @param {string} key - The key to listen for
|
|
72
|
+
* @param {function} func - The function to call when the key is released
|
|
73
|
+
*/
|
|
74
|
+
addKeyUp(key, func) {
|
|
75
|
+
if (!this.keyUpListeners.has(key.length <= 1 ? key.toLowerCase() : key)) {
|
|
76
|
+
this.keyUpListeners.set(
|
|
77
|
+
key.length <= 1 ? key.toLowerCase() : key,
|
|
78
|
+
new Set()
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
this.keyUpListeners
|
|
82
|
+
.get(key.length <= 1 ? key.toLowerCase() : key)
|
|
83
|
+
.add(func);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* @method removeKeyDown
|
|
88
|
+
* @description Removes a key down event listener
|
|
89
|
+
* @param {string} key - The key to remove the listener for
|
|
90
|
+
* @param {function} func - The function to remove
|
|
91
|
+
*/
|
|
92
|
+
removeKeyDown(key, func) {
|
|
93
|
+
if (this.keyDownListeners.has(key.length <= 1 ? key.toLowerCase() : key)) {
|
|
94
|
+
this.keyDownListeners
|
|
95
|
+
.get(key.length <= 1 ? key.toLowerCase() : key)
|
|
96
|
+
.delete(func);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* @method removeKeyUp
|
|
102
|
+
* @description Removes a key up event listener
|
|
103
|
+
* @param {string} key - The key to remove the listener for
|
|
104
|
+
* @param {function} func - The function to remove
|
|
105
|
+
*/
|
|
106
|
+
removeKeyUp(key, func) {
|
|
107
|
+
if (this.keyUpListeners.has(key.length <= 1 ? key.toLowerCase() : key)) {
|
|
108
|
+
this.keyUpListeners
|
|
109
|
+
.get(key.length <= 1 ? key.toLowerCase() : key)
|
|
110
|
+
.delete(func);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* @method handleKeyDown
|
|
116
|
+
* @description Handles a key down event
|
|
117
|
+
* @param {KeyboardEvent} event - The keyboard event
|
|
118
|
+
*/
|
|
119
|
+
handleKeyDown(event) {
|
|
120
|
+
this.pressedKeys.set(
|
|
121
|
+
event.key.length <= 1 ? event.key.toLowerCase() : event.key,
|
|
122
|
+
true
|
|
123
|
+
);
|
|
124
|
+
const listeners = this.keyDownListeners.get(
|
|
125
|
+
event.key.length <= 1 ? event.key.toLowerCase() : event.key
|
|
126
|
+
);
|
|
127
|
+
if (listeners) {
|
|
128
|
+
listeners.forEach((func) => func(event));
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* @method handleKeyUp
|
|
134
|
+
* @description Handles a key up event
|
|
135
|
+
* @param {KeyboardEvent} event - The keyboard event
|
|
136
|
+
*/
|
|
137
|
+
handleKeyUp(event) {
|
|
138
|
+
this.pressedKeys.set(
|
|
139
|
+
event.key.length <= 1 ? event.key.toLowerCase() : event.key,
|
|
140
|
+
false
|
|
141
|
+
);
|
|
142
|
+
const listeners = this.keyUpListeners.get(
|
|
143
|
+
event.key.length <= 1 ? event.key.toLowerCase() : event.key
|
|
144
|
+
);
|
|
145
|
+
if (listeners) {
|
|
146
|
+
listeners.forEach((func) => func(event));
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* @method isKeyPressed
|
|
152
|
+
* @description Checks if a key is pressed
|
|
153
|
+
* @param {string} key - The key to check
|
|
154
|
+
* @returns {boolean} - True if the key is pressed
|
|
155
|
+
*/
|
|
156
|
+
isKeyPressed(key) {
|
|
157
|
+
return (
|
|
158
|
+
this.pressedKeys.get(key.length <= 1 ? key.toLowerCase() : key) || false
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* @method addClickEvent
|
|
164
|
+
* @description Adds a click event listener
|
|
165
|
+
* @param {GameObject} object - The object to listen for
|
|
166
|
+
* @param {function} func - The function to call when the object is clicked
|
|
167
|
+
*/
|
|
168
|
+
addClickEvent(object, func) {
|
|
169
|
+
if (!this.clickListeners.has(object.id)) {
|
|
170
|
+
this.clickListeners.set(object.id, new Set());
|
|
171
|
+
}
|
|
172
|
+
this.clickListeners.get(object.id).add(func);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* @method handleClick
|
|
177
|
+
* @description Handles a click event
|
|
178
|
+
* @param {MouseEvent} event - The mouse event
|
|
179
|
+
*/
|
|
180
|
+
handleClick(event) {
|
|
181
|
+
const canvas = event.target;
|
|
182
|
+
const rect = canvas.getBoundingClientRect();
|
|
183
|
+
|
|
184
|
+
// Calculate click position relative to the canvas
|
|
185
|
+
const canvasX = event.clientX - rect.left;
|
|
186
|
+
const canvasY = event.clientY - rect.top;
|
|
187
|
+
|
|
188
|
+
// Convert to world coordinates
|
|
189
|
+
const worldX =
|
|
190
|
+
canvasX - this.canvasWidth / 2 - this.camera.transform.position.x;
|
|
191
|
+
const worldY =
|
|
192
|
+
this.canvasHeight / 2 - canvasY - this.camera.transform.position.y;
|
|
193
|
+
|
|
194
|
+
this.scene.objects.forEach((sceneObject) => {
|
|
195
|
+
if (!sceneObject.isActive) return; // Skip inactive objects
|
|
196
|
+
// Check if the object has an InstancedTexture component
|
|
197
|
+
let instanceHandled = false;
|
|
198
|
+
if (
|
|
199
|
+
sceneObject.getComponent &&
|
|
200
|
+
sceneObject.getComponent(InstancedTexture)
|
|
201
|
+
) {
|
|
202
|
+
const instancedTexture = sceneObject.getComponent(InstancedTexture);
|
|
203
|
+
instanceHandled = instancedTexture.handleInstanceClick(
|
|
204
|
+
event,
|
|
205
|
+
worldX,
|
|
206
|
+
worldY
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// If no instance handled the click, check the object itself
|
|
211
|
+
if (
|
|
212
|
+
!instanceHandled &&
|
|
213
|
+
this.isPointInObject(worldX, worldY, sceneObject)
|
|
214
|
+
) {
|
|
215
|
+
const listeners = this.clickListeners.get(sceneObject.id);
|
|
216
|
+
if (listeners) {
|
|
217
|
+
listeners.forEach((func) => func(event, sceneObject));
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* @method removeClickEvent
|
|
226
|
+
* @description Removes a click event listener
|
|
227
|
+
* @param {GameObject} object - The object to remove the listener for
|
|
228
|
+
* @param {function} func - The function to remove
|
|
229
|
+
*/
|
|
230
|
+
removeClickEvent(object, func) {
|
|
231
|
+
if (this.clickListeners.has(object.id)) {
|
|
232
|
+
this.clickListeners.get(object.id).delete(func);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* @method isPointInObject
|
|
238
|
+
* @description Checks if a point is in an object
|
|
239
|
+
* @param {number} x - The x coordinate of the point
|
|
240
|
+
* @param {number} y - The y coordinate of the point
|
|
241
|
+
* @param {GameObject} object - The object to check
|
|
242
|
+
* @returns {boolean} - True if the point is in the object
|
|
243
|
+
*/
|
|
244
|
+
isPointInObject(x, y, object) {
|
|
245
|
+
const left = object.transform.position.x - object.transform.scale.x;
|
|
246
|
+
const right = object.transform.position.x + object.transform.scale.x;
|
|
247
|
+
const top = object.transform.position.y + object.transform.scale.y;
|
|
248
|
+
const bottom = object.transform.position.y - object.transform.scale.y;
|
|
249
|
+
return x >= left && x <= right && y >= bottom && y <= top;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* @method addHoverEvent
|
|
254
|
+
* @description Adds a hover event listener
|
|
255
|
+
* @param {GameObject} object - The object to listen for
|
|
256
|
+
* @param {function} enterFunc - The function to call when the object is hovered
|
|
257
|
+
* @param {function} leaveFunc - The function to call when the object is no longer hovered
|
|
258
|
+
*/
|
|
259
|
+
addHoverEvent(object, enterFunc, leaveFunc) {
|
|
260
|
+
if (!this.hoverListeners.has(object.id)) {
|
|
261
|
+
this.hoverListeners.set(object.id, {
|
|
262
|
+
enter: new Set(),
|
|
263
|
+
leave: new Set(),
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
this.hoverListeners.get(object.id).enter.add(enterFunc);
|
|
267
|
+
this.hoverListeners.get(object.id).leave.add(leaveFunc);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* @method removeHoverEvent
|
|
272
|
+
* @description Removes a hover event listener
|
|
273
|
+
* @param {GameObject} object - The object to remove the listener for
|
|
274
|
+
* @param {function} enterFunc - The function to remove
|
|
275
|
+
* @param {function} leaveFunc - The function to remove
|
|
276
|
+
*/
|
|
277
|
+
removeHoverEvent(object, enterFunc, leaveFunc) {
|
|
278
|
+
if (this.hoverListeners.has(object.id)) {
|
|
279
|
+
const listeners = this.hoverListeners.get(object.id);
|
|
280
|
+
listeners.enter.delete(enterFunc);
|
|
281
|
+
listeners.leave.delete(leaveFunc);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* @method handleMouseDown
|
|
287
|
+
* @description Handles a mouse down event
|
|
288
|
+
* @param {MouseEvent} event - The mouse event
|
|
289
|
+
*/
|
|
290
|
+
handleMouseDown(event) {
|
|
291
|
+
if (event.button === 1) {
|
|
292
|
+
event.preventDefault();
|
|
293
|
+
this.isDragging = true;
|
|
294
|
+
this.dragStartX = event.clientX;
|
|
295
|
+
this.dragStartY = event.clientY;
|
|
296
|
+
this.initialCameraX = this.camera.transform.position.x;
|
|
297
|
+
this.initialCameraY = this.camera.transform.position.y;
|
|
298
|
+
this.canvas.style.cursor = "grabbing";
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* @method handleMouseUp
|
|
304
|
+
* @description Handles a mouse up event
|
|
305
|
+
* @param {MouseEvent} event - The mouse event
|
|
306
|
+
*/
|
|
307
|
+
handleMouseUp(event) {
|
|
308
|
+
if (event.button === 1 && this.isDragging) {
|
|
309
|
+
this.isDragging = false;
|
|
310
|
+
this.canvas.style.cursor = "default";
|
|
311
|
+
this.cameraWasMoved = true;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* @method handleMouseMove
|
|
317
|
+
* @description Handles a mouse move event
|
|
318
|
+
* @param {MouseEvent} event - The mouse event
|
|
319
|
+
*/
|
|
320
|
+
handleMouseMove(event) {
|
|
321
|
+
const rect = this.canvas.getBoundingClientRect();
|
|
322
|
+
|
|
323
|
+
// Calculate mouse position relative to the canvas
|
|
324
|
+
const canvasX = event.clientX - rect.left;
|
|
325
|
+
const canvasY = event.clientY - rect.top;
|
|
326
|
+
|
|
327
|
+
// Convert to world coordinates
|
|
328
|
+
const worldX =
|
|
329
|
+
canvasX - this.canvasWidth / 2 - this.camera.transform.position.x;
|
|
330
|
+
const worldY =
|
|
331
|
+
this.canvasHeight / 2 - canvasY - this.camera.transform.position.y;
|
|
332
|
+
this.mousePosition.x = worldX;
|
|
333
|
+
this.mousePosition.y = worldY;
|
|
334
|
+
let hoveredObject = null;
|
|
335
|
+
let hoveredInstance = null;
|
|
336
|
+
|
|
337
|
+
this.scene.objects.forEach((sceneObject) => {
|
|
338
|
+
if (!sceneObject.isActive) return; // Skip inactive objects
|
|
339
|
+
|
|
340
|
+
// Check if the object has an InstancedTexture component
|
|
341
|
+
if (
|
|
342
|
+
sceneObject.getComponent &&
|
|
343
|
+
sceneObject.getComponent(InstancedTexture)
|
|
344
|
+
) {
|
|
345
|
+
const instancedTexture = sceneObject.getComponent(InstancedTexture);
|
|
346
|
+
const instanceAtPoint = instancedTexture.getInstanceAtPoint(
|
|
347
|
+
worldX,
|
|
348
|
+
worldY
|
|
349
|
+
);
|
|
350
|
+
if (instanceAtPoint) {
|
|
351
|
+
hoveredInstance = instanceAtPoint;
|
|
352
|
+
hoveredObject = sceneObject; // Also set the parent object as hovered
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// If no instance was hovered, check the object itself
|
|
357
|
+
if (
|
|
358
|
+
!hoveredInstance &&
|
|
359
|
+
this.isPointInObject(worldX, worldY, sceneObject)
|
|
360
|
+
) {
|
|
361
|
+
hoveredObject = sceneObject;
|
|
362
|
+
}
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
// Handle instance hover events
|
|
366
|
+
if (hoveredInstance !== this.lastHoveredInstance) {
|
|
367
|
+
if (this.lastHoveredInstance) {
|
|
368
|
+
const parent = this.lastHoveredInstance.parent;
|
|
369
|
+
if (parent && parent instanceof InstancedTexture) {
|
|
370
|
+
parent.handleInstanceHover(
|
|
371
|
+
event,
|
|
372
|
+
worldX,
|
|
373
|
+
worldY,
|
|
374
|
+
this.lastHoveredInstance
|
|
375
|
+
);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
if (hoveredInstance) {
|
|
380
|
+
const parent = hoveredInstance.parent;
|
|
381
|
+
if (parent && parent instanceof InstancedTexture) {
|
|
382
|
+
parent.handleInstanceHover(
|
|
383
|
+
event,
|
|
384
|
+
worldX,
|
|
385
|
+
worldY,
|
|
386
|
+
this.lastHoveredInstance
|
|
387
|
+
);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
this.lastHoveredInstance = hoveredInstance;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// Handle object hover events
|
|
395
|
+
if (hoveredObject !== this.lastHoveredObject) {
|
|
396
|
+
// Always trigger leave event if we had a previously hovered object
|
|
397
|
+
if (this.lastHoveredObject && this.lastHoveredObject.isActive) {
|
|
398
|
+
const leaveListeners = this.hoverListeners.get(
|
|
399
|
+
this.lastHoveredObject.id
|
|
400
|
+
);
|
|
401
|
+
if (leaveListeners) {
|
|
402
|
+
leaveListeners.leave.forEach((func) =>
|
|
403
|
+
func(event, this.lastHoveredObject)
|
|
404
|
+
);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// Only trigger enter event if we're not hovering over an instance
|
|
409
|
+
if (hoveredObject && hoveredObject.isActive && !hoveredInstance) {
|
|
410
|
+
const enterListeners = this.hoverListeners.get(hoveredObject.id);
|
|
411
|
+
if (enterListeners) {
|
|
412
|
+
enterListeners.enter.forEach((func) => func(event, hoveredObject));
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
this.lastHoveredObject = hoveredObject;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* @method getMousePosition
|
|
422
|
+
* @description Returns the mouse position
|
|
423
|
+
* @returns {Object} - The mouse position
|
|
424
|
+
*/
|
|
425
|
+
getMousePosition() {
|
|
426
|
+
return this.mousePosition;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* @method wasCameraMoved
|
|
431
|
+
* @description Checks if the camera was moved
|
|
432
|
+
* @returns {boolean} - True if the camera was moved
|
|
433
|
+
*/
|
|
434
|
+
wasCameraMoved() {
|
|
435
|
+
return this.cameraWasMoved;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* @method resetCameraMoved
|
|
440
|
+
* @description Resets the camera moved flag
|
|
441
|
+
*/
|
|
442
|
+
resetCameraMoved() {
|
|
443
|
+
this.cameraWasMoved = false;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* @method changeScene
|
|
448
|
+
* @description Changes the scene
|
|
449
|
+
* @param {Scene} scene - The scene to change to
|
|
450
|
+
*/
|
|
451
|
+
changeScene(scene) {
|
|
452
|
+
if (scene instanceof Scene) {
|
|
453
|
+
this.scene = scene;
|
|
454
|
+
} else {
|
|
455
|
+
console.error(
|
|
456
|
+
"[EventManager] > Specified argument is not an instance of Scene class"
|
|
457
|
+
);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* @method clean
|
|
463
|
+
* @description Cleans up the event manager
|
|
464
|
+
*/
|
|
465
|
+
clean() {
|
|
466
|
+
window.removeEventListener("mousemove", this.boundHandleMouseMove);
|
|
467
|
+
window.removeEventListener("keydown", this.boundHandleKeyDown);
|
|
468
|
+
window.removeEventListener("keyup", this.boundHandleKeyUp);
|
|
469
|
+
window.removeEventListener("click", this.boundHandleClick);
|
|
470
|
+
window.removeEventListener("mousedown", this.boundHandleMouseDown);
|
|
471
|
+
window.removeEventListener("mouseup", this.boundHandleMouseUp);
|
|
472
|
+
this.pressedKeys.clear();
|
|
473
|
+
this.keyDownListeners.clear();
|
|
474
|
+
this.lastHoveredObject = null;
|
|
475
|
+
this.lastHoveredInstance = null;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
export default EventManager;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @class GLManager
|
|
3
|
+
* @description Manages the WebGL context for the game
|
|
4
|
+
*/
|
|
5
|
+
class GLManager {
|
|
6
|
+
static gl = null;
|
|
7
|
+
static programInfo = null;
|
|
8
|
+
static canvas = null;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @method setGL
|
|
12
|
+
* @description Sets the WebGL context
|
|
13
|
+
* @param {WebGLRenderingContext} gl - The WebGL context
|
|
14
|
+
*/
|
|
15
|
+
static setGL(gl) {
|
|
16
|
+
this.gl = gl;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @method setProgramInfo
|
|
21
|
+
* @description Sets the program info
|
|
22
|
+
* @param {Object} programInfo - The program info
|
|
23
|
+
*/
|
|
24
|
+
static setProgramInfo(programInfo) {
|
|
25
|
+
this.programInfo = programInfo;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @method setCanvas
|
|
30
|
+
* @description Sets the canvas
|
|
31
|
+
* @param {HTMLCanvasElement} canvas - The canvas
|
|
32
|
+
*/
|
|
33
|
+
static setCanvas(canvas) {
|
|
34
|
+
this.canvas = canvas;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @method getGL
|
|
39
|
+
* @description Returns the WebGL context
|
|
40
|
+
* @returns {WebGLRenderingContext} - The WebGL context
|
|
41
|
+
*/
|
|
42
|
+
static getGL() {
|
|
43
|
+
return this.gl;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @method getProgramInfo
|
|
48
|
+
* @description Returns the program info
|
|
49
|
+
* @returns {Object} - The program info
|
|
50
|
+
*/
|
|
51
|
+
static getProgramInfo() {
|
|
52
|
+
return this.programInfo;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @method getCanvas
|
|
57
|
+
* @description Returns the canvas
|
|
58
|
+
* @returns {HTMLCanvasElement} - The canvas
|
|
59
|
+
*/
|
|
60
|
+
static getCanvas() {
|
|
61
|
+
return this.canvas;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export default GLManager;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @class IDManager
|
|
3
|
+
* @description Manages the IDs for the game
|
|
4
|
+
*/
|
|
5
|
+
class IDManager {
|
|
6
|
+
static existingIDs = new Set();
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @method generateID
|
|
10
|
+
* @description Generates a random ID
|
|
11
|
+
* @returns {string} - The random ID
|
|
12
|
+
*/
|
|
13
|
+
static generateID() {
|
|
14
|
+
return Math.random().toString(36).substring(2, 10);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @method generateUniqueID
|
|
19
|
+
* @description Generates a unique ID
|
|
20
|
+
* @returns {string} - The unique ID
|
|
21
|
+
*/
|
|
22
|
+
static generateUniqueID() {
|
|
23
|
+
let id;
|
|
24
|
+
do {
|
|
25
|
+
id = this.generateID();
|
|
26
|
+
} while (this.existingIDs.has(id));
|
|
27
|
+
this.existingIDs.add(id);
|
|
28
|
+
return id;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export default IDManager;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @class SceneManager
|
|
3
|
+
* @description Manages the scene for the game
|
|
4
|
+
*/
|
|
5
|
+
class SceneManager {
|
|
6
|
+
static scene = null;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @method setScene
|
|
10
|
+
* @description Sets the scene
|
|
11
|
+
* @param {Scene} scene - The scene to set
|
|
12
|
+
*/
|
|
13
|
+
static setScene(scene) {
|
|
14
|
+
this.scene = scene;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @method getScene
|
|
19
|
+
* @description Returns the scene
|
|
20
|
+
* @returns {Scene} - The scene
|
|
21
|
+
*/
|
|
22
|
+
static getScene() {
|
|
23
|
+
return this.scene;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export default SceneManager;
|