idle_flutter 0.1.1
idle_flutter: ^0.1.1 copied to clipboard
A Flutter binding layer for idle/incremental games built on idle_core and idle_save
import 'package:flutter/material.dart';
import 'package:idle_core/idle_core.dart';
import 'package:idle_flutter/idle_flutter.dart';
import 'package:idle_save/idle_save.dart';
void main() {
runApp(const MyApp());
}
class GameState extends IdleState {
final int gold;
final int rate;
const GameState({required this.gold, required this.rate});
GameState copyWith({int? gold, int? rate}) =>
GameState(gold: gold ?? this.gold, rate: rate ?? this.rate);
@override
Map<String, dynamic> toJson() => {'gold': gold, 'rate': rate};
static GameState fromJson(Map<String, dynamic> json) => GameState(
gold: json['gold'] as int? ?? 0,
rate: json['rate'] as int? ?? 1,
);
}
class UpgradeRate extends IdleAction {
final int delta;
const UpgradeRate(this.delta);
}
GameState reducer(GameState state, IdleAction action) {
if (action is IdleTickAction) {
return state.copyWith(gold: state.gold + state.rate);
}
if (action is UpgradeRate) {
return state.copyWith(rate: state.rate + action.delta);
}
return state;
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late final IdleFlutterController<GameState> controller;
@override
void initState() {
super.initState();
final store = SharedPreferencesStore('idle_demo_save');
controller = IdleFlutterController<GameState>(
config: IdleConfig<GameState>(
dtMs: 1000,
maxOfflineMs: 24 * 60 * 60 * 1000,
maxTicksTotal: 10_000,
),
reducer: reducer,
initialState: const GameState(gold: 0, rate: 1),
stateDecoder: GameState.fromJson,
store: store,
migrator: Migrator(latestVersion: 1),
autosaveDebounce: const Duration(milliseconds: 500),
);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('idle_flutter example')),
body: IdleControllerHost<GameState>(
controller: controller,
loading: const Center(child: CircularProgressIndicator()),
rebuildOnChange: false,
builder: (context, c) {
return Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
IdleSelector<GameState, int>(
controller: c,
selector: (c) => c.state.gold,
builder: (context, gold, c) {
return Text(
'Gold: $gold',
style: const TextStyle(fontSize: 28),
);
},
),
const SizedBox(height: 8),
IdleSelector<GameState, int>(
controller: c,
selector: (c) => c.state.rate,
builder: (context, rate, c) {
return Text('Rate: $rate/sec');
},
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () => c.dispatch(const UpgradeRate(1)),
child: const Text('Upgrade +1 rate'),
),
const SizedBox(height: 16),
IdleSelector<GameState, int>(
controller: c,
selector: (c) => c.lastSeenMs,
builder: (context, lastSeenMs, c) {
return Text('lastSeenMs: $lastSeenMs');
},
),
],
),
);
},
),
),
);
}
}