Files
llamamod/docs/guide/levels-in-code.md
T

98 lines
5.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Levels from scripts
Besides the editor, a level can be described as a short script that a **level builder** turns
into a complete WAD: geometry made of boxes, ramps, stairs, trees and sea, objects placed by type
name, lighting baked automatically. There are two builders with the same ideas:
| Builder | Language | Used by |
|---|---|---|
| [`tools/levelbuild.py`](../../tools/levelbuild.py) | Python 3 (numpy, Pillow) | the original test world [`levels/testwelt.py`](../../levels/testwelt.py), the jump lab [`levels/sprunglabor.py`](../../levels/sprunglabor.py) |
| [`levelbuild/LevelBuilder.java`](../../src/main/java/com/eliasmueller/llamamod/levelbuild/LevelBuilder.java) | Java (`LevelScript`) | the Test World mod ([`mods/testworld/`](../../src/main/java/com/eliasmueller/llamamod/mods/testworld/)), the [Alligator Arena](../strats/arena.md), the editor's brushes |
Both start from a **base level** (default Village 1): its object code, textures and sound are
kept; geometry, tile grid, vertex colours, objects and waypoints are generated from scratch. Full
documentation of the Python builder, the measured physics and the test world:
[notes/levelbau.md](../../notes/levelbau.md).
## A Python level
```python
LEVEL_ARGS = dict(name='MyLevel', seed=7)
def build(L):
L.sea(0, 0, 60, 60, y=-2.0, kill=(6, 4, 54, 56)) # sea + death plane
L.box(14, 12, 26, 24, -0.4, 0, top='stein', side='stein') # a stone plaza
L.stairs(26, 18, 29, 22, 0, 1.5, 3, '+x') # stairs up to the east
L.box(29, 17, 33, 23, 0, 1.5, top='gras', side='erde')
L.player(20, 14.5, rot=0) # facing +z
L.checkpoint(17, 18.5)
L.coins([(27, 20), (28, 20)])
L.strat('Bunny', 31, 20)
L.box(31, 21, 32, 22, 1.5, 1.56, top='platte', side='stein', mat=16) # exit floor
L.exit(31.5, 21.5) # LevelDoor in the same cell
```
```bash
python3 tools/levelbuild.py my_level.py out/my_level.wad # build
python3 tools/levelbuild.py --types # object types of the base
python3 tools/levelbuild.py --textures tex.png # texture names and a contact sheet
```
Coordinates are game units: x east, y up, z = grid row ("south"); angles in degrees, 0° faces +z.
Building blocks: `floor`, `box`, `platform`, `pillar`, `ramp`, `stairs`, `fence`, `tree`, `sea`,
`quad`, `collider`, `obj` (an OBJ file), `height_at`. The exit needs a floor with collision
material 16 in its cell – the test world uses `box(..., mat=16)` under the door.
**Texture names**: the Python builder's own names are German (`gras`, `stein`, `erde`, `platte`,
`meer` …, list: `--textures`); the English names of the Java builder (`grass`, `stone`, `earth`,
`slab`, `sea` …) work as well and give the same result.
The base level is `t1l1m001.wad` in the CD folder `$LLAMAMOD_CD/wads` (default
`~/.wine-lama/iso-dk/Setup/Eng/Cd`), or `--base <file>`. `--install` copies the WAD into the TestLevel
mod of a hand-made Wine setup (`$LAMA_WINEPREFIX/mods/testlevel`, default `~/.wine-lama`) – with
LlamaMod, use a Java level or the editor instead. All variables: [Tools: Paths](../tools.md#paths).
## A Java level
Implement [`LevelScript`](../../src/main/java/com/eliasmueller/llamamod/levelbuild/LevelScript.java):
```java
public final class MyLevel implements LevelScript {
@Override public String levelName() { return "My Level"; }
@Override public void build(LevelBuilder l) {
l.sea(0, 0, 40, 40, -1.5, new double[] {7, 7, 33, 33});
l.floor(10, 10, 30, 30, 0, "grass");
l.box(18, 24, 22, 25, 0, 0.06, o().top("pattern_purple").mat(16)); // exit floor
l.player(20, 12, 0);
l.checkpoint(12, 12);
l.exit(20.5, 24.5, null, null, new int[] {1, 9, 32});
l.coins(List.of(new double[] {20, 16}, new double[] {20, 18}));
}
}
```
`buildWad(baseWad, wads, opts)` returns the WAD. To ship it, write a small
[mod](../developers.md#writing-a-mod) whose `apply` writes `wads/T1L9M0nn.wad` (chapter 1 or
32–49) and a loading picture – [`ArenaMod`](../../src/main/java/com/eliasmueller/llamamod/mods/arena/ArenaMod.java)
is a complete example. Texture names are English here (`grass`, `stone`, `sand`, `inca`, …) and are
matched by picture on the chosen base.
## The editor from the command line
The editor's project format can be scripted too:
```bash
llamamod --editor-new my.llamalevel t1l1m001 --name "My level" # new project on a base
llamamod --editor-import t1l2m001 jungle.llamalevel # an original level as a project
llamamod --editor-build my.llamalevel out.wad # build the WAD
llamamod --import-level my.llamalevel # install as a level mod
```
## Seeing the result without the game
* [`tools/geom_export.py`](../../tools/geom_export.py) `level.wad outdir --collision --objects`
writes OBJ files, texture pages and two preview images.
* [`tools/vorschau/`](../../tools/vorschau/) renders labelled overviews with Blender (Eevee).
* In the game: the test harness, see [Tools](../tools.md#testing-in-the-game).