{"id":40577584,"url":"https://github.com/anibalanto/kinetic_ball","last_synced_at":"2026-02-21T04:04:36.127Z","repository":{"id":331562959,"uuid":"1029952474","full_name":"anibalanto/kinetic_ball","owner":"anibalanto","description":"Play with friends (futbol with geometries)","archived":false,"fork":false,"pushed_at":"2026-01-30T22:44:56.000Z","size":11430,"stargazers_count":1,"open_issues_count":3,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-01-31T08:54:18.745Z","etag":null,"topics":["bevy","game","geometry-processing","matchbox","multiplayer","p2p","physics","rapier2d","real-time","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/anibalanto.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-07-31T20:59:49.000Z","updated_at":"2026-01-30T22:44:24.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/anibalanto/kinetic_ball","commit_stats":null,"previous_names":["anibalanto/rustball","anibalanto/kinetic_ball"],"tags_count":36,"template":false,"template_full_name":null,"purl":"pkg:github/anibalanto/kinetic_ball","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anibalanto%2Fkinetic_ball","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anibalanto%2Fkinetic_ball/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anibalanto%2Fkinetic_ball/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anibalanto%2Fkinetic_ball/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/anibalanto","download_url":"https://codeload.github.com/anibalanto/kinetic_ball/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anibalanto%2Fkinetic_ball/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29186743,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-07T03:35:06.566Z","status":"ssl_error","status_checked_at":"2026-02-07T03:34:57.604Z","response_time":63,"last_error":"SSL_read: 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":["bevy","game","geometry-processing","matchbox","multiplayer","p2p","physics","rapier2d","real-time","rust"],"created_at":"2026-01-21T02:10:36.650Z","updated_at":"2026-02-07T05:03:28.850Z","avatar_url":"https://github.com/anibalanto.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"images/logo.png\" alt=\"kinetic_ball\" width=\"400\"\u003e\n\u003c/p\u003e\n\n# kinetic_ball\n\nA multiplayer physics-based ball game inspired by HaxBall, written in Rust using [Bevy](https://bevyengine.org/) and [Matchbox](https://github.com/johanhelsing/matchbox) for WebRTC peer-to-peer networking.\n\n[kinetic_ball.webm](https://github.com/user-attachments/assets/be8b2554-8de4-4d9b-b5e9-213c9693464f)\n\n\n\n\n## Features\n\n- **Unified app**: Host or join games from the same application\n- **Local multiplayer**: 2 local players with dynamic split-screen\n- **Admin panel**: Drag \u0026 drop player management, team assignment, kick players\n- Authoritative physics simulation with Rapier2D\n- WebRTC peer-to-peer networking via matchbox_socket\n- Room/lobby system with REST API and auto-cleanup\n- Create and host rooms directly from the UI\n- Custom map support (HaxBall format `.hbs`, `.json`, `.json5`)\n- Configurable keybindings per device (keyboard + gamepads)\n- Smart camera with dynamic zoom and split-screen transitions\n- Minimap and player detail camera\n- Kick system with curve/spin effect\n- Sprint, slide and cube mode with dash/ultra-run\n- Protocol version checking for compatibility\n- Cloud deployment support (Fly.io)\n\n## Requirements\n\n- Rust 1.75+\n- `matchbox_server` for WebRTC signaling (for local development)\n\n```bash\ncargo install matchbox_server\n```\n\n## Building\n\n```bash\n# Build the unified game application\ncargo build --release -p kinetic_ball\n\n# Build the cloud server (optional, for dedicated hosting)\ncargo build --release -p kinetic_ball_server\n\n# Or build everything at once\ncargo build --release\n```\n\n**Binaries will be located at:**\n- `target/release/kinetic_ball` (or `kinetic_ball.exe` on Windows)\n- `target/release/kinetic_ball_server` (or `kinetic_ball_server.exe` on Windows)\n\nYou can distribute the `kinetic_ball` binary to players - it's a standalone executable that includes all game assets.\n\n## How to Play\n\n### Quick Start (Local Game)\n\n1. **Start the infrastructure (one time setup):**\n   ```bash\n   # Terminal 1: Start matchbox signaling server\n   matchbox_server\n\n   # Terminal 2: Start the proxy/lobby server\n   cargo run --release -p kinetic_ball_server -- --port 3537 --matchbox-url ws://127.0.0.1:3536\n   ```\n\n2. **Launch the game:**\n   ```bash\n   cargo run --release -p kinetic_ball\n   ```\n\n3. **Play:**\n   - **To host a game:** Click \"Crear Sala\" → Configure room settings → Click \"Crear y Hostear\"\n   - **To join a game:** Click \"Ver Salas\" → Double-click a room to join\n   - **Configure keys:** Click \"Teclas\" to customize keybindings\n\n**That's it!** The same application can host or join games. When hosting, the physics server runs in the background while you play with the graphical interface.\n\n### Room Creation Options\n\nWhen creating a room, you can configure:\n- **Room name**: Display name for the lobby\n- **Max players**: 2-16 players\n- **Map** (optional): Path to a custom map file (`.hbs`, `.json`, `.json5`)\n- **Map scale**: Scale multiplier for the map (0.5-2.0)\n\n### Architecture\n\n```mermaid\nflowchart LR\n    subgraph Cloud\n        KBS[kinetic_ball_server \u003cbr/\u003e API REST + WS Proxy]\n        MB[Matchbox]\n    end\n\n    subgraph \"kinetic_ball (App Host \u0026 Play)\"\n        C1[Play \u003cbr/\u003e UI - Input]\n        H[Host \u003cbr/\u003e Physics + GameState]\n    end\n    \n    subgraph \"kinetic_ball (Play)\"\n        C2[Play \u003cbr/\u003e UI - Input]\n    end\n\n    H --\u003e|1. POST /api/rooms room_id, etc. response token| KBS\n    H --\u003e|2. WSS /connect token| KBS\n    KBS -.-|3. WS room_id| MB\n    C1 --\u003e|4. GET /api/rooms . response room_ids| KBS\n    C1 -.-|5. WSS /connect room_id| KBS\n    KBS -.-|6. WS room_id| MB\n    H \u003c-.-\u003e|7. WebRTC P2P| C1\n    C2 --\u003e|8. GET /api/rooms . response room_ids| KBS\n    C2 -.-|9. WSS /connect room_id| KBS\n    KBS -.-|10. WS room_id| MB\n    H \u003c-.-\u003e|11. WebRTC P2P| C2\n```\n\n- **kinetic_ball_server**: Unified cloud server (REST API + WebSocket proxy + Matchbox signaling)\n- **kinetic_ball (Host Mode)**: Runs physics simulation + renders locally\n- **kinetic_ball (Client Mode)**: Connects to a room and renders game state\n\n**Key advantage**: The same binary can host or join games. No need for separate client/server processes.\n\n### Online Play with ngrok\n\nTo play with friends over the internet, expose the server using [ngrok](https://ngrok.com/):\n\n1. **Start the infrastructure locally:**\n   ```bash\n   # Terminal 1: matchbox_server (local signaling)\n   matchbox_server\n\n   # Terminal 2: kinetic_ball_server\n   cargo run --release -p kinetic_ball_server -- --port 3537 --matchbox-url ws://127.0.0.1:3536\n   ```\n\n2. **Expose server with ngrok:**\n   ```bash\n   ngrok http 3537\n   ```\n   ngrok will give you a URL like `https://xxxx.ngrok-free.app`\n\n3. **Everyone connects using the ngrok URL:**\n   - Launch `kinetic_ball`\n   - In the menu, change \"Servidor\" to `xxxx.ngrok-free.app` (without protocol)\n   - Click \"Crear Sala\" to host, or \"Ver Salas\" to join\n\n**Note:** The host will run the physics locally and see the game with zero latency. Remote players connect via WebRTC P2P after signaling through the proxy.\n\n### Cloud Deployment (Fly.io)\n\nThe game server can be deployed to Fly.io for public hosting:\n\n```bash\n# First time setup\nfly launch\n\n# Deploy\nfly deploy\n```\n\nThe server runs on `https://kinetic-ball.fly.dev` (São Paulo region by default).\n\nConfiguration in `fly.toml`:\n- Runs both `matchbox_server` and `kinetic_ball_server` in a single container\n- HTTPS enforced automatically\n- Minimal resources (256MB RAM, shared CPU)\n\n## Local Multiplayer\n\nThe game supports 2 local players on the same machine with dynamic split-screen.\n\n### How It Works\n\n- Connect multiple input devices (keyboards, gamepads)\n- Each device controls a separate player\n- When players are close together: single unified camera\n- When players separate: screen splits dynamically with smooth transition\n- The split line orients based on player positions\n\n### Supported Devices\n\n- Keyboard (primary)\n- Bevy-compatible gamepads\n- Generic gamepads via `gilrs`\n\nEach device can have independent keybinding configurations.\n\n### Admin Panel\n\nPress **ESC** during a game to open the admin panel (host/admin only):\n\n- **Three-column layout**: Red Team | Spectators | Blue Team\n- **Drag \u0026 drop** players between teams and slots (Starter/Substitute)\n- **Right-click menu**: Grant/revoke admin, kick players\n- **Room ID** display with copy button\n\n## Controls\n\n![Keyboard controls](images/keyboard.png)\n\n### Sphere Mode\nDefault mode that allows ball control and kicking\n\n| Action | Default Key |\n|--------|-------------|\n| Move | Arrow keys |\n| Kick | S |\n| Curve left | A |\n| Curve right | D |\n| Sprint/Run | Space |\n| Wildcard (Don't touch ball) | Shift |\n\n### Cube Mode (Right Ctrl)\nAllows sliding and dribbling with ultra-run speed. Always runs and doesn't interact with the ball unless using the wildcard key.\nWhen stamina runs out, it automatically returns to sphere mode.\n\n| Action | Default Key |\n|--------|-------------|\n| Slide | S |\n| Slide right | D |\n| Slide left | A |\n| Direction change | Space + arrows |\n| Wildcard (Dash - touch ball) | Shift |\n\n### Wildcard Key\n\nThe **Shift** key (configurable) changes behavior based on the current mode:\n- **Sphere mode**: Prevents ball contact (pass through without touching)\n- **Cube mode**: Dash - makes contact with the ball without kicking (for dribbling)\n\n### Settings\n| Action | Key |\n|--------|-----|\n| Camera zoom | Keys 1-9 |\n\nKeybindings can be reconfigured from the \"Keys\" menu in the client.\n\n## Project Structure\n\n```\nkinetic_ball/\n├── kinetic_ball/              # Unified game application\n│   └── src/\n│       ├── main.rs            # Client UI and rendering\n│       ├── keybindings.rs     # Configurable controls\n│       ├── shared/            # Shared code (protocol, maps, movements)\n│       │   ├── mod.rs\n│       │   ├── protocol.rs    # Network messages\n│       │   ├── map.rs         # Map structures\n│       │   └── movements.rs   # Animations\n│       └── host/              # Host mode (physics server)\n│           ├── mod.rs\n│           ├── host.rs        # Host entry point\n│           ├── engine.rs      # Physics and game logic\n│           ├── network.rs     # WebRTC server + proxy registration\n│           ├── map/           # Map loading and conversion\n│           └── input/         # Input handling\n├── kinetic_ball_server/       # Cloud server (proxy + signaling)\n│   └── src/\n│       ├── main.rs            # CLI + axum server\n│       ├── state.rs           # Room state management\n│       ├── api/               # REST API (rooms CRUD)\n│       └── ws/                # WebSocket proxy to matchbox\n├── maps/                      # Custom maps\n├── images/                    # Assets\n└── docs/                      # Documentation and ADRs\n```\n\n**Key points:**\n- `kinetic_ball` is a single binary that can host or join games\n- Host mode includes physics simulation (`host/` module)\n- Client mode only uses rendering and UI (`main.rs`)\n- `kinetic_ball_server` is optional for dedicated hosting\n\n## Maps\n\nThe game supports custom maps in HaxBall format (`.hbs`) and JSON/JSON5. When creating a room, you can specify:\n- **Map path**: e.g., `maps/futsal_fah.hbs`\n- **Scale**: Adjust map size from 0.5x to 2.0x\n\nLeave the map field empty to use the default arena.\n\nTo create compatible maps, you can use the [HaxBall Map Editor](https://www.haxball.com/mapeditor) or create them manually in JSON5 format.\n\n## Troubleshooting\n\n### \"No rooms available\" / Can't see created rooms\n- Make sure `kinetic_ball_server` is running on the correct port\n- Check that the server URL in the menu matches your proxy (default: `127.0.0.1:3537`, without protocol)\n- Verify `matchbox_server` is running (needed for WebRTC signaling)\n\n### Connection issues\n- **Local play**: Both proxy and matchbox should be on localhost\n- **Online play**: Use the same ngrok URL for all players\n- **Firewall**: Ensure WebRTC ports are not blocked (or use ngrok)\n\n### High latency\n- When hosting locally, the host always has zero latency (direct access to physics)\n- Remote players connect P2P via WebRTC - latency depends on internet connection\n- For best results, the host should have good upload speed\n\n### Version mismatch\n- The game checks protocol version compatibility when joining rooms\n- If you see a version error, update your client to match the server's minimum required version\n- Version format follows semver (major.minor.patch)\n\n## Architecture Evolution\n\nThe project recently underwent a major restructuring (see [ADR-001](docs/adr/001-restructure-client-server-architecture.md)) to improve user experience:\n\n**Before**: Separate client, server, and proxy binaries\n**Now**: Unified `kinetic_ball` app that can host or join games\n\n**Benefits:**\n- Simpler UX: One app for everything\n- Host with UI: No more headless server\n- Easier distribution: Single binary for end users\n- Localhost optimization: WebRTC uses loopback for local host+client\n\n## Future Development\n\nThis project is under active development. Some ideas for contribution:\n\n- Goal system and scoreboard\n- 4-player local split-screen\n- In-game chat\n- Replay/match recording\n- WebAssembly compilation for browser play\n- Power-ups and alternative game modes\n- Netcode improvements (client-side prediction, reconciliation)\n- Integrated map editor in the UI\n- Automatic updates and distribution\n\n## Contributing\n\nContributions are welcome. Fork the repo, create a branch, and open a PR.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanibalanto%2Fkinetic_ball","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fanibalanto%2Fkinetic_ball","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanibalanto%2Fkinetic_ball/lists"}