Private
Public Access
1
0
Sebi 7f40dcda50
All checks were successful
Dynamic Branch Deploy / build-and-deploy (push) Successful in 1m41s
Merge pull request 'fix-debug' (#15) from fix-debug into main
Reviewed-on: #15
2025-11-27 19:19:02 +00:00
2025-11-27 20:17:10 +01:00
2025-11-27 19:42:08 +01:00
2025-11-26 18:56:59 +01:00
2025-11-27 20:14:51 +01:00
2025-11-25 23:36:09 +01:00
2025-11-24 22:32:10 +01:00
2025-11-25 18:13:08 +01:00
2025-11-24 22:32:10 +01:00
2025-11-24 22:32:10 +01:00
2025-11-27 20:14:51 +01:00
2025-11-26 18:56:59 +01:00
2025-11-25 23:36:09 +01:00
2025-11-27 19:43:03 +01:00
2025-11-25 18:11:47 +01:00
2025-11-27 19:42:08 +01:00
2025-11-27 19:42:08 +01:00
2025-11-26 18:56:59 +01:00

🏃 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

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
└── ...

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! 🏃💨

Description
No description provided
Readme 36 MiB
Languages
JavaScript 85.9%
HTML 7.6%
Go 5.2%
CSS 1.1%
Dockerfile 0.2%