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

Improve game architecture/conception

parent 3fd635d8
No related branches found
No related tags found
1 merge request!40Resolve "Improve game architecture"
Pipeline #5476 passed
Showing
with 612 additions and 152 deletions
org.gradle.jvmargs=-Xmx1536M org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true android.useAndroidX=true
android.enableJetifier=true android.enableJetifier=true
app.versionName=0.1.16 app.versionName=0.1.17
app.versionCode=37 app.versionCode=38
File added
File added
File added
File added
{
"app_name": "Minehunter",
"long_press_to_quit": "Long press to quit game...",
"bottom_nav_home": "Game",
"bottom_nav_settings": "Settings",
"bottom_nav_about": "About",
"settings_title": "Settings",
"settings_label_theme": "Theme mode",
"about_title": "About",
"about_content": "Minehunter.",
"about_version": "Version: {version}"
}
{
"app_name": "Démineur",
"long_press_to_quit": "Appuyer longtemps pour quitter le jeu...",
"bottom_nav_home": "Jeu",
"bottom_nav_settings": "Réglages",
"bottom_nav_about": "Infos",
"settings_title": "Réglages",
"settings_label_theme": "Thème de couleurs",
"about_title": "Informations",
"about_content": "Démineur.",
"about_version": "Version : {version}"
}
Improve game conception/architecture.
Amélioration de la conception/architecture du jeu.
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:minehunter/ui/screens/about_page.dart';
import 'package:minehunter/ui/screens/game_page.dart';
import 'package:minehunter/ui/screens/settings_page.dart';
import 'package:unicons/unicons.dart';
class MenuItem {
final String code;
final Icon icon;
final Widget page;
const MenuItem({
required this.code,
required this.icon,
required this.page,
});
}
class Menu {
static List<MenuItem> items = [
const MenuItem(
code: 'bottom_nav_home',
icon: Icon(UniconsLine.home),
page: GamePage(),
),
const MenuItem(
code: 'bottom_nav_settings',
icon: Icon(UniconsLine.setting),
page: SettingsPage(),
),
const MenuItem(
code: 'bottom_nav_about',
icon: Icon(UniconsLine.info_circle),
page: AboutPage(),
),
];
static Widget getPageWidget(int pageIndex) {
return Menu.items.elementAt(pageIndex).page;
}
static List<BottomNavigationBarItem> getMenuItems() {
return Menu.items
.map((MenuItem item) => BottomNavigationBarItem(
icon: item.icon,
label: tr(item.code),
))
.toList();
}
static int itemsCount = Menu.items.length;
}
import 'package:flutter/material.dart';
/// Colors from Tailwind CSS (v3.0) - June 2022
///
/// https://tailwindcss.com/docs/customizing-colors
const int _primaryColor = 0xFF6366F1;
const MaterialColor primarySwatch = MaterialColor(_primaryColor, <int, Color>{
50: Color(0xFFEEF2FF), // indigo-50
100: Color(0xFFE0E7FF), // indigo-100
200: Color(0xFFC7D2FE), // indigo-200
300: Color(0xFFA5B4FC), // indigo-300
400: Color(0xFF818CF8), // indigo-400
500: Color(_primaryColor), // indigo-500
600: Color(0xFF4F46E5), // indigo-600
700: Color(0xFF4338CA), // indigo-700
800: Color(0xFF3730A3), // indigo-800
900: Color(0xFF312E81), // indigo-900
});
const int _textColor = 0xFF64748B;
const MaterialColor textSwatch = MaterialColor(_textColor, <int, Color>{
50: Color(0xFFF8FAFC), // slate-50
100: Color(0xFFF1F5F9), // slate-100
200: Color(0xFFE2E8F0), // slate-200
300: Color(0xFFCBD5E1), // slate-300
400: Color(0xFF94A3B8), // slate-400
500: Color(_textColor), // slate-500
600: Color(0xFF475569), // slate-600
700: Color(0xFF334155), // slate-700
800: Color(0xFF1E293B), // slate-800
900: Color(0xFF0F172A), // slate-900
});
const Color errorColor = Color(0xFFDC2626); // red-600
final ColorScheme lightColorScheme = ColorScheme.light(
primary: primarySwatch.shade500,
secondary: primarySwatch.shade500,
onSecondary: Colors.white,
error: errorColor,
background: textSwatch.shade200,
onBackground: textSwatch.shade500,
onSurface: textSwatch.shade500,
surface: textSwatch.shade50,
surfaceVariant: Colors.white,
shadow: textSwatch.shade900.withOpacity(.1),
);
final ColorScheme darkColorScheme = ColorScheme.dark(
primary: primarySwatch.shade500,
secondary: primarySwatch.shade500,
onSecondary: Colors.white,
error: errorColor,
background: const Color(0xFF171724),
onBackground: textSwatch.shade400,
onSurface: textSwatch.shade300,
surface: const Color(0xFF262630),
surfaceVariant: const Color(0xFF282832),
shadow: textSwatch.shade900.withOpacity(.2),
);
final ThemeData lightTheme = ThemeData(
colorScheme: lightColorScheme,
fontFamily: 'Nunito',
textTheme: TextTheme(
displayLarge: TextStyle(
color: textSwatch.shade700,
fontFamily: 'Nunito',
),
displayMedium: TextStyle(
color: textSwatch.shade600,
fontFamily: 'Nunito',
),
displaySmall: TextStyle(
color: textSwatch.shade500,
fontFamily: 'Nunito',
),
headlineLarge: TextStyle(
color: textSwatch.shade700,
fontFamily: 'Nunito',
),
headlineMedium: TextStyle(
color: textSwatch.shade600,
fontFamily: 'Nunito',
),
headlineSmall: TextStyle(
color: textSwatch.shade500,
fontFamily: 'Nunito',
),
titleLarge: TextStyle(
color: textSwatch.shade700,
fontFamily: 'Nunito',
),
titleMedium: TextStyle(
color: textSwatch.shade600,
fontFamily: 'Nunito',
),
titleSmall: TextStyle(
color: textSwatch.shade500,
fontFamily: 'Nunito',
),
bodyLarge: TextStyle(
color: textSwatch.shade700,
fontFamily: 'Nunito',
),
bodyMedium: TextStyle(
color: textSwatch.shade600,
fontFamily: 'Nunito',
),
bodySmall: TextStyle(
color: textSwatch.shade500,
fontFamily: 'Nunito',
),
labelLarge: TextStyle(
color: textSwatch.shade700,
fontFamily: 'Nunito',
),
labelMedium: TextStyle(
color: textSwatch.shade600,
fontFamily: 'Nunito',
),
labelSmall: TextStyle(
color: textSwatch.shade500,
fontFamily: 'Nunito',
),
),
);
final ThemeData darkTheme = lightTheme.copyWith(
colorScheme: darkColorScheme,
textTheme: TextTheme(
displayLarge: TextStyle(
color: textSwatch.shade200,
fontFamily: 'Nunito',
),
displayMedium: TextStyle(
color: textSwatch.shade300,
fontFamily: 'Nunito',
),
displaySmall: TextStyle(
color: textSwatch.shade400,
fontFamily: 'Nunito',
),
headlineLarge: TextStyle(
color: textSwatch.shade200,
fontFamily: 'Nunito',
),
headlineMedium: TextStyle(
color: textSwatch.shade300,
fontFamily: 'Nunito',
),
headlineSmall: TextStyle(
color: textSwatch.shade400,
fontFamily: 'Nunito',
),
titleLarge: TextStyle(
color: textSwatch.shade200,
fontFamily: 'Nunito',
),
titleMedium: TextStyle(
color: textSwatch.shade300,
fontFamily: 'Nunito',
),
titleSmall: TextStyle(
color: textSwatch.shade400,
fontFamily: 'Nunito',
),
bodyLarge: TextStyle(
color: textSwatch.shade200,
fontFamily: 'Nunito',
),
bodyMedium: TextStyle(
color: textSwatch.shade300,
fontFamily: 'Nunito',
),
bodySmall: TextStyle(
color: textSwatch.shade400,
fontFamily: 'Nunito',
),
labelLarge: TextStyle(
color: textSwatch.shade200,
fontFamily: 'Nunito',
),
labelMedium: TextStyle(
color: textSwatch.shade300,
fontFamily: 'Nunito',
),
labelSmall: TextStyle(
color: textSwatch.shade400,
fontFamily: 'Nunito',
),
),
);
final ThemeData appTheme = darkTheme;
import 'package:hydrated_bloc/hydrated_bloc.dart';
import 'package:minehunter/config/menu.dart';
class BottomNavCubit extends HydratedCubit<int> {
BottomNavCubit() : super(0);
void updateIndex(int index) {
if (isIndexAllowed(index)) {
emit(index);
} else {
goToHomePage();
}
}
bool isIndexAllowed(int index) {
return (index >= 0) && (index < Menu.itemsCount);
}
void goToHomePage() => emit(0);
@override
int fromJson(Map<String, dynamic> json) {
return 0;
}
@override
Map<String, dynamic>? toJson(int state) {
return <String, int>{'pageIndex': state};
}
}
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:hydrated_bloc/hydrated_bloc.dart';
part 'theme_state.dart';
class ThemeCubit extends HydratedCubit<ThemeModeState> {
ThemeCubit() : super(const ThemeModeState());
void getTheme(ThemeModeState state) {
emit(state);
}
@override
ThemeModeState? fromJson(Map<String, dynamic> json) {
switch (json['themeMode']) {
case 'ThemeMode.dark':
return const ThemeModeState(themeMode: ThemeMode.dark);
case 'ThemeMode.light':
return const ThemeModeState(themeMode: ThemeMode.light);
case 'ThemeMode.system':
default:
return const ThemeModeState(themeMode: ThemeMode.system);
}
}
@override
Map<String, String>? toJson(ThemeModeState state) {
return <String, String>{'themeMode': state.themeMode.toString()};
}
}
part of 'theme_cubit.dart';
@immutable
class ThemeModeState extends Equatable {
const ThemeModeState({
this.themeMode,
});
final ThemeMode? themeMode;
@override
List<Object?> get props => <Object?>[
themeMode,
];
}
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:minehunter/provider/data.dart'; import 'package:minehunter/provider/data.dart';
import 'package:minehunter/utils/board_animate.dart'; import 'package:minehunter/utils/board_animate.dart';
import 'package:minehunter/utils/board_utils.dart'; import 'package:minehunter/utils/board_utils.dart';
...@@ -43,7 +42,7 @@ class Cell { ...@@ -43,7 +42,7 @@ class Cell {
onTap: () { onTap: () {
// Set mines on board after first player try // Set mines on board after first player try
if (!myProvider.isBoardMined) { if (!myProvider.isBoardMined) {
myProvider.updateCells(BoardUtils.createBoard(myProvider, row, col)); myProvider.updateBoard(BoardUtils.createBoard(myProvider, row, col));
myProvider.updateIsBoardMined(true); myProvider.updateIsBoardMined(true);
} }
......
import 'package:flutter/material.dart';
import 'package:minehunter/entities/cell.dart';
import 'package:minehunter/provider/data.dart';
class Board {
static Container buildGameBoard(Data myProvider) {
return Container(
margin: const EdgeInsets.all(2),
padding: const EdgeInsets.all(2),
child: Column(
children: [
buildGameTileset(myProvider),
],
),
);
}
static Widget buildGameTileset(Data myProvider) {
List<List<Cell>> cells = myProvider.cells;
Color borderColor = myProvider.reportMode ? Colors.blue : Colors.black;
return Container(
decoration: BoxDecoration(
color: borderColor,
borderRadius: BorderRadius.circular(2),
border: Border.all(
color: borderColor,
width: 2,
),
),
child: Table(
defaultColumnWidth: const IntrinsicColumnWidth(),
children: [
for (int row = 0; row < myProvider.sizeVertical; row++)
TableRow(
children: [
for (int col = 0; col < myProvider.sizeHorizontal; col++)
Column(
children: [
cells[row][col].widget(myProvider, row, col),
],
),
],
),
],
),
);
}
static TextButton buildWalkIndicator(Data myProvider) {
String reportModeSuffix = myProvider.reportMode ? 'off' : 'on';
return TextButton(
child: Image(
image: AssetImage(
'assets/skins/${myProvider.parameterSkin}_indicator_walk_$reportModeSuffix.png'),
fit: BoxFit.fill,
),
onPressed: () => myProvider.updateReportMode(false),
);
}
static TextButton buildReportIndicator(Data myProvider) {
String reportModeSuffix = myProvider.reportMode ? 'on' : 'off';
return TextButton(
child: Image(
image: AssetImage(
'assets/skins/${myProvider.parameterSkin}_indicator_report_$reportModeSuffix.png'),
fit: BoxFit.fill,
),
onPressed: () => myProvider.updateReportMode(true),
);
}
static TextButton buildToggleFlagModeButton(Data myProvider) {
String reportModeSuffix = myProvider.reportMode ? 'on' : 'off';
return TextButton(
child: Image(
image: AssetImage(
'assets/skins/${myProvider.parameterSkin}_button_mark_mine_$reportModeSuffix.png'),
fit: BoxFit.fill,
),
onPressed: () => myProvider.updateReportMode(!myProvider.reportMode),
);
}
static Widget buildToggleFlagModeLayout(Data myProvider) {
Image paddingBlock = Image(
image: AssetImage('assets/skins/${myProvider.parameterSkin}_empty.png'),
fit: BoxFit.fill,
);
return Table(
defaultColumnWidth: const IntrinsicColumnWidth(),
children: [
TableRow(
children: [
TableCell(child: paddingBlock),
TableCell(child: buildWalkIndicator(myProvider)),
TableCell(child: buildToggleFlagModeButton(myProvider)),
TableCell(child: buildReportIndicator(myProvider)),
TableCell(child: paddingBlock),
],
),
],
);
}
}
import 'dart:io';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:provider/provider.dart'; import 'package:hive/hive.dart';
import 'package:hydrated_bloc/hydrated_bloc.dart';
import 'package:overlay_support/overlay_support.dart'; import 'package:overlay_support/overlay_support.dart';
import 'package:path_provider/path_provider.dart';
import 'package:provider/provider.dart';
import 'package:minehunter/config/theme.dart';
import 'package:minehunter/cubit/bottom_nav_cubit.dart';
import 'package:minehunter/cubit/theme_cubit.dart';
import 'package:minehunter/provider/data.dart'; import 'package:minehunter/provider/data.dart';
import 'package:minehunter/screens/home.dart'; import 'package:minehunter/ui/skeleton.dart';
void main() { void main() async {
/// Initialize packages
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]) await EasyLocalization.ensureInitialized();
.then((value) => runApp(const MyApp())); final Directory tmpDir = await getTemporaryDirectory();
Hive.init(tmpDir.toString());
HydratedBloc.storage = await HydratedStorage.build(
storageDirectory: tmpDir,
);
runApp(
EasyLocalization(
path: 'assets/translations',
supportedLocales: const <Locale>[
Locale('en'),
Locale('fr'),
],
fallbackLocale: const Locale('en'),
useFallbackTranslations: true,
child: const MyApp(),
),
);
} }
class MyApp extends StatelessWidget { class MyApp extends StatelessWidget {
...@@ -17,19 +44,34 @@ class MyApp extends StatelessWidget { ...@@ -17,19 +44,34 @@ class MyApp extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider<BottomNavCubit>(create: (context) => BottomNavCubit()),
BlocProvider<ThemeCubit>(create: (context) => ThemeCubit()),
],
child: BlocBuilder<ThemeCubit, ThemeModeState>(
builder: (BuildContext context, ThemeModeState state) {
return ChangeNotifierProvider( return ChangeNotifierProvider(
create: (BuildContext context) => Data(), create: (BuildContext context) => Data(),
child: Consumer<Data>(builder: (context, data, child) { child: Consumer<Data>(
builder: (context, data, child) {
return OverlaySupport( return OverlaySupport(
child: MaterialApp( child: MaterialApp(
title: 'Minehunter',
home: const SkeletonScreen(),
// Theme stuff
theme: lightTheme,
darkTheme: darkTheme,
themeMode: state.themeMode,
// Localization stuff
localizationsDelegates: context.localizationDelegates,
supportedLocales: context.supportedLocales,
locale: context.locale,
debugShowCheckedModeBanner: false, debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
), ),
home: const Home(), );
routes: {
Home.id: (context) => const Home(),
}, },
), ),
); );
......
...@@ -4,6 +4,10 @@ import 'package:flutter/foundation.dart'; ...@@ -4,6 +4,10 @@ import 'package:flutter/foundation.dart';
import 'package:minehunter/entities/cell.dart'; import 'package:minehunter/entities/cell.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
typedef Board = List<List<Cell>>;
typedef AnimatedBoard = List<List<bool>>;
typedef AnimatedBoardSequence = List<AnimatedBoard>;
class Data extends ChangeNotifier { class Data extends ChangeNotifier {
// Configuration available parameters // Configuration available parameters
final List<String> _availableParameters = ['level', 'size', 'skin']; final List<String> _availableParameters = ['level', 'size', 'skin'];
...@@ -37,7 +41,7 @@ class Data extends ChangeNotifier { ...@@ -37,7 +41,7 @@ class Data extends ChangeNotifier {
bool _animationInProgress = false; bool _animationInProgress = false;
int _sizeVertical = 0; int _sizeVertical = 0;
int _sizeHorizontal = 0; int _sizeHorizontal = 0;
List<List<Cell>> _cells = []; Board _board = [];
bool _isBoardMined = false; bool _isBoardMined = false;
int _minesCount = 0; int _minesCount = 0;
bool _reportMode = false; bool _reportMode = false;
...@@ -136,13 +140,13 @@ class Data extends ChangeNotifier { ...@@ -136,13 +140,13 @@ class Data extends ChangeNotifier {
String computeCurrentGameState() { String computeCurrentGameState() {
String cellsValues = ''; String cellsValues = '';
for (int rowIndex = 0; rowIndex < _cells.length; rowIndex++) { for (int rowIndex = 0; rowIndex < _board.length; rowIndex++) {
for (int colIndex = 0; colIndex < _cells[rowIndex].length; colIndex++) { for (int colIndex = 0; colIndex < _board[rowIndex].length; colIndex++) {
cellsValues += _cells[rowIndex][colIndex].isMined ? 'X' : ' '; cellsValues += _board[rowIndex][colIndex].isMined ? 'X' : ' ';
cellsValues += _cells[rowIndex][colIndex].isExplored ? 'E' : ' '; cellsValues += _board[rowIndex][colIndex].isExplored ? 'E' : ' ';
cellsValues += _cells[rowIndex][colIndex].isMarked ? 'P' : ' '; cellsValues += _board[rowIndex][colIndex].isMarked ? 'P' : ' ';
cellsValues += _cells[rowIndex][colIndex].isExploded ? '*' : ' '; cellsValues += _board[rowIndex][colIndex].isExploded ? '*' : ' ';
cellsValues += _cells[rowIndex][colIndex].minesCountAround.toString(); cellsValues += _board[rowIndex][colIndex].minesCountAround.toString();
cellsValues += ';'; cellsValues += ';';
} }
} }
...@@ -216,17 +220,17 @@ class Data extends ChangeNotifier { ...@@ -216,17 +220,17 @@ class Data extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
List<List<Cell>> get cells => _cells; Board get board => _board;
void updateCells(List<List<Cell>> cells) { void updateBoard(Board board) {
_cells = cells; _board = board;
notifyListeners(); notifyListeners();
} }
void setCellAsExplored(int row, int col) { void setCellAsExplored(int row, int col) {
_cells[row][col].isExplored = true; _board[row][col].isExplored = true;
_cells[row][col].isMarked = false; _board[row][col].isMarked = false;
if (_cells[row][col].isMined) { if (_board[row][col].isMined) {
_cells[row][col].isExploded = true; _board[row][col].isExploded = true;
} }
saveCurrentGameState(); saveCurrentGameState();
...@@ -234,7 +238,7 @@ class Data extends ChangeNotifier { ...@@ -234,7 +238,7 @@ class Data extends ChangeNotifier {
} }
void toggleCellMark(int row, int col) { void toggleCellMark(int row, int col) {
_cells[row][col].isMarked = !_cells[row][col].isMarked; _board[row][col].isMarked = !_board[row][col].isMarked;
saveCurrentGameState(); saveCurrentGameState();
notifyListeners(); notifyListeners();
...@@ -271,7 +275,7 @@ class Data extends ChangeNotifier { ...@@ -271,7 +275,7 @@ class Data extends ChangeNotifier {
void setAnimatedBackground(List animatedCellsPattern) { void setAnimatedBackground(List animatedCellsPattern) {
for (int row = 0; row < _sizeVertical; row++) { for (int row = 0; row < _sizeVertical; row++) {
for (int col = 0; col < _sizeHorizontal; col++) { for (int col = 0; col < _sizeHorizontal; col++) {
_cells[row][col].isAnimated = animatedCellsPattern[row][col]; _board[row][col].isAnimated = animatedCellsPattern[row][col];
} }
} }
notifyListeners(); notifyListeners();
...@@ -280,7 +284,7 @@ class Data extends ChangeNotifier { ...@@ -280,7 +284,7 @@ class Data extends ChangeNotifier {
void resetAnimatedBackground() { void resetAnimatedBackground() {
for (int row = 0; row < _sizeVertical; row++) { for (int row = 0; row < _sizeVertical; row++) {
for (int col = 0; col < _sizeHorizontal; col++) { for (int col = 0; col < _sizeHorizontal; col++) {
_cells[row][col].isAnimated = false; _board[row][col].isAnimated = false;
} }
} }
} }
......
import 'package:flutter/material.dart';
import 'package:minehunter/provider/data.dart';
import 'package:minehunter/ui/layout/tileset.dart';
import 'package:minehunter/ui/widgets/game/indicator_top.dart';
import 'package:minehunter/ui/widgets/game/message_game_end.dart';
import 'package:minehunter/ui/widgets/game/mode_toggle.dart';
class Game extends StatelessWidget {
const Game({super.key, required this.myProvider});
final Data myProvider;
@override
Widget build(BuildContext context) {
final bool gameIsFinished = myProvider.gameWin || myProvider.gameFail;
return Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox(height: 8),
TopIndicator(myProvider: myProvider),
const SizedBox(height: 2),
Expanded(
child: Tileset(myProvider: myProvider),
),
const SizedBox(height: 2),
Container(
child: gameIsFinished
? EndGameMessage(myProvider: myProvider)
: ToggleGameMode(myProvider: myProvider),
),
const SizedBox(height: 8),
],
);
}
}
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:minehunter/provider/data.dart'; import 'package:minehunter/provider/data.dart';
import 'package:minehunter/utils/game_utils.dart'; import 'package:minehunter/ui/widgets/home/button_game_resume.dart';
import 'package:minehunter/ui/widgets/home/button_game_start_new.dart';
class Parameters {
static double separatorHeight = 2.0; class Parameters extends StatelessWidget {
static double blockMargin = 3.0; const Parameters({super.key, required this.myProvider});
static double blockPadding = 2.0;
static Color buttonBackgroundColor = Colors.white; final Data myProvider;
static Color buttonBorderColorActive = Colors.blue;
static Color buttonBorderColorInactive = Colors.white; static const double separatorHeight = 2.0;
static double buttonBorderWidth = 10.0; static const double blockMargin = 3.0;
static double buttonBorderRadius = 8.0; static const double blockPadding = 2.0;
static double buttonPadding = 0.0; static const Color buttonBackgroundColor = Colors.white;
static double buttonMargin = 0.0; static const Color buttonBorderColorActive = Colors.blue;
static const Color buttonBorderColorInactive = Colors.white;
static Widget buildParametersSelector(Data myProvider) { static const double buttonBorderWidth = 10.0;
static const double buttonBorderRadius = 8.0;
static const double buttonPadding = 0.0;
static const double buttonMargin = 0.0;
@override
Widget build(BuildContext context) {
List<Widget> lines = []; List<Widget> lines = [];
List<String> parameters = myProvider.availableParameters; final List<String> parameters = myProvider.availableParameters;
for (int index = 0; index < parameters.length; index++) { for (int index = 0; index < parameters.length; index++) {
lines.add(buildParameterSelector(myProvider, parameters[index])); lines.add(buildParameterSelector(myProvider, parameters[index]));
lines.add(SizedBox(height: separatorHeight)); lines.add(const SizedBox(height: separatorHeight));
} }
myProvider.loadCurrentSavedState(); myProvider.loadCurrentSavedState();
Widget buttonsBlock = myProvider.hasCurrentSavedState() Widget buttonsBlock = myProvider.hasCurrentSavedState()
? buildResumeGameButton(myProvider) ? ResumeGameButton(myProvider: myProvider)
: buildStartNewGameButton(myProvider); : StartNewGameButton(myProvider: myProvider);
return Column( return Column(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
SizedBox(height: separatorHeight), const SizedBox(height: separatorHeight),
Expanded( Expanded(
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
...@@ -41,7 +47,7 @@ class Parameters { ...@@ -41,7 +47,7 @@ class Parameters {
children: lines, children: lines,
), ),
), ),
SizedBox(height: separatorHeight), const SizedBox(height: separatorHeight),
Container( Container(
child: buttonsBlock, child: buttonsBlock,
), ),
...@@ -56,7 +62,7 @@ class Parameters { ...@@ -56,7 +62,7 @@ class Parameters {
); );
} }
static Widget buildImageContainerWidget(String imageAssetCode) { static Container buildImageContainerWidget(String imageAssetCode) {
return Container( return Container(
child: buildImageWidget(imageAssetCode), child: buildImageWidget(imageAssetCode),
); );
...@@ -73,67 +79,8 @@ class Parameters { ...@@ -73,67 +79,8 @@ class Parameters {
); );
} }
static Widget buildStartNewGameButton(Data myProvider) { Widget buildParameterSelector(Data myProvider, String parameterCode) {
return Container( final List<String> availableValues = myProvider.getParameterAvailableValues(parameterCode);
margin: EdgeInsets.all(blockMargin),
padding: EdgeInsets.all(blockPadding),
child: Table(
defaultColumnWidth: const IntrinsicColumnWidth(),
children: [
TableRow(
children: [
buildDecorationImageWidget(),
Column(
children: [
TextButton(
child: buildImageContainerWidget('button_start'),
onPressed: () => GameUtils.startNewGame(myProvider),
),
],
),
buildDecorationImageWidget(),
],
),
],
),
);
}
static Widget buildResumeGameButton(Data myProvider) {
return Container(
margin: EdgeInsets.all(blockMargin),
padding: EdgeInsets.all(blockPadding),
child: Table(
defaultColumnWidth: const IntrinsicColumnWidth(),
children: [
TableRow(
children: [
Column(
children: [
TextButton(
child: buildImageContainerWidget('button_delete_saved_game'),
onPressed: () => GameUtils.deleteSavedGame(myProvider),
),
],
),
Column(
children: [
TextButton(
child: buildImageContainerWidget('button_resume_game'),
onPressed: () => GameUtils.resumeSavedGame(myProvider),
),
],
),
buildDecorationImageWidget(),
],
),
],
),
);
}
static Widget buildParameterSelector(Data myProvider, String parameterCode) {
List<String> availableValues = myProvider.getParameterAvailableValues(parameterCode);
if (availableValues.length == 1) { if (availableValues.length == 1) {
return const SizedBox(height: 0.0); return const SizedBox(height: 0.0);
...@@ -147,7 +94,7 @@ class Parameters { ...@@ -147,7 +94,7 @@ class Parameters {
for (int index = 0; index < availableValues.length; index++) for (int index = 0; index < availableValues.length; index++)
Column( Column(
children: [ children: [
_buildParameterButton(myProvider, parameterCode, availableValues[index]) buildParameterButton(myProvider, parameterCode, availableValues[index])
], ],
), ),
], ],
...@@ -156,17 +103,16 @@ class Parameters { ...@@ -156,17 +103,16 @@ class Parameters {
); );
} }
static Widget _buildParameterButton( Widget buildParameterButton(Data myProvider, String parameterCode, String parameterValue) {
Data myProvider, String parameterCode, String parameterValue) { final String currentValue = myProvider.getParameterValue(parameterCode).toString();
String currentValue = myProvider.getParameterValue(parameterCode).toString();
bool isActive = (parameterValue == currentValue); final bool isActive = (parameterValue == currentValue);
String imageAsset = '${parameterCode}_$parameterValue'; final String imageAsset = '${parameterCode}_$parameterValue';
return TextButton( return TextButton(
child: Container( child: Container(
margin: EdgeInsets.all(buttonMargin), margin: const EdgeInsets.all(buttonMargin),
padding: EdgeInsets.all(buttonPadding), padding: const EdgeInsets.all(buttonPadding),
decoration: BoxDecoration( decoration: BoxDecoration(
color: buttonBackgroundColor, color: buttonBackgroundColor,
borderRadius: BorderRadius.circular(buttonBorderRadius), borderRadius: BorderRadius.circular(buttonBorderRadius),
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment