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,88 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Super Plumber 64 - Nova64</title>
7
+ <style>
8
+ body {
9
+ margin: 0;
10
+ padding: 0;
11
+ background: #111;
12
+ display: flex;
13
+ justify-content: center;
14
+ align-items: center;
15
+ min-height: 100vh;
16
+ font-family: 'Courier New', monospace;
17
+ color: white;
18
+ }
19
+ #game-container {
20
+ position: relative;
21
+ max-width: 100vw;
22
+ max-height: 100vh;
23
+ }
24
+ canvas {
25
+ display: block;
26
+ image-rendering: pixelated;
27
+ image-rendering: crisp-edges;
28
+ }
29
+ #loading {
30
+ position: absolute;
31
+ top: 50%;
32
+ left: 50%;
33
+ transform: translate(-50%, -50%);
34
+ text-align: center;
35
+ font-size: 24px;
36
+ color: #ff0000;
37
+ text-shadow: 2px 2px 4px #000;
38
+ }
39
+ </style>
40
+ </head>
41
+ <body>
42
+ <div id="game-container">
43
+ <div id="loading">🎮 Loading Super Plumber 64...</div>
44
+ <canvas id="screen"></canvas>
45
+ </div>
46
+ <script type="module">
47
+ import { createRuntime } from '../../runtime/core.js';
48
+
49
+ const loadingEl = document.getElementById('loading');
50
+
51
+ async function startGame() {
52
+ try {
53
+ loadingEl.textContent = '🎮 Initializing Nova64...';
54
+
55
+ const gameModule = await import('./code.js');
56
+
57
+ loadingEl.textContent = '🎮 Starting Super Plumber 64...';
58
+
59
+ const runtime = createRuntime({
60
+ canvas: document.getElementById('screen'),
61
+ width: 640,
62
+ height: 360,
63
+ scale: 2,
64
+ game: gameModule
65
+ });
66
+
67
+ runtime.start();
68
+
69
+ loadingEl.style.display = 'none';
70
+
71
+ console.log('🎮 SUPER PLUMBER 64 - Ready!');
72
+ console.log('Controls:');
73
+ console.log(' Arrow Keys / WASD - Move');
74
+ console.log(' Space / Z - Jump (triple jump!)');
75
+ console.log(' Down + Jump in air - Ground Pound');
76
+ console.log(' Q/E - Rotate Camera');
77
+ console.log(' Gamepad supported!');
78
+ } catch (error) {
79
+ console.error('Failed to start game:', error);
80
+ loadingEl.textContent = '❌ Error loading game. Check console.';
81
+ loadingEl.style.color = '#ff0000';
82
+ }
83
+ }
84
+
85
+ startGame();
86
+ </script>
87
+ </body>
88
+ </html>
@@ -0,0 +1,32 @@
1
+ // MINIMAL 2D OVERLAY TEST - Tests if 2D rendering works AT ALL
2
+
3
+ let testTime = 0;
4
+
5
+ export async function init() {
6
+ console.log('🧪 MINIMAL 2D OVERLAY TEST - Starting...');
7
+
8
+ // Just setup a basic 3D scene so we have something
9
+ setCameraPosition(0, 5, 15);
10
+ setCameraTarget(0, 0, 0);
11
+
12
+ // Create one cube so we know 3D works
13
+ const cube = createCube(2, 0xff0000, [0, 0, 0]);
14
+ console.log('✅ Created test cube');
15
+ }
16
+
17
+ export function update(dt) {
18
+ testTime += dt;
19
+ }
20
+
21
+ export function draw() {
22
+ // ABSOLUTE SIMPLEST 2D DRAWING - Just a filled rectangle
23
+ console.log('🎨 Drawing 2D overlay...');
24
+
25
+ // Try to draw a big red rectangle
26
+ rect(100, 100, 400, 200, rgba8(255, 0, 0, 255), true);
27
+
28
+ // Try to draw text
29
+ print('HELLO 2D OVERLAY', 150, 150, rgba8(255, 255, 0, 255), 1);
30
+
31
+ console.log('✅ Draw calls completed');
32
+ }
@@ -0,0 +1,51 @@
1
+ // Font Test - Complete Character Set Demo
2
+ // Testing uppercase, lowercase, symbols, arrows, and emoji handling
3
+
4
+ export async function init() {
5
+ console.log('🔤 Font Test - Complete Character Set');
6
+ }
7
+
8
+ export function update() {}
9
+
10
+ export function draw() {
11
+ cls(rgba8(20, 20, 40, 255));
12
+
13
+ // Title
14
+ print('NOVA64 FONT - COMPLETE TEST', 140, 10, rgba8(255, 200, 0, 255), 1);
15
+
16
+ // Uppercase
17
+ print('UPPERCASE: ABCDEFGHIJKLMNOPQRSTUVWXYZ', 20, 35, rgba8(255, 255, 255, 255), 1);
18
+
19
+ // Lowercase
20
+ print('lowercase: abcdefghijklmnopqrstuvwxyz', 20, 52, rgba8(0, 255, 200, 255), 1);
21
+
22
+ // Numbers
23
+ print('Numbers: 0123456789', 20, 69, rgba8(255, 255, 100, 255), 1);
24
+
25
+ // Punctuation
26
+ print("Symbols: !?.,;:'-_()[]{}", 20, 86, rgba8(255, 150, 255, 255), 1);
27
+ print(' <>=+*&%$#@^~`"|\\/', 20, 103, rgba8(255, 150, 255, 255), 1);
28
+
29
+ // Arrows (Unicode)
30
+ print('Arrows: ← → ↑ ↓ ↔ ↕', 20, 120, rgba8(100, 255, 100, 255), 1);
31
+ print('Controls: ↑↓ UP/DOWN ←→ LEFT/RIGHT', 20, 137, rgba8(200, 200, 255, 255), 1);
32
+
33
+ // Mixed case examples
34
+ print('Mixed: Hello World! The Quick Brown Fox', 20, 154, rgba8(255, 200, 150, 255), 1);
35
+ print(' Jumps Over The Lazy Dog 123!', 20, 171, rgba8(255, 200, 150, 255), 1);
36
+
37
+ // Emoji handling (should strip or replace)
38
+ print('Emoji Test: 🎮 🚀 ⚡ ✨ (cleaned automatically)', 20, 195, rgba8(255, 100, 100, 255), 1);
39
+
40
+ // Game-style text examples
41
+ print('Game Text:', 20, 219, rgba8(0, 255, 255, 255), 1);
42
+ print(' SCORE: 1234567890', 20, 236, rgba8(255, 255, 0, 255), 1);
43
+ print(' HEALTH: [##########] 100%', 20, 253, rgba8(0, 255, 0, 255), 1);
44
+ print(' Press X to Fire! Press Z for Boost!', 20, 270, rgba8(200, 200, 200, 255), 1);
45
+
46
+ // Status
47
+ rect(20, 295, 600, 50, rgba8(0, 0, 0, 200), true);
48
+ rect(20, 295, 600, 50, rgba8(0, 255, 0, 255), false);
49
+ print('✅ All Characters Rendering Correctly!', 35, 303, rgba8(0, 255, 100, 255), 1);
50
+ print('No more ??? for lowercase, arrows, or emojis!', 35, 320, rgba8(150, 255, 150, 255), 1);
51
+ }
@@ -0,0 +1,21 @@
1
+ // ABSOLUTE MINIMUM TEST - Does 2D work at all?
2
+
3
+ export async function init() {
4
+ console.log('⚡ ULTRA SIMPLE TEST');
5
+ }
6
+
7
+ export function update(dt) {
8
+ // Nothing
9
+ }
10
+
11
+ export function draw() {
12
+ // Draw ONE red rectangle - simplest possible test
13
+ console.log('🎨 Attempting to draw red rectangle...');
14
+ rect(50, 50, 200, 100, rgba8(255, 0, 0, 255), true);
15
+ console.log('✅ rect() called successfully');
16
+
17
+ // Draw text
18
+ console.log('🎨 Attempting to draw text...');
19
+ print('TEST TEXT', 100, 100, rgba8(255, 255, 0, 255), 1);
20
+ console.log('✅ print() called successfully');
21
+ }
@@ -0,0 +1,306 @@
1
+ // 🎨 Nova64 UI System Demo - First Class Interface
2
+ // Showcases all professional UI components
3
+
4
+ let demo = {
5
+ panel1: null,
6
+ panel2: null,
7
+ panel3: null,
8
+ buttons: [],
9
+ health: 75,
10
+ mana: 50,
11
+ exp: 380,
12
+ maxExp: 1000,
13
+ score: 12345,
14
+ time: 0,
15
+ };
16
+
17
+ export async function init() {
18
+ console.log('🎨 Nova64 UI System Demo - Loading...');
19
+
20
+ // Create demo panels
21
+ demo.panel1 = createPanel(20, 20, 280, 200, {
22
+ title: 'Player Stats',
23
+ borderColor: uiColors.primary,
24
+ shadow: true,
25
+ gradient: true,
26
+ });
27
+
28
+ demo.panel2 = createPanel(320, 20, 300, 150, {
29
+ title: 'Control Panel',
30
+ borderColor: uiColors.success,
31
+ shadow: true,
32
+ bgColor: rgba8(20, 40, 60, 220),
33
+ });
34
+
35
+ demo.panel3 = createPanel(20, 240, 600, 100, {
36
+ title: 'Button Showcase',
37
+ borderColor: uiColors.warning,
38
+ shadow: true,
39
+ });
40
+
41
+ // Create demo buttons
42
+ demo.buttons.push(
43
+ createButton(
44
+ 40,
45
+ 270,
46
+ 120,
47
+ 35,
48
+ 'PRIMARY',
49
+ () => {
50
+ console.log('Primary clicked!');
51
+ demo.health = Math.min(100, demo.health + 10);
52
+ },
53
+ { normalColor: uiColors.primary }
54
+ )
55
+ );
56
+
57
+ demo.buttons.push(
58
+ createButton(
59
+ 170,
60
+ 270,
61
+ 120,
62
+ 35,
63
+ 'SUCCESS',
64
+ () => {
65
+ console.log('Success clicked!');
66
+ demo.mana = Math.min(100, demo.mana + 15);
67
+ },
68
+ { normalColor: uiColors.success }
69
+ )
70
+ );
71
+
72
+ demo.buttons.push(
73
+ createButton(
74
+ 300,
75
+ 270,
76
+ 120,
77
+ 35,
78
+ 'WARNING',
79
+ () => {
80
+ console.log('Warning clicked!');
81
+ demo.exp += 50;
82
+ },
83
+ { normalColor: uiColors.warning }
84
+ )
85
+ );
86
+
87
+ demo.buttons.push(
88
+ createButton(
89
+ 430,
90
+ 270,
91
+ 120,
92
+ 35,
93
+ 'DANGER',
94
+ () => {
95
+ console.log('Danger clicked!');
96
+ demo.health = Math.max(0, demo.health - 20);
97
+ },
98
+ { normalColor: uiColors.danger }
99
+ )
100
+ );
101
+
102
+ demo.buttons.push(
103
+ createButton(
104
+ 560,
105
+ 270,
106
+ 50,
107
+ 35,
108
+ 'X',
109
+ () => {
110
+ console.log('Close clicked!');
111
+ },
112
+ {
113
+ normalColor: rgba8(100, 100, 100, 255),
114
+ textColor: uiColors.white,
115
+ }
116
+ )
117
+ );
118
+
119
+ console.log('✅ UI Demo Ready!');
120
+ console.log('🖱️ Click buttons to interact');
121
+ }
122
+
123
+ export function update(dt) {
124
+ demo.time += dt;
125
+
126
+ // Simulate mouse position from keyboard for demo
127
+ // In real game, you'd use actual mouse input
128
+ if (isKeyDown('arrowleft')) {
129
+ setMousePosition(Math.max(0, getMousePosition().x - 200 * dt), getMousePosition().y);
130
+ }
131
+ if (isKeyDown('arrowright')) {
132
+ setMousePosition(Math.min(640, getMousePosition().x + 200 * dt), getMousePosition().y);
133
+ }
134
+ if (isKeyDown('arrowup')) {
135
+ setMousePosition(getMousePosition().x, Math.max(0, getMousePosition().y - 200 * dt));
136
+ }
137
+ if (isKeyDown('arrowdown')) {
138
+ setMousePosition(getMousePosition().x, Math.min(360, getMousePosition().y + 200 * dt));
139
+ }
140
+
141
+ // Space to click
142
+ setMouseButton(isKeyDown('space'));
143
+
144
+ // Update all buttons
145
+ updateAllButtons();
146
+
147
+ // Animate values
148
+ if (demo.health < 100) demo.health += dt * 2;
149
+ if (demo.mana < 100) demo.mana += dt * 3;
150
+ }
151
+
152
+ export function draw() {
153
+ // Clear background
154
+ cls();
155
+
156
+ // Draw gradient background
157
+ drawGradientRect(0, 0, 640, 360, rgba8(10, 10, 30, 255), rgba8(30, 10, 50, 255), true);
158
+
159
+ // Draw all panels
160
+ drawAllPanels();
161
+
162
+ // ============================================
163
+ // Panel 1: Player Stats
164
+ // ============================================
165
+
166
+ setFont('normal');
167
+ setTextAlign('left');
168
+ setTextBaseline('top');
169
+
170
+ // Health bar
171
+ drawText('HEALTH', 40, 50, uiColors.danger, 1);
172
+ uiProgressBar(40, 70, 240, 20, demo.health, 100, {
173
+ fillColor:
174
+ demo.health > 50 ? uiColors.success : demo.health > 25 ? uiColors.warning : uiColors.danger,
175
+ showText: true,
176
+ });
177
+
178
+ // Mana bar
179
+ drawText('MANA', 40, 100, uiColors.primary, 1);
180
+ uiProgressBar(40, 120, 240, 20, demo.mana, 100, {
181
+ fillColor: uiColors.primary,
182
+ showText: true,
183
+ });
184
+
185
+ // Experience bar
186
+ drawText('EXPERIENCE', 40, 150, uiColors.warning, 1);
187
+ uiProgressBar(40, 170, 240, 20, demo.exp, demo.maxExp, {
188
+ fillColor: uiColors.warning,
189
+ showText: true,
190
+ });
191
+
192
+ // Level indicator
193
+ setFont('large');
194
+ setTextAlign('center');
195
+ setTextBaseline('middle');
196
+ const level = Math.floor(demo.exp / 1000) + 1;
197
+ drawTextShadow('LVL ' + level, 280, 200, uiColors.white, rgba8(0, 0, 0, 200), 3, 1);
198
+
199
+ // ============================================
200
+ // Panel 2: Control Panel
201
+ // ============================================
202
+
203
+ setFont('normal');
204
+ setTextAlign('left');
205
+ setTextBaseline('top');
206
+
207
+ // Score with outline
208
+ setFont('large');
209
+ const scoreText = 'SCORE: ' + demo.score.toString().padStart(8, '0');
210
+ drawTextOutline(scoreText, 340, 50, uiColors.warning, rgba8(0, 0, 0, 255), 1);
211
+
212
+ // Time
213
+ setFont('normal');
214
+ const minutes = Math.floor(demo.time / 60);
215
+ const seconds = Math.floor(demo.time % 60);
216
+ const timeText = `TIME: ${minutes}:${seconds.toString().padStart(2, '0')}`;
217
+ drawText(timeText, 340, 90, uiColors.light, 1);
218
+
219
+ // Status indicators
220
+ drawText('STATUS: ACTIVE', 340, 115, uiColors.success, 1);
221
+
222
+ // Pulsing indicator
223
+ const pulse = Math.sin(demo.time * 3) * 0.5 + 0.5;
224
+ const pulseColor = rgba8(0, 255, 0, Math.floor(pulse * 255));
225
+ circle(560, 125, 5, pulseColor, true);
226
+
227
+ // ============================================
228
+ // Panel 3: Buttons
229
+ // ============================================
230
+
231
+ drawAllButtons();
232
+
233
+ // ============================================
234
+ // Header Title
235
+ // ============================================
236
+
237
+ setFont('huge');
238
+ setTextAlign('center');
239
+ setTextBaseline('top');
240
+ const titleY = 5 + Math.sin(demo.time * 2) * 2;
241
+ drawTextOutline('NOVA64 UI SYSTEM', 320, titleY, uiColors.primary, rgba8(0, 0, 0, 255), 1);
242
+
243
+ // ============================================
244
+ // Instructions
245
+ // ============================================
246
+
247
+ setFont('small');
248
+ setTextAlign('center');
249
+ setTextBaseline('bottom');
250
+ drawText(
251
+ 'ARROW KEYS: Move Cursor | SPACE: Click | Buttons: Test UI',
252
+ 320,
253
+ 355,
254
+ rgba8(200, 200, 200, 255),
255
+ 1
256
+ );
257
+
258
+ // ============================================
259
+ // Cursor
260
+ // ============================================
261
+
262
+ const mouse = getMousePosition();
263
+
264
+ // Cursor shadow
265
+ line(mouse.x + 2, mouse.y + 2, mouse.x + 12, mouse.y + 12, rgba8(0, 0, 0, 150));
266
+ line(mouse.x + 2, mouse.y + 2, mouse.x + 7, mouse.y + 12, rgba8(0, 0, 0, 150));
267
+
268
+ // Cursor
269
+ line(mouse.x, mouse.y, mouse.x + 10, mouse.y + 10, uiColors.white);
270
+ line(mouse.x, mouse.y, mouse.x + 5, mouse.y + 10, uiColors.white);
271
+ line(mouse.x + 5, mouse.y + 10, mouse.x + 10, mouse.y + 10, uiColors.white);
272
+
273
+ // Cursor highlight
274
+ if (isMouseDown()) {
275
+ circle(mouse.x, mouse.y, 15, rgba8(255, 255, 0, 100), false);
276
+ } else {
277
+ circle(mouse.x, mouse.y, 12, rgba8(255, 255, 255, 80), false);
278
+ }
279
+
280
+ // ============================================
281
+ // Font Showcase (bottom right)
282
+ // ============================================
283
+
284
+ setTextAlign('right');
285
+ setTextBaseline('bottom');
286
+
287
+ let fontY = 340;
288
+ setFont('tiny');
289
+ drawText('Tiny Font', 630, fontY, uiColors.light, 1);
290
+ fontY -= 10;
291
+
292
+ setFont('small');
293
+ drawText('Small Font', 630, fontY, uiColors.light, 1);
294
+ fontY -= 12;
295
+
296
+ setFont('normal');
297
+ drawText('Normal Font', 630, fontY, uiColors.light, 1);
298
+ fontY -= 14;
299
+
300
+ setFont('large');
301
+ drawText('Large Font', 630, fontY, uiColors.light, 1);
302
+ fontY -= 18;
303
+
304
+ setFont('huge');
305
+ drawText('Huge Font', 630, fontY, uiColors.light, 1);
306
+ }
@@ -0,0 +1,180 @@
1
+ # Wing Commander Space Combat
2
+
3
+ A first-person space combat game inspired by Wing Commander, featuring asteroid field combat and enemy fighters.
4
+
5
+ ## Features
6
+
7
+ ### ✅ First-Person Cockpit View
8
+
9
+ - True first-person camera from pilot perspective
10
+ - 6-degrees of freedom flight (pitch, yaw, roll)
11
+ - Camera stays at origin, world moves around you
12
+ - Smooth camera shake on hits
13
+
14
+ ### ✅ Flight Controls
15
+
16
+ - **Arrow Keys**: Pitch and Yaw (up/down/left/right)
17
+ - **Q/E**: Roll (barrel roll left/right)
18
+ - **W/S**: Speed up/slow down
19
+ - **SHIFT**: Boost (drains energy)
20
+ - **Z/SPACE**: Fire lasers
21
+ - **X**: Fire homing missile
22
+
23
+ ### ✅ Combat System
24
+
25
+ - **Dual lasers** firing from wing positions
26
+ - **Homing missiles** that track enemies
27
+ - **Enemy fighters** with AI attack patterns:
28
+ - Straight attack
29
+ - Weaving maneuvers
30
+ - Circle strafing
31
+ - **Asteroids** to dodge and destroy
32
+
33
+ ### ✅ Game Mechanics
34
+
35
+ - Health and shield system
36
+ - Energy management (regenerates when not boosting)
37
+ - Weapon cooldowns
38
+ - Limited missiles (20 per mission)
39
+ - Score and kill tracking
40
+ - Progressive difficulty (more enemies spawn)
41
+
42
+ ### ✅ Visual Effects
43
+
44
+ - Star field background
45
+ - Explosion effects with particles
46
+ - Laser trails
47
+ - Missile smoke trails
48
+ - Screen shake on impacts
49
+ - HUD with all vital information
50
+
51
+ ### ✅ Fixed Start Button Issue
52
+
53
+ - **ENTER key** works to start game
54
+ - **SPACE key** works to start game
55
+ - **Mouse click** on START button works
56
+ - Uses `isKeyDown()` instead of `isKeyPressed()` for reliable detection
57
+
58
+ ## HUD Information
59
+
60
+ ### Top Left Panel
61
+
62
+ - **SCORE**: Points earned
63
+ - **KILLS**: Enemies destroyed
64
+ - **HULL**: Ship health (red bar)
65
+ - **SHIELD**: Shield energy (blue bar)
66
+
67
+ ### Top Right Panel
68
+
69
+ - **ENERGY**: Boost and weapon energy (green bar)
70
+ - **SPEED**: Current velocity
71
+
72
+ ### Center Top Panel
73
+
74
+ - **WEAPONS**: Laser and missile status
75
+ - Shows cooldown and ammo count
76
+
77
+ ### Bottom Center (When Targeting)
78
+
79
+ - **TARGET**: Distance to nearest enemy
80
+
81
+ ### Center
82
+
83
+ - **Crosshair**: Green targeting reticle with corner brackets
84
+
85
+ ## Gameplay Tips
86
+
87
+ 1. **Keep Moving**: Stationary targets are easy to hit
88
+ 2. **Manage Energy**: Boost when needed, regenerate when safe
89
+ 3. **Use Missiles Wisely**: Only 20 missiles, save for tough enemies
90
+ 4. **Shield First**: Shields regenerate, hull damage doesn't
91
+ 5. **Aim Ahead**: Lasers have travel time
92
+ 6. **Dodge Asteroids**: They do massive damage
93
+ 7. **Roll and Weave**: Use Q/E to barrel roll out of danger
94
+
95
+ ## Enemy Patterns
96
+
97
+ ### Fighter Types
98
+
99
+ 1. **Straight Attackers**: Rush directly at you
100
+ 2. **Weavers**: Zigzag while approaching
101
+ 3. **Circle Strafers**: Orbit around you while firing
102
+
103
+ ### Strategy
104
+
105
+ - Missiles work best on straight attackers
106
+ - Lead your shots against weavers
107
+ - Circle strafers require prediction
108
+
109
+ ## Technical Details
110
+
111
+ ### Camera System
112
+
113
+ ```javascript
114
+ // First-person view - camera at origin, world moves
115
+ setCameraPosition(0, 0, 0);
116
+ setCameraTarget(lookX, lookY, lookZ); // Based on ship rotation
117
+ ```
118
+
119
+ ### Movement System
120
+
121
+ ```javascript
122
+ // Ship rotation affects forward direction
123
+ forward.x = -sin(yaw) * cos(pitch);
124
+ forward.y = sin(pitch);
125
+ forward.z = -cos(yaw) * cos(pitch);
126
+
127
+ // World moves opposite to player velocity
128
+ worldPos -= playerVelocity * deltaTime;
129
+ ```
130
+
131
+ ### Collision Detection
132
+
133
+ - Sphere-sphere collision for all objects
134
+ - Distance checks for laser hits
135
+ - Proximity detection for player collisions
136
+
137
+ ## Configuration
138
+
139
+ Edit `CONFIG` object to tune gameplay:
140
+
141
+ ```javascript
142
+ const CONFIG = {
143
+ SHIP_SPEED: 20, // Base speed
144
+ SHIP_TURN_SPEED: 2.5, // Rotation speed
145
+ SHIP_BOOST_MULTIPLIER: 2, // Boost factor
146
+ LASER_SPEED: 80, // Laser velocity
147
+ LASER_COOLDOWN: 0.15, // Seconds between shots
148
+ MISSILE_SPEED: 40, // Missile velocity
149
+ MISSILE_COOLDOWN: 1.0, // Seconds between launches
150
+ ASTEROID_SPAWN_DISTANCE: 100, // Spawn distance
151
+ };
152
+ ```
153
+
154
+ ## Future Enhancements
155
+
156
+ - [ ] Cockpit frame overlay
157
+ - [ ] Power-up pickups (health, missiles, energy)
158
+ - [ ] Multiple weapon types
159
+ - [ ] Boss battles
160
+ - [ ] Mission objectives
161
+ - [ ] Wingman AI allies
162
+ - [ ] Capital ship battles
163
+ - [ ] Hyperspace jumps between sectors
164
+ - [ ] Saving/loading progress
165
+ - [ ] Sound effects and music
166
+
167
+ ## Known Issues
168
+
169
+ - None currently!
170
+
171
+ ## Credits
172
+
173
+ Inspired by:
174
+
175
+ - Wing Commander series
176
+ - X-Wing vs TIE Fighter
177
+ - Freespace 2
178
+ - Elite Dangerous
179
+
180
+ Built with Nova64 fantasy console.