# **🏃 Escape the Teacher** **A server-authoritative 2D endless runner built with Go, Redis, and JavaScript.** ## **📖 About the Project** "Escape the Teacher" is a high-performance web game developed as a school project. You play as a student caught cheating, running away from an angry teacher. The game features increasing difficulty, power-ups, boss phases, and a competitive global leaderboard. Unlike typical browser games, this project implements **anti-cheat architecture** usually found in multiplayer RTS or FPS games. The browser does not decide if you survived; the server does. ## **✨ Features** ### **🎮 Gameplay** * **Endless Progression:** The game speeds up over time. * **Controls:** * **Jump:** Space / Arrow Up / Tap / Left Click. * **Crouch:** Arrow Down / Swipe Down (Mobile). * **Power-Ups:** * 🛡️ **Godmode:** Survives 3 hits. * ⚾ **Baseball Bat:** Eliminates the next teacher obstacle. * 👟 **Jumpboots:** Grants higher jumping power for a limited time. * 💰 **Coins:** Bonus points (visual score only, does not affect game speed). * **Dynamic Backgrounds:** Environment changes as you progress. * **Boss Phases:** Every 1500 ticks, special boss enemies spawn. ### **📱 Mobile First** * Fully responsive Canvas rendering (Letterboxing). * Touch gestures (Swipe to crouch). * "Rotate Device" enforcement for optimal gameplay. ### **🛡️ Security & Admin** * **Admin Panel:** Password-protected (/admin) interface. * **Moderation:** Review and delete leaderboard entries. * **Badword Filter:** Automatic blocking of inappropriate names using Redis Sets. * **Proof System:** Players receive an 8-character "Claim Code" to prove their high score to the teacher. ## **🏗️ Technical Architecture** The core philosophy is **"Server-Authoritative, Client-Predicted"**. 1. **Frontend (JS):** Captures inputs and renders the game state immediately (Client-Side Prediction) to ensure zero input lag. It sends input logs to the server in chunks. 2. **Backend (Go):** Validates the inputs by re-simulating the game physics tick-by-tick. 3. **Database (Redis):** Stores active sessions, RNG states, and leaderboards (Sorted Sets). ### **Tech Stack** * **Backend:** Go (Golang) 1.21+ * **Frontend:** Vanilla JavaScript (Canvas API), CSS3 * **Database:** Redis * **Containerization:** Docker (Multi-Stage Build: Node Minifier \-\> Go Builder \-\> Alpine Runner) * **Orchestration:** Kubernetes (Deployment, Service, Ingress) ## **🔧 Development Challenges & Solutions** Developing a cheat-proof game for the web came with significant technical hurdles. Here is how we solved them: ### **1\. The "Butterfly Effect" (RNG Desynchronization)** * **Problem:** JavaScript's Math.random() and Go's rand implementations are different. Even if seeded with the same number, they produce different sequences. This caused "Ghost Objects" (Server spawns a teacher, Client spawns a coin). * **Solution:** We implemented a custom **Linear Congruential Generator (LCG)** in both languages. * **The Tricky Part:** JavaScript uses 64-bit Floating Point numbers for everything, while Go uses strict types. Math operations drifted apart after a few hundred iterations. * **Fix:** We forced JavaScript to use BigInt to simulate 32-bit integer overflows exactly like Go's uint32. ### **2\. Floating Point Drift & Spawning** * **Problem:** We initially spawned objects based on pixel positions (if x \< 800). Due to floating point precision errors, the client sometimes calculated 799.99 (Spawn\!) while the server calculated 800.01 (Wait\!). This desynchronized the RNG state immediately. * **Solution:** **Tick-Based Spawning.** We decoupled spawning from spatial positions. The game now decides: *"The next object spawns at Tick 500"* rather than *"at Pixel 1200"*. Integers don't drift. ### **3\. Logic-Score Coupling** * **Problem:** Initially, game speed and boss phases depended on the *Score*. When we added Coins (+2000 Points), the client's score jumped instantly, speeding up the game on the client side before the server acknowledged the coin pickup. This caused massive desyncs. * **Solution:** We decoupled logic from the visual score. Game difficulty now depends strictly on **"Ticks Alive" (Time)**, which cannot be manipulated by picking up items. ### **4\. Physics Tunneling (High Speed Collisions)** * **Problem:** At high speeds, the player could move 20 pixels per frame. If an obstacle was only 15 pixels wide, the player effectively "teleported" through it without triggering a collision. * **Solution:** **Continuous Collision Detection (CCD).** We extend the hitbox of obstacles dynamically based on their current speed (width \+ speed). ### **5\. "Ghost Hits" (The CCD Side Effect)** * **Problem:** The CCD fix caused a new issue where the extended hitbox would hit the player *after* they had already jumped over the obstacle (hitting them from behind). * **Solution:** A **"Passed Check"**. Before checking collisions, we verify if the obstacle's right edge is already physically behind the player's left edge. If so, collision is ignored. ## **🚀 Getting Started** ### **Using Docker (Recommended)** This project includes a production-ready Dockerfile and docker-compose.yml. 1. **Clone the repository:** git clone \[https://git.zb-server.de/ZB-Server/it232Abschied.git\](https://git.zb-server.de/ZB-Server/it232Abschied.git) cd it232Abschied 2. Configure Environment (Optional): Edit docker-compose.yml to set your admin credentials: environment: \- ADMIN\_USER=teacher \- ADMIN\_PASS=secret123 3. **Run:** docker-compose up \--build \-d 4. **Play:** Open http://localhost:8080 ### **Local Development (Go & Redis)** 1. Start Redis: docker run \-d \-p 6379:6379 redis:alpine 2. Start the Server: go run . *(Note: Use go run . to include all files, not just main.go)* ## **📂 Project Structure** . ├── k8s/ \# Kubernetes manifests ├── static/ \# Frontend files │ ├── assets/ \# Images & Sprites │ ├── fonts/ \# Local GDPR-compliant fonts │ ├── js/ \# Modular Game Engine │ │ ├── config.js \# Constants │ │ ├── logic.js \# Physics & Collision │ │ ├── network.js \# Server-Sync │ │ └── ... │ ├── index.html \# Entry Point │ └── style.css \# Retro Design ├── secure/ \# Protected Admin Files ├── main.go \# Go Server Entrypoint ├── simulation.go \# Server-side Physics Engine ├── rng.go \# Deterministic RNG ├── types.go \# Data Structures ├── Dockerfile \# Multi-Stage Build └── ... ## **📜 Legal** This is a non-commercial educational project. * **Privacy:** No tracking cookies are used. Highscores are stored in Redis; local scores in LocalStorage. * **Assets:** Font "Press Start 2P" is hosted locally. **Good luck escaping\! 🏃💨**