oriverse-engine 0.1.2 → 0.1.3
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/LICENSE.md +30 -30
- package/dist/AGENT_ONBOARDING.md +74 -74
- package/dist/CODEX_PROMPT.md +7 -7
- package/dist/examples/coin_collector.weave +70 -70
- package/dist/examples/dodge_blocks.weave +70 -70
- package/dist/examples/target_range.weave +82 -82
- package/dist/ktx_bridge.js +121 -121
- package/dist/ktx_lib.js +1 -1
- package/dist/oriverse_wgpu.d.ts +16 -17
- package/dist/oriverse_wgpu.js +90 -100
- package/dist/oriverse_wgpu_bg.wasm +0 -0
- package/dist/oriverse_wgpu_bg.wasm.d.ts +16 -17
- package/dist/snippets/oriverse_wgpu-255445ce6d9a0851/inline0.js +2 -1
- package/dist/starter/AGENTS.md +2 -2
- package/dist/starter/CLAUDE.md +2 -2
- package/dist/starter/game.html +5 -5
- package/dist/templates/game_cdn.html +5 -5
- package/dist/weave_documentation.txt +8 -10
- package/package.json +1 -1
package/LICENSE.md
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
# Oriverse Artifact Bundle License
|
|
2
|
-
|
|
3
|
-
> PLACEHOLDER — review with legal counsel before the first `npm publish`.
|
|
4
|
-
|
|
5
|
-
Copyright (c) 2026 Oriverse. All rights reserved.
|
|
6
|
-
|
|
7
|
-
This package contains a compiled, proprietary build of the Oriverse engine
|
|
8
|
-
("the Bundle"). No source code is included or licensed.
|
|
9
|
-
|
|
10
|
-
Permission is hereby granted, free of charge and royalty-free, to any person
|
|
11
|
-
obtaining a copy of the Bundle to:
|
|
12
|
-
|
|
13
|
-
1. Use the Bundle to run and serve games and applications, commercial or
|
|
14
|
-
non-commercial.
|
|
15
|
-
2. Redistribute the Bundle **unmodified** (including via CDNs such as unpkg,
|
|
16
|
-
bundlers, or by copying the `dist/` files alongside your game), provided this
|
|
17
|
-
license file accompanies any standalone redistribution of the Bundle.
|
|
18
|
-
|
|
19
|
-
The following are NOT permitted:
|
|
20
|
-
|
|
21
|
-
- Modifying, decompiling, disassembling, or reverse-engineering the Bundle,
|
|
22
|
-
except to the extent such restriction is prohibited by applicable law.
|
|
23
|
-
- Redistributing modified versions of the Bundle.
|
|
24
|
-
- Representing the Bundle as your own work or removing copyright notices.
|
|
25
|
-
|
|
26
|
-
THE BUNDLE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
27
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
28
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
29
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
30
|
-
LIABILITY ARISING FROM THE USE OF THE BUNDLE.
|
|
1
|
+
# Oriverse Artifact Bundle License
|
|
2
|
+
|
|
3
|
+
> PLACEHOLDER — review with legal counsel before the first `npm publish`.
|
|
4
|
+
|
|
5
|
+
Copyright (c) 2026 Oriverse. All rights reserved.
|
|
6
|
+
|
|
7
|
+
This package contains a compiled, proprietary build of the Oriverse engine
|
|
8
|
+
("the Bundle"). No source code is included or licensed.
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge and royalty-free, to any person
|
|
11
|
+
obtaining a copy of the Bundle to:
|
|
12
|
+
|
|
13
|
+
1. Use the Bundle to run and serve games and applications, commercial or
|
|
14
|
+
non-commercial.
|
|
15
|
+
2. Redistribute the Bundle **unmodified** (including via CDNs such as unpkg,
|
|
16
|
+
bundlers, or by copying the `dist/` files alongside your game), provided this
|
|
17
|
+
license file accompanies any standalone redistribution of the Bundle.
|
|
18
|
+
|
|
19
|
+
The following are NOT permitted:
|
|
20
|
+
|
|
21
|
+
- Modifying, decompiling, disassembling, or reverse-engineering the Bundle,
|
|
22
|
+
except to the extent such restriction is prohibited by applicable law.
|
|
23
|
+
- Redistributing modified versions of the Bundle.
|
|
24
|
+
- Representing the Bundle as your own work or removing copyright notices.
|
|
25
|
+
|
|
26
|
+
THE BUNDLE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
27
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
28
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
29
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
30
|
+
LIABILITY ARISING FROM THE USE OF THE BUNDLE.
|
package/dist/AGENT_ONBOARDING.md
CHANGED
|
@@ -1,74 +1,74 @@
|
|
|
1
|
-
# Oriverse artifact package — agent onboarding
|
|
2
|
-
|
|
3
|
-
This folder is a self-contained, offline, single-player build of the Oriverse engine.
|
|
4
|
-
It runs without SharedArrayBuffer, web workers, or any network access, so it can be
|
|
5
|
-
served by any dumb static file server — no COOP/COEP headers needed.
|
|
6
|
-
|
|
7
|
-
## Quick start
|
|
8
|
-
|
|
9
|
-
1. Serve this folder:
|
|
10
|
-
|
|
11
|
-
```bash
|
|
12
|
-
python -m http.server 8000
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
2. Open `http://localhost:8000/game.html` in a WebGPU-capable browser (Chrome/Edge,
|
|
16
|
-
or iOS Safari with the WebGPU feature flag enabled).
|
|
17
|
-
|
|
18
|
-
No server at all: `oriverse_single_game.html` is the same engine + world in ONE
|
|
19
|
-
self-contained file (wasm embedded as base64, zero fetches) — double-click it to run
|
|
20
|
-
via `file://` (a secure context in Chrome, so WebGPU works there too).
|
|
21
|
-
|
|
22
|
-
## Authoring a game
|
|
23
|
-
|
|
24
|
-
Edit `game.html` and replace the Weave source inside:
|
|
25
|
-
|
|
26
|
-
```html
|
|
27
|
-
<script type="text/weave" id="oriverse-weave"> ...your world... </script>
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
(Alternatives: set `window.ORIVERSE_ARTIFACT_WEAVE` to a string before the module
|
|
31
|
-
script runs, or omit the tag entirely and call the typed export
|
|
32
|
-
`bootOriverseArtifact(weaveSource)` once after `initOriverse(...)` resolves — with no
|
|
33
|
-
inline Weave present the engine waits for that call instead of auto-booting.)
|
|
34
|
-
|
|
35
|
-
For game-making patterns and three complete engine-tested example games, read
|
|
36
|
-
`GAME_AUTHORING.md` (npm package `dist/`; examples also under `dist/examples/`).
|
|
37
|
-
|
|
38
|
-
Rules for artifact worlds:
|
|
39
|
-
|
|
40
|
-
- Content must be fully procedural. Allowed: primitive models (`"cube"`, `"sphere"`, ...),
|
|
41
|
-
`#mesh` clauses (procedural mesh DSL), `#texture` clauses (procedural texture DSL,
|
|
42
|
-
`baked.*` urls), `#particles` clauses, and triplanar materials.
|
|
43
|
-
- `color = (r, g, b)` channels are 0-1 floats (or `#RRGGBB` hex). Values above 1 clamp
|
|
44
|
-
to 1.0 per channel, so 0-255 style colors silently render as untinted white.
|
|
45
|
-
- The game boots directly into play mode (no editor). WASD moves the player: if your
|
|
46
|
-
world has no `#class player ... #end` block, the engine injects the default
|
|
47
|
-
third-person controller (camera-relative move + Space jump). Define `#class player`
|
|
48
|
-
yourself to override movement/camera (see `weave_documentation.txt`).
|
|
49
|
-
- Market assets (`Ori.model.*`, `Ori.image.*`, fonts from the network, ...) are NOT
|
|
50
|
-
available. Any runtime HTTP request hard-errors with `[artifact][zero-fetch]`.
|
|
51
|
-
- The world is built once at boot from the inline Weave; a load error is fatal and shows
|
|
52
|
-
in the status banner / browser console.
|
|
53
|
-
|
|
54
|
-
The Weave language reference is in `weave_documentation.txt` in this folder.
|
|
55
|
-
|
|
56
|
-
## Package contents
|
|
57
|
-
|
|
58
|
-
- `game.html` — template page with inline Weave (this is the file you author). The default
|
|
59
|
-
world is injected from `default_world.weave` at packaging time and compile-tested natively.
|
|
60
|
-
- `oriverse_single_game.html` — single-file variant of the same game (edit the same
|
|
61
|
-
`#oriverse-weave` block inside it); runs from `file://` or any static server.
|
|
62
|
-
- `oriverse_wgpu.js` / `oriverse_wgpu_bg.wasm` — engine glue + wasm (single-threaded,
|
|
63
|
-
non-shared memory).
|
|
64
|
-
- `ktx_lib.js` / `ktx_lib.wasm` / `ktx_bridge.js` — KTX2 texture transcoder sidecar
|
|
65
|
-
(loaded as classic scripts; the one non-module exception).
|
|
66
|
-
- `weave_documentation.txt` — Weave language + API reference.
|
|
67
|
-
|
|
68
|
-
## How it works (for the curious)
|
|
69
|
-
|
|
70
|
-
The engine runs its normal deterministic client simulation, but instead of a network
|
|
71
|
-
relay it talks to an in-process loopback relay: your inputs are packed into real relay
|
|
72
|
-
wire packets, merged one frame per tick, and fed back through the production frame
|
|
73
|
-
reader. The whole sim runs on the browser main thread (fixed-step accumulator inside
|
|
74
|
-
requestAnimationFrame, with a small catch-up cap).
|
|
1
|
+
# Oriverse artifact package — agent onboarding
|
|
2
|
+
|
|
3
|
+
This folder is a self-contained, offline, single-player build of the Oriverse engine.
|
|
4
|
+
It runs without SharedArrayBuffer, web workers, or any network access, so it can be
|
|
5
|
+
served by any dumb static file server — no COOP/COEP headers needed.
|
|
6
|
+
|
|
7
|
+
## Quick start
|
|
8
|
+
|
|
9
|
+
1. Serve this folder:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
python -m http.server 8000
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
2. Open `http://localhost:8000/game.html` in a WebGPU-capable browser (Chrome/Edge,
|
|
16
|
+
or iOS Safari with the WebGPU feature flag enabled).
|
|
17
|
+
|
|
18
|
+
No server at all: `oriverse_single_game.html` is the same engine + world in ONE
|
|
19
|
+
self-contained file (wasm embedded as base64, zero fetches) — double-click it to run
|
|
20
|
+
via `file://` (a secure context in Chrome, so WebGPU works there too).
|
|
21
|
+
|
|
22
|
+
## Authoring a game
|
|
23
|
+
|
|
24
|
+
Edit `game.html` and replace the Weave source inside:
|
|
25
|
+
|
|
26
|
+
```html
|
|
27
|
+
<script type="text/weave" id="oriverse-weave"> ...your world... </script>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
(Alternatives: set `window.ORIVERSE_ARTIFACT_WEAVE` to a string before the module
|
|
31
|
+
script runs, or omit the tag entirely and call the typed export
|
|
32
|
+
`bootOriverseArtifact(weaveSource)` once after `initOriverse(...)` resolves — with no
|
|
33
|
+
inline Weave present the engine waits for that call instead of auto-booting.)
|
|
34
|
+
|
|
35
|
+
For game-making patterns and three complete engine-tested example games, read
|
|
36
|
+
`GAME_AUTHORING.md` (npm package `dist/`; examples also under `dist/examples/`).
|
|
37
|
+
|
|
38
|
+
Rules for artifact worlds:
|
|
39
|
+
|
|
40
|
+
- Content must be fully procedural. Allowed: primitive models (`"cube"`, `"sphere"`, ...),
|
|
41
|
+
`#mesh` clauses (procedural mesh DSL), `#texture` clauses (procedural texture DSL,
|
|
42
|
+
`baked.*` urls), `#particles` clauses, and triplanar materials.
|
|
43
|
+
- `color = (r, g, b)` channels are 0-1 floats (or `#RRGGBB` hex). Values above 1 clamp
|
|
44
|
+
to 1.0 per channel, so 0-255 style colors silently render as untinted white.
|
|
45
|
+
- The game boots directly into play mode (no editor). WASD moves the player: if your
|
|
46
|
+
world has no `#class player ... #end` block, the engine injects the default
|
|
47
|
+
third-person controller (camera-relative move + Space jump). Define `#class player`
|
|
48
|
+
yourself to override movement/camera (see `weave_documentation.txt`).
|
|
49
|
+
- Market assets (`Ori.model.*`, `Ori.image.*`, fonts from the network, ...) are NOT
|
|
50
|
+
available. Any runtime HTTP request hard-errors with `[artifact][zero-fetch]`.
|
|
51
|
+
- The world is built once at boot from the inline Weave; a load error is fatal and shows
|
|
52
|
+
in the status banner / browser console.
|
|
53
|
+
|
|
54
|
+
The Weave language reference is in `weave_documentation.txt` in this folder.
|
|
55
|
+
|
|
56
|
+
## Package contents
|
|
57
|
+
|
|
58
|
+
- `game.html` — template page with inline Weave (this is the file you author). The default
|
|
59
|
+
world is injected from `default_world.weave` at packaging time and compile-tested natively.
|
|
60
|
+
- `oriverse_single_game.html` — single-file variant of the same game (edit the same
|
|
61
|
+
`#oriverse-weave` block inside it); runs from `file://` or any static server.
|
|
62
|
+
- `oriverse_wgpu.js` / `oriverse_wgpu_bg.wasm` — engine glue + wasm (single-threaded,
|
|
63
|
+
non-shared memory).
|
|
64
|
+
- `ktx_lib.js` / `ktx_lib.wasm` / `ktx_bridge.js` — KTX2 texture transcoder sidecar
|
|
65
|
+
(loaded as classic scripts; the one non-module exception).
|
|
66
|
+
- `weave_documentation.txt` — Weave language + API reference.
|
|
67
|
+
|
|
68
|
+
## How it works (for the curious)
|
|
69
|
+
|
|
70
|
+
The engine runs its normal deterministic client simulation, but instead of a network
|
|
71
|
+
relay it talks to an in-process loopback relay: your inputs are packed into real relay
|
|
72
|
+
wire packets, merged one frame per tick, and fed back through the production frame
|
|
73
|
+
reader. The whole sim runs on the browser main thread (fixed-step accumulator inside
|
|
74
|
+
requestAnimationFrame, with a small catch-up cap).
|
package/dist/CODEX_PROMPT.md
CHANGED
|
@@ -53,15 +53,15 @@ object BlueCube {
|
|
|
53
53
|
</script>
|
|
54
54
|
<!-- ==== END OF EDITABLE BLOCK ==== -->
|
|
55
55
|
|
|
56
|
-
<script src="https://unpkg.com/oriverse-engine@0.1.
|
|
57
|
-
<script src="https://unpkg.com/oriverse-engine@0.1.
|
|
56
|
+
<script src="https://unpkg.com/oriverse-engine@0.1.3/dist/ktx_lib.js"></script>
|
|
57
|
+
<script src="https://unpkg.com/oriverse-engine@0.1.3/dist/ktx_bridge.js"></script>
|
|
58
58
|
<script type="module">
|
|
59
|
-
import initOriverse from "https://unpkg.com/oriverse-engine@0.1.
|
|
59
|
+
import initOriverse from "https://unpkg.com/oriverse-engine@0.1.3/dist/oriverse_wgpu.js";
|
|
60
60
|
const setBoot = (t) => { const b = document.getElementById('oriverse-status-banner'); if (b) b.textContent = t; };
|
|
61
61
|
(async () => {
|
|
62
62
|
try {
|
|
63
63
|
setBoot('instantiating wasm...');
|
|
64
|
-
await initOriverse({ module_or_path: "https://unpkg.com/oriverse-engine@0.1.
|
|
64
|
+
await initOriverse({ module_or_path: "https://unpkg.com/oriverse-engine@0.1.3/dist/oriverse_wgpu_bg.wasm" });
|
|
65
65
|
} catch (e) {
|
|
66
66
|
setBoot('WASM init failed:\n' + ((e && e.stack) ? e.stack : String(e)));
|
|
67
67
|
console.error('[wasm_boot] initOriverse failed:', e);
|
|
@@ -96,9 +96,9 @@ Rules — the engine hard-errors if you break the first two:
|
|
|
96
96
|
Authoritative references, served next to the engine (fetch if you can — the authoring
|
|
97
97
|
guide contains three complete tested example games to pattern-match from):
|
|
98
98
|
|
|
99
|
-
- https://unpkg.com/oriverse-engine@0.1.
|
|
100
|
-
- https://unpkg.com/oriverse-engine@0.1.
|
|
101
|
-
- https://unpkg.com/oriverse-engine@0.1.
|
|
99
|
+
- https://unpkg.com/oriverse-engine@0.1.3/dist/GAME_AUTHORING.md <- game patterns + 3 full example games
|
|
100
|
+
- https://unpkg.com/oriverse-engine@0.1.3/dist/weave_documentation.txt <- full language + API reference
|
|
101
|
+
- https://unpkg.com/oriverse-engine@0.1.3/dist/examples/coin_collector.weave (also dodge_blocks / target_range)
|
|
102
102
|
|
|
103
103
|
## Step 3: test
|
|
104
104
|
|
|
@@ -1,70 +1,70 @@
|
|
|
1
|
-
// Coin Collector — walk into the 10 spinning coins to collect them all. Press R to replay.
|
|
2
|
-
// Demonstrates: saved objects + runtime spawning, tags, proximity pickup, HUD score text,
|
|
3
|
-
// win + restart flow. Movement uses the engine's default player controller (no #class player).
|
|
4
|
-
|
|
5
|
-
#class Coin
|
|
6
|
-
event OnPreSpawn {
|
|
7
|
-
AddTag(Tag.Coin)
|
|
8
|
-
}
|
|
9
|
-
event OnSpawned {
|
|
10
|
-
forever {
|
|
11
|
-
RotateLeftInstantly(4)
|
|
12
|
-
var p = NearestPlayer()
|
|
13
|
-
if p.Exists() and SurfaceGapTo(p) < 70 {
|
|
14
|
-
p.SpawnFloatingText("+1", Vector(1, 0.9, 0.2))
|
|
15
|
-
Destroy()
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
#end
|
|
20
|
-
|
|
21
|
-
#class GameManager
|
|
22
|
-
var TotalCoins = 10
|
|
23
|
-
var SeenCoins = false
|
|
24
|
-
event OnSpawned {
|
|
25
|
-
for i in 0..TotalCoins {
|
|
26
|
-
var pos = Position(RandomNumber(-1400, 1400), RandomNumber(-1400, 1400), 80)
|
|
27
|
-
SpawnObject(SavedObject.coin, pos)
|
|
28
|
-
}
|
|
29
|
-
var scoreLabel = ResolveObjectByNameOnce("ScoreText")
|
|
30
|
-
var midLabel = ResolveObjectByNameOnce("MidText")
|
|
31
|
-
forever {
|
|
32
|
-
// Spawned coins register their tag on the next tick, so wait until the census
|
|
33
|
-
// has seen at least one coin before treating "0 left" as a win.
|
|
34
|
-
var left = GetAllObjectsWithTag(Tag.Coin).Count()
|
|
35
|
-
var collected = TotalCoins - left
|
|
36
|
-
scoreLabel.SetText("Coins: " + collected + " / " + TotalCoins)
|
|
37
|
-
if left == 0 and collected == TotalCoins and SeenCoins {
|
|
38
|
-
midLabel.SetText("YOU WIN! Press R to play again")
|
|
39
|
-
} else {
|
|
40
|
-
midLabel.SetText("")
|
|
41
|
-
}
|
|
42
|
-
if left > 0 {
|
|
43
|
-
SeenCoins = true
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
event KeyboardDown[R] {
|
|
48
|
-
RestartGame()
|
|
49
|
-
}
|
|
50
|
-
#end
|
|
51
|
-
|
|
52
|
-
saved coin {
|
|
53
|
-
display coin : Coin { model = "cylinder" size = (60, 60, 12) rotation = (90, 0, 0) color = (1, 0.85, 0.2) }
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
object Ground {
|
|
57
|
-
model = "cube"
|
|
58
|
-
position = (0, 0, -50)
|
|
59
|
-
size = (4000, 4000, 100)
|
|
60
|
-
color = (0.32, 0.5, 0.34)
|
|
61
|
-
}
|
|
62
|
-
object PillarA { position = (400, 400, 150) size = (100, 100, 300) color = (0.62, 0.58, 0.52) }
|
|
63
|
-
object PillarB { position = (-600, 300, 150) size = (100, 100, 300) color = (0.62, 0.58, 0.52) }
|
|
64
|
-
object PillarC { position = (200, -700, 150) size = (100, 100, 300) color = (0.62, 0.58, 0.52) }
|
|
65
|
-
display manager : GameManager { visible = false }
|
|
66
|
-
|
|
67
|
-
screenCanvas HUD {
|
|
68
|
-
textLabel ScoreText { offset = (20, 20) text = "Coins: 0 / 10" color = (1, 1, 0.85) }
|
|
69
|
-
textLabel MidText { align = (center, center) text = "" color = (1, 1, 0.3) }
|
|
70
|
-
}
|
|
1
|
+
// Coin Collector — walk into the 10 spinning coins to collect them all. Press R to replay.
|
|
2
|
+
// Demonstrates: saved objects + runtime spawning, tags, proximity pickup, HUD score text,
|
|
3
|
+
// win + restart flow. Movement uses the engine's default player controller (no #class player).
|
|
4
|
+
|
|
5
|
+
#class Coin
|
|
6
|
+
event OnPreSpawn {
|
|
7
|
+
AddTag(Tag.Coin)
|
|
8
|
+
}
|
|
9
|
+
event OnSpawned {
|
|
10
|
+
forever {
|
|
11
|
+
RotateLeftInstantly(4)
|
|
12
|
+
var p = NearestPlayer()
|
|
13
|
+
if p.Exists() and SurfaceGapTo(p) < 70 {
|
|
14
|
+
p.SpawnFloatingText("+1", Vector(1, 0.9, 0.2))
|
|
15
|
+
Destroy()
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
#end
|
|
20
|
+
|
|
21
|
+
#class GameManager
|
|
22
|
+
var TotalCoins = 10
|
|
23
|
+
var SeenCoins = false
|
|
24
|
+
event OnSpawned {
|
|
25
|
+
for i in 0..TotalCoins {
|
|
26
|
+
var pos = Position(RandomNumber(-1400, 1400), RandomNumber(-1400, 1400), 80)
|
|
27
|
+
SpawnObject(SavedObject.coin, pos)
|
|
28
|
+
}
|
|
29
|
+
var scoreLabel = ResolveObjectByNameOnce("ScoreText")
|
|
30
|
+
var midLabel = ResolveObjectByNameOnce("MidText")
|
|
31
|
+
forever {
|
|
32
|
+
// Spawned coins register their tag on the next tick, so wait until the census
|
|
33
|
+
// has seen at least one coin before treating "0 left" as a win.
|
|
34
|
+
var left = GetAllObjectsWithTag(Tag.Coin).Count()
|
|
35
|
+
var collected = TotalCoins - left
|
|
36
|
+
scoreLabel.SetText("Coins: " + collected + " / " + TotalCoins)
|
|
37
|
+
if left == 0 and collected == TotalCoins and SeenCoins {
|
|
38
|
+
midLabel.SetText("YOU WIN! Press R to play again")
|
|
39
|
+
} else {
|
|
40
|
+
midLabel.SetText("")
|
|
41
|
+
}
|
|
42
|
+
if left > 0 {
|
|
43
|
+
SeenCoins = true
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
event KeyboardDown[R] {
|
|
48
|
+
RestartGame()
|
|
49
|
+
}
|
|
50
|
+
#end
|
|
51
|
+
|
|
52
|
+
saved coin {
|
|
53
|
+
display coin : Coin { model = "cylinder" size = (60, 60, 12) rotation = (90, 0, 0) color = (1, 0.85, 0.2) }
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
object Ground {
|
|
57
|
+
model = "cube"
|
|
58
|
+
position = (0, 0, -50)
|
|
59
|
+
size = (4000, 4000, 100)
|
|
60
|
+
color = (0.32, 0.5, 0.34)
|
|
61
|
+
}
|
|
62
|
+
object PillarA { position = (400, 400, 150) size = (100, 100, 300) color = (0.62, 0.58, 0.52) }
|
|
63
|
+
object PillarB { position = (-600, 300, 150) size = (100, 100, 300) color = (0.62, 0.58, 0.52) }
|
|
64
|
+
object PillarC { position = (200, -700, 150) size = (100, 100, 300) color = (0.62, 0.58, 0.52) }
|
|
65
|
+
display manager : GameManager { visible = false }
|
|
66
|
+
|
|
67
|
+
screenCanvas HUD {
|
|
68
|
+
textLabel ScoreText { offset = (20, 20) text = "Coins: 0 / 10" color = (1, 1, 0.85) }
|
|
69
|
+
textLabel MidText { align = (center, center) text = "" color = (1, 1, 0.3) }
|
|
70
|
+
}
|
|
@@ -1,70 +1,70 @@
|
|
|
1
|
-
// Dodge the Falling Blocks — red cubes rain down; touching one ends the run. Press R to retry.
|
|
2
|
-
// Demonstrates: a hidden manager object, timed spawning with Timer, dynamic physics objects,
|
|
3
|
-
// cross-object variable writes (block -> manager), survival-seconds score, lose + restart flow.
|
|
4
|
-
// Movement uses the engine's default player controller (no #class player).
|
|
5
|
-
|
|
6
|
-
#class FallingBlock
|
|
7
|
-
var LifeTmr : Timer
|
|
8
|
-
event OnSpawned {
|
|
9
|
-
LifeTmr.StartCountDown(8) // despawn landed blocks so the arena stays playable
|
|
10
|
-
forever {
|
|
11
|
-
if LifeTmr.IsDone() {
|
|
12
|
-
Destroy()
|
|
13
|
-
}
|
|
14
|
-
var p = NearestPlayer()
|
|
15
|
-
if p.Exists() and SurfaceGapTo(p) < 5 {
|
|
16
|
-
NearestObjectWithTag(Tag.Manager).GameOver = true
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
#end
|
|
21
|
-
|
|
22
|
-
#class GameManager
|
|
23
|
-
var GameOver = false
|
|
24
|
-
var Score = 0
|
|
25
|
-
event OnPreSpawn {
|
|
26
|
-
AddTag(Tag.Manager)
|
|
27
|
-
}
|
|
28
|
-
event OnSpawned {
|
|
29
|
-
var secondTmr = Timer()
|
|
30
|
-
var dropTmr = Timer()
|
|
31
|
-
var scoreLabel = ResolveObjectByNameOnce("ScoreText")
|
|
32
|
-
var midLabel = ResolveObjectByNameOnce("MidText")
|
|
33
|
-
forever {
|
|
34
|
-
if GameOver {
|
|
35
|
-
midLabel.SetText("GAME OVER — survived " + Score + " s. Press R to retry")
|
|
36
|
-
continue
|
|
37
|
-
}
|
|
38
|
-
if secondTmr.IsDone() {
|
|
39
|
-
secondTmr.StartCountDown(1)
|
|
40
|
-
Score += 1
|
|
41
|
-
scoreLabel.SetText("Survived: " + Score + " s")
|
|
42
|
-
}
|
|
43
|
-
if dropTmr.IsDone() {
|
|
44
|
-
dropTmr.StartCountDown(0.35)
|
|
45
|
-
var pos = Position(RandomNumber(-900, 900), RandomNumber(-900, 900), 1300)
|
|
46
|
-
SpawnObject(SavedObject.block, pos)
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
event KeyboardDown[R] {
|
|
51
|
-
RestartGame()
|
|
52
|
-
}
|
|
53
|
-
#end
|
|
54
|
-
|
|
55
|
-
saved block {
|
|
56
|
-
physics block : FallingBlock { model = "cube" size = (120, 120, 120) color = (0.85, 0.25, 0.2) }
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
object Ground {
|
|
60
|
-
model = "cube"
|
|
61
|
-
position = (0, 0, -50)
|
|
62
|
-
size = (2200, 2200, 100)
|
|
63
|
-
color = (0.4, 0.42, 0.5)
|
|
64
|
-
}
|
|
65
|
-
display manager : GameManager { visible = false }
|
|
66
|
-
|
|
67
|
-
screenCanvas HUD {
|
|
68
|
-
textLabel ScoreText { offset = (20, 20) text = "Survived: 0 s" color = (1, 1, 1) }
|
|
69
|
-
textLabel MidText { align = (center, center) text = "" color = (1, 0.45, 0.35) }
|
|
70
|
-
}
|
|
1
|
+
// Dodge the Falling Blocks — red cubes rain down; touching one ends the run. Press R to retry.
|
|
2
|
+
// Demonstrates: a hidden manager object, timed spawning with Timer, dynamic physics objects,
|
|
3
|
+
// cross-object variable writes (block -> manager), survival-seconds score, lose + restart flow.
|
|
4
|
+
// Movement uses the engine's default player controller (no #class player).
|
|
5
|
+
|
|
6
|
+
#class FallingBlock
|
|
7
|
+
var LifeTmr : Timer
|
|
8
|
+
event OnSpawned {
|
|
9
|
+
LifeTmr.StartCountDown(8) // despawn landed blocks so the arena stays playable
|
|
10
|
+
forever {
|
|
11
|
+
if LifeTmr.IsDone() {
|
|
12
|
+
Destroy()
|
|
13
|
+
}
|
|
14
|
+
var p = NearestPlayer()
|
|
15
|
+
if p.Exists() and SurfaceGapTo(p) < 5 {
|
|
16
|
+
NearestObjectWithTag(Tag.Manager).GameOver = true
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
#end
|
|
21
|
+
|
|
22
|
+
#class GameManager
|
|
23
|
+
var GameOver = false
|
|
24
|
+
var Score = 0
|
|
25
|
+
event OnPreSpawn {
|
|
26
|
+
AddTag(Tag.Manager)
|
|
27
|
+
}
|
|
28
|
+
event OnSpawned {
|
|
29
|
+
var secondTmr = Timer()
|
|
30
|
+
var dropTmr = Timer()
|
|
31
|
+
var scoreLabel = ResolveObjectByNameOnce("ScoreText")
|
|
32
|
+
var midLabel = ResolveObjectByNameOnce("MidText")
|
|
33
|
+
forever {
|
|
34
|
+
if GameOver {
|
|
35
|
+
midLabel.SetText("GAME OVER — survived " + Score + " s. Press R to retry")
|
|
36
|
+
continue
|
|
37
|
+
}
|
|
38
|
+
if secondTmr.IsDone() {
|
|
39
|
+
secondTmr.StartCountDown(1)
|
|
40
|
+
Score += 1
|
|
41
|
+
scoreLabel.SetText("Survived: " + Score + " s")
|
|
42
|
+
}
|
|
43
|
+
if dropTmr.IsDone() {
|
|
44
|
+
dropTmr.StartCountDown(0.35)
|
|
45
|
+
var pos = Position(RandomNumber(-900, 900), RandomNumber(-900, 900), 1300)
|
|
46
|
+
SpawnObject(SavedObject.block, pos)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
event KeyboardDown[R] {
|
|
51
|
+
RestartGame()
|
|
52
|
+
}
|
|
53
|
+
#end
|
|
54
|
+
|
|
55
|
+
saved block {
|
|
56
|
+
physics block : FallingBlock { model = "cube" size = (120, 120, 120) color = (0.85, 0.25, 0.2) }
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
object Ground {
|
|
60
|
+
model = "cube"
|
|
61
|
+
position = (0, 0, -50)
|
|
62
|
+
size = (2200, 2200, 100)
|
|
63
|
+
color = (0.4, 0.42, 0.5)
|
|
64
|
+
}
|
|
65
|
+
display manager : GameManager { visible = false }
|
|
66
|
+
|
|
67
|
+
screenCanvas HUD {
|
|
68
|
+
textLabel ScoreText { offset = (20, 20) text = "Survived: 0 s" color = (1, 1, 1) }
|
|
69
|
+
textLabel MidText { align = (center, center) text = "" color = (1, 0.45, 0.35) }
|
|
70
|
+
}
|