335 lines
8.3 KiB
Dart
335 lines
8.3 KiB
Dart
import 'dart:io';
|
|
|
|
import 'package:audioplayers/audioplayers.dart';
|
|
import 'package:flame/cache.dart';
|
|
import 'package:flame/flame.dart';
|
|
import 'package:flame/game.dart';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
import 'package:funny_letters/app_binder.dart';
|
|
import 'package:funny_letters/funny_letters.dart';
|
|
import 'package:funny_letters/gen/assets.gen.dart';
|
|
import 'package:funny_letters/runner/ui/button.dart';
|
|
import 'package:mnemo_cards_game_api/mnemo_cards_game_api.dart';
|
|
|
|
import 'runner/bonuses/letter_bonus.dart';
|
|
import 'runner/game_manager.dart';
|
|
|
|
var _game = GameManager()..pauseEngine();
|
|
var menuKey = GlobalKey();
|
|
var effectPlayer = AudioPlayer();
|
|
var audioPlayer = AudioPlayer()..setVolume(0.25);
|
|
|
|
late AppBinder assetLoader;
|
|
late FunnyLettersSettings gameSettings;
|
|
|
|
// Run web app
|
|
Future<void> main(List<String> args) async {
|
|
WidgetsFlutterBinding.ensureInitialized();
|
|
Flame.images.prefix = '';
|
|
await Flame.images.loadAll([
|
|
Assets.images.gameOver.path,
|
|
Assets.images.icons.play.path,
|
|
Assets.images.icons.restart.path,
|
|
]);
|
|
await Flame.device.fullScreen();
|
|
|
|
runApp(
|
|
ScreenUtilInit(
|
|
designSize: const Size(360, 690),
|
|
minTextAdapt: true,
|
|
splitScreenMode: true,
|
|
child: MaterialApp(
|
|
home: FutureBuilder(
|
|
future: Future.value(),//MyApp.initialize(),
|
|
builder: (context, snapshot) {
|
|
if (snapshot.hasError) {
|
|
return Center(
|
|
child: Text('Error: ${snapshot.error}'),
|
|
);
|
|
}
|
|
if (!snapshot.hasData) {
|
|
return const Center(
|
|
child: CircularProgressIndicator(),
|
|
);
|
|
}
|
|
return snapshot.data!;
|
|
},
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
class MyApp extends StatelessWidget {
|
|
final AppBinder assetLoader;
|
|
final FunnyLettersSettings gameSettings;
|
|
|
|
MyApp._({
|
|
required this.assetLoader,
|
|
required this.gameSettings,
|
|
});
|
|
|
|
static Future<MyApp?> initialize() async {
|
|
// final loader = AppBinderImpl();
|
|
// Initialize JavaScript environment for web communication
|
|
// loader.initializeJavaScript();
|
|
// final settings = await loader.loadSettings();
|
|
// return MyApp._(
|
|
// assetLoader: loader,
|
|
// gameSettings: settings,
|
|
// );
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return MaterialApp(
|
|
theme: gameSettings.themeData.toMaterialTheme(),
|
|
home: GameView(
|
|
assetLoader,
|
|
gameSettings,
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class GameView extends StatelessWidget {
|
|
GameView(
|
|
AppBinder loader,
|
|
FunnyLettersSettings settings, {
|
|
super.key,
|
|
}) {
|
|
assetLoader = loader;
|
|
gameSettings = settings;
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
WidgetsBinding.instance.addObserver(_Handler());
|
|
Flame.images = Images(prefix: '');
|
|
Flame.assets = AssetsCache(prefix: '');
|
|
_game = GameManager()..pauseEngine();
|
|
menuKey = GlobalKey();
|
|
effectPlayer = AudioPlayer();
|
|
audioPlayer = AudioPlayer()..setVolume(0.25);
|
|
|
|
return PopScope(
|
|
onPopInvokedWithResult: (didPop, result) {
|
|
if (didPop) {
|
|
_game.pauseEngine();
|
|
audioPlayer.stop();
|
|
effectPlayer.stop();
|
|
_game.dispose();
|
|
}
|
|
},
|
|
child: Menu(key: menuKey),
|
|
);
|
|
}
|
|
}
|
|
|
|
class Menu extends StatefulWidget {
|
|
@override
|
|
State<StatefulWidget> createState() => MenuState();
|
|
|
|
const Menu({super.key});
|
|
}
|
|
|
|
class MenuState extends State<Menu> {
|
|
int index = 2;
|
|
|
|
void openGameOver() {
|
|
setState(() {
|
|
index = 0;
|
|
});
|
|
}
|
|
|
|
void restartGame() => _startGame();
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
|
|
// audioPlayer.setReleaseMode(ReleaseMode.loop);
|
|
// if (gameSettings.musicEnabled) {
|
|
// audioPlayer.play(
|
|
// BytesSource(
|
|
// assetLoader.loadFile('assets/go.mp3').readAsBytesSync(),
|
|
// ),
|
|
// );
|
|
// }
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return MaterialApp(
|
|
theme: gameSettings.themeData.toMaterialTheme(),
|
|
home: Scaffold(
|
|
body: Container(
|
|
decoration: background != null
|
|
? null // Background will be handled by GameManager
|
|
: null,
|
|
child: IndexedStack(
|
|
index: index,
|
|
children: [
|
|
gameOver(),
|
|
game(),
|
|
startPage(),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget gameOver() {
|
|
return Column(
|
|
mainAxisAlignment: MainAxisAlignment.end,
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
children: [
|
|
const SizedBox(
|
|
height: 80,
|
|
),
|
|
Image(
|
|
image: Assets.images.gameOver.provider(),
|
|
width: MediaQuery.of(context).size.width,
|
|
),
|
|
const SizedBox(
|
|
height: 64,
|
|
),
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 50.0),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
...goText.characters.map(
|
|
(e) => e == ' '
|
|
? const SizedBox(width: 20)
|
|
: LetterBonus.image(letter: e, width: 42),
|
|
)
|
|
],
|
|
),
|
|
),
|
|
Button(
|
|
Assets.images.icons.restart.path,
|
|
() => restartGame(),
|
|
),
|
|
const SizedBox(
|
|
height: 64,
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget startPage() {
|
|
return Column(
|
|
mainAxisAlignment: MainAxisAlignment.end,
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
children: [
|
|
const SizedBox(
|
|
height: 80,
|
|
),
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 50.0),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
...goText.characters.map(
|
|
(e) => e == ' '
|
|
? const SizedBox(width: 20)
|
|
: LetterBonus.image(letter: e, width: 42),
|
|
)
|
|
],
|
|
),
|
|
),
|
|
Button(
|
|
Assets.images.icons.play.path,
|
|
() => setState(() {
|
|
_startGame();
|
|
}),
|
|
),
|
|
const SizedBox(
|
|
height: 64,
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget game() => GameWidget(
|
|
game: _game,
|
|
backgroundBuilder: (context) => Scaffold(),
|
|
);
|
|
|
|
Widget levelButton(
|
|
VoidCallback onTap,
|
|
String title,
|
|
) {
|
|
return InkWell(
|
|
onTap: onTap,
|
|
child: Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 12.0),
|
|
child: Container(
|
|
padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 12.0),
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.circular(32),
|
|
gradient: const LinearGradient(
|
|
colors: [
|
|
Color(0xff2F61D1),
|
|
Color(0xff53AFED),
|
|
],
|
|
begin: Alignment.bottomLeft,
|
|
end: Alignment.topRight,
|
|
)),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
...title.toLowerCase().characters.map(
|
|
(e) => e == ' '
|
|
? const SizedBox(
|
|
width: 32,
|
|
)
|
|
: LetterBonus.image(letter: e, width: 32),
|
|
)
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
void _startGame() {
|
|
setState(() {
|
|
index = 1;
|
|
// level = nextLevel;
|
|
_game.resumeEngine();
|
|
});
|
|
}
|
|
|
|
Widget button(VoidCallback onTap, String asset) {
|
|
return Container(
|
|
padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 24),
|
|
width: 240,
|
|
child: InkWell(
|
|
onTap: onTap,
|
|
child: Image(image: AssetImage('assets/images/$asset')),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _Handler extends WidgetsBindingObserver {
|
|
@override
|
|
void didChangeAppLifecycleState(AppLifecycleState state) {
|
|
if (state == AppLifecycleState.resumed) {
|
|
if (gameSettings.musicEnabled) {
|
|
audioPlayer.resume();
|
|
}
|
|
if (gameSettings.soundEnabled) {
|
|
effectPlayer.resume();
|
|
}
|
|
} else {
|
|
audioPlayer.pause();
|
|
effectPlayer.pause();
|
|
}
|
|
}
|
|
}
|