diff --git a/README.md b/README.md new file mode 100644 index 0000000..8aebaaf --- /dev/null +++ b/README.md @@ -0,0 +1,88 @@ +# 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 +``` + +**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 +```