Skip to content
Snippets Groups Projects
Commit c7667f5f authored by Benoît Harrault's avatar Benoît Harrault
Browse files

Normalize game architecture

parent 6c63633d
No related branches found
No related tags found
1 merge request!24Resolve "Normalize game architecture"
Pipeline #5685 passed
Showing
with 584 additions and 178 deletions
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:twister/cubit/game_cubit.dart';
class QuitGameButton extends StatelessWidget {
const QuitGameButton({super.key});
@override
Widget build(BuildContext context) {
return TextButton(
child: const Image(
image: AssetImage('assets/ui/button_back.png'),
fit: BoxFit.fill,
),
onPressed: () {
BlocProvider.of<GameCubit>(context).quitGame();
},
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:twister/cubit/game_cubit.dart';
import 'package:twister/cubit/settings_game_cubit.dart';
import 'package:twister/cubit/settings_global_cubit.dart';
class StartNewGameButton extends StatelessWidget {
const StartNewGameButton({super.key});
@override
Widget build(BuildContext context) {
return BlocBuilder<GameSettingsCubit, GameSettingsState>(
builder: (BuildContext context, GameSettingsState gameSettingsState) {
return BlocBuilder<GlobalSettingsCubit, GlobalSettingsState>(
builder: (BuildContext context, GlobalSettingsState globalSettingsState) {
return TextButton(
child: const Image(
image: AssetImage('assets/ui/button_start.png'),
fit: BoxFit.fill,
),
onPressed: () {
BlocProvider.of<GameCubit>(context).startNewGame(
gameSettings: gameSettingsState.settings,
globalSettings: globalSettingsState.settings,
);
},
);
},
);
},
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:twister/cubit/game_cubit.dart';
class ResumeSavedGameButton extends StatelessWidget {
const ResumeSavedGameButton({super.key});
@override
Widget build(BuildContext context) {
return TextButton(
child: const Image(
image: AssetImage('assets/ui/button_resume_game.png'),
fit: BoxFit.fill,
),
onPressed: () {
BlocProvider.of<GameCubit>(context).resumeSavedGame();
},
);
}
}
import 'package:flutter/material.dart';
import 'package:twister/ui/widgets/app_titles.dart';
class StandardAppBar extends StatelessWidget implements PreferredSizeWidget {
const StandardAppBar({super.key});
@override
Widget build(BuildContext context) {
return AppBar(
title: const AppTitle(text: 'app_name'),
actions: const [],
);
}
@override
Size get preferredSize => const Size.fromHeight(50);
}
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:twister/cubit/bottom_nav_cubit.dart';
import 'package:twister/ui/screens/settings.dart';
import 'package:twister/ui/screens/home.dart';
class BottomNavBar extends StatelessWidget {
const BottomNavBar({super.key});
@override
Widget build(BuildContext context) {
return Card(
margin: const EdgeInsets.only(top: 1, right: 4, left: 4),
elevation: 4,
shadowColor: Theme.of(context).colorScheme.shadow,
color: Theme.of(context).colorScheme.surfaceVariant,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(16),
topRight: Radius.circular(16),
),
),
child: BlocBuilder<BottomNavCubit, int>(builder: (BuildContext context, int state) {
return BottomNavigationBar(
currentIndex: state,
onTap: (int index) => context.read<BottomNavCubit>().updateIndex(index),
type: BottomNavigationBarType.fixed,
elevation: 0,
backgroundColor: Colors.transparent,
selectedItemColor: Theme.of(context).colorScheme.primary,
unselectedItemColor: Theme.of(context).textTheme.bodySmall!.color,
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: ScreenHome.navBarIcon,
label: tr(ScreenHome.navBarText),
),
BottomNavigationBarItem(
icon: ScreenSettings.navBarIcon,
label: tr(ScreenSettings.navBarText),
),
],
);
}),
);
}
}
import 'package:flutter/material.dart';
import 'package:twister/ui/widgets/game/game_current_move.dart';
import 'package:twister/ui/widgets/game/game_moves_history.dart';
class GameBoardWidget extends StatelessWidget {
const GameBoardWidget({super.key});
@override
Widget build(BuildContext context) {
return const Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
GameCurrentMoveWidget(),
GameMovesHistoryWidget(),
],
);
}
}
import 'dart:async';
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:twister/cubit/game_cubit.dart';
import 'package:twister/models/game/move.dart';
import 'package:twister/ui/widgets/game/move.dart';
class GameCurrentMoveWidget extends StatefulWidget {
const GameCurrentMoveWidget({super.key});
@override
State<GameCurrentMoveWidget> createState() => _GameCurrentMoveWidgetState();
}
class _GameCurrentMoveWidgetState extends State<GameCurrentMoveWidget> {
Move? shuffledMove;
void animate() {
final GameCubit gameCubit = BlocProvider.of<GameCubit>(context);
if (gameCubit.state.currentGame.animationInProgress == true) {
return;
}
const interval = Duration(milliseconds: 200);
int iterationsLeft = 10;
gameCubit.setAnimationIsRunning(true);
shuffledMove = null;
setState(() {});
Timer.periodic(
interval,
(Timer timer) {
// animate with random move
if (iterationsLeft > 1) {
shuffledMove = Move.pickRandom();
}
// last iteration => clear
if (iterationsLeft == 1) {
shuffledMove = null;
}
// end: pick and keep random move
if (iterationsLeft == 0) {
shuffledMove = null;
timer.cancel();
gameCubit.pickNewMove();
gameCubit.setAnimationIsRunning(false);
}
setState(() {});
iterationsLeft--;
},
);
}
@override
Widget build(BuildContext context) {
return BlocBuilder<GameCubit, GameState>(
builder: (BuildContext context, GameState gameState) {
return GestureDetector(
child: gameState.currentGame.animationInProgress
? Transform.rotate(
angle: 2 * pi * Random().nextDouble(),
child: MoveWidget(move: shuffledMove ?? Move.createEmpty()),
)
: MoveWidget(move: gameState.currentGame.move ?? Move.createEmpty()),
onTap: () {
animate();
},
);
},
);
}
}
import 'dart:async';
import 'dart:math';
import 'package:audioplayers/audioplayers.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:twister/cubit/game_cubit.dart'; import 'package:twister/cubit/game_cubit.dart';
import 'package:twister/models/move.dart'; import 'package:twister/models/game/move.dart';
import 'package:twister/models/twister_color.dart'; import 'package:twister/models/game/twister_color.dart';
import 'package:twister/models/twister_member.dart'; import 'package:twister/models/game/twister_member.dart';
import 'package:twister/ui/widgets/show_move.dart'; import 'package:twister/ui/widgets/game/move.dart';
class Game extends StatefulWidget { class GameMovesHistoryWidget extends StatelessWidget {
const Game({super.key}); const GameMovesHistoryWidget({super.key});
@override @override
State<Game> createState() => _GameState(); Widget build(BuildContext context) {
} return BlocBuilder<GameCubit, GameState>(
builder: (BuildContext context, GameState gameState) {
class _GameState extends State<Game> { return GestureDetector(
final player = AudioPlayer(); child: currentGlobalState(gameState.currentGame.history),
bool shuffling = false; onTap: () {
Move? shuffledMove; BlocProvider.of<GameCubit>(context).deleteHistory();
void animate() {
const interval = Duration(milliseconds: 200);
int iterationsLeft = 10;
shuffling = true;
shuffledMove = null;
setState(() {});
Timer.periodic(
interval,
(Timer timer) {
if (iterationsLeft > 1) {
shuffledMove = Move.pickRandom();
}
if (iterationsLeft == 1) {
shuffledMove = null;
}
if (iterationsLeft == 0) {
shuffledMove = null;
pickNewMove();
timer.cancel();
shuffling = false;
}
setState(() {});
iterationsLeft--;
}, },
); );
} },
void pickNewMove() {
Move newMove = Move.pickRandom();
BlocProvider.of<GameCubit>(context).setValues(
move: newMove,
); );
player.play(AssetSource(newMove.toSoundAsset()));
} }
Widget buildCurrentStateWidget(List<Move>? history) { Widget currentGlobalState(List<Move>? history) {
Map<String, TwisterColor?> currentState = {}; Map<String, TwisterColor?> currentState = {};
history?.forEach((move) { history?.forEach((move) {
...@@ -103,11 +61,11 @@ class _GameState extends State<Game> { ...@@ -103,11 +61,11 @@ class _GameState extends State<Game> {
children: [ children: [
Padding( Padding(
padding: const EdgeInsets.all(10), padding: const EdgeInsets.all(10),
child: ShowMove(move: leftHandMove), child: MoveWidget(move: leftHandMove),
), ),
Padding( Padding(
padding: const EdgeInsets.all(10), padding: const EdgeInsets.all(10),
child: ShowMove(move: rightHandMove), child: MoveWidget(move: rightHandMove),
), ),
], ],
), ),
...@@ -115,11 +73,11 @@ class _GameState extends State<Game> { ...@@ -115,11 +73,11 @@ class _GameState extends State<Game> {
children: [ children: [
Padding( Padding(
padding: const EdgeInsets.all(10), padding: const EdgeInsets.all(10),
child: ShowMove(move: leftFootMove), child: MoveWidget(move: leftFootMove),
), ),
Padding( Padding(
padding: const EdgeInsets.all(10), padding: const EdgeInsets.all(10),
child: ShowMove(move: rightFootMove), child: MoveWidget(move: rightFootMove),
), ),
], ],
) )
...@@ -127,33 +85,4 @@ class _GameState extends State<Game> { ...@@ -127,33 +85,4 @@ class _GameState extends State<Game> {
), ),
); );
} }
@override
Widget build(BuildContext context) {
return BlocBuilder<GameCubit, GameState>(
builder: (BuildContext context, GameState gameState) {
return Column(
children: [
GestureDetector(
child: shuffling
? Transform.rotate(
angle: 2 * pi * Random().nextDouble(),
child: ShowMove(move: shuffledMove ?? Move.createNull()),
)
: ShowMove(move: gameState.move ?? Move.createNull()),
onTap: () {
animate();
},
),
GestureDetector(
child: buildCurrentStateWidget(gameState.history),
onTap: () {
BlocProvider.of<GameCubit>(context).deleteHistory();
},
),
],
);
},
);
}
} }
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:twister/config/colors.dart'; import 'package:twister/config/color_theme.dart';
import 'package:twister/models/move.dart'; import 'package:twister/models/game/move.dart';
import 'package:twister/models/twister_color.dart'; import 'package:twister/models/game/twister_color.dart';
import 'package:twister/models/twister_member.dart'; import 'package:twister/models/game/twister_member.dart';
import 'package:twister/utils/color_extensions.dart'; import 'package:twister/utils/color_extensions.dart';
class ShowMove extends StatelessWidget { class MoveWidget extends StatelessWidget {
const ShowMove({super.key, required this.move}); const MoveWidget({super.key, required this.move});
final Move move; final Move move;
...@@ -27,12 +27,6 @@ class ShowMove extends StatelessWidget { ...@@ -27,12 +27,6 @@ class ShowMove extends StatelessWidget {
} }
} }
Widget getImageWidget(Move move) {
String imageAsset = 'assets/images/${move.member?.toString() ?? 'blank'}.png';
return Image.asset(imageAsset);
}
Widget getTextWidget(Move move) { Widget getTextWidget(Move move) {
TextStyle style = const TextStyle( TextStyle style = const TextStyle(
color: Colors.black, color: Colors.black,
...@@ -54,7 +48,11 @@ class ShowMove extends StatelessWidget { ...@@ -54,7 +48,11 @@ class ShowMove extends StatelessWidget {
} }
} }
Widget buildWidget(Move move, double maxWidth) { @override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) {
final double maxWidth = constraints.maxWidth;
Color color = getColor(move); Color color = getColor(move);
double containerSize = maxWidth * 0.8; double containerSize = maxWidth * 0.8;
...@@ -75,17 +73,9 @@ class ShowMove extends StatelessWidget { ...@@ -75,17 +73,9 @@ class ShowMove extends StatelessWidget {
width: 15, width: 15,
), ),
), ),
child: getImageWidget(move), child: Image.asset('assets/ui/move-${move.member?.toString() ?? 'blank'}.png'),
), ),
); );
}
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) {
final double maxWidth = constraints.maxWidth;
return buildWidget(move, maxWidth);
}, },
); );
} }
......
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:twister/config/menu.dart';
import 'package:twister/cubit/game_cubit.dart';
import 'package:twister/cubit/nav_cubit.dart';
import 'package:twister/models/game/game.dart';
import 'package:twister/ui/helpers/app_titles.dart';
class GlobalAppBar extends StatelessWidget implements PreferredSizeWidget {
const GlobalAppBar({super.key});
@override
Widget build(BuildContext context) {
return BlocBuilder<GameCubit, GameState>(
builder: (BuildContext context, GameState gameState) {
return BlocBuilder<NavCubit, int>(
builder: (BuildContext context, int pageIndex) {
final Game currentGame = gameState.currentGame;
final List<Widget> menuActions = [];
if (currentGame.isRunning && !currentGame.isFinished) {
menuActions.add(TextButton(
child: const Image(
image: AssetImage('assets/ui/button_back.png'),
fit: BoxFit.fill,
),
onPressed: () {},
onLongPress: () {
BlocProvider.of<GameCubit>(context).quitGame();
},
));
} else {
if (pageIndex == Menu.indexGame) {
// go to Settings page
menuActions.add(ElevatedButton(
onPressed: () {
context.read<NavCubit>().goToSettingsPage();
},
style: ElevatedButton.styleFrom(
shape: const CircleBorder(),
),
child: Menu.menuItemSettings.icon,
));
// go to About page
menuActions.add(ElevatedButton(
onPressed: () {
context.read<NavCubit>().goToAboutPage();
},
style: ElevatedButton.styleFrom(
shape: const CircleBorder(),
),
child: Menu.menuItemAbout.icon,
));
} else {
// back to Home page
menuActions.add(ElevatedButton(
onPressed: () {
context.read<NavCubit>().goToGamePage();
},
style: ElevatedButton.styleFrom(
shape: const CircleBorder(),
),
child: Menu.menuItemGame.icon,
));
}
}
return AppBar(
title: const AppHeader(text: 'app_name'),
actions: menuActions,
);
},
);
},
);
}
@override
Size get preferredSize => const Size.fromHeight(50);
}
...@@ -5,10 +5,10 @@ packages: ...@@ -5,10 +5,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: args name: args
sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.2" version: "2.5.0"
async: async:
dependency: transitive dependency: transitive
description: description:
...@@ -21,66 +21,66 @@ packages: ...@@ -21,66 +21,66 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: audioplayers name: audioplayers
sha256: c05c6147124cd63e725e861335a8b4d57300b80e6e92cea7c145c739223bbaef sha256: "752039d6aa752597c98ec212e9759519061759e402e7da59a511f39d43aa07d2"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.2.1" version: "6.0.0"
audioplayers_android: audioplayers_android:
dependency: transitive dependency: transitive
description: description:
name: audioplayers_android name: audioplayers_android
sha256: b00e1a0e11365d88576320ec2d8c192bc21f1afb6c0e5995d1c57ae63156acb5 sha256: de576b890befe27175c2f511ba8b742bec83765fa97c3ce4282bba46212f58e4
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.0.3" version: "5.0.0"
audioplayers_darwin: audioplayers_darwin:
dependency: transitive dependency: transitive
description: description:
name: audioplayers_darwin name: audioplayers_darwin
sha256: "3034e99a6df8d101da0f5082dcca0a2a99db62ab1d4ddb3277bed3f6f81afe08" sha256: e507887f3ff18d8e5a10a668d7bedc28206b12e10b98347797257c6ae1019c3b
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.0.2" version: "6.0.0"
audioplayers_linux: audioplayers_linux:
dependency: transitive dependency: transitive
description: description:
name: audioplayers_linux name: audioplayers_linux
sha256: "60787e73fefc4d2e0b9c02c69885402177e818e4e27ef087074cf27c02246c9e" sha256: "3d3d244c90436115417f170426ce768856d8fe4dfc5ed66a049d2890acfa82f9"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.0" version: "4.0.0"
audioplayers_platform_interface: audioplayers_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: audioplayers_platform_interface name: audioplayers_platform_interface
sha256: "365c547f1bb9e77d94dd1687903a668d8f7ac3409e48e6e6a3668a1ac2982adb" sha256: "6834dd48dfb7bc6c2404998ebdd161f79cd3774a7e6779e1348d54a3bfdcfaa5"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.1.0" version: "7.0.0"
audioplayers_web: audioplayers_web:
dependency: transitive dependency: transitive
description: description:
name: audioplayers_web name: audioplayers_web
sha256: "22cd0173e54d92bd9b2c80b1204eb1eb159ece87475ab58c9788a70ec43c2a62" sha256: db8fc420dadf80da18e2286c18e746fb4c3b2c5adbf0c963299dde046828886d
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.1.0" version: "5.0.0"
audioplayers_windows: audioplayers_windows:
dependency: transitive dependency: transitive
description: description:
name: audioplayers_windows name: audioplayers_windows
sha256: "9536812c9103563644ada2ef45ae523806b0745f7a78e89d1b5fb1951de90e1a" sha256: "8605762dddba992138d476f6a0c3afd9df30ac5b96039929063eceed416795c2"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.0" version: "4.0.0"
bloc: bloc:
dependency: transitive dependency: transitive
description: description:
name: bloc name: bloc
sha256: f53a110e3b48dcd78136c10daa5d51512443cea5e1348c9d80a320095fa2db9e sha256: "106842ad6569f0b60297619e9e0b1885c2fb9bf84812935490e6c5275777804e"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "8.1.3" version: "8.1.4"
characters: characters:
dependency: transitive dependency: transitive
description: description:
...@@ -117,10 +117,10 @@ packages: ...@@ -117,10 +117,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: easy_localization name: easy_localization
sha256: c145aeb6584aedc7c862ab8c737c3277788f47488bfdf9bae0fe112bd0a4789c sha256: fa59bcdbbb911a764aa6acf96bbb6fa7a5cf8234354fc45ec1a43a0349ef0201
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.5" version: "3.0.7"
easy_logger: easy_logger:
dependency: transitive dependency: transitive
description: description:
...@@ -170,18 +170,18 @@ packages: ...@@ -170,18 +170,18 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_bloc name: flutter_bloc
sha256: "87325da1ac757fcc4813e6b34ed5dd61169973871fdf181d6c2109dd6935ece1" sha256: b594505eac31a0518bdcb4b5b79573b8d9117b193cc80cc12e17d639b10aa27a
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "8.1.4" version: "8.1.6"
flutter_lints: flutter_lints:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: flutter_lints name: flutter_lints
sha256: e2a421b7e59244faef694ba7b30562e489c2b489866e505074eb005cd7060db7 sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.1" version: "4.0.0"
flutter_localizations: flutter_localizations:
dependency: transitive dependency: transitive
description: flutter description: flutter
...@@ -220,34 +220,26 @@ packages: ...@@ -220,34 +220,26 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: hydrated_bloc name: hydrated_bloc
sha256: "00a2099680162e74b5a836b8a7f446e478520a9cae9f6032e028ad8129f4432d" sha256: af35b357739fe41728df10bec03aad422cdc725a1e702e03af9d2a41ea05160c
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "9.1.4" version: "9.1.5"
intl: intl:
dependency: transitive dependency: transitive
description: description:
name: intl name: intl
sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.18.1" version: "0.19.0"
js:
dependency: transitive
description:
name: js
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
url: "https://pub.dev"
source: hosted
version: "0.6.7"
lints: lints:
dependency: transitive dependency: transitive
description: description:
name: lints name: lints
sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290 sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.0" version: "4.0.0"
material_color_utilities: material_color_utilities:
dependency: transitive dependency: transitive
description: description:
...@@ -260,10 +252,10 @@ packages: ...@@ -260,10 +252,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: meta name: meta
sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.11.0" version: "1.12.0"
nested: nested:
dependency: transitive dependency: transitive
description: description:
...@@ -272,6 +264,22 @@ packages: ...@@ -272,6 +264,22 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.0" version: "1.0.0"
package_info_plus:
dependency: "direct main"
description:
name: package_info_plus
sha256: b93d8b4d624b4ea19b0a5a208b2d6eff06004bc3ce74c06040b120eeadd00ce0
url: "https://pub.dev"
source: hosted
version: "8.0.0"
package_info_plus_platform_interface:
dependency: transitive
description:
name: package_info_plus_platform_interface
sha256: f49918f3433a3146047372f9d4f1f847511f2acd5cd030e1f44fe5a50036b70e
url: "https://pub.dev"
source: hosted
version: "3.0.0"
path: path:
dependency: transitive dependency: transitive
description: description:
...@@ -284,26 +292,26 @@ packages: ...@@ -284,26 +292,26 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: path_provider name: path_provider
sha256: b27217933eeeba8ff24845c34003b003b2b22151de3c908d0e679e8fe1aa078b sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.2" version: "2.1.3"
path_provider_android: path_provider_android:
dependency: transitive dependency: transitive
description: description:
name: path_provider_android name: path_provider_android
sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668" sha256: "9c96da072b421e98183f9ea7464898428e764bc0ce5567f27ec8693442e72514"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.2" version: "2.2.5"
path_provider_foundation: path_provider_foundation:
dependency: transitive dependency: transitive
description: description:
name: path_provider_foundation name: path_provider_foundation
sha256: "5a7999be66e000916500be4f15a3633ebceb8302719b47b9cc49ce924125350f" sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.2" version: "2.4.0"
path_provider_linux: path_provider_linux:
dependency: transitive dependency: transitive
description: description:
...@@ -332,10 +340,10 @@ packages: ...@@ -332,10 +340,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: platform name: platform
sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec" sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.4" version: "3.1.5"
plugin_platform_interface: plugin_platform_interface:
dependency: transitive dependency: transitive
description: description:
...@@ -356,26 +364,26 @@ packages: ...@@ -356,26 +364,26 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences name: shared_preferences
sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02" sha256: d3bbe5553a986e83980916ded2f0b435ef2e1893dfaa29d5a7a790d0eca12180
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.2" version: "2.2.3"
shared_preferences_android: shared_preferences_android:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_android name: shared_preferences_android
sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06" sha256: "93d0ec9dd902d85f326068e6a899487d1f65ffcd5798721a95330b26c8131577"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.1" version: "2.2.3"
shared_preferences_foundation: shared_preferences_foundation:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_foundation name: shared_preferences_foundation
sha256: "7708d83064f38060c7b39db12aefe449cb8cdc031d6062280087bc4cdb988f5c" sha256: "0a8a893bf4fd1152f93fec03a415d11c27c74454d96e2318a7ac38dd18683ab7"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.5" version: "2.4.0"
shared_preferences_linux: shared_preferences_linux:
dependency: transitive dependency: transitive
description: description:
...@@ -473,10 +481,10 @@ packages: ...@@ -473,10 +481,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: uuid name: uuid
sha256: cd210a09f7c18cbe5a02511718e0334de6559871052c90a90c0cca46a4aa81c8 sha256: "814e9e88f21a176ae1359149021870e87f7cddaf633ab678a5d2b0bff7fd1ba8"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.3.3" version: "4.4.0"
vector_math: vector_math:
dependency: transitive dependency: transitive
description: description:
...@@ -489,18 +497,18 @@ packages: ...@@ -489,18 +497,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: web name: web
sha256: "1d9158c616048c38f712a6646e317a3426da10e884447626167240d45209cbad" sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.5.0" version: "0.5.1"
win32: win32:
dependency: transitive dependency: transitive
description: description:
name: win32 name: win32
sha256: "464f5674532865248444b4c3daca12bd9bf2d7c47f759ce2617986e7229494a8" sha256: a79dbe579cb51ecd6d30b17e0cae4e0ea15e2c0e66f69ad4198f22a6789e94f4
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.2.0" version: "5.5.1"
xdg_directories: xdg_directories:
dependency: transitive dependency: transitive
description: description:
...@@ -510,5 +518,5 @@ packages: ...@@ -510,5 +518,5 @@ packages:
source: hosted source: hosted
version: "1.0.4" version: "1.0.4"
sdks: sdks:
dart: ">=3.3.0 <4.0.0" dart: ">=3.4.0 <4.0.0"
flutter: ">=3.19.0" flutter: ">=3.22.0"
name: twister name: twister
description: twister game companion description: Twister game companion
publish_to: 'none' publish_to: "none"
version: 0.0.23+23 version: 0.1.0+24
environment: environment:
sdk: '^3.0.0' sdk: "^3.0.0"
dependencies: dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
audioplayers: ^5.2.1 # base
easy_localization: ^3.0.1 easy_localization: ^3.0.1
equatable: ^2.0.5 equatable: ^2.0.5
flutter_bloc: ^8.1.1 flutter_bloc: ^8.1.1
hive: ^2.2.3 hive: ^2.2.3
path_provider: ^2.0.11
hydrated_bloc: ^9.0.0 hydrated_bloc: ^9.0.0
package_info_plus: ^8.0.0
path_provider: ^2.0.11
unicons: ^2.1.1 unicons: ^2.1.1
# specific
audioplayers: ^6.0.0
dev_dependencies: dev_dependencies:
flutter_lints: ^3.0.1 flutter_lints: ^4.0.0
flutter: flutter:
uses-material-design: false uses-material-design: true
assets: assets:
- assets/images/ - assets/ui/
- assets/translations/ - assets/translations/
- assets/voices/ - assets/voices/
...@@ -42,3 +46,4 @@ flutter: ...@@ -42,3 +46,4 @@ flutter:
weight: 400 weight: 400
- asset: assets/fonts/Nunito-Light.ttf - asset: assets/fonts/Nunito-Light.ttf
weight: 300 weight: 300
...@@ -6,7 +6,7 @@ command -v scour >/dev/null 2>&1 || { echo >&2 "I require scour but it's not ins ...@@ -6,7 +6,7 @@ command -v scour >/dev/null 2>&1 || { echo >&2 "I require scour but it's not ins
command -v optipng >/dev/null 2>&1 || { echo >&2 "I require optipng but it's not installed. Aborting."; exit 1; } command -v optipng >/dev/null 2>&1 || { echo >&2 "I require optipng but it's not installed. Aborting."; exit 1; }
CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
BASE_DIR="$(dirname "${CURRENT_DIR}")" BASE_DIR="$(dirname "$(dirname "${CURRENT_DIR}")")"
SOURCE_ICON="${CURRENT_DIR}/icon.svg" SOURCE_ICON="${CURRENT_DIR}/icon.svg"
SOURCE_FASTLANE="${CURRENT_DIR}/featureGraphic.svg" SOURCE_FASTLANE="${CURRENT_DIR}/featureGraphic.svg"
......
File moved
File moved
#! /bin/bash
CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
${CURRENT_DIR}/app/build_application_resources.sh
${CURRENT_DIR}/ui/build_ui_resources.sh
${CURRENT_DIR}/tts/generate_sounds.sh
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
command -v pico2wave >/dev/null 2>&1 || { echo >&2 "I require pico2wave (libttspico-utils) but it's not installed. Aborting."; exit 1; } command -v pico2wave >/dev/null 2>&1 || { echo >&2 "I require pico2wave (libttspico-utils) but it's not installed. Aborting."; exit 1; }
CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
BASE_DIR="$(dirname "${CURRENT_DIR}")" BASE_DIR="$(dirname "$(dirname "${CURRENT_DIR}")")"
OUTPUT_BASE_FOLDER="${BASE_DIR}/assets/voices" OUTPUT_BASE_FOLDER="${BASE_DIR}/assets/voices"
mkdir -p "${OUTPUT_BASE_FOLDER}" mkdir -p "${OUTPUT_BASE_FOLDER}"
......
...@@ -6,22 +6,33 @@ command -v scour >/dev/null 2>&1 || { echo >&2 "I require scour but it's not ins ...@@ -6,22 +6,33 @@ command -v scour >/dev/null 2>&1 || { echo >&2 "I require scour but it's not ins
command -v optipng >/dev/null 2>&1 || { echo >&2 "I require optipng but it's not installed. Aborting."; exit 1; } command -v optipng >/dev/null 2>&1 || { echo >&2 "I require optipng but it's not installed. Aborting."; exit 1; }
CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
BASE_DIR="$(dirname "${CURRENT_DIR}")" BASE_DIR="$(dirname "$(dirname "${CURRENT_DIR}")")"
ASSETS_DIR="${BASE_DIR}/assets" ASSETS_DIR="${BASE_DIR}/assets"
OPTIPNG_OPTIONS="-preserve -quiet -o7" OPTIPNG_OPTIONS="-preserve -quiet -o7"
ICON_SIZE=512 ICON_SIZE=512
ICON_SIZE=192
####################################################### #######################################################
# Game images # Game images (svg files found in `images` folder)
AVAILABLE_GAME_IMAGES=" AVAILABLE_GAME_IMAGES=""
blank if [ -d "${CURRENT_DIR}/images" ]; then
left-hand AVAILABLE_GAME_IMAGES="$(find "${CURRENT_DIR}/images" -type f -name "*.svg" | awk -F/ '{print $NF}' | cut -d"." -f1 | sort)"
right-hand fi
left-foot
right-foot # Skins (subfolders found in `skins` folder)
" AVAILABLE_SKINS=""
if [ -d "${CURRENT_DIR}/skins" ]; then
AVAILABLE_SKINS="$(find "${CURRENT_DIR}/skins" -mindepth 1 -type d | awk -F/ '{print $NF}')"
fi
# Images per skin (svg files found recursively in `skins` folder and subfolders)
SKIN_IMAGES=""
if [ -d "${CURRENT_DIR}/skins" ]; then
SKIN_IMAGES="$(find "${CURRENT_DIR}/skins" -type f -name "*.svg" | awk -F/ '{print $NF}' | cut -d"." -f1 | sort | uniq)"
fi
####################################################### #######################################################
# optimize svg # optimize svg
...@@ -42,7 +53,7 @@ function optimize_svg() { ...@@ -42,7 +53,7 @@ function optimize_svg() {
} }
# build icons # build icons
function build_icon() { function build_image() {
SOURCE="$1" SOURCE="$1"
TARGET="$2" TARGET="$2"
...@@ -55,26 +66,46 @@ function build_icon() { ...@@ -55,26 +66,46 @@ function build_icon() {
optimize_svg "${SOURCE}" optimize_svg "${SOURCE}"
mkdir -p "$(dirname "${TARGET}")"
inkscape \ inkscape \
--export-width=${ICON_SIZE} \ --export-width=${ICON_SIZE} \
--export-height=${ICON_SIZE} \ --export-height=${ICON_SIZE} \
--export-filename=${TARGET} \ --export-filename=${TARGET} \
${SOURCE} "${SOURCE}"
optipng ${OPTIPNG_OPTIONS} ${TARGET} optipng ${OPTIPNG_OPTIONS} "${TARGET}"
} }
####################################################### function build_image_for_skin() {
SKIN_CODE="$1"
# skin images
for SKIN_IMAGE in ${SKIN_IMAGES}
do
build_image ${CURRENT_DIR}/skins/${SKIN_CODE}/${SKIN_IMAGE}.svg ${ASSETS_DIR}/skins/${SKIN_CODE}_${SKIN_IMAGE}.png
done
}
# Create output folder #######################################################
mkdir -p ${ASSETS_DIR}/images
# Delete existing generated images # Delete existing generated images
find ${ASSETS_DIR}/images -type f -name "*.png" -delete if [ -d "${ASSETS_DIR}/ui" ]; then
find ${ASSETS_DIR}/ui -type f -name "*.png" -delete
fi
if [ -d "${ASSETS_DIR}/skins" ]; then
find ${ASSETS_DIR}/skins -type f -name "*.png" -delete
fi
# build game images # build game images
for GAME_IMAGE in ${AVAILABLE_GAME_IMAGES} for GAME_IMAGE in ${AVAILABLE_GAME_IMAGES}
do do
build_icon ${CURRENT_DIR}/${GAME_IMAGE}.svg ${ASSETS_DIR}/images/${GAME_IMAGE}.png build_image ${CURRENT_DIR}/images/${GAME_IMAGE}.svg ${ASSETS_DIR}/ui/${GAME_IMAGE}.png
done
# build skins images
for SKIN in ${AVAILABLE_SKINS}
do
build_image_for_skin "${SKIN}"
done done
<?xml version="1.0" encoding="UTF-8"?>
<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x=".44662" y=".89101" width="92.772" height="91.894" ry="11.689" fill="#e41578" stroke="#fff" stroke-width=".238"/><path d="m59.387 71.362c1.1248 1.1302 4.0012 1.1302 4.0012 0v-45.921c0-1.1316-2.8832-1.1316-4.0121 0l-37.693 20.918c-1.1289 1.1248-1.1479 2.9551-0.02171 4.084z" fill="#fefeff" stroke="#930e4e" stroke-linecap="round" stroke-linejoin="round" stroke-width="8.257"/><path d="m57.857 68.048c0.96243 0.96706 3.4236 0.96706 3.4236 0v-39.292c0-0.96825-2.467-0.96825-3.4329 0l-32.252 17.898c-0.96594 0.96243-0.9822 2.5285-0.01858 3.4945z" fill="#fefeff" stroke="#feffff" stroke-linecap="round" stroke-linejoin="round" stroke-width="4.314"/></svg>
<?xml version="1.0" encoding="UTF-8"?>
<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x=".44662" y=".89101" width="92.772" height="91.894" ry="11.689" fill="#ee7d49" stroke="#fff" stroke-width=".238"/><path d="m61.07 35.601-1.7399 27.837c-0.13442 2.1535-1.9205 3.8312-4.0781 3.8312h-16.84c-2.1576 0-3.9437-1.6777-4.0781-3.8312l-1.7399-27.837h-2.6176c-0.84621 0-1.5323-0.68613-1.5323-1.5323 0-0.84655 0.68613-1.5323 1.5323-1.5323h33.711c0.84621 0 1.5323 0.68578 1.5323 1.5323 0 0.84621-0.68613 1.5323-1.5323 1.5323zm-3.2617 0h-21.953l1.4715 26.674c0.05985 1.0829 0.95531 1.9305 2.0403 1.9305h14.929c1.085 0 1.9804-0.84757 2.0403-1.9305zm-10.977 3.0647c0.78977 0 1.4301 0.6403 1.4301 1.4301v19.614c0 0.78977-0.6403 1.4301-1.4301 1.4301s-1.4301-0.6403-1.4301-1.4301v-19.614c0-0.78977 0.6403-1.4301 1.4301-1.4301zm-6.1293 0c0.80004 0 1.4588 0.62935 1.495 1.4286l0.89647 19.719c0.03182 0.70016-0.50998 1.2933-1.2101 1.3255-0.01915 7.02e-4 -0.03831 1e-3 -0.05781 1e-3 -0.74462 0-1.3596-0.58215-1.4003-1.3261l-1.0757-19.719c-0.0407-0.74701 0.53188-1.3852 1.2786-1.4259 0.02462-0.0014 0.04926-2e-3 0.07388-2e-3zm12.259 0c0.74804 0 1.3541 0.60609 1.3541 1.3541 0 0.02462-3.28e-4 0.04926-0.0017 0.07388l-1.0703 19.618c-0.04379 0.80106-0.70597 1.4281-1.5081 1.4281-0.74804 0-1.3541-0.60609-1.3541-1.3541 0-0.02462 3.49e-4 -0.04925 0.0017-0.07388l1.0703-19.618c0.04379-0.80106 0.70597-1.4281 1.5081-1.4281zm-10.216-12.259h8.1728c2.2567 0 4.086 1.8293 4.086 4.086v2.0433h-16.344v-2.0433c0-2.2567 1.8293-4.086 4.086-4.086zm0.20453 3.0647c-0.67725 0-1.2259 0.54863-1.2259 1.2259v1.8388h10.215v-1.8388c0-0.67725-0.54863-1.2259-1.2259-1.2259z" fill="#fff" fill-rule="evenodd" stroke="#bd4812" stroke-width=".75383"/></svg>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment