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,77 @@
|
|
|
1
|
+
# Nova64 Performance Benchmarks
|
|
2
|
+
|
|
3
|
+
> Results captured on Apple Silicon (M-series). Run `pnpm bench` to reproduce.
|
|
4
|
+
|
|
5
|
+
## Running Benchmarks
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Full suite (default 1000 iterations)
|
|
9
|
+
pnpm bench
|
|
10
|
+
|
|
11
|
+
# Individual suites
|
|
12
|
+
pnpm bench:material
|
|
13
|
+
pnpm bench:instancing
|
|
14
|
+
pnpm bench:mesh
|
|
15
|
+
|
|
16
|
+
# Custom iteration count
|
|
17
|
+
node tests/bench.js --iterations=5000
|
|
18
|
+
|
|
19
|
+
# Specific suite with custom count
|
|
20
|
+
node tests/bench.js --suite=instancing --iterations=500
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Results (iterations = 1000)
|
|
24
|
+
|
|
25
|
+
### Material Caching
|
|
26
|
+
|
|
27
|
+
| Scenario | avg (ms) | ops/s |
|
|
28
|
+
| -------------- | -------- | ------------ |
|
|
29
|
+
| Cache **hit** | 0.0020 | ~490 000 |
|
|
30
|
+
| Cache **miss** | 0.0023 | ~435 000 |
|
|
31
|
+
| **Speedup** | — | **1.1–1.2×** |
|
|
32
|
+
|
|
33
|
+
Material caching provides modest but consistent gains. The bigger win is GPU-side: reusing a `MeshStandardMaterial` eliminates shader recompilation per object type.
|
|
34
|
+
|
|
35
|
+
### Mesh Creation Throughput
|
|
36
|
+
|
|
37
|
+
| Primitive | avg (ms) | ops/s |
|
|
38
|
+
| ---------------- | -------- | -------- |
|
|
39
|
+
| `createCube` | 0.0020 | ~510 000 |
|
|
40
|
+
| `createSphere` | 0.0020 | ~505 000 |
|
|
41
|
+
| `createPlane` | 0.0022 | ~455 000 |
|
|
42
|
+
| `createCylinder` | 0.0023 | ~435 000 |
|
|
43
|
+
|
|
44
|
+
All primitives create at ~450–530K/s in Node (headless, mock GPU). In the browser with a real WebGL context, geometry upload is the primary cost — instancing eliminates that per call.
|
|
45
|
+
|
|
46
|
+
### Instancing vs Individual Meshes
|
|
47
|
+
|
|
48
|
+
| Approach | avg (ms) | ops/s | Ratio |
|
|
49
|
+
| --------------------------------------------- | -------- | ------ | --------------- |
|
|
50
|
+
| 1000 × `createCube` (individual) | 1.20 | ~830 | 1× |
|
|
51
|
+
| `createInstancedMesh(1000)` + 1000 transforms | 0.22 | ~4 500 | **5–6× faster** |
|
|
52
|
+
|
|
53
|
+
**Instancing reduces setup cost 5–6× for 1000-object batches.** More importantly, it collapses 1000 draw calls into 1 — measured GPU speedup in the browser ranges from 10× to 100× depending on object complexity and hardware.
|
|
54
|
+
|
|
55
|
+
### Per-Frame Transform Update (500 instances)
|
|
56
|
+
|
|
57
|
+
| Operation | avg (ms) | ops/s |
|
|
58
|
+
| -------------------------------------------------- | -------- | ------- |
|
|
59
|
+
| 500 × `setInstanceTransform` + `finalizeInstances` | 0.082 | ~12 000 |
|
|
60
|
+
|
|
61
|
+
At 60 fps you have ~16.6 ms per frame. Updating 500 instance transforms takes **< 0.1 ms** of CPU time, leaving ample headroom for game logic.
|
|
62
|
+
|
|
63
|
+
### Mesh Cleanup
|
|
64
|
+
|
|
65
|
+
| Operation | avg (ms) | ops/s |
|
|
66
|
+
| ------------- | -------- | ---------- |
|
|
67
|
+
| `destroyMesh` | 0.0005 | ~1 900 000 |
|
|
68
|
+
|
|
69
|
+
Cleanup is negligible — geometry and material disposal is O(1).
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Notes
|
|
74
|
+
|
|
75
|
+
- **LOD benchmarking** requires a real WebGL context (Three.js `LOD` builds real `BufferGeometry` objects). Run `examples/instancing-demo` in the browser and use the DevTools **Performance** panel to measure LOD overhead.
|
|
76
|
+
- **Frustum culling** benefits are render-thread only and not measurable in Node; in the browser, culling reduces GPU fragment work for off-screen objects.
|
|
77
|
+
- **Material cache** gains compound with scene complexity: a scene with 1000 cubes of 10 distinct colours allocates 10 materials instead of 1000 — 100× fewer GPU shader instances.
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
# Nova64 Cheatsheet
|
|
2
|
+
|
|
3
|
+
> One-page reference. For full docs see `NOVA64_API_REFERENCE.md`.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Cart structure
|
|
8
|
+
|
|
9
|
+
```js
|
|
10
|
+
export function init() {
|
|
11
|
+
// runs once — create objects, set up lighting
|
|
12
|
+
setCameraPosition(0, 5, 10);
|
|
13
|
+
setCameraTarget(0, 0, 0);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function update(dt) {
|
|
17
|
+
// runs every frame — move things, read input
|
|
18
|
+
if (key('KeyW')) playerZ -= 5 * dt;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function draw() {
|
|
22
|
+
// runs every frame — 3D renders automatically; use this for 2D HUD only
|
|
23
|
+
print('Score: ' + score, 8, 8, 0xffffff);
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Colors
|
|
30
|
+
|
|
31
|
+
| Context | Format | Example |
|
|
32
|
+
| ----------------- | ------------------------------ | -------------------- |
|
|
33
|
+
| 3D (color arg) | `0xRRGGBB` hex | `0xff0000` red |
|
|
34
|
+
| 2D (print/rect/…) | `0xRRGGBB` or `rgba8(r,g,b,a)` | `rgba8(255,0,0,200)` |
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## 3D Primitives
|
|
39
|
+
|
|
40
|
+
```js
|
|
41
|
+
createCube(size, color, [x, y, z], opts); // → mesh handle
|
|
42
|
+
createSphere(radius, color, [x, y, z], opts);
|
|
43
|
+
createPlane(w, h, color, [x, y, z], opts);
|
|
44
|
+
createCylinder(rt, rb, h, color, [x, y, z], opts);
|
|
45
|
+
createCone(radius, h, color, [x, y, z], opts);
|
|
46
|
+
createCapsule(radius, h, color, [x, y, z], opts);
|
|
47
|
+
createTorus(radius, tube, color, [x, y, z], opts);
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**`opts`** keys: `material` (`'standard'`|`'metallic'`|`'emissive'`|`'holographic'`), `roughness`, `metalness`, `emissive`, `texture`
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Transforms
|
|
55
|
+
|
|
56
|
+
```js
|
|
57
|
+
setPosition(mesh, x, y, z);
|
|
58
|
+
setRotation(mesh, rx, ry, rz); // radians
|
|
59
|
+
setScale(mesh, sx, sy, sz);
|
|
60
|
+
rotateMesh(mesh, rx, ry, rz); // add to current rotation
|
|
61
|
+
removeMesh(mesh); // also: destroyMesh(mesh)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Camera
|
|
67
|
+
|
|
68
|
+
```js
|
|
69
|
+
setCameraPosition(x, y, z);
|
|
70
|
+
setCameraTarget(x, y, z);
|
|
71
|
+
setCameraFOV(degrees); // default 75
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Lighting & Atmosphere
|
|
77
|
+
|
|
78
|
+
```js
|
|
79
|
+
setAmbientLight(color, intensity); // e.g. 0x334455, 1.0
|
|
80
|
+
setLightDirection(x, y, z);
|
|
81
|
+
setLightColor(color);
|
|
82
|
+
createPointLight(color, intensity, distance, x, y, z); // → light handle
|
|
83
|
+
setFog(color, near, far);
|
|
84
|
+
clearFog();
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Skybox
|
|
90
|
+
|
|
91
|
+
```js
|
|
92
|
+
createSpaceSkybox({ starCount, starSize, nebulae, nebulaColor });
|
|
93
|
+
createGradientSkybox(topColor, bottomColor); // e.g. 0x87ceeb, 0x228b22
|
|
94
|
+
createSolidSkybox(color); // e.g. 0x000000 cave / indoor
|
|
95
|
+
animateSkybox(dt); // call in update() or:
|
|
96
|
+
enableSkyboxAutoAnimate(speed); // engine calls it for you
|
|
97
|
+
setSkyboxSpeed(multiplier); // 0=pause, -1=reverse
|
|
98
|
+
clearSkybox();
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Input
|
|
104
|
+
|
|
105
|
+
```js
|
|
106
|
+
key(code); // held e.g. key('KeyW'), key('Space'), key('ArrowLeft')
|
|
107
|
+
keyp(code); // just-pressed (one frame)
|
|
108
|
+
btn(index); // gamepad held (0=A, 1=B, 2=X, 3=Y, 4=LB, 5=RB, 12=↑…)
|
|
109
|
+
btnp(index); // gamepad just-pressed
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## 2D Overlay (HUD)
|
|
115
|
+
|
|
116
|
+
```js
|
|
117
|
+
// Clear / pixels
|
|
118
|
+
cls(color);
|
|
119
|
+
pset(x, y, color);
|
|
120
|
+
|
|
121
|
+
// Shapes
|
|
122
|
+
rectfill(x, y, w, h, color);
|
|
123
|
+
rect(x, y, w, h, color);
|
|
124
|
+
circfill(x, y, r, color);
|
|
125
|
+
circ(x, y, r, color);
|
|
126
|
+
line(x0, y0, x1, y1, color);
|
|
127
|
+
|
|
128
|
+
// Text
|
|
129
|
+
print(text, x, y, color);
|
|
130
|
+
printCentered(text, y, color); // horizontally centred
|
|
131
|
+
setFont('small' | 'normal' | 'large');
|
|
132
|
+
|
|
133
|
+
// HUD helpers
|
|
134
|
+
drawProgressBar(x, y, w, h, t, fgColor, bgColor, borderColor);
|
|
135
|
+
drawHealthBar(x, y, w, h, current, max, opts);
|
|
136
|
+
drawCrosshair(cx, cy, size, color, style); // style: 'cross'|'dot'|'circle'
|
|
137
|
+
drawPanel(x, y, w, h, opts);
|
|
138
|
+
|
|
139
|
+
// Colours
|
|
140
|
+
rgba8(r, g, b, a); // returns color value (0–255 each channel)
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Post-processing
|
|
146
|
+
|
|
147
|
+
```js
|
|
148
|
+
enableBloom(strength, radius, threshold);
|
|
149
|
+
disableBloom();
|
|
150
|
+
enableFXAA(); // anti-aliasing
|
|
151
|
+
enableVignette(darkness, offset);
|
|
152
|
+
enableChromaticAberration();
|
|
153
|
+
enableGlitch(intensity); // screen glitch (scanlines, RGB split, block artifacts)
|
|
154
|
+
disableGlitch();
|
|
155
|
+
setGlitchIntensity(intensity); // adjust live (0-1)
|
|
156
|
+
|
|
157
|
+
// One-call visual presets
|
|
158
|
+
enableN64Mode(); // flat shading, no bloom, crisp FXAA
|
|
159
|
+
enablePSXMode(); // bloom + vignette + chromatic aberration
|
|
160
|
+
enableLowPolyMode(); // flat shading, subtle bloom
|
|
161
|
+
disablePresetMode(); // restore defaults
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Audio
|
|
167
|
+
|
|
168
|
+
```js
|
|
169
|
+
sfx(preset) // 0/1/2 or named: 'jump','coin','explosion','laser',
|
|
170
|
+
// 'hit','death','select','confirm','error','blip','powerup','land'
|
|
171
|
+
sfx({ wave, freq, dur, vol, sweep }) // custom: wave = 'sine'|'square'|'sawtooth'|'noise'
|
|
172
|
+
setVolume(0..1) // master volume
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## Physics
|
|
178
|
+
|
|
179
|
+
```js
|
|
180
|
+
createBody(x, y, w, h, opts); // opts: vx,vy,restitution,friction
|
|
181
|
+
destroyBody(body);
|
|
182
|
+
stepPhysics(dt); // call in update(dt)
|
|
183
|
+
setGravity(px_per_s2); // default 500
|
|
184
|
+
setCollisionMap(fn); // fn(tx,ty) → true if solid
|
|
185
|
+
// also: setTileSolidFn(fn)
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## Storage
|
|
191
|
+
|
|
192
|
+
```js
|
|
193
|
+
saveData(key, value); // persists to localStorage (JSON)
|
|
194
|
+
loadData(key, fallback); // returns parsed value or fallback
|
|
195
|
+
deleteData(key);
|
|
196
|
+
// also: saveJSON / loadJSON as aliases
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## 5-Minute Patterns
|
|
202
|
+
|
|
203
|
+
**Spinning cube**
|
|
204
|
+
|
|
205
|
+
```js
|
|
206
|
+
let cube;
|
|
207
|
+
export function init() {
|
|
208
|
+
cube = createCube(1, 0x00aaff, [0, 0, -5]);
|
|
209
|
+
}
|
|
210
|
+
export function update(dt) {
|
|
211
|
+
rotateMesh(cube, 0, dt, 0);
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
**WASD player**
|
|
216
|
+
|
|
217
|
+
```js
|
|
218
|
+
const p = { x: 0, z: 0 };
|
|
219
|
+
export function update(dt) {
|
|
220
|
+
if (key('KeyW')) p.z -= 5 * dt;
|
|
221
|
+
if (key('KeyS')) p.z += 5 * dt;
|
|
222
|
+
if (key('KeyA')) p.x -= 5 * dt;
|
|
223
|
+
if (key('KeyD')) p.x += 5 * dt;
|
|
224
|
+
setPosition(mesh, p.x, 0, p.z);
|
|
225
|
+
setCameraPosition(p.x, 4, p.z + 8);
|
|
226
|
+
setCameraTarget(p.x, 0, p.z);
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
**Save high score**
|
|
231
|
+
|
|
232
|
+
```js
|
|
233
|
+
let best = loadData('best', 0);
|
|
234
|
+
if (score > best) {
|
|
235
|
+
best = score;
|
|
236
|
+
saveData('best', best);
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
**Space skybox with auto-rotate**
|
|
241
|
+
|
|
242
|
+
```js
|
|
243
|
+
export function init() {
|
|
244
|
+
createSpaceSkybox({ starCount: 1500 });
|
|
245
|
+
enableSkyboxAutoAnimate(0.5);
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
**Sunset gradient sky**
|
|
250
|
+
|
|
251
|
+
```js
|
|
252
|
+
export function init() {
|
|
253
|
+
createGradientSkybox(0x1a6aa8, 0xf4a460);
|
|
254
|
+
}
|
|
255
|
+
```
|