nova64 0.2.5 → 0.2.7
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/dist/runtime/api-2d.js +1158 -0
- package/dist/runtime/api-3d/camera.js +73 -0
- package/dist/runtime/api-3d/instancing.js +180 -0
- package/dist/runtime/api-3d/lights.js +51 -0
- package/dist/runtime/api-3d/materials.js +47 -0
- package/dist/runtime/api-3d/models.js +84 -0
- package/dist/runtime/api-3d/particles.js +296 -0
- package/dist/runtime/api-3d/pbr.js +113 -0
- package/dist/runtime/api-3d/primitives.js +304 -0
- package/dist/runtime/api-3d/scene.js +169 -0
- package/dist/runtime/api-3d/transforms.js +161 -0
- package/dist/runtime/api-3d.js +166 -0
- package/dist/runtime/api-effects.js +840 -0
- package/dist/runtime/api-gameutils.js +476 -0
- package/dist/runtime/api-generative.js +610 -0
- package/dist/runtime/api-presets.js +85 -0
- package/dist/runtime/api-skybox.js +232 -0
- package/dist/runtime/api-sprites.js +100 -0
- package/dist/runtime/api-voxel.js +712 -0
- package/dist/runtime/api.js +201 -0
- package/dist/runtime/assets.js +27 -0
- package/dist/runtime/audio.js +114 -0
- package/dist/runtime/collision.js +47 -0
- package/dist/runtime/console.js +101 -0
- package/dist/runtime/editor.js +233 -0
- package/dist/runtime/font.js +233 -0
- package/dist/runtime/framebuffer.js +28 -0
- package/dist/runtime/fullscreen-button.js +185 -0
- package/dist/runtime/gpu-canvas2d.js +47 -0
- package/dist/runtime/gpu-threejs.js +643 -0
- package/dist/runtime/gpu-webgl2.js +310 -0
- package/dist/runtime/index.d.ts +682 -0
- package/dist/runtime/index.js +22 -0
- package/dist/runtime/input.js +225 -0
- package/dist/runtime/logger.js +60 -0
- package/dist/runtime/physics.js +101 -0
- package/dist/runtime/screens.js +213 -0
- package/dist/runtime/storage.js +38 -0
- package/dist/runtime/store.js +151 -0
- package/dist/runtime/textinput.js +68 -0
- package/dist/runtime/ui/buttons.js +124 -0
- package/dist/runtime/ui/panels.js +105 -0
- package/dist/runtime/ui/text.js +86 -0
- package/dist/runtime/ui/widgets.js +141 -0
- package/dist/runtime/ui.js +111 -0
- package/index.html +6 -1
- package/package.json +9 -2
- 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 +20 -0
- package/public/os9-shell/assets/index-B1Uvacma.js +0 -32825
- 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.
|