64 lines
2.5 KiB
Markdown
64 lines
2.5 KiB
Markdown
|
|
# GALAGA — a C engine with akbasic embedded as its enemy brain
|
||
|
|
|
||
|
|
A GALAGA-style fixed shooter whose core engine is C on libakgl, with akbasic
|
||
|
|
linked in as the scripting engine that owns every enemy's behavior. One BASIC
|
||
|
|
script — `galaga.bas`, nothing but `DEF` functions and an `END` — is called
|
||
|
|
once per enemy per frame through a custom `akgl_Actor` update hook. Bullets,
|
||
|
|
collision, scoring and screens are C forever; everything an enemy *decides* is
|
||
|
|
BASIC.
|
||
|
|
|
||
|
|
This is the checked-in example behind two tutorial chapters, and the chapters
|
||
|
|
are the intended way in:
|
||
|
|
|
||
|
|
* **[Chapter 20](../../docs/20-tutorial-galaga.md)** — the engine and the
|
||
|
|
boundary: from an empty file to a C game that boots a script and hands one
|
||
|
|
actor to BASIC.
|
||
|
|
* **[Chapter 21](../../docs/21-tutorial-galaga-enemies.md)** — the data
|
||
|
|
structures and the AI: from `SELF@` to a full attacking wave.
|
||
|
|
|
||
|
|
It is an academic exercise demonstrating *how* such an embed is done, not a
|
||
|
|
claim that it is the best way to write a GALAGA.
|
||
|
|
|
||
|
|
## Building and running
|
||
|
|
|
||
|
|
The example builds when both example and graphics builds are on:
|
||
|
|
|
||
|
|
```
|
||
|
|
cmake -S . -B build-akgl -DAKBASIC_WITH_AKGL=ON
|
||
|
|
cmake --build build-akgl --target akbasic_example_galaga
|
||
|
|
build-akgl/akbasic_example_galaga
|
||
|
|
```
|
||
|
|
|
||
|
|
| Key | Does |
|
||
|
|
|---|---|
|
||
|
|
| Left / Right | move the ship |
|
||
|
|
| Space | fire (two shots on screen, the classic rule) |
|
||
|
|
| Return | choose a menu entry |
|
||
|
|
|
||
|
|
## Flags
|
||
|
|
|
||
|
|
```
|
||
|
|
akbasic_example_galaga [--assets DIR] [--script PATH] [--frames N]
|
||
|
|
[--autoplay] [--screenshot PATH] [--screenshot-frame N]
|
||
|
|
```
|
||
|
|
|
||
|
|
`--script` points at a different enemy script, which is the whole point of the
|
||
|
|
architecture: edit `galaga.bas`, run again, no rebuild. `--frames N` with
|
||
|
|
`--autoplay` is the headless smoke test CI runs under the dummy SDL drivers;
|
||
|
|
the final log line reports frames, score, kills and shots per kind, and the
|
||
|
|
script-error count — a wave of dumb enemies still exits 0, and that count is
|
||
|
|
how you notice.
|
||
|
|
|
||
|
|
## The files
|
||
|
|
|
||
|
|
| File | Owns |
|
||
|
|
|---|---|
|
||
|
|
| `galaga.h` | the shared structs — the whole boundary in one header |
|
||
|
|
| `main.c` | startup order, the frame loop, screens, the starfield |
|
||
|
|
| `script.c` | everything that touches the interpreter |
|
||
|
|
| `enemies.c` | wave table, formation grid, the enemy update hook |
|
||
|
|
| `player.c` | the ship, both bullet kinds, every collision |
|
||
|
|
| `galaga.bas` | every decision an enemy makes |
|
||
|
|
| `interop_test.c` | round-trip proof the boundary works, run by CTest |
|
||
|
|
| `assets/` | sprite/character JSON, and Kenney CC0 art under `assets/art/` |
|