All checks were successful
Dynamic Branch Deploy / build-and-deploy (push) Successful in 2m27s
133 lines
5.8 KiB
Markdown
133 lines
5.8 KiB
Markdown
# **🏃 Escape the Teacher**
|
|
|
|
**A high-performance, server-authoritative 2D endless runner built with Go, Redis, and WebSockets.**
|
|
|
|
## **📖 About the Project**
|
|
|
|
"Escape the Teacher" is a 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 **competitive multiplayer architecture** usually found in games like *Agar.io* or FPS titles. The browser is just a "dumb" terminal; the server simulates the entire world.
|
|
|
|
## **✨ 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.
|
|
* 💰 **Coins:** Bonus points.
|
|
* **Level Editor:** Custom chunks (platforms, enemies) can be designed in a secure Admin UI and are streamed into the game live.
|
|
* **Juice:** Particle effects and retro sound system.
|
|
|
|
### **🛡️ Security & Admin**
|
|
|
|
* **Server-Authoritative:** Physics runs on the server. Cheating (speedhack, godmode) is impossible.
|
|
* **Admin Panel:** Create levels, manage badwords, and moderate the leaderboard.
|
|
* **Proof System:** Players receive an 8-character "Claim Code" to prove their high score offline.
|
|
|
|
## **🏗️ Technical Architecture**
|
|
|
|
We moved from a traditional HTTP-Request model to a **Realtime Streaming Architecture**.
|
|
|
|
1. **Backend (Go):**
|
|
* Runs the physics simulation at a fixed **20 TPS (Ticks Per Second)**.
|
|
* Generates level segments ("Chunks") 5 seconds into the future.
|
|
* Streams object positions via **WebSockets** to the client.
|
|
2. **Frontend (JS):**
|
|
* **Client-Side Prediction:** Inputs are applied immediately for zero-latency feel.
|
|
* **Buffering:** Incoming server data is buffered and played back smoothly.
|
|
* **Interpolation:** Although physics runs at 20 FPS, the game renders at 60+ FPS by interpolating positions (`lerp`).
|
|
3. **Database (Redis):**
|
|
* Stores active sessions, highscores, and custom level chunks.
|
|
|
|
### **Tech Stack**
|
|
|
|
* **Backend:** Go (Golang) 1.22+ (`gorilla/websocket`)
|
|
* **Frontend:** Vanilla JavaScript (Canvas API)
|
|
* **Database:** Redis
|
|
* **Containerization:** Docker (Multi-Stage Build)
|
|
* **Orchestration:** Kubernetes
|
|
|
|
## **🔧 Engineering Challenges & Solutions**
|
|
|
|
### **1. The "Netflix" Approach (Streaming vs. RNG)**
|
|
* **Problem:** Syncing Random Number Generators (RNG) between Client and Server caused "Butterfly Effects" where one wrong number broke the whole game state.
|
|
* **Solution:** **Streaming.** The client no longer generates anything. The server generates objects in the future and streams them into a buffer on the client. The client simply plays back what it receives.
|
|
|
|
### **2. Lag Compensation & RTT**
|
|
* **Problem:** If the internet lags, the server's objects appear too late on the client, causing "Ghost Kills".
|
|
* **Solution:** **RTT (Round Trip Time) Measurement.** The client constantly measures the Ping. Incoming objects are visually shifted based on latency (`Latency * Speed`), so they appear exactly where they are on the server.
|
|
|
|
### **3. Low Tick-Rate & Interpolation**
|
|
* **Problem:** To save server CPU, we run physics at only **20 TPS**. This usually looks choppy (like a slideshow).
|
|
* **Solution:** **Linear Interpolation.** The rendering loop runs at 60/144 FPS and calculates the visual position between two physics ticks. The game looks buttery smooth despite low server load.
|
|
|
|
### **4. "Instant" Death**
|
|
* **Problem:** Waiting for the server to confirm "You died" feels laggy.
|
|
* **Solution:** **Optimistic Client Death.** The client detects collisions locally and stops the game visually (`Game Over`). It sends a `DEATH` signal to the server, which then validates and saves the highscore.
|
|
|
|
## **🚀 Getting Started**
|
|
|
|
### **Using Docker (Recommended)**
|
|
|
|
1. **Clone the repository:**
|
|
```bash
|
|
git clone [https://git.zb-server.de/ZB-Server/it232Abschied.git](https://git.zb-server.de/ZB-Server/it232Abschied.git)
|
|
cd it232Abschied
|
|
```
|
|
|
|
2. **Run:**
|
|
```bash
|
|
docker-compose up --build -d
|
|
```
|
|
|
|
3. **Play:** Open `http://localhost:8080`
|
|
4. **Admin:** Open `http://localhost:8080/admin` (User: `lehrer`, Pass: `geheim123`)
|
|
|
|
### **Local Development**
|
|
|
|
1. Start Redis:
|
|
```bash
|
|
docker run -d -p 6379:6379 redis:alpine
|
|
```
|
|
2. Start the Server:
|
|
```bash
|
|
go run .
|
|
```
|
|
|
|
## **📂 Project Structure**
|
|
|
|
```
|
|
.
|
|
├── k8s/ \# Kubernetes manifests
|
|
├── static/ \# Frontend files
|
|
│ ├── assets/ \# Images & Audio
|
|
│ ├── js/ \# Game Engine
|
|
│ │ ├── audio.js \# Sound Manager
|
|
│ │ ├── logic.js \# Physics & Buffer Logic
|
|
│ │ ├── render.js \# Drawing & Interpolation
|
|
│ │ ├── network.js \# WebSocket & RTT Sync
|
|
│ │ └── ...
|
|
│ ├── index.html \# Entry Point
|
|
│ └── style.css \# Styling
|
|
├── secure/ \# Protected Admin Files (Editor)
|
|
├── main.go \# HTTP Routes & Setup
|
|
├── websocket.go \# Game Loop & Streaming Logic
|
|
├── simulation.go \# Physics Core
|
|
├── types.go \# Data Structures
|
|
└── Dockerfile \# Multi-Stage Build
|
|
```
|
|
|
|
## **📜 Legal**
|
|
|
|
This is a non-commercial educational project.
|
|
* **Privacy:** No tracking cookies.
|
|
* **Assets:** Font "Press Start 2P" hosted locally. Sounds generated via bfxr.net.
|
|
|
|
**Run for your grade! 🏃💨**
|