{"id":48187949,"url":"https://github.com/widgrensit/flame_asobi","last_synced_at":"2026-04-04T17:52:02.582Z","repository":{"id":348073513,"uuid":"1196325948","full_name":"widgrensit/flame_asobi","owner":"widgrensit","description":"Flame bridge package for the Asobi game backend — multiplayer, matchmaking, leaderboards","archived":false,"fork":false,"pushed_at":"2026-03-30T16:52:44.000Z","size":18,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-30T18:28:13.964Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/widgrensit.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2026-03-30T15:35:15.000Z","updated_at":"2026-03-30T16:52:49.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/widgrensit/flame_asobi","commit_stats":null,"previous_names":["widgrensit/flame_asobi"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/widgrensit/flame_asobi","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/widgrensit%2Fflame_asobi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/widgrensit%2Fflame_asobi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/widgrensit%2Fflame_asobi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/widgrensit%2Fflame_asobi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/widgrensit","download_url":"https://codeload.github.com/widgrensit/flame_asobi/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/widgrensit%2Fflame_asobi/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31407655,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-04T10:20:44.708Z","status":"ssl_error","status_checked_at":"2026-04-04T10:20:06.846Z","response_time":60,"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":[],"created_at":"2026-04-04T17:52:02.442Z","updated_at":"2026-04-04T17:52:02.559Z","avatar_url":"https://github.com/widgrensit.png","language":"Dart","readme":"# flame_asobi\n\nFlame bridge package for the [Asobi](https://pub.dev/packages/asobi) multiplayer game backend. Provides Flame-native components and mixins for real-time multiplayer, matchmaking, and leaderboards.\n\nInstead of manually managing WebSocket state, entity tracking, and input serialization, `flame_asobi` gives you drop-in components that handle it all.\n\n## Installation\n\n```bash\nflutter pub add flame_asobi\n```\n\n## Quick Start\n\n```dart\nimport 'package:flame/game.dart';\nimport 'package:flame_asobi/flame_asobi.dart';\n\nclass MyGame extends FlameGame with HasAsobi, KeyboardEvents {\n  @override\n  Future\u003cvoid\u003e onLoad() async {\n    await asobiConnect('localhost', port: 8080);\n    await asobi.auth.login('player1', 'secret');\n    await asobi.realtime.connect();\n\n    // Automatically syncs server state → Flame components\n    world.add(AsobiNetworkSync(\n      client: asobi,\n      pixelsPerUnit: 50,\n      onMatchFinished: (result) =\u003e print('Game over!'),\n    ));\n\n    // Captures WASD + mouse and sends to server\n    world.add(AsobiInputSender(client: asobi, pixelsPerUnit: 50));\n  }\n}\n```\n\n## Components\n\n### `HasAsobi` mixin\n\nAdds an `AsobiClient` to your `FlameGame` with lifecycle management.\n\n```dart\nclass MyGame extends FlameGame with HasAsobi {\n  @override\n  Future\u003cvoid\u003e onLoad() async {\n    await asobiConnect('my-server.com', port: 8080, useSsl: true);\n    // asobi.auth, asobi.realtime, asobi.leaderboards, etc.\n  }\n}\n```\n\nThe client is automatically disposed when the game is removed.\n\n### `AsobiNetworkSync`\n\nThe core component. Listens to `match.state` events from the server and automatically creates, updates, and removes `AsobiPlayer` and `AsobiProjectile` children.\n\n```dart\nworld.add(AsobiNetworkSync(\n  client: asobi,\n  pixelsPerUnit: 50,\n  onStateUpdate: (state) {\n    // Update HUD with timer, kills, HP\n    final player = sync.localPlayer;\n    timerText.text = formatTime(sync.timeRemainingMs);\n    killsText.text = 'Kills: ${player?.kills ?? 0}';\n  },\n  onMatchFinished: (result) {\n    // Navigate to results screen\n  },\n));\n```\n\n**Custom entity rendering:**\n\n```dart\nworld.add(AsobiNetworkSync(\n  client: asobi,\n  pixelsPerUnit: 50,\n  playerBuilder: (playerId, isLocal) =\u003e MyCustomPlayer(\n    playerId: playerId,\n    isLocal: isLocal,\n    sprite: myPlayerSprite,\n  ),\n  projectileBuilder: (id, owner, isLocal) =\u003e MyCustomBullet(\n    projectileId: id,\n    owner: owner,\n    isLocal: isLocal,\n  ),\n));\n```\n\n### `AsobiPlayer`\n\nA networked player component with automatic position interpolation and built-in rendering (circle body, HP bar, name label).\n\n```dart\nfinal player = AsobiPlayer(\n  playerId: 'abc123',\n  isLocal: true,\n  size: Vector2.all(0.64),\n  lerpSpeed: 0.3,  // interpolation smoothing\n);\n```\n\nProperties updated from server state:\n- `position` — interpolated toward server position\n- `hp`, `kills`, `deaths` — from match state\n- `color` — cyan (local), red (enemy), grey (dead)\n- `isDead` — true when hp \u003c= 0\n\n### `AsobiProjectile`\n\nA networked projectile component. Position is set directly from server state (no interpolation — projectiles move fast enough).\n\n```dart\nfinal bullet = AsobiProjectile(\n  projectileId: 1,\n  owner: 'player-uuid',\n  isLocal: true,  // yellow for local, white for enemy\n  radius: 0.15,\n);\n```\n\n### `AsobiInputSender`\n\nCaptures keyboard and mouse input and sends it to the server as match input every frame.\n\n```dart\nworld.add(AsobiInputSender(\n  client: asobi,\n  pixelsPerUnit: 50,\n  // Default keys (override to customize):\n  // keyUp: LogicalKeyboardKey.keyW,\n  // keyDown: LogicalKeyboardKey.keyS,\n  // keyLeft: LogicalKeyboardKey.keyA,\n  // keyRight: LogicalKeyboardKey.keyD,\n  // keyShoot: LogicalKeyboardKey.space,\n));\n```\n\nFor mouse aiming and click-to-shoot, forward events from your game:\n\n```dart\n@override\nvoid onMouseMove(PointerHoverInfo info) {\n  inputSender.updateMousePosition(\n    camera.viewfinder.globalToLocal(info.eventPosition.global),\n  );\n}\n\n@override\nvoid onTapDown(TapDownEvent event) {\n  inputSender.setMouseDown(true);\n}\n\n@override\nvoid onTapUp(TapUpEvent event) {\n  inputSender.setMouseDown(false);\n}\n```\n\n### `AsobiMatchmaker`\n\nManages the matchmaking lifecycle with callbacks.\n\n```dart\nfinal matchmaker = AsobiMatchmaker(\n  client: asobi,\n  mode: 'arena',\n  onConnected: () =\u003e print('Ready to play'),\n  onMatched: (payload) =\u003e startGame(),\n  onError: (err) =\u003e showError(err),\n);\n\nworld.add(matchmaker);\nawait matchmaker.connect();\nmatchmaker.findMatch();\n\n// Check status:\nprint(matchmaker.isSearching);  // true\nprint(matchmaker.searchTime);   // seconds elapsed\n```\n\n## Architecture\n\n```\n┌─────────────────────────────────────────┐\n│              FlameGame                  │\n│                                         │\n│  AsobiNetworkSync                       │\n│  ├── Listens to match.state (10Hz)      │\n│  ├── Creates/updates AsobiPlayer        │\n│  ├── Creates/updates AsobiProjectile    │\n│  └── Fires onStateUpdate / onFinished   │\n│                                         │\n│  AsobiInputSender                       │\n│  ├── Captures WASD + mouse each frame   │\n│  └── Sends match.input to server        │\n│                                         │\n│  AsobiMatchmaker                        │\n│  ├── Connects WebSocket                 │\n│  ├── Queues for matchmaking             │\n│  └── Fires onMatched callback           │\n│                                         │\n│  AsobiClient (from asobi package)       │\n│  ├── HTTP: auth, leaderboards, etc.     │\n│  └── WebSocket: realtime events         │\n└─────────────────────────────────────────┘\n```\n\n## Full Example\n\nSee the [asobi-flame-demo](https://github.com/widgrensit/asobi-flame-demo) for a complete arena shooter using this package.\n\n## License\n\nApache-2.0\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwidgrensit%2Fflame_asobi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwidgrensit%2Fflame_asobi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwidgrensit%2Fflame_asobi/lists"}