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.
- package/README.md +25 -8
- package/bin/nova64.js +165 -0
- package/dist/assets/console-CY_kygm3.js +14 -0
- package/dist/assets/console-CY_kygm3.js.map +1 -0
- package/dist/assets/main-l0sNRNKZ.js.map +1 -0
- package/dist/assets/sky/studio/nx.png +0 -0
- package/dist/assets/sky/studio/ny.png +0 -0
- package/dist/assets/sky/studio/nz.png +0 -0
- package/dist/assets/sky/studio/px.png +0 -0
- package/dist/assets/sky/studio/py.png +0 -0
- package/dist/assets/sky/studio/pz.png +0 -0
- package/dist/assets/vanilla-Dcuy32gi.js +2 -0
- package/dist/assets/vanilla-Dcuy32gi.js.map +1 -0
- package/dist/console.html +899 -0
- package/dist/docs/BENCHMARK.md +77 -0
- package/dist/docs/CHEATSHEET.md +255 -0
- package/dist/docs/EFFECTS_API_GUIDE.md +577 -0
- package/dist/docs/EFFECTS_QUICK_REFERENCE.md +331 -0
- package/dist/docs/FONT_CHARACTER_REFERENCE.md +219 -0
- package/dist/docs/FREE_GLB_ASSETS.md +330 -0
- package/dist/docs/FULLSCREEN_BUTTON_FEATURE.md +296 -0
- package/dist/docs/GAMEPAD_SUPPORT.md +348 -0
- package/dist/docs/GAME_IMPROVEMENTS.md +278 -0
- package/dist/docs/GAME_QUALITY_STATUS.md +300 -0
- package/dist/docs/MIGRATION_GUIDE.md +553 -0
- package/dist/docs/NOVA64_3D_API.md +356 -0
- package/dist/docs/NOVA64_API_REFERENCE.md +1406 -0
- package/dist/docs/NOVA64_UI_API.md +503 -0
- package/dist/docs/UI_SYSTEM_SUMMARY.md +445 -0
- package/dist/docs/VOXEL_ENGINE_GUIDE.md +662 -0
- package/dist/docs/VOXEL_QUICK_REFERENCE.md +386 -0
- package/dist/docs/api-3d.html +750 -0
- package/dist/docs/api-effects.html +385 -0
- package/dist/docs/api-improvements.md +121 -0
- package/dist/docs/api-skybox.html +407 -0
- package/dist/docs/api-sprites.html +321 -0
- package/dist/docs/api-voxel.html +337 -0
- package/dist/docs/api.html +543 -0
- package/dist/docs/assets.html +306 -0
- package/dist/docs/audio.html +340 -0
- package/dist/docs/blogs.html +286 -0
- package/dist/docs/collision.html +316 -0
- package/dist/docs/console.html +247 -0
- package/dist/docs/editor.html +297 -0
- package/dist/docs/font.html +247 -0
- package/dist/docs/framebuffer.html +247 -0
- package/dist/docs/fullscreen-button.html +297 -0
- package/dist/docs/gpu-systems.html +247 -0
- package/dist/docs/index.html +580 -0
- package/dist/docs/input.html +491 -0
- package/dist/docs/physics.html +311 -0
- package/dist/docs/screens.html +311 -0
- package/dist/docs/storage.html +311 -0
- package/dist/docs/textinput.html +332 -0
- package/dist/docs/ui.html +488 -0
- package/dist/examples/3d-advanced/code.js +695 -0
- package/dist/examples/adventure-comic-3d/code.js +342 -0
- package/dist/examples/audio-lab/code.js +150 -0
- package/dist/examples/boids-flocking/code.js +270 -0
- package/dist/examples/crystal-cathedral-3d/code.js +706 -0
- package/dist/examples/cyberpunk-city-3d/code.js +1383 -0
- package/dist/examples/demoscene/README.md +192 -0
- package/dist/examples/demoscene/code.js +1081 -0
- package/dist/examples/demoscene/meta.json +21 -0
- package/dist/examples/dungeon-crawler-3d/code.js +1117 -0
- package/dist/examples/f-zero-nova-3d/code.js +865 -0
- package/dist/examples/f-zero-nova-3d/code_old.js +1555 -0
- package/dist/examples/fps-demo-3d/code.js +744 -0
- package/dist/examples/game-of-life-3d/code.js +338 -0
- package/dist/examples/generative-art/code.js +632 -0
- package/dist/examples/hello-3d/code.js +325 -0
- package/dist/examples/hello-skybox/code.js +183 -0
- package/dist/examples/hello-world/code.js +19 -0
- package/dist/examples/input-showcase/code.js +109 -0
- package/dist/examples/instancing-demo/code.js +315 -0
- package/dist/examples/minecraft-demo/code.js +387 -0
- package/dist/examples/model-viewer-3d/code.js +114 -0
- package/dist/examples/mystical-realm-3d/code.js +1203 -0
- package/dist/examples/nature-explorer-3d/code.js +1318 -0
- package/dist/examples/particles-demo/code.js +522 -0
- package/dist/examples/pbr-showcase/code.js +140 -0
- package/dist/examples/physics-demo-3d/code.js +948 -0
- package/dist/examples/screen-demo/code.js +267 -0
- package/dist/examples/shooter-demo-3d/code.js +1286 -0
- package/dist/examples/space-combat-3d/IMPLEMENTATION_SUMMARY.md +109 -0
- package/dist/examples/space-combat-3d/README.md +135 -0
- package/dist/examples/space-combat-3d/code.js +1332 -0
- package/dist/examples/space-harrier-3d/code.js +923 -0
- package/dist/examples/star-fox-nova-3d/code.js +1116 -0
- package/dist/examples/star-fox-nova-3d/code_backup.js +410 -0
- package/dist/examples/star-fox-nova-3d/code_broken.js +1821 -0
- package/dist/examples/storage-quest/code.js +209 -0
- package/dist/examples/strider-demo-3d/IMPROVEMENT_OPTIONS.md +285 -0
- package/dist/examples/strider-demo-3d/cache-test.html +132 -0
- package/dist/examples/strider-demo-3d/code-fixed.js +582 -0
- package/dist/examples/strider-demo-3d/code-old.js +1537 -0
- package/dist/examples/strider-demo-3d/code.js +1462 -0
- package/dist/examples/strider-demo-3d/code.js.bak2 +1169 -0
- package/dist/examples/strider-demo-3d/fix-game.sh +53 -0
- package/dist/examples/super-plumber-64/README.md +128 -0
- package/dist/examples/super-plumber-64/code.js +1185 -0
- package/dist/examples/super-plumber-64/index.html +88 -0
- package/dist/examples/test-2d-overlay/code.js +32 -0
- package/dist/examples/test-font/code.js +51 -0
- package/dist/examples/test-minimal/code.js +21 -0
- package/dist/examples/ui-demo/code.js +306 -0
- package/dist/examples/wing-commander-space/README.md +180 -0
- package/dist/examples/wing-commander-space/code.js +1285 -0
- package/dist/examples/wizardry-3d/CHANGELOG.md +366 -0
- package/dist/examples/wizardry-3d/code.js +3928 -0
- package/dist/index.html +666 -0
- package/dist/os9-shell/assets/index-DIHfrTaW.css +1 -0
- package/dist/os9-shell/assets/index-KchE_ngx.js +483 -0
- package/dist/os9-shell/assets/index-KchE_ngx.js.map +1 -0
- package/dist/os9-shell/index.html +23 -0
- package/dist/os9-shell/nova-icon.svg +12 -0
- package/index.html +6 -1
- package/package.json +37 -32
- package/public/assets/sky/studio/nx.png +0 -0
- package/public/assets/sky/studio/ny.png +0 -0
- package/public/assets/sky/studio/nz.png +0 -0
- package/public/assets/sky/studio/px.png +0 -0
- package/public/assets/sky/studio/py.png +0 -0
- package/public/assets/sky/studio/pz.png +0 -0
- package/public/os9-shell/assets/index-KchE_ngx.js +483 -0
- package/public/os9-shell/assets/index-KchE_ngx.js.map +1 -0
- package/public/os9-shell/index.html +10 -1
- package/runtime/api-2d.js +301 -21
- package/runtime/api-3d/pbr.js +45 -1
- package/runtime/api-3d.js +1 -0
- package/runtime/api-effects.js +90 -3
- package/runtime/api-gameutils.js +476 -0
- package/runtime/api-generative.js +610 -0
- package/runtime/api-skybox.js +54 -0
- package/runtime/api-voxel.js +139 -28
- package/runtime/gpu-threejs.js +13 -9
- package/runtime/ui.js +2 -2
- package/src/main.js +24 -1
- package/public/os9-shell/assets/index-B1Uvacma.js +0 -32825
- 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
|
+
}
|