Quick start - Flame
Wire an Asobi backend into a Flame game. Flame games use flame_asobi - a thin binding that re-exports the Dart SDK plus Flame glue for input and state sync. No server yet? Run the server quickstart first.
1. Add the binding
Add flame_asobi - it pulls in the asobi Dart package transitively, so it's the only asobi dependency you declare.
dependencies:
flame: ^1.22.0
flame_asobi:
git:
url: https://github.com/widgrensit/flame_asobi.git
ref: main2. Hold one shared client
Auth and the WebSocket session live on a single AsobiClient reused across every screen and the game. Authenticate (guest) and queue for a match from your lobby, before entering the Flame game - see the Dart quickstart for the underlying connect / addToMatchmaker flow.
class GameConfig {
static final client = AsobiClient('localhost', port: 8084);
static const gameMode = 'default';
}
// in your lobby, before starting the game:
await GameConfig.client.auth.guest(deviceId, deviceSecret);
await GameConfig.client.realtime.connect();
GameConfig.client.realtime.addToMatchmaker(mode: GameConfig.gameMode);3. Drive the game from asobi state
flame_asobi gives you two pieces. Input out: the HasAsobiInput mixin on your FlameGame turns Flame input into match.input each frame. State in: the AsobiNetworkSync component (added to world) bridges the match-state stream into the game loop and spawns/updates your components.
class ArenaGame extends FlameGame with HasAsobiInput {
@override AsobiClient get inputClient => GameConfig.client;
@override Map<String, dynamic>? buildMatchInput({...}) => {'move_x': dx, 'move_y': dy};
@override
Future<void> onLoad() async {
world.add(AsobiNetworkSync(
client: GameConfig.client,
playerBuilder: (id, {required isLocal}) => ShipComponent(id, isLocal: isLocal),
onStateUpdate: (state) => _hud.timeLeft = state.timeRemaining,
));
}
}Read snapshots through onStateUpdate and the sync's localPlayer; don't also subscribe to onMatchState yourself, or you double-process state.
Gotchas
- One client, shared statically. Auth, the WS session, and
playerIdall live on that instance - reach it viainputClient => GameConfig.client, never a new client per screen. - Let the sync component own the stream. Lobby/UI code listens to raw
.streams; inside Flame,AsobiNetworkSyncsubscribes and mutates on the Flame thread for you. - Cancel subscriptions. Cancel every
StreamSubscriptionindispose()/onRemove()across the lobby -> game -> results navigation.
What's next
- Dart quickstart - the underlying client API.
- Authentication