# 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 ```