Files
endless-runner-vibe/README.md
Gabriel Kaszewski 951bd51f12 Add WebAssembly build support via Emscripten
- Cargo.toml: gate `wayland` feature behind cfg(not(wasm32)) so the
  dependency resolves correctly for both native and web targets
- .cargo/config.toml: WASM linker flags (ASYNCIFY, GLFW, memory growth)
- build_web.sh: sets required EMCC_CFLAGS, builds, copies artefacts to web/;
  accepts --serve to start a local HTTP server
- web/index.html: minimal Emscripten shell with canvas and status line
- .gitignore: exclude generated web/*.js and web/*.wasm artefacts
- README: document web build prerequisites and usage

ASYNCIFY lets the native while-loop main loop run unchanged in the browser.
Build output: ~267 KB JS + ~458 KB WASM.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 00:35:21 +01:00

100 lines
3.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.
# Endless Runner
A 2D side-scrolling endless runner built with Rust and [raylib](https://www.raylib.com/).
![Rust](https://img.shields.io/badge/Rust-2024-orange)
## Gameplay
Run as far as you can on procedurally generated platforms. The world scrolls faster the longer you survive. Stomp enemies for bonus points, collect power-ups, and don't fall off the screen.
**Controls**
| Action | Keys |
|--------|------|
| Jump | `Space` / `W` / `↑` |
| Restart | `Space` / `R` / `Enter` |
### Power-ups
| Icon | Name | Effect |
|------|------|--------|
| I | **Invincible** | Immune to side hits for 5 s |
| J | **Jump Boost** | 1.45× jump height for 6 s |
| 2 | **2× Score** | Double score gain for 8 s |
### Scoring
- Passive: 80 pts/s (multiplied by any active score effect)
- Stomp: 100 pt bonus per enemy (also multiplied)
## Building
**Prerequisites:** Rust toolchain, raylib system library, a Wayland compositor.
```sh
# debug
cargo run
# release (LTO + stripped)
cargo run --release
```
**Web (WebAssembly)**
Prerequisites: [Emscripten SDK](https://emscripten.org/docs/getting_started/downloads.html) activated in your shell.
```sh
./build_web.sh # produces web/*.js + web/*.wasm
./build_web.sh --serve # build then serve at http://localhost:8080
```
The web build uses ASYNCIFY so the main game loop requires no changes between native and browser targets.
**Tests**
```sh
cargo test
```
42 unit tests covering physics, collision, effects, and level generation.
## Architecture
```
src/
main.rs — entry point, 60 fps cap, dt capped at 0.05 s
config.rs — Config struct (all tunable parameters)
player.rs — vertical physics, coyote-time jump window
platform.rs — scrolling platforms
enemy.rs — scrolling enemies with stomp detection
pickup.rs — PickupDef (data) + in-world Pickup instance
effects.rs — ActiveEffect trait + three concrete impls
level_gen.rs — procedural generation (StdRng, scrolling frontier)
world.rs — simulation loop, collision resolution, rendering
game.rs — state machine (Playing / GameOver), HUD
```
**Key design decisions**
- Player x is fixed; only the world scrolls.
- Speed follows `initial + factor × ln(1 + elapsed / time_scale)` — fast early ramp, logarithmic plateau.
- Landing detection uses the previous and current bottom-y crossing the platform surface, making it tunnelling-safe at high speeds.
- Coyote time: the jump window stays open for 120 ms after leaving a platform edge.
- Power-ups are fully data-driven via `Config::pickup_defs`; adding a new type requires one `PickupDef` entry and one `ActiveEffect` impl.
## Tuning
All gameplay parameters live in `Config::default()` in `src/config.rs` — no recompilation of other modules needed when tweaking values.
```rust
initial_speed: 280.0, // px/s at t=0
speed_log_factor: 150.0, // how much speed grows
speed_time_scale: 30.0, // seconds before growth slows
gravity: 1900.0, // px/s²
jump_velocity: -800.0, // px/s (negative = up)
coyote_time: 0.12, // seconds
enemy_spawn_chance: 0.35, // per platform
pickup_spawn_chance: 0.28, // per platform
```