Skip to content

CryptoSingh1337/serpent-clash

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

388 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🎮 Serpent Clash — Multiplayer Snake Game

Serpent Clash is a fast-paced, multiplayer snake game where players compete to outmaneuver and outgrow their rivals in a dynamic online arena. Control your serpent with precision, dodge enemies, and strategically cut them off as you slither your way to the top of the leaderboard.

The game is built using Vue.js on the frontend and Golang on the backend, utilizing modern WebSocket communication and an authoritative server model to maintain a fair and synchronized game state. With server reconciliation and interpolation, players experience smooth gameplay and accurate movement.

🎥 Demo - https://www.youtube.com/watch?v=GLIhDvpuB-0

wakatime

🔑 Key Features

  • ⚔️ Multiplayer with low-latency WebSocket communication
  • 🛡️ Authoritative Server Model to ensure fairness and consistency
  • 🔄 Server Reconciliation for accurate game state even under lag
  • Player Movement Interpolation for smooth rendering of players
  • 🐍 Dynamic Snake Rendering using multiple coordinates and mouse input
  • 🍔 Growth and stamina mechanics where snakes can consume food to grow longer and use stamina for speed boosts
  • 🌐 Efficient Collision Detection powered by Quad Tree data structure
  • 🧩 Entity Component System (ECS) Architecture for efficient resource management and maintainability

🚀 Future Enhancements

  • 🏆 Leaderboard & UI Enhancements
    Improve the overall player experience with a more interactive UI and detailed leaderboard statistics to showcase top players.

💪 Motivation & Journey

The goal of this project is to get hands-on experience with backend game development, focusing on low latency communication, architecture design, and multiplayer game simulation. During the development, I also learned Golang and its ecosystem, which has been a great experience. Initially, I was not familiar with the language and how to structure a game server, but I managed to create a working prototype in a short time. Later, I got to know about the Entity Component System (ECS) architecture, which I found to be a great fit for this project. It allows for better organization of game entities and their behaviors, making the codebase more maintainable and scalable.

While working on collision detection, I learned about the Quad Tree data structure, which significantly improved the performance of collision checks in the game. For rendering, I used the HTML 2D canvas, but as the complexity of the game increased, it became unmanageable. Therefore, I switched to Pixi.js, which provided a more efficient rendering engine and better performance, basically I offloaded the rendering logic to Pixi.js, allowing me to focus on the game mechanics and logic.

Overall, this project has been a great learning experience and has helped me understand the complexities of game development and real-time systems.

🧱 Backend ECS Architecture

🧍‍♂️ Entities

  • Player
  • Food

🧩 Components

  • Expiry
  • Input
  • Network
  • PlayerInfo
  • Position
  • Snake

⚙️ Systems

  • Collision - Detect and handle collisions:
    • Between players (e.g., head-to-head, head-to-body)
    • With world boundaries
    • With food entities
  • Food despawn - Remove food entities either when consumed or after a predefined number of ticks.
  • Food spawn - Spawn food entities at random valid positions within the game world.
  • Movement - Update player movement based on the last recorded mouse direction. If speed boost is active, decrease both snake length and stamina accordingly.
  • Network - Broadcast the current game state to all clients. Send pong responses to clients for ping calculation.
  • Player despawn - Handle player leave events by removing the player entity and all its associated components.
  • Player spawn - Handle player join events by creating a player entity and initializing its associated components.
  • Quad tree - Rebuild the quad tree each tick using all food entities and snake segments for optimized spatial queries (e.g., collision detection).

🔗 Entity-Component Relationships

  • Player -> Input, Network, PlayerInfo, Snake
  • Food -> Expiry, Position

🐍 Snake movement logic

1. Definitions

  • Head position: $\mathbf{H} = (H_x, H_y)$
  • Mouse position: $\mathbf{M} = (M_x, M_y)$
  • Previous mouse position: $\mathbf{M_prev} = (M_{x_p}, M_{y_p})$
  • Current head angle: $\theta$
  • Target angle: $\theta_t$
  • Maximum turn rate: $\Delta_{\max}$
  • Default speed: $v_0$
  • Speed boost: $v_b$
  • Segment distance: $d_s $
  • Snake segments: $\mathbf{S}_0, \mathbf{S}_1, \dots, \mathbf{S}_n$ where $\mathbf{S}_0 = \mathbf{H}$

2. Determine Target Angle

$\theta_t = \arctan2(M_y - H_y, M_x - H_x)$ $\text{if } M_{x_p} \neq M_x \text{ or } M_{y_p} \neq M_y $

3. Smoothly Rotate Towards Target

LerpAngle (linear interpolation for angles) is: $\theta \gets \theta + \mathrm{clamp}(\theta_t - \theta, -\Delta_{\max}, \Delta_{\max})$ $\text{if } M_{x_p} \neq M_x \text{ or } M_{y_p} \neq M_y $

4. Determine Speed

Boost logic: $v = v_0$ $\text{if boosting:} \quad v \gets v + v_b$

5. Move Head

$H_x \gets H_x + \cos(\theta) \cdot v$

$H_y \gets H_y + \sin(\theta) \cdot v$

6. Move Following Segments

For each segment $i = 1 \dots n$:

  1. Previous segment: $\mathbf{P} = \mathbf{S}_{i-1}$
  2. Current segment: $\mathbf{C} = \mathbf{S}_i$
  3. Angle from current to previous: $\theta_p = \arctan2(P_y - C_y, P_x - C_x)$
  4. Position update to maintain fixed distance $d_s$:
    • $C_x \gets P_x - \cos(\theta_p) \cdot d_s$
    • $C_y \gets P_y - \sin(\theta_p) \cdot d_s$

7. Summary

  • Head rotates towards mouse by at most $\Delta_{\max}$ per tick.
  • Head moves forward by $v$ units per tick.
  • Each following segment stays exactly $d_s$ behind its predecessor, aligned along the connecting vector.

📸 Screenshots

Landing page

Landing page

Game menu

Game menu

Hud & Gameplay

Hud and Gameplay

Dashboard

Server metrics

Server metrics

Game metrics

Game metrics

Quad Tree visualization

Quad Tree visualization

✅ TODO Tracker

  • Serve Vue files from backend
  • POC: WebSocket server
  • Connect/disconnect player
  • Show statistics on client-side
  • POC: Render snake based on multiple coordinates (client-side)
  • POC: Player movement based on mouse coordinates (client-side)
  • Design authoritative server based on ticker
  • Server-side player movement
  • Adopt class-based design for client-side
  • Add support for ping calculation
  • Add client-side prediction for smoother movement (client-side) (removed)
  • Add server reconciliation for handling lag (client-side)
  • Add interpolation for smoother movement (client-side)
  • Make world finite with a larger dimension
  • Add camera logic
  • Add collision detection
  • Create debug menu (e.g., teleport feature)
  • Adjust player speed on mousedown / mouseup
  • Improve snake spawn logic (consider world radius)
  • Refactor into driver classes for better readability
  • Detect collisions with world boundaries
  • Re-architect backend using ECS
  • Optimize collision detection using Quad Tree
  • Improve collision detection logic (beyond head-to-head only)
  • Create spawn system for snake with world-awareness
  • Migrate from HTML 2D canvas to Pixi.js renderer engine
  • Create dashboard & API for server metrics
  • Implement food spawning functionality with world-awareness
  • Randomized food generation
  • Food consumption and snake growth logic
  • Compensate speed boosts by reducing snake length
  • Implement leaderboard
  • Chat system using SSE and channels
  • Client UI design improvements

⚡ Optimizations

  • Store delta state in each system and send only the delta to the client
  • Switch to binary data formats instead of JSON for faster network communication
  • Switch to gorilla websocket
  • Explore Pixi.js to improve performance

📚 Resources

🔌 Dependencies