{"id":19184370,"url":"https://github.com/cryptosingh1337/serpent-clash","last_synced_at":"2026-05-05T14:31:25.944Z","repository":{"id":259056955,"uuid":"851223294","full_name":"CryptoSingh1337/serpent-clash","owner":"CryptoSingh1337","description":"Multiplayer snake game","archived":false,"fork":false,"pushed_at":"2025-08-23T14:46:58.000Z","size":3970,"stargazers_count":2,"open_issues_count":3,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-08-23T17:40:00.285Z","etag":null,"topics":["canvas2d","ecs","golang","multiplayer-game","pixi-js","quadtree","tailwindcss","vue3","websocket"],"latest_commit_sha":null,"homepage":"https://serpent-clash.saransh.pro","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/CryptoSingh1337.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-09-02T16:59:09.000Z","updated_at":"2025-08-23T14:47:01.000Z","dependencies_parsed_at":"2024-11-16T10:18:15.425Z","dependency_job_id":"33d782bf-383b-4f7d-82e5-27197eabe974","html_url":"https://github.com/CryptoSingh1337/serpent-clash","commit_stats":null,"previous_names":["cryptosingh1337/serpent-clash"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/CryptoSingh1337/serpent-clash","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CryptoSingh1337%2Fserpent-clash","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CryptoSingh1337%2Fserpent-clash/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CryptoSingh1337%2Fserpent-clash/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CryptoSingh1337%2Fserpent-clash/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CryptoSingh1337","download_url":"https://codeload.github.com/CryptoSingh1337/serpent-clash/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CryptoSingh1337%2Fserpent-clash/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32653450,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-05T11:29:49.557Z","status":"ssl_error","status_checked_at":"2026-05-05T11:29:48.587Z","response_time":54,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["canvas2d","ecs","golang","multiplayer-game","pixi-js","quadtree","tailwindcss","vue3","websocket"],"created_at":"2024-11-09T11:06:54.182Z","updated_at":"2026-05-05T14:31:25.937Z","avatar_url":"https://github.com/CryptoSingh1337.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🎮 Serpent Clash — Multiplayer Snake Game \n**Serpent Clash** is a **fast-paced**, **multiplayer snake game** where players compete to outmaneuver and \noutgrow their rivals in a dynamic online arena. Control your serpent with precision, dodge enemies, and strategically \ncut them off as you slither your way to the top of the leaderboard.\n\nThe game is built using Vue.js on the frontend and Golang on the backend, utilizing modern **WebSocket communication** and \nan **authoritative server** model to maintain a fair and synchronized game state. With **server reconciliation** and \n**interpolation**, players experience smooth gameplay and accurate movement.\n\n🎥 **Demo** - [https://www.youtube.com/watch?v=GLIhDvpuB-0](https://www.youtube.com/watch?v=GLIhDvpuB-0\u0026utm_source=github)\n\n[![wakatime](https://wakatime.com/badge/github/CryptoSingh1337/serpent-clash.svg)](https://wakatime.com/badge/github/CryptoSingh1337/serpent-clash)\n\n### 🔑 Key Features\n- ⚔️ **Multiplayer** with low-latency WebSocket communication\n- 🛡️ **Authoritative Server Model** to ensure fairness and consistency\n- 🔄 **Server Reconciliation** for accurate game state even under lag\n- ✨ **Player Movement Interpolation** for smooth rendering of players\n- 🐍 **Dynamic Snake Rendering** using multiple coordinates and mouse input\n- 🍔 **Growth and stamina mechanics** where snakes can consume food to grow longer and use stamina for speed boosts\n- 🌐 **Efficient Collision Detection** powered by Quad Tree data structure\n- 🧩 **Entity Component System (ECS)** Architecture for efficient resource management and maintainability\n\n### 🚀 Future Enhancements\n- 🏆 **Leaderboard \u0026 UI Enhancements**\n\u003cbr\u003eImprove the overall player experience with a more interactive UI and detailed leaderboard statistics to showcase top players.\n\n### 💪 Motivation \u0026 Journey\nThe goal of this project is to get hands-on experience with backend game development, focusing on low latency communication,\narchitecture design, and multiplayer game simulation. During the development, I also learned Golang and its ecosystem,\nwhich has been a great experience. Initially, I was not familiar with the language and how to structure a game server, but I\nmanaged to create a working prototype in a short time. Later, I got to know about the Entity Component System (ECS) architecture,\nwhich I found to be a great fit for this project. It allows for better organization of game entities and their behaviors, \nmaking the codebase more maintainable and scalable.\n\nWhile working on collision detection, I learned about the Quad Tree data structure, which significantly improved the \nperformance of collision checks in the game. For rendering, I used the HTML 2D canvas, but as the complexity of the game increased,\nit became unmanageable. Therefore, I switched to Pixi.js, which provided a more efficient rendering engine and better performance, \nbasically I offloaded the rendering logic to Pixi.js, allowing me to focus on the game mechanics and logic.\n\nOverall, this project has been a great learning experience and has helped me understand the complexities of game development\nand real-time systems.\n\n### 🧱 Backend ECS Architecture\n\n#### 🧍‍♂️ Entities\n- `Player`\n- `Food`\n\n#### 🧩 Components\n- `Expiry`\n- `Input`\n- `Network`\n- `PlayerInfo`\n- `Position`\n- `Snake`\n\n#### ⚙️ Systems\n- `Collision` - Detect and handle collisions:\n  - Between players (e.g., head-to-head, head-to-body)\n  - With world boundaries\n  - With food entities\n- `Food despawn` - Remove food entities either when consumed or after a predefined number of ticks.\n- `Food spawn` - Spawn food entities at random valid positions within the game world.\n- `Movement` - Update player movement based on the last recorded mouse direction. If speed boost is active, decrease both snake length and stamina accordingly.\n- `Network` - Broadcast the current game state to all clients. Send pong responses to clients for ping calculation.\n- `Player despawn` - Handle player leave events by removing the player entity and all its associated components.\n- `Player spawn` - Handle player join events by creating a player entity and initializing its associated components.\n- `Quad tree` - Rebuild the quad tree each tick using all food entities and snake segments for optimized spatial queries (e.g., collision detection).\n\n#### 🔗 Entity-Component Relationships\n- **Player** -\u003e `Input`, `Network`, `PlayerInfo`, `Snake`\n- **Food** -\u003e `Expiry`, `Position`\n\n#### 🐍 Snake movement logic\n\n**1. Definitions**\n- **Head position**: $\\mathbf{H} = (H_x, H_y)$\n- **Mouse position**: $\\mathbf{M} = (M_x, M_y)$\n- **Previous mouse position**: $\\mathbf{M_prev} = (M_{x_p}, M_{y_p})$\n- **Current head angle**: $\\theta$\n- **Target angle**: $\\theta_t$\n- **Maximum turn rate**: $\\Delta_{\\max}$\n- **Default speed**: $v_0$\n- **Speed boost**: $v_b$\n- **Segment distance**: $d_s $\n- **Snake segments**: $\\mathbf{S}_0, \\mathbf{S}_1, \\dots, \\mathbf{S}_n$ where $\\mathbf{S}_0 = \\mathbf{H}$\n\n**2. Determine Target Angle**\n\n$\\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 $\n\n**3. Smoothly Rotate Towards Target**\n\nLerpAngle (linear interpolation for angles) is:\n$\\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 $\n\n**4. Determine Speed**\n\nBoost logic:\n$v = v_0$ $\\text{if boosting:} \\quad v \\gets v + v_b$\n\n**5. Move Head**\n\n$H_x \\gets H_x + \\cos(\\theta) \\cdot v$\n\n$H_y \\gets H_y + \\sin(\\theta) \\cdot v$\n\n**6. Move Following Segments**\n\nFor each segment $i = 1 \\dots n$:\n1. Previous segment: $\\mathbf{P} = \\mathbf{S}_{i-1}$\n2. Current segment: $\\mathbf{C} = \\mathbf{S}_i$\n3. Angle from current to previous: $\\theta_p = \\arctan2(P_y - C_y, P_x - C_x)$\n4. Position update to maintain fixed distance $d_s$:\n   - $C_x \\gets P_x - \\cos(\\theta_p) \\cdot d_s$\n   - $C_y \\gets P_y - \\sin(\\theta_p) \\cdot d_s$\n\n**7. Summary**\n- Head rotates towards mouse by at most $\\Delta_{\\max}$ per tick.\n- Head moves forward by $v$ units per tick.\n- Each following segment stays exactly $d_s$ behind its predecessor, aligned along the connecting vector.\n\n### 📸 Screenshots\n\n##### Landing page\n![Landing page](/assets/landing-page.png)\n\n##### Game menu\n![Game menu](/assets/game-menu.png)\n\n##### Hud \u0026 Gameplay\n![Hud and Gameplay](/assets/hud-plus-gameplay.png)\n\n#### Dashboard\n\n##### Server metrics\n![Server metrics](/assets/server-metrics.png)\n\n##### Game metrics\n![Game metrics](/assets/game-metrics.png)\n\n##### Quad Tree visualization\n![Quad Tree visualization](/assets/quad-tree.png)\n\n### ✅ TODO Tracker\n- [x] Serve Vue files from backend\n- [x] POC: WebSocket server\n- [x] Connect/disconnect player\n- [x] Show statistics on client-side\n- [x] POC: Render snake based on multiple coordinates (client-side)\n- [x] POC: Player movement based on mouse coordinates (client-side)\n- [x] Design authoritative server based on ticker\n- [x] Server-side player movement\n- [x] Adopt class-based design for client-side\n- [x] Add support for ping calculation\n- [x] ~~Add client-side prediction for smoother movement (client-side)~~ (removed)\n- [x] Add server reconciliation for handling lag (client-side)\n- [x] Add interpolation for smoother movement (client-side)\n- [x] Make world finite with a larger dimension\n- [x] Add camera logic\n- [x] Add collision detection\n- [x] Create debug menu (e.g., teleport feature)\n- [x] Adjust player speed on `mousedown` / `mouseup`\n- [x] Improve snake spawn logic (consider world radius)\n- [x] Refactor into driver classes for better readability\n- [x] Detect collisions with world boundaries\n- [x] Re-architect backend using ECS\n- [x] Optimize collision detection using Quad Tree\n- [x] Improve collision detection logic (beyond head-to-head only)\n- [x] Create spawn system for snake with world-awareness\n- [x] Migrate from HTML 2D canvas to Pixi.js renderer engine\n- [x] Create dashboard \u0026 API for server metrics\n- [x] Implement food spawning functionality with world-awareness\n- [x] Randomized food generation\n- [x] Food consumption and snake growth logic\n- [x] Compensate speed boosts by reducing snake length\n- [ ] Implement leaderboard\n- [ ] Chat system using SSE and channels\n- [ ] Client UI design improvements\n\n### ⚡ Optimizations\n- [ ] Store delta state in each system and send only the delta to the client\n- [ ] Switch to binary data formats instead of JSON for faster network communication\n- [x] Switch to gorilla websocket\n- [x] Explore Pixi.js to improve performance\n\n### 📚 Resources\n- [https://www.gabrielgambetta.com/client-server-game-architecture.html](https://www.gabrielgambetta.com/client-server-game-architecture.html)\n\n### 🔌 Dependencies\n- ~~**Websocket** - [https://github.com/lesismal/nbio](https://github.com/lesismal/nbio)~~\n- **Websocket** - [https://github.com/gorilla/websocket](https://github.com/gorilla/websocket)\n- **Pixijs** - [https://pixijs.com/](https://pixijs.com/)\n- **Echo** - [https://echo.labstack.com/](https://echo.labstack.com/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcryptosingh1337%2Fserpent-clash","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcryptosingh1337%2Fserpent-clash","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcryptosingh1337%2Fserpent-clash/lists"}