nova64 0.2.4 → 0.2.6

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 (140) hide show
  1. package/README.md +25 -8
  2. package/bin/nova64.js +165 -0
  3. package/dist/assets/console-CY_kygm3.js +14 -0
  4. package/dist/assets/console-CY_kygm3.js.map +1 -0
  5. package/dist/assets/main-l0sNRNKZ.js.map +1 -0
  6. package/dist/assets/sky/studio/nx.png +0 -0
  7. package/dist/assets/sky/studio/ny.png +0 -0
  8. package/dist/assets/sky/studio/nz.png +0 -0
  9. package/dist/assets/sky/studio/px.png +0 -0
  10. package/dist/assets/sky/studio/py.png +0 -0
  11. package/dist/assets/sky/studio/pz.png +0 -0
  12. package/dist/assets/vanilla-Dcuy32gi.js +2 -0
  13. package/dist/assets/vanilla-Dcuy32gi.js.map +1 -0
  14. package/dist/console.html +899 -0
  15. package/dist/docs/BENCHMARK.md +77 -0
  16. package/dist/docs/CHEATSHEET.md +255 -0
  17. package/dist/docs/EFFECTS_API_GUIDE.md +577 -0
  18. package/dist/docs/EFFECTS_QUICK_REFERENCE.md +331 -0
  19. package/dist/docs/FONT_CHARACTER_REFERENCE.md +219 -0
  20. package/dist/docs/FREE_GLB_ASSETS.md +330 -0
  21. package/dist/docs/FULLSCREEN_BUTTON_FEATURE.md +296 -0
  22. package/dist/docs/GAMEPAD_SUPPORT.md +348 -0
  23. package/dist/docs/GAME_IMPROVEMENTS.md +278 -0
  24. package/dist/docs/GAME_QUALITY_STATUS.md +300 -0
  25. package/dist/docs/MIGRATION_GUIDE.md +553 -0
  26. package/dist/docs/NOVA64_3D_API.md +356 -0
  27. package/dist/docs/NOVA64_API_REFERENCE.md +1406 -0
  28. package/dist/docs/NOVA64_UI_API.md +503 -0
  29. package/dist/docs/UI_SYSTEM_SUMMARY.md +445 -0
  30. package/dist/docs/VOXEL_ENGINE_GUIDE.md +662 -0
  31. package/dist/docs/VOXEL_QUICK_REFERENCE.md +386 -0
  32. package/dist/docs/api-3d.html +750 -0
  33. package/dist/docs/api-effects.html +385 -0
  34. package/dist/docs/api-improvements.md +121 -0
  35. package/dist/docs/api-skybox.html +407 -0
  36. package/dist/docs/api-sprites.html +321 -0
  37. package/dist/docs/api-voxel.html +337 -0
  38. package/dist/docs/api.html +543 -0
  39. package/dist/docs/assets.html +306 -0
  40. package/dist/docs/audio.html +340 -0
  41. package/dist/docs/blogs.html +286 -0
  42. package/dist/docs/collision.html +316 -0
  43. package/dist/docs/console.html +247 -0
  44. package/dist/docs/editor.html +297 -0
  45. package/dist/docs/font.html +247 -0
  46. package/dist/docs/framebuffer.html +247 -0
  47. package/dist/docs/fullscreen-button.html +297 -0
  48. package/dist/docs/gpu-systems.html +247 -0
  49. package/dist/docs/index.html +580 -0
  50. package/dist/docs/input.html +491 -0
  51. package/dist/docs/physics.html +311 -0
  52. package/dist/docs/screens.html +311 -0
  53. package/dist/docs/storage.html +311 -0
  54. package/dist/docs/textinput.html +332 -0
  55. package/dist/docs/ui.html +488 -0
  56. package/dist/examples/3d-advanced/code.js +695 -0
  57. package/dist/examples/adventure-comic-3d/code.js +342 -0
  58. package/dist/examples/audio-lab/code.js +150 -0
  59. package/dist/examples/boids-flocking/code.js +270 -0
  60. package/dist/examples/crystal-cathedral-3d/code.js +706 -0
  61. package/dist/examples/cyberpunk-city-3d/code.js +1383 -0
  62. package/dist/examples/demoscene/README.md +192 -0
  63. package/dist/examples/demoscene/code.js +1081 -0
  64. package/dist/examples/demoscene/meta.json +21 -0
  65. package/dist/examples/dungeon-crawler-3d/code.js +1117 -0
  66. package/dist/examples/f-zero-nova-3d/code.js +865 -0
  67. package/dist/examples/f-zero-nova-3d/code_old.js +1555 -0
  68. package/dist/examples/fps-demo-3d/code.js +744 -0
  69. package/dist/examples/game-of-life-3d/code.js +338 -0
  70. package/dist/examples/generative-art/code.js +632 -0
  71. package/dist/examples/hello-3d/code.js +325 -0
  72. package/dist/examples/hello-skybox/code.js +183 -0
  73. package/dist/examples/hello-world/code.js +19 -0
  74. package/dist/examples/input-showcase/code.js +109 -0
  75. package/dist/examples/instancing-demo/code.js +315 -0
  76. package/dist/examples/minecraft-demo/code.js +387 -0
  77. package/dist/examples/model-viewer-3d/code.js +114 -0
  78. package/dist/examples/mystical-realm-3d/code.js +1203 -0
  79. package/dist/examples/nature-explorer-3d/code.js +1318 -0
  80. package/dist/examples/particles-demo/code.js +522 -0
  81. package/dist/examples/pbr-showcase/code.js +140 -0
  82. package/dist/examples/physics-demo-3d/code.js +948 -0
  83. package/dist/examples/screen-demo/code.js +267 -0
  84. package/dist/examples/shooter-demo-3d/code.js +1286 -0
  85. package/dist/examples/space-combat-3d/IMPLEMENTATION_SUMMARY.md +109 -0
  86. package/dist/examples/space-combat-3d/README.md +135 -0
  87. package/dist/examples/space-combat-3d/code.js +1332 -0
  88. package/dist/examples/space-harrier-3d/code.js +923 -0
  89. package/dist/examples/star-fox-nova-3d/code.js +1116 -0
  90. package/dist/examples/star-fox-nova-3d/code_backup.js +410 -0
  91. package/dist/examples/star-fox-nova-3d/code_broken.js +1821 -0
  92. package/dist/examples/storage-quest/code.js +209 -0
  93. package/dist/examples/strider-demo-3d/IMPROVEMENT_OPTIONS.md +285 -0
  94. package/dist/examples/strider-demo-3d/cache-test.html +132 -0
  95. package/dist/examples/strider-demo-3d/code-fixed.js +582 -0
  96. package/dist/examples/strider-demo-3d/code-old.js +1537 -0
  97. package/dist/examples/strider-demo-3d/code.js +1462 -0
  98. package/dist/examples/strider-demo-3d/code.js.bak2 +1169 -0
  99. package/dist/examples/strider-demo-3d/fix-game.sh +53 -0
  100. package/dist/examples/super-plumber-64/README.md +128 -0
  101. package/dist/examples/super-plumber-64/code.js +1185 -0
  102. package/dist/examples/super-plumber-64/index.html +88 -0
  103. package/dist/examples/test-2d-overlay/code.js +32 -0
  104. package/dist/examples/test-font/code.js +51 -0
  105. package/dist/examples/test-minimal/code.js +21 -0
  106. package/dist/examples/ui-demo/code.js +306 -0
  107. package/dist/examples/wing-commander-space/README.md +180 -0
  108. package/dist/examples/wing-commander-space/code.js +1285 -0
  109. package/dist/examples/wizardry-3d/CHANGELOG.md +366 -0
  110. package/dist/examples/wizardry-3d/code.js +3928 -0
  111. package/dist/index.html +666 -0
  112. package/dist/os9-shell/assets/index-DIHfrTaW.css +1 -0
  113. package/dist/os9-shell/assets/index-KchE_ngx.js +483 -0
  114. package/dist/os9-shell/assets/index-KchE_ngx.js.map +1 -0
  115. package/dist/os9-shell/index.html +23 -0
  116. package/dist/os9-shell/nova-icon.svg +12 -0
  117. package/index.html +6 -1
  118. package/package.json +37 -32
  119. package/public/assets/sky/studio/nx.png +0 -0
  120. package/public/assets/sky/studio/ny.png +0 -0
  121. package/public/assets/sky/studio/nz.png +0 -0
  122. package/public/assets/sky/studio/px.png +0 -0
  123. package/public/assets/sky/studio/py.png +0 -0
  124. package/public/assets/sky/studio/pz.png +0 -0
  125. package/public/os9-shell/assets/index-KchE_ngx.js +483 -0
  126. package/public/os9-shell/assets/index-KchE_ngx.js.map +1 -0
  127. package/public/os9-shell/index.html +10 -1
  128. package/runtime/api-2d.js +301 -21
  129. package/runtime/api-3d/pbr.js +45 -1
  130. package/runtime/api-3d.js +1 -0
  131. package/runtime/api-effects.js +90 -3
  132. package/runtime/api-gameutils.js +476 -0
  133. package/runtime/api-generative.js +610 -0
  134. package/runtime/api-skybox.js +54 -0
  135. package/runtime/api-voxel.js +139 -28
  136. package/runtime/gpu-threejs.js +13 -9
  137. package/runtime/ui.js +2 -2
  138. package/src/main.js +24 -1
  139. package/public/os9-shell/assets/index-B1Uvacma.js +0 -32825
  140. package/public/os9-shell/assets/index-B1Uvacma.js.map +0 -1
@@ -0,0 +1,706 @@
1
+ // CRYSTAL CATHEDRAL 3D - Ultimate Nintendo 64/PlayStation visual showcase
2
+ // Demonstrates the most advanced graphics features: holographic materials, dynamic lighting, atmospheric effects
3
+
4
+ let cathedral = {
5
+ pillars: [],
6
+ crystals: [],
7
+ floatingElements: [],
8
+ lightBeams: [],
9
+ particles: [],
10
+ };
11
+
12
+ let camera = {
13
+ angle: 0,
14
+ height: 8,
15
+ radius: 25,
16
+ target: { x: 0, y: 5, z: 0 },
17
+ };
18
+
19
+ let time = 0;
20
+ let musicTime = 0;
21
+ let atmosphereIntensity = 0;
22
+
23
+ // Screen management
24
+ let gameState = 'start'; // 'start', 'viewing'
25
+ let startScreenTime = 0;
26
+ let uiButtons = [];
27
+
28
+ export async function init() {
29
+ cls();
30
+
31
+ console.log('🏛️ Initializing Crystal Cathedral - Ultimate Graphics Showcase...');
32
+
33
+ // Setup dramatic camera
34
+ setCameraPosition(25, 8, 0);
35
+ setCameraTarget(0, 5, 0);
36
+ setCameraFOV(70);
37
+
38
+ // Enable all advanced effects — use real post-processing API
39
+ enablePixelation(1);
40
+ enableDithering(true);
41
+ enableBloom(0.8, 0.4, 0.5); // UnrealBloomPass: strength, radius, threshold
42
+ enableFXAA(); // Smooth jagged edges
43
+ enableVignette(1.4, 0.9); // Cinematic dark border
44
+
45
+ // Build the magnificent cathedral
46
+ await buildCathedral();
47
+ await createFloatingCrystals();
48
+ await addAtmosphericElements();
49
+
50
+ // Set dramatic lighting
51
+ setLightDirection(-0.3, -1, -0.2);
52
+ setLightColor(0xffffff);
53
+ setAmbientLight(0x202040);
54
+ setFog(0x000011, 40, 120);
55
+
56
+ // Initialize start screen
57
+ initStartScreen();
58
+
59
+ console.log('✨ Crystal Cathedral loaded - Experience ultimate 3D graphics!');
60
+ }
61
+
62
+ function initStartScreen() {
63
+ uiButtons = [];
64
+
65
+ // Enter cathedral button
66
+ uiButtons.push(
67
+ createButton(
68
+ centerX(240),
69
+ 150,
70
+ 240,
71
+ 60,
72
+ '◆ ENTER CATHEDRAL ◆',
73
+ () => {
74
+ console.log('🎯 ENTER CATHEDRAL CLICKED! Changing gameState to viewing...');
75
+ gameState = 'viewing';
76
+ console.log('✅ gameState is now:', gameState);
77
+ },
78
+ {
79
+ normalColor: rgba8(70, 150, 255, 255),
80
+ hoverColor: rgba8(100, 180, 255, 255),
81
+ pressedColor: rgba8(40, 120, 220, 255),
82
+ }
83
+ )
84
+ );
85
+
86
+ // Features button
87
+ uiButtons.push(
88
+ createButton(
89
+ centerX(200),
90
+ 355,
91
+ 200,
92
+ 45,
93
+ '✨ FEATURES',
94
+ () => {
95
+ console.log('Crystal Cathedral - Advanced graphics showcase');
96
+ },
97
+ {
98
+ normalColor: rgba8(100, 200, 255, 255),
99
+ hoverColor: rgba8(130, 220, 255, 255),
100
+ pressedColor: rgba8(70, 170, 230, 255),
101
+ }
102
+ )
103
+ );
104
+ }
105
+
106
+ async function buildCathedral() {
107
+ console.log('🏗️ Building Crystal Cathedral...');
108
+
109
+ // Create magnificent crystal floor
110
+ const floor = createAdvancedCube(
111
+ 1,
112
+ {
113
+ color: 0x111144,
114
+ emissive: 0x000022,
115
+ emissiveIntensity: 0.3,
116
+ metallic: true,
117
+ animated: true,
118
+ },
119
+ [0, -1, 0]
120
+ );
121
+ setScale(floor, 60, 0.5, 60);
122
+
123
+ // Create towering crystal pillars in a circle
124
+ for (let i = 0; i < 12; i++) {
125
+ const angle = (i / 12) * Math.PI * 2;
126
+ const x = Math.cos(angle) * 20;
127
+ const z = Math.sin(angle) * 20;
128
+ const height = 15 + Math.sin(i * 0.5) * 5;
129
+
130
+ // Main pillar
131
+ const pillar = createAdvancedCube(
132
+ 1,
133
+ {
134
+ color: 0x4488ff,
135
+ emissive: 0x112244,
136
+ emissiveIntensity: 0.6,
137
+ metallic: true,
138
+ holographic: i % 3 === 0,
139
+ animated: true,
140
+ },
141
+ [x, height / 2, z]
142
+ );
143
+ setScale(pillar, 2, height, 2);
144
+
145
+ // Crystal cap
146
+ const cap = createAdvancedSphere(
147
+ 1.5,
148
+ {
149
+ color: 0x88ddff,
150
+ emissive: 0x224488,
151
+ emissiveIntensity: 0.8,
152
+ holographic: true,
153
+ animated: true,
154
+ transparent: true,
155
+ opacity: 0.9,
156
+ },
157
+ [x, height + 1, z],
158
+ 16
159
+ );
160
+
161
+ cathedral.pillars.push({
162
+ main: pillar,
163
+ cap: cap,
164
+ x,
165
+ z,
166
+ height,
167
+ glowPhase: Math.random() * Math.PI * 2,
168
+ originalHeight: height,
169
+ });
170
+ }
171
+
172
+ // Create central altar with ultimate crystal
173
+ const altarBase = createAdvancedCube(
174
+ 1,
175
+ {
176
+ color: 0x666699,
177
+ emissive: 0x111133,
178
+ emissiveIntensity: 0.4,
179
+ metallic: true,
180
+ animated: true,
181
+ },
182
+ [0, 1, 0]
183
+ );
184
+ setScale(altarBase, 6, 2, 6);
185
+
186
+ const masterCrystal = createAdvancedSphere(
187
+ 2,
188
+ {
189
+ color: 0xffffff,
190
+ emissive: 0x444488,
191
+ emissiveIntensity: 1.2,
192
+ holographic: true,
193
+ animated: true,
194
+ transparent: true,
195
+ opacity: 0.8,
196
+ },
197
+ [0, 4, 0],
198
+ 20
199
+ );
200
+
201
+ cathedral.masterCrystal = {
202
+ mesh: masterCrystal,
203
+ rotationSpeed: 0.5,
204
+ pulsePhase: 0,
205
+ };
206
+
207
+ // Create crystal archways
208
+ for (let i = 0; i < 6; i++) {
209
+ const angle = (i / 6) * Math.PI * 2;
210
+ const radius = 35;
211
+ const x = Math.cos(angle) * radius;
212
+ const z = Math.sin(angle) * radius;
213
+
214
+ // Arch supports
215
+ const support1 = createAdvancedCube(
216
+ 1,
217
+ {
218
+ color: 0x8844ff,
219
+ emissive: 0x221144,
220
+ emissiveIntensity: 0.5,
221
+ holographic: true,
222
+ animated: true,
223
+ },
224
+ [x - 3, 6, z]
225
+ );
226
+ setScale(support1, 1.5, 12, 1.5);
227
+
228
+ const support2 = createAdvancedCube(
229
+ 1,
230
+ {
231
+ color: 0x8844ff,
232
+ emissive: 0x221144,
233
+ emissiveIntensity: 0.5,
234
+ holographic: true,
235
+ animated: true,
236
+ },
237
+ [x + 3, 6, z]
238
+ );
239
+ setScale(support2, 1.5, 12, 1.5);
240
+
241
+ // Arch top
242
+ const archTop = createAdvancedCube(
243
+ 1,
244
+ {
245
+ color: 0xaa66ff,
246
+ emissive: 0x332244,
247
+ emissiveIntensity: 0.7,
248
+ holographic: true,
249
+ animated: true,
250
+ transparent: true,
251
+ opacity: 0.9,
252
+ },
253
+ [x, 11, z]
254
+ );
255
+ setScale(archTop, 8, 2, 2);
256
+ }
257
+ }
258
+
259
+ async function createFloatingCrystals() {
260
+ console.log('💎 Creating floating crystal formation...');
261
+
262
+ // Create floating crystal clusters at different heights
263
+ for (let layer = 0; layer < 4; layer++) {
264
+ const numCrystals = 8 - layer * 2;
265
+ const radius = 12 + layer * 4;
266
+ const height = 8 + layer * 6;
267
+
268
+ for (let i = 0; i < numCrystals; i++) {
269
+ const angle = (i / numCrystals) * Math.PI * 2 + layer * 0.5;
270
+ const x = Math.cos(angle) * radius;
271
+ const z = Math.sin(angle) * radius;
272
+
273
+ const crystal = createAdvancedSphere(
274
+ 0.8 + layer * 0.2,
275
+ {
276
+ color: layer % 2 === 0 ? 0xff88aa : 0x88aaff,
277
+ emissive: layer % 2 === 0 ? 0x441122 : 0x112244,
278
+ emissiveIntensity: 0.9,
279
+ holographic: true,
280
+ animated: true,
281
+ transparent: true,
282
+ opacity: 0.85,
283
+ },
284
+ [x, height, z],
285
+ 12
286
+ );
287
+
288
+ cathedral.floatingElements.push({
289
+ mesh: crystal,
290
+ x,
291
+ y: height,
292
+ z,
293
+ originalY: height,
294
+ rotationSpeed: 0.5 + Math.random() * 1,
295
+ orbitSpeed: 0.2 + layer * 0.1,
296
+ orbitRadius: radius,
297
+ orbitPhase: angle,
298
+ bobPhase: Math.random() * Math.PI * 2,
299
+ layer,
300
+ });
301
+ }
302
+ }
303
+
304
+ // Create spiral of energy crystals
305
+ for (let i = 0; i < 20; i++) {
306
+ const spiralPhase = (i / 20) * Math.PI * 4;
307
+ const spiralRadius = 8 + Math.sin(spiralPhase) * 3;
308
+ const x = Math.cos(spiralPhase) * spiralRadius;
309
+ const z = Math.sin(spiralPhase) * spiralRadius;
310
+ const y = 2 + i * 0.8;
311
+
312
+ const energyCrystal = createAdvancedSphere(
313
+ 0.3,
314
+ {
315
+ color: 0xffff44,
316
+ emissive: 0x444411,
317
+ emissiveIntensity: 1.1,
318
+ holographic: true,
319
+ animated: true,
320
+ transparent: true,
321
+ opacity: 0.7,
322
+ },
323
+ [x, y, z],
324
+ 8
325
+ );
326
+
327
+ cathedral.crystals.push({
328
+ mesh: energyCrystal,
329
+ x,
330
+ y,
331
+ z,
332
+ spiralPhase,
333
+ spiralIndex: i,
334
+ });
335
+ }
336
+ }
337
+
338
+ async function addAtmosphericElements() {
339
+ console.log('🌟 Adding atmospheric elements...');
340
+
341
+ // Create light beam effects (simulated with transparent planes)
342
+ for (let i = 0; i < 6; i++) {
343
+ const angle = (i / 6) * Math.PI * 2;
344
+ const x = Math.cos(angle) * 15;
345
+ const z = Math.sin(angle) * 15;
346
+
347
+ const lightBeam = createPlane(2, 20, 0xffffff, [x, 10, z]);
348
+ setRotation(lightBeam, 0, angle, 0);
349
+
350
+ cathedral.lightBeams.push({
351
+ mesh: lightBeam,
352
+ angle,
353
+ intensity: Math.random(),
354
+ });
355
+ }
356
+ }
357
+
358
+ export function update(dt) {
359
+ time += dt;
360
+ musicTime += dt * 0.5; // Slower for atmospheric effect
361
+ atmosphereIntensity = (Math.sin(musicTime) + 1) * 0.5;
362
+
363
+ if (gameState === 'start') {
364
+ startScreenTime += dt;
365
+ updateAllButtons();
366
+
367
+ // Still animate scene in background
368
+ updateCamera(dt);
369
+ updatePillars(dt);
370
+ updateFloatingElements(dt);
371
+ updateMasterCrystal(dt);
372
+ updateSpiral(dt);
373
+ return;
374
+ }
375
+
376
+ // Viewing state
377
+ // Update camera orbit
378
+ updateCamera(dt);
379
+
380
+ // Update cathedral elements
381
+ updatePillars(dt);
382
+ updateFloatingElements(dt);
383
+ updateMasterCrystal(dt);
384
+ updateSpiral(dt);
385
+ updateAtmosphere(dt);
386
+
387
+ // Dynamic lighting effects
388
+ updateDynamicLighting(dt);
389
+ }
390
+
391
+ function updateCamera(dt) {
392
+ camera.angle += dt * 0.3;
393
+ camera.height = 8 + Math.sin(time * 0.4) * 3;
394
+
395
+ const x = Math.cos(camera.angle) * camera.radius;
396
+ const z = Math.sin(camera.angle) * camera.radius;
397
+
398
+ setCameraPosition(x, camera.height, z);
399
+ setCameraTarget(camera.target.x, camera.target.y, camera.target.z);
400
+ }
401
+
402
+ function updatePillars(dt) {
403
+ cathedral.pillars.forEach((pillar, index) => {
404
+ pillar.glowPhase += dt * 2;
405
+
406
+ // Subtle height animation
407
+ const heightVariation = Math.sin(pillar.glowPhase + index) * 0.5;
408
+ const newHeight = pillar.originalHeight + heightVariation;
409
+ setScale(pillar.main, 2, newHeight, 2);
410
+ setPosition(pillar.main, pillar.x, newHeight / 2, pillar.z);
411
+ setPosition(pillar.cap, pillar.x, newHeight + 1, pillar.z);
412
+
413
+ // Rotation
414
+ rotateMesh(pillar.cap, 0, dt * 0.5, 0);
415
+ });
416
+ }
417
+
418
+ function updateFloatingElements(dt) {
419
+ cathedral.floatingElements.forEach(element => {
420
+ // Orbital motion
421
+ element.orbitPhase += dt * element.orbitSpeed;
422
+ element.x = Math.cos(element.orbitPhase) * element.orbitRadius;
423
+ element.z = Math.sin(element.orbitPhase) * element.orbitRadius;
424
+
425
+ // Vertical bobbing
426
+ element.bobPhase += dt * 3;
427
+ const bobY = Math.sin(element.bobPhase) * 1.5;
428
+ element.y = element.originalY + bobY;
429
+
430
+ // Update position and rotation
431
+ setPosition(element.mesh, element.x, element.y, element.z);
432
+ rotateMesh(element.mesh, dt * element.rotationSpeed, dt * element.rotationSpeed * 0.7, 0);
433
+ });
434
+ }
435
+
436
+ function updateMasterCrystal(dt) {
437
+ if (cathedral.masterCrystal) {
438
+ cathedral.masterCrystal.pulsePhase += dt * 4;
439
+
440
+ // Pulsing scale effect
441
+ const pulseScale = 1 + Math.sin(cathedral.masterCrystal.pulsePhase) * 0.2;
442
+ setScale(cathedral.masterCrystal.mesh, pulseScale, pulseScale, pulseScale);
443
+
444
+ // Rotation
445
+ rotateMesh(cathedral.masterCrystal.mesh, 0, dt * cathedral.masterCrystal.rotationSpeed, 0);
446
+
447
+ // Vertical floating motion
448
+ const floatY = 4 + Math.sin(time * 2) * 1;
449
+ setPosition(cathedral.masterCrystal.mesh, 0, floatY, 0);
450
+ }
451
+ }
452
+
453
+ function updateSpiral(dt) {
454
+ cathedral.crystals.forEach(crystal => {
455
+ crystal.spiralPhase += dt * 2;
456
+
457
+ const spiralRadius = 8 + Math.sin(crystal.spiralPhase) * 3;
458
+ const x = Math.cos(crystal.spiralPhase) * spiralRadius;
459
+ const z = Math.sin(crystal.spiralPhase) * spiralRadius;
460
+ const y = crystal.y + Math.sin(time + crystal.spiralIndex * 0.5) * 0.5;
461
+
462
+ setPosition(crystal.mesh, x, y, z);
463
+ rotateMesh(crystal.mesh, dt, dt * 2, dt * 0.5);
464
+ });
465
+ }
466
+
467
+ function updateAtmosphere(dt) {
468
+ // Update light beams
469
+ cathedral.lightBeams.forEach((beam, index) => {
470
+ beam.intensity += dt * 2;
471
+ const alpha = (Math.sin(beam.intensity + index) + 1) * 0.3 + 0.1;
472
+ // Note: In a real implementation, we would update material opacity here
473
+ });
474
+ }
475
+
476
+ function updateDynamicLighting(dt) {
477
+ // Cycle through different lighting moods
478
+ const lightPhase = time * 0.3;
479
+
480
+ // Main light color cycling
481
+ const hue = Math.sin(lightPhase) * 180 + 180;
482
+ const lightColor = hslToHex(hue, 70, 80);
483
+ setLightColor(lightColor);
484
+
485
+ // Ambient light pulsing
486
+ const ambientIntensity = 0x202040 + Math.floor(atmosphereIntensity * 0x202020);
487
+ setAmbientLight(ambientIntensity);
488
+
489
+ // Fog color changes
490
+ const fogHue = Math.sin(lightPhase * 0.7) * 60 + 240; // Blue to purple range
491
+ const fogColor = hslToHex(fogHue, 50, 10);
492
+ setFog(fogColor, 40, 120);
493
+ }
494
+
495
+ function hslToHex(h, s, l) {
496
+ l /= 100;
497
+ const a = (s * Math.min(l, 1 - l)) / 100;
498
+ const f = n => {
499
+ const k = (n + h / 30) % 12;
500
+ const color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
501
+ return Math.round(255 * color);
502
+ };
503
+ return (f(0) << 16) | (f(8) << 8) | f(4);
504
+ }
505
+
506
+ export function draw() {
507
+ if (gameState === 'start') {
508
+ drawStartScreen();
509
+ return;
510
+ }
511
+
512
+ // Viewing - Atmospheric UI with dynamic colors
513
+ const titleColor = hslToHex((time * 50) % 360, 80, 70);
514
+ const accentColor = hslToHex((time * 30 + 180) % 360, 70, 60);
515
+
516
+ print('🏛️ CRYSTAL CATHEDRAL', 8, 8, titleColor);
517
+ print('Ultimate Nintendo 64 / PlayStation Graphics Showcase', 8, 24, accentColor);
518
+
519
+ // Atmosphere info
520
+ const moodNames = ['Mystical', 'Ethereal', 'Transcendent', 'Divine', 'Cosmic'];
521
+ const currentMood = moodNames[Math.floor(atmosphereIntensity * moodNames.length)];
522
+ print(
523
+ `Atmosphere: ${currentMood} | Intensity: ${(atmosphereIntensity * 100).toFixed(0)}%`,
524
+ 8,
525
+ 50,
526
+ rgba8(200, 150, 255, 255)
527
+ );
528
+
529
+ // Crystal count
530
+ const totalCrystals = cathedral.floatingElements.length + cathedral.crystals.length + 1;
531
+ print(
532
+ `Sacred Crystals: ${totalCrystals} | Pillars: ${cathedral.pillars.length}`,
533
+ 8,
534
+ 66,
535
+ rgba8(150, 200, 255, 255)
536
+ );
537
+
538
+ // Visual effects status
539
+ print(
540
+ 'Effects: Holographic + Bloom + Motion + Dynamic Lighting',
541
+ 8,
542
+ 82,
543
+ rgba8(255, 200, 100, 255)
544
+ );
545
+
546
+ // Advanced 3D stats
547
+ const stats = get3DStats();
548
+ if (stats && stats.render) {
549
+ const objectCount =
550
+ cathedral.pillars.length * 2 +
551
+ cathedral.floatingElements.length +
552
+ cathedral.crystals.length +
553
+ 10;
554
+ print(`3D Objects: ${objectCount} | GPU: Three.js Advanced`, 8, 108, rgba8(150, 150, 255, 255));
555
+ print(
556
+ `Shadows: Ultra | Materials: Holographic | Lighting: Dynamic`,
557
+ 8,
558
+ 124,
559
+ rgba8(150, 150, 255, 255)
560
+ );
561
+ }
562
+
563
+ // Experience description
564
+ print(
565
+ 'Witness the ultimate fusion of retro and modern 3D graphics!',
566
+ 8,
567
+ 300,
568
+ rgba8(255, 255, 100, 200)
569
+ );
570
+ print(
571
+ 'Nintendo 64/PlayStation aesthetics with cutting-edge effects!',
572
+ 8,
573
+ 316,
574
+ rgba8(100, 255, 255, 180)
575
+ );
576
+ print(
577
+ 'Camera automatically orbits - sit back and enjoy the show!',
578
+ 8,
579
+ 332,
580
+ rgba8(100, 255, 100, 160)
581
+ );
582
+
583
+ // Dynamic status indicators
584
+ const pulseAlpha = Math.floor((Math.sin(time * 8) + 1) * 127 + 128);
585
+ print('🔮 TRANSCENDENT EXPERIENCE ACTIVE 🔮', 200, 8, rgba8(255, 100, 255, pulseAlpha));
586
+ }
587
+
588
+ function drawStartScreen() {
589
+ // Deep space gradient background
590
+ drawGradient(0, 0, 640, 360, rgba8(5, 10, 40, 245), rgba8(10, 30, 60, 230), 'v');
591
+
592
+ // Radial glow behind title
593
+ drawRadialGradient(320, 100, 220, rgba8(0, 140, 255, 55), rgba8(0, 0, 0, 0));
594
+
595
+ // Noise grain for depth
596
+ drawNoise(0, 0, 640, 360, 12, Math.floor(startScreenTime * 10));
597
+
598
+ // Corner starbursts
599
+ const cornerPulse = Math.sin(startScreenTime * 2) * 0.5 + 0.5;
600
+ drawStarburst(28, 28, 18, 8, 6, rgba8(100, 200, 255, Math.floor(cornerPulse * 210)), true);
601
+ drawStarburst(612, 28, 18, 8, 6, rgba8(100, 200, 255, Math.floor(cornerPulse * 210)), true);
602
+ drawStarburst(28, 332, 13, 5, 5, rgba8(60, 150, 255, Math.floor(cornerPulse * 160)), true);
603
+ drawStarburst(612, 332, 13, 5, 5, rgba8(60, 150, 255, Math.floor(cornerPulse * 160)), true);
604
+
605
+ // Animated holographic title
606
+ const hueShift = (startScreenTime * 50) % 360;
607
+ const hologramColor = hslToRgba8(hueShift, 80, 70, 255);
608
+ const float = Math.sin(startScreenTime * 2) * 10;
609
+
610
+ drawGlowTextCentered('CRYSTAL', 320, 48 + float, hologramColor, rgba8(0, 80, 200, 180), 2);
611
+ drawGlowTextCentered(
612
+ 'CATHEDRAL',
613
+ 320,
614
+ 100 + float,
615
+ rgba8(100, 220, 255, 255),
616
+ rgba8(0, 40, 120, 160),
617
+ 2
618
+ );
619
+
620
+ // Holographic subtitle
621
+ setFont('large');
622
+ setTextAlign('center');
623
+ const pulse = Math.sin(startScreenTime * 4) * 0.2 + 0.8;
624
+ drawText(
625
+ '◆ Ultimate Graphics Showcase ◆',
626
+ 320,
627
+ 162,
628
+ rgba8(150, 220, 255, Math.floor(pulse * 255)),
629
+ 1
630
+ );
631
+
632
+ // Info panel with holographic border
633
+ const panel = createPanel(centerX(480), 208, 480, 118, {
634
+ bgColor: rgba8(10, 25, 50, 210),
635
+ borderColor: rgba8(70, 150, 255, 255),
636
+ borderWidth: 3,
637
+ shadow: true,
638
+ gradient: true,
639
+ gradientColor: rgba8(20, 40, 80, 210),
640
+ });
641
+ drawPanel(panel);
642
+
643
+ setFont('normal');
644
+ setTextAlign('center');
645
+ drawText('ADVANCED FEATURES', 320, 225, rgba8(100, 200, 255, 255), 1);
646
+
647
+ setFont('small');
648
+ drawText('◆ Holographic Materials & Dynamic Lighting', 320, 247, uiColors.light, 1);
649
+ drawText('◆ Motion Blur, Bloom & Atmospheric Effects', 320, 262, uiColors.light, 1);
650
+ drawText('◆ 12 Sacred Pillars + Floating Crystal Array', 320, 277, uiColors.light, 1);
651
+ drawText('◆ Nintendo 64 / PlayStation Retro Aesthetics', 320, 292, uiColors.light, 1);
652
+
653
+ setFont('tiny');
654
+ drawText('Camera orbits automatically - Pure visual experience', 320, 310, uiColors.secondary, 1);
655
+
656
+ // Draw buttons
657
+ drawAllButtons();
658
+
659
+ // Pulsing crystal prompt
660
+ const alpha = Math.floor((Math.sin(startScreenTime * 5) * 0.5 + 0.5) * 255);
661
+ setFont('normal');
662
+ drawText('◆ WITNESS THE ULTIMATE 3D GRAPHICS ◆', 320, 430, rgba8(100, 200, 255, alpha), 1);
663
+
664
+ // Tech info
665
+ setFont('tiny');
666
+ drawText('Powered by Three.js + WebGL 2.0', 320, 340, rgba8(120, 160, 200, 150), 1);
667
+
668
+ // CRT scanlines for retro feel
669
+ drawScanlines(40, 2);
670
+ }
671
+
672
+ // Helper to convert HSL to rgba8
673
+ function hslToRgba8(h, s, l, a) {
674
+ const c = ((1 - Math.abs((2 * l) / 100 - 1)) * s) / 100;
675
+ const x = c * (1 - Math.abs(((h / 60) % 2) - 1));
676
+ const m = l / 100 - c / 2;
677
+
678
+ let r, g, b;
679
+ if (h < 60) {
680
+ r = c;
681
+ g = x;
682
+ b = 0;
683
+ } else if (h < 120) {
684
+ r = x;
685
+ g = c;
686
+ b = 0;
687
+ } else if (h < 180) {
688
+ r = 0;
689
+ g = c;
690
+ b = x;
691
+ } else if (h < 240) {
692
+ r = 0;
693
+ g = x;
694
+ b = c;
695
+ } else if (h < 300) {
696
+ r = x;
697
+ g = 0;
698
+ b = c;
699
+ } else {
700
+ r = c;
701
+ g = 0;
702
+ b = x;
703
+ }
704
+
705
+ return rgba8(Math.floor((r + m) * 255), Math.floor((g + m) * 255), Math.floor((b + m) * 255), a);
706
+ }