action-engine-js 1.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.
Files changed (93) hide show
  1. package/LICENSE +45 -0
  2. package/README.md +348 -0
  3. package/actionengine/3rdparty/goblin/goblin.js +9609 -0
  4. package/actionengine/3rdparty/goblin/goblin.min.js +5 -0
  5. package/actionengine/camera/actioncamera.js +90 -0
  6. package/actionengine/camera/cameracollisionhandler.js +69 -0
  7. package/actionengine/character/actioncharacter.js +360 -0
  8. package/actionengine/character/actioncharacter3D.js +61 -0
  9. package/actionengine/core/app.js +430 -0
  10. package/actionengine/debug/basedebugpanel.js +858 -0
  11. package/actionengine/display/canvasmanager.js +75 -0
  12. package/actionengine/display/gl/programmanager.js +570 -0
  13. package/actionengine/display/gl/shaders/lineshader.js +118 -0
  14. package/actionengine/display/gl/shaders/objectshader.js +1756 -0
  15. package/actionengine/display/gl/shaders/particleshader.js +43 -0
  16. package/actionengine/display/gl/shaders/shadowshader.js +319 -0
  17. package/actionengine/display/gl/shaders/spriteshader.js +100 -0
  18. package/actionengine/display/gl/shaders/watershader.js +67 -0
  19. package/actionengine/display/graphics/actionmodel3D.js +191 -0
  20. package/actionengine/display/graphics/actionsprite3D.js +230 -0
  21. package/actionengine/display/graphics/lighting/actiondirectionalshadowlight.js +864 -0
  22. package/actionengine/display/graphics/lighting/actionlight.js +211 -0
  23. package/actionengine/display/graphics/lighting/actionomnidirectionalshadowlight.js +862 -0
  24. package/actionengine/display/graphics/lighting/lightingconstants.js +263 -0
  25. package/actionengine/display/graphics/lighting/lightmanager.js +789 -0
  26. package/actionengine/display/graphics/renderableobject.js +44 -0
  27. package/actionengine/display/graphics/renderers/actionrenderer2D.js +341 -0
  28. package/actionengine/display/graphics/renderers/actionrenderer3D/actionrenderer3D.js +655 -0
  29. package/actionengine/display/graphics/renderers/actionrenderer3D/canvasmanager3D.js +82 -0
  30. package/actionengine/display/graphics/renderers/actionrenderer3D/debugrenderer3D.js +493 -0
  31. package/actionengine/display/graphics/renderers/actionrenderer3D/objectrenderer3D.js +790 -0
  32. package/actionengine/display/graphics/renderers/actionrenderer3D/spriteRenderer3D.js +266 -0
  33. package/actionengine/display/graphics/renderers/actionrenderer3D/sunrenderer3D.js +140 -0
  34. package/actionengine/display/graphics/renderers/actionrenderer3D/waterrenderer3D.js +173 -0
  35. package/actionengine/display/graphics/renderers/actionrenderer3D/weatherrenderer3D.js +87 -0
  36. package/actionengine/display/graphics/texture/proceduraltexture.js +192 -0
  37. package/actionengine/display/graphics/texture/texturemanager.js +242 -0
  38. package/actionengine/display/graphics/texture/textureregistry.js +177 -0
  39. package/actionengine/input/actionscrollablearea.js +1405 -0
  40. package/actionengine/input/inputhandler.js +1647 -0
  41. package/actionengine/math/geometry/geometrybuilder.js +161 -0
  42. package/actionengine/math/geometry/glbexporter.js +364 -0
  43. package/actionengine/math/geometry/glbloader.js +722 -0
  44. package/actionengine/math/geometry/modelcodegenerator.js +97 -0
  45. package/actionengine/math/geometry/triangle.js +33 -0
  46. package/actionengine/math/geometry/triangleutils.js +34 -0
  47. package/actionengine/math/mathutils.js +25 -0
  48. package/actionengine/math/matrix4.js +785 -0
  49. package/actionengine/math/physics/actionphysics.js +108 -0
  50. package/actionengine/math/physics/actionphysicsobject3D.js +164 -0
  51. package/actionengine/math/physics/actionphysicsworld3D.js +238 -0
  52. package/actionengine/math/physics/actionraycast.js +129 -0
  53. package/actionengine/math/physics/shapes/actionphysicsbox3D.js +158 -0
  54. package/actionengine/math/physics/shapes/actionphysicscapsule3D.js +200 -0
  55. package/actionengine/math/physics/shapes/actionphysicscompoundshape3D.js +147 -0
  56. package/actionengine/math/physics/shapes/actionphysicscone3D.js +126 -0
  57. package/actionengine/math/physics/shapes/actionphysicsconvexshape3D.js +72 -0
  58. package/actionengine/math/physics/shapes/actionphysicscylinder3D.js +117 -0
  59. package/actionengine/math/physics/shapes/actionphysicsmesh3D.js +74 -0
  60. package/actionengine/math/physics/shapes/actionphysicsplane3D.js +100 -0
  61. package/actionengine/math/physics/shapes/actionphysicssphere3D.js +95 -0
  62. package/actionengine/math/quaternion.js +61 -0
  63. package/actionengine/math/vector2.js +277 -0
  64. package/actionengine/math/vector3.js +318 -0
  65. package/actionengine/math/viewfrustum.js +136 -0
  66. package/actionengine/network/ACTIONNETREADME.md +810 -0
  67. package/actionengine/network/client/ActionNetManager.js +802 -0
  68. package/actionengine/network/client/ActionNetManagerGUI.js +1709 -0
  69. package/actionengine/network/client/ActionNetManagerP2P.js +1537 -0
  70. package/actionengine/network/client/SyncSystem.js +422 -0
  71. package/actionengine/network/p2p/ActionNetPeer.js +142 -0
  72. package/actionengine/network/p2p/ActionNetTrackerClient.js +623 -0
  73. package/actionengine/network/p2p/DataConnection.js +282 -0
  74. package/actionengine/network/p2p/README.md +510 -0
  75. package/actionengine/network/p2p/example.html +502 -0
  76. package/actionengine/network/server/ActionNetServer.js +577 -0
  77. package/actionengine/network/server/ActionNetServerSSL.js +579 -0
  78. package/actionengine/network/server/ActionNetServerUtils.js +458 -0
  79. package/actionengine/network/server/SERVERREADME.md +314 -0
  80. package/actionengine/network/server/package-lock.json +35 -0
  81. package/actionengine/network/server/package.json +13 -0
  82. package/actionengine/network/server/start.bat +27 -0
  83. package/actionengine/network/server/start.sh +25 -0
  84. package/actionengine/network/server/startwss.bat +27 -0
  85. package/actionengine/sound/audiomanager.js +1589 -0
  86. package/actionengine/sound/soundfont/ACTIONSOUNDFONT_README.md +205 -0
  87. package/actionengine/sound/soundfont/actionparser.js +718 -0
  88. package/actionengine/sound/soundfont/actionreverb.js +252 -0
  89. package/actionengine/sound/soundfont/actionsoundfont.js +543 -0
  90. package/actionengine/sound/soundfont/sf2playerlicence.txt +29 -0
  91. package/actionengine/sound/soundfont/soundfont.js +2 -0
  92. package/dist/action-engine.min.js +328 -0
  93. package/package.json +35 -0
@@ -0,0 +1,430 @@
1
+ // actionengine/core/app.js
2
+
3
+ // Inject overlay CSS immediately when this script loads
4
+ (function() {
5
+ const css = `:root {
6
+ --primary: #00f0f0;
7
+ --primary-dark: #00b0b0;
8
+ --secondary: #ff4444;
9
+ --background: #0a0a2a;
10
+ --surface: #1a1a4a;
11
+ --surface-light: #2a2a6a;
12
+ --text: #ffffff;
13
+ --text-secondary: rgba(255, 255, 255, 0.7);
14
+ --space-xs: 0.25rem;
15
+ --space-sm: 0.5rem;
16
+ --space-md: 1rem;
17
+ --space-lg: 1.5rem;
18
+ --space-xl: 2rem;
19
+ --transition-fast: 150ms;
20
+ --transition-normal: 250ms;
21
+ --transition-slow: 350ms;
22
+ --cubic-bounce: cubic-bezier(0.68, -0.55, 0.265, 1.55);
23
+ }
24
+
25
+ * {
26
+ margin: 0;
27
+ padding: 0;
28
+ box-sizing: border-box;
29
+ user-select: none;
30
+ -webkit-user-select: none;
31
+ -webkit-tap-highlight-color: transparent;
32
+ }
33
+
34
+ html, body {
35
+ width: 100%;
36
+ height: 100%;
37
+ overflow: hidden;
38
+ background: var(--background);
39
+ color: var(--text);
40
+ font-family: 'Orbitron', sans-serif;
41
+ }
42
+
43
+ #appContainer {
44
+ position: relative;
45
+ width: 100%;
46
+ height: 100%;
47
+ display: flex;
48
+ justify-content: center;
49
+ align-items: flex-start;
50
+ padding-top: calc(80px + var(--space-md));
51
+ background: radial-gradient(circle at center, var(--surface) 0%, var(--background) 100%);
52
+ }
53
+
54
+ @media (orientation: landscape) {
55
+ #appContainer {
56
+ align-items: center;
57
+ padding-top: 0;
58
+ }
59
+ }
60
+
61
+ #gameCanvas, #guiCanvas, #debugCanvas {
62
+ position: absolute;
63
+ left: 50%;
64
+ transform: translateX(-50%);
65
+ top: calc(80px + var(--space-xl));
66
+ }
67
+
68
+ @media (min-aspect-ratio: 4/3) {
69
+ #gameCanvas, #guiCanvas, #debugCanvas {
70
+ top: 50%;
71
+ transform: translate(-50%, -50%);
72
+ }
73
+ }
74
+
75
+ canvas {
76
+ outline: none !important;
77
+ }
78
+
79
+ .dpad-button {
80
+ width: 60px;
81
+ height: 60px;
82
+ background: rgba(255, 255, 255, 0.1);
83
+ border: 2px solid rgba(255, 255, 255, 0.2);
84
+ border-radius: 10px;
85
+ color: var(--text);
86
+ font-size: 1.5rem;
87
+ pointer-events: auto;
88
+ }
89
+
90
+ .action-button {
91
+ width: 80px;
92
+ height: 80px;
93
+ background: rgba(255, 68, 68, 0.2);
94
+ border: 2px solid rgba(255, 68, 68, 0.4);
95
+ border-radius: 50%;
96
+ color: var(--text);
97
+ font-size: 2rem;
98
+ pointer-events: auto;
99
+ }
100
+
101
+ #dpadUpContainer,
102
+ #dpadLeftContainer,
103
+ #dpadRightContainer,
104
+ #dpadDownContainer,
105
+ #button1Container,
106
+ #button2Container,
107
+ #button3Container,
108
+ #button4Container{
109
+ position: absolute;
110
+ z-index: 50;
111
+ transition: all 0.3s ease;
112
+ }
113
+
114
+ @media (max-aspect-ratio: 3/4) {
115
+ #dpadUpContainer {
116
+ left: calc(25% - 30px);
117
+ top: calc(60px + min(100vw, 100vh) + 10px);
118
+ }
119
+ #dpadLeftContainer {
120
+ left: calc(25% - 90px);
121
+ top: calc(60px + min(100vw, 100vh) + 80px);
122
+ }
123
+ #dpadRightContainer {
124
+ left: calc(25% + 30px);
125
+ top: calc(60px + min(100vw, 100vh) + 80px);
126
+ }
127
+ #dpadDownContainer {
128
+ left: calc(25% - 30px);
129
+ top: calc(60px + min(100vw, 100vh) + 150px);
130
+ }
131
+
132
+ #button1Container {
133
+ right: calc(7% + 30px);
134
+ top: calc(60px + min(100vw, 100vh) + 150px);
135
+ }
136
+ #button2Container {
137
+ right: calc(7% + 90px);
138
+ top: calc(60px + min(100vw, 100vh) + 80px);
139
+ }
140
+ #button3Container {
141
+ right: calc(7% - 30px);
142
+ top: calc(60px + min(100vw, 100vh) + 80px);
143
+ }
144
+ #button4Container {
145
+ right: calc(7% + 30px);
146
+ top: calc(60px + min(100vw, 100vh) + 10px);
147
+ }
148
+ }
149
+
150
+ @media (min-aspect-ratio: 3/4) and (max-aspect-ratio: 4/3) {
151
+ #dpadUpContainer {
152
+ left: calc(var(--space-xl) + 60px);
153
+ bottom: calc(var(--space-xl) + 140px);
154
+ }
155
+ #dpadLeftContainer {
156
+ left: var(--space-xl);
157
+ bottom: calc(var(--space-xl) + 70px);
158
+ }
159
+ #dpadRightContainer {
160
+ left: calc(var(--space-xl) + 120px);
161
+ bottom: calc(var(--space-xl) + 70px);
162
+ }
163
+ #dpadDownContainer {
164
+ left: calc(var(--space-xl) + 60px);
165
+ bottom: var(--space-xl);
166
+ }
167
+
168
+ #button1Container {
169
+ right: calc(var(--space-xl) + 90px);
170
+ bottom: var(--space-xl);
171
+ }
172
+ #button2Container {
173
+ right: calc(var(--space-xl) + 150px);
174
+ bottom: calc(var(--space-xl) + 70px);
175
+ }
176
+ #button3Container {
177
+ right: calc(var(--space-xl) + 30px);
178
+ bottom: calc(var(--space-xl) + 70px);
179
+ }
180
+ #button4Container {
181
+ right: calc(var(--space-xl) + 90px);
182
+ bottom: calc(var(--space-xl) + 140px);
183
+ }
184
+ }
185
+
186
+ @media (min-aspect-ratio: 4/3) {
187
+ #dpadUpContainer {
188
+ left: calc(var(--space-xl) + 60px);
189
+ bottom: calc(33vh + 70px);
190
+ }
191
+ #dpadLeftContainer {
192
+ left: var(--space-xl);
193
+ bottom: 33vh;
194
+ }
195
+ #dpadRightContainer {
196
+ left: calc(var(--space-xl) + 120px);
197
+ bottom: 33vh;
198
+ }
199
+ #dpadDownContainer {
200
+ left: calc(var(--space-xl) + 60px);
201
+ bottom: calc(33vh - 70px);
202
+ }
203
+ #button1Container {
204
+ right: calc(var(--space-xl) + 90px);
205
+ bottom: calc(33vh - 70px);
206
+ }
207
+ #button2Container {
208
+ right: calc(var(--space-xl) + 150px);
209
+ bottom: 33vh;
210
+ }
211
+ #button3Container {
212
+ right: calc(var(--space-xl) + 30px);
213
+ bottom: 33vh;
214
+ }
215
+ #button4Container {
216
+ right: calc(var(--space-xl) + 90px);
217
+ bottom: calc(33vh + 70px);
218
+ }
219
+ }
220
+
221
+ #controlsToggleContainer,
222
+ #soundToggleContainer,
223
+ #fullscreenToggleContainer,
224
+ #pauseButtonContainer {
225
+ position: absolute;
226
+ top: var(--space-md);
227
+ display: flex;
228
+ z-index: 1000;
229
+ }
230
+
231
+ #controlsToggleContainer {
232
+ left: 50%;
233
+ transform: translateX(calc(-170px));
234
+ }
235
+
236
+ #soundToggleContainer {
237
+ left: 50%;
238
+ transform: translateX(calc(-80px));
239
+ }
240
+
241
+ #fullscreenToggleContainer {
242
+ left: 50%;
243
+ transform: translateX(10px);
244
+ }
245
+
246
+ #pauseButtonContainer {
247
+ left: 50%;
248
+ transform: translateX(100px);
249
+ }
250
+
251
+ @media (min-aspect-ratio: 4/3) {
252
+ #controlsToggleContainer {
253
+ left: var(--space-xl);
254
+ transform: none;
255
+ }
256
+
257
+ #soundToggleContainer {
258
+ left: calc(var(--space-xl) + 90px);
259
+ transform: none;
260
+ }
261
+
262
+ #fullscreenToggleContainer {
263
+ right: calc(var(--space-xl) + 90px);
264
+ left: auto;
265
+ transform: none;
266
+ }
267
+
268
+ #pauseButtonContainer {
269
+ right: var(--space-xl);
270
+ left: auto;
271
+ transform: none;
272
+ }
273
+ }
274
+
275
+ .ui-button {
276
+ width: 80px;
277
+ height: 80px;
278
+ background: rgba(255, 255, 255, 0.1);
279
+ border: 1px solid rgba(255, 255, 255, 0.2);
280
+ border-radius: 10px;
281
+ color: var(--text);
282
+ font-size: 1.2rem;
283
+ cursor: pointer;
284
+ }
285
+
286
+ .hidden {
287
+ display: none !important;
288
+ }
289
+
290
+ @keyframes spin {
291
+ to { transform: rotate(360deg); }
292
+ }
293
+
294
+ @media (max-width: 768px) {
295
+ .menu-container {
296
+ width: 90%;
297
+ max-width: 400px;
298
+ padding: var(--space-lg);
299
+ }
300
+
301
+ .dpad-button {
302
+ width: 50px;
303
+ height: 50px;
304
+ }
305
+
306
+ .action-button {
307
+ width: 70px;
308
+ height: 70px;
309
+ }
310
+ }
311
+
312
+ @media (orientation: landscape) and (max-height: 600px) {
313
+ #virtualControls {
314
+ bottom: var(--space-md);
315
+ }
316
+
317
+ .dpad-button {
318
+ width: 40px;
319
+ height: 40px;
320
+ font-size: 1.2rem;
321
+ }
322
+
323
+ .action-button {
324
+ width: 60px;
325
+ height: 60px;
326
+ font-size: 1.5rem;
327
+ }
328
+ }`;
329
+
330
+ const style = document.createElement('style');
331
+ style.textContent = css;
332
+ document.head.appendChild(style);
333
+ })();
334
+
335
+ class App {
336
+ constructor(options = {}) {
337
+ this.threelayersystem = new CanvasManager();
338
+ const canvases = this.threelayersystem.getCanvases();
339
+ this.audio = new ActionAudioManager();
340
+ this.input = new ActionInputHandler(this.audio, canvases);
341
+ this.game = new Game(canvases, this.input, this.audio);
342
+
343
+ // Fixed timestep configuration
344
+ this.fixedTimeStep = options.fixedTimeStep || 1/60; // Default 60Hz
345
+ this.maxAccumulatedTime = options.maxAccumulatedTime || 0.2; // Prevent spiral of death
346
+ this.accumulatedTime = 0;
347
+
348
+ this.lastTime = null;
349
+ // Start the game loop
350
+ console.log("[App] Starting game loop...");
351
+ this.loop();
352
+ }
353
+
354
+ // Engine-driven loop
355
+ loop(timestamp) {
356
+ // Calculate deltaTime (time since last frame in seconds)
357
+ const now = timestamp || performance.now();
358
+ let deltaTime = this.lastTime ? (now - this.lastTime) / 1000 : 0;
359
+ this.lastTime = now;
360
+
361
+ // Cap deltaTime to prevent spiral of death on slow frames
362
+ deltaTime = Math.min(deltaTime, 0.25);
363
+
364
+ // Accumulate time for fixed updates
365
+ this.accumulatedTime += deltaTime;
366
+ this.accumulatedTime = Math.min(this.accumulatedTime, this.maxAccumulatedTime);
367
+
368
+ // Capture input state for this frame (for regular updates)
369
+ this.input.captureKeyState();
370
+ this.input.setContext('update');
371
+
372
+ // Pre-update phase (variable timestep, good for input handling)
373
+ if (typeof this.game.action_pre_update === "function") {
374
+ this.game.action_pre_update(deltaTime);
375
+ }
376
+
377
+ // Process fixed updates for physics and consistent game logic
378
+ if (typeof this.game.action_fixed_update === "function") {
379
+ // Check if we're going to do any physics updates this frame
380
+ if (this.accumulatedTime >= this.fixedTimeStep) {
381
+ // Capture fixed state ONCE before the physics loop starts
382
+ this.input.captureFixedKeyState();
383
+ this.input.setContext('fixed_update');
384
+
385
+ // Run as many fixed updates as needed based on accumulated time
386
+ while (this.accumulatedTime >= this.fixedTimeStep) {
387
+ this.game.action_fixed_update(this.fixedTimeStep);
388
+ this.accumulatedTime -= this.fixedTimeStep;
389
+ }
390
+
391
+ // Reset context back to update after physics is done
392
+ this.input.setContext('update');
393
+ }
394
+ }
395
+
396
+ // Update phase (variable timestep, good for non-physics logic)
397
+ if (typeof this.game.action_update === "function") {
398
+ this.game.action_update(deltaTime);
399
+ }
400
+
401
+ // Post-update phase (variable timestep)
402
+ if (typeof this.game.action_post_update === "function") {
403
+ this.game.action_post_update(deltaTime);
404
+ }
405
+
406
+ // Pre-draw phase
407
+ if (typeof this.game.action_pre_draw === "function") {
408
+ this.game.action_pre_draw();
409
+ }
410
+
411
+ // Draw phase
412
+ if (typeof this.game.action_draw === "function") {
413
+ // Pass an interpolation factor for smooth rendering between fixed steps
414
+ const alpha = this.accumulatedTime / this.fixedTimeStep;
415
+ this.game.action_draw(alpha);
416
+ }
417
+
418
+ // Post-draw phase
419
+ if (typeof this.game.action_post_draw === "function") {
420
+ this.game.action_post_draw();
421
+ }
422
+
423
+ // Schedule the next frame
424
+ requestAnimationFrame((timestamp) => this.loop(timestamp));
425
+ }
426
+ }
427
+
428
+ window.addEventListener("load", () => {
429
+ window.game = new App();
430
+ });