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

Merge branch '47-add-draw-board-game' into 'master'

Resolve "Add draw board game"

Closes #47

See merge request !46
parents 8de3f0ea 149a5dbb
No related branches found
No related tags found
1 merge request!46Resolve "Add draw board game"
Pipeline #4874 passed
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true
app.versionName=1.0.37
app.versionCode=38
app.versionName=1.0.38
app.versionCode=39
......@@ -4,6 +4,7 @@
"bottom_nav_sample": "Sample",
"bottom_nav_api": "API",
"bottom_nav_chart": "Graph",
"bottom_nav_game": "Game",
"bottom_nav_settings": "Settings",
"bottom_nav_about": "About",
......
......@@ -4,6 +4,7 @@
"bottom_nav_sample": "Démo",
"bottom_nav_api": "API",
"bottom_nav_chart": "Graph",
"bottom_nav_game": "Jeu",
"bottom_nav_settings": "Paramètres",
"bottom_nav_about": "À propos",
......
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:hydrated_bloc/hydrated_bloc.dart';
import 'package:random/models/game_data.dart';
part 'game_state.dart';
class GameCubit extends HydratedCubit<GameState> {
GameCubit() : super(const GameState());
void getData(GameState state) {
emit(state);
}
void updateGameState(GameData game) {
emit(GameState(game: game));
}
@override
GameState? fromJson(Map<String, dynamic> json) {
GameData game = json['game'] as GameData;
return GameState(
game: game,
);
}
@override
Map<String, dynamic>? toJson(GameState state) {
return <String, dynamic>{
'game': state.game?.toJson(),
};
}
}
part of 'game_cubit.dart';
@immutable
class GameState extends Equatable {
const GameState({
this.game,
});
final GameData? game;
@override
List<Object?> get props => <Object?>[
game,
];
}
......@@ -10,6 +10,7 @@ import 'package:path_provider/path_provider.dart';
import 'package:random/config/theme.dart';
import 'package:random/cubit/bottom_nav_cubit.dart';
import 'package:random/cubit/data_cubit.dart';
import 'package:random/cubit/game_cubit.dart';
import 'package:random/cubit/settings_cubit.dart';
import 'package:random/cubit/api_cubit.dart';
import 'package:random/repository/api.dart';
......@@ -50,6 +51,7 @@ class MyApp extends StatelessWidget {
BlocProvider<SettingsCubit>(create: (context) => SettingsCubit()),
BlocProvider<BottomNavCubit>(create: (context) => BottomNavCubit()),
BlocProvider<DataCubit>(create: (context) => DataCubit()),
BlocProvider<GameCubit>(create: (context) => GameCubit()),
BlocProvider<ApiDataCubit>(
create: (context) => ApiDataCubit(
apiRepository: ApiRepository(
......
import 'dart:convert';
import 'dart:math';
class GameDataItem {
final int value;
const GameDataItem({
required this.value,
});
factory GameDataItem.fromJson(Map<String, dynamic>? json) {
return GameDataItem(
value: (json?['value'] != null) ? (json?['value'] as int) : 0,
);
}
Map<String, dynamic>? toJson() {
return <String, dynamic>{
'value': this.value,
};
}
String toString() {
return jsonEncode(this.toJson());
}
}
class GameData {
final int boardSize;
final List<List<GameDataItem>> board;
const GameData({
required this.boardSize,
required this.board,
});
factory GameData.createNew(int boardSize) {
final List<List<GameDataItem>> cells = [];
for (var y = 0; y < boardSize; y++) {
final List<GameDataItem> line = [];
for (var x = 0; x < boardSize; x++) {
final GameDataItem item = new GameDataItem(value: 0);
line.add(item);
}
cells.add(line);
}
return GameData(
boardSize: boardSize,
board: cells,
);
}
factory GameData.createRandom(int boardSize) {
const allowedValues = [0, 1, 2, 3, 4, 5];
final allowedValuesSize = allowedValues.length;
final List<List<GameDataItem>> cells = [];
for (var y = 0; y < boardSize; y++) {
final List<GameDataItem> line = [];
for (var x = 0; x < boardSize; x++) {
final value = allowedValues[Random().nextInt(allowedValuesSize)];
final GameDataItem item = new GameDataItem(value: value);
line.add(item);
}
cells.add(line);
}
return GameData(
boardSize: boardSize,
board: cells,
);
}
factory GameData.fromJson(Map<String, dynamic>? json) {
return GameData(
boardSize: (json?['boardSize'] != null) ? (json?['boardSize'] as int) : 0,
board: (json?['board'] != null) ? (json?['board'] as List<List<GameDataItem>>) : [],
);
}
Map<String, dynamic>? toJson() {
return <String, dynamic>{
'boardSize': this.boardSize,
'board': this.board,
};
}
String toString() {
return jsonEncode(this.toJson());
}
}
import 'package:flutter/material.dart';
import 'package:random/config/app_colors.dart';
class CellPainter extends CustomPainter {
const CellPainter({required this.value});
final int value;
Color getIndexedColor(int index) {
const List<Color> availableColors = [
AppColors.contentColorCyan,
AppColors.contentColorGreen,
AppColors.contentColorOrange,
AppColors.contentColorPurple,
AppColors.contentColorYellow,
AppColors.contentColorPink,
AppColors.contentColorWhite,
AppColors.mainTextColor3,
];
return availableColors[index % availableColors.length];
}
@override
void paint(Canvas canvas, Size size) {
final paintBackground = Paint();
paintBackground.color = getIndexedColor(value);
paintBackground.style = PaintingStyle.fill;
final Rect rectBackground = Rect.fromPoints(Offset(0, 0), Offset(size.width, size.height));
canvas.drawRect(rectBackground, paintBackground);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return false;
}
}
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:random/cubit/game_cubit.dart';
import 'package:random/models/game_data.dart';
import 'package:random/ui/widgets/game_board.dart';
import 'package:unicons/unicons.dart';
class GamePage extends StatefulWidget {
const GamePage({super.key});
@override
State<GamePage> createState() => _GamePageState();
}
class _GamePageState extends State<GamePage> {
@override
Widget build(BuildContext context) {
return BlocBuilder<GameCubit, GameState>(
builder: (context, gameState) {
return Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
gameState.game != null
? Container(
margin: EdgeInsets.all(4),
padding: EdgeInsets.all(4),
child: GameBoardWidget(
gameData: gameState.game!,
),
)
: SizedBox.shrink(),
IconButton(
onPressed: () {
const boardSize = 6;
final GameData newGame = GameData.createRandom(boardSize);
BlocProvider.of<GameCubit>(context).updateGameState(newGame);
print(gameState);
},
icon: Icon(UniconsSolid.star),
color: Colors.white,
),
],
);
},
);
}
}
......@@ -6,6 +6,7 @@ import 'package:random/cubit/bottom_nav_cubit.dart';
import 'package:random/ui/screens/about_page.dart';
import 'package:random/ui/screens/api_page.dart';
import 'package:random/ui/screens/demo_page.dart';
import 'package:random/ui/screens/game_page.dart';
import 'package:random/ui/screens/graph_page.dart';
import 'package:random/ui/screens/settings_page.dart';
import 'package:random/ui/widgets/app_bar.dart';
......@@ -25,6 +26,7 @@ class _SkeletonScreenState extends State<SkeletonScreen> {
DemoPage(),
ApiPage(),
GraphPage(),
GamePage(),
SettingsPage(),
AboutPage(),
];
......
......@@ -54,6 +54,10 @@ class BottomNavBar extends StatelessWidget {
icon: const Icon(UniconsLine.pen),
label: tr('bottom_nav_chart'),
),
BottomNavigationBarItem(
icon: const Icon(UniconsLine.star),
label: tr('bottom_nav_game'),
),
BottomNavigationBarItem(
icon: const Icon(UniconsLine.setting),
label: tr('bottom_nav_settings'),
......
import 'package:flutter/material.dart';
import 'package:random/models/game_data.dart';
import 'package:random/ui/painters/cell_painter.dart';
class GameBoardWidget extends StatelessWidget {
const GameBoardWidget({super.key, required this.gameData});
final GameData gameData;
@override
Widget build(BuildContext context) {
const staticBoardWidth = 300;
const staticBoardHeight = 300;
final rowsCount = this.gameData.board.length;
final columnsCount = this.gameData.board[0].length;
print('counts: rows=' + rowsCount.toString() + ' / columns=' + columnsCount.toString());
final cellWidth = staticBoardWidth / columnsCount;
final cellHeight = staticBoardHeight / rowsCount;
print('cell: width=' + cellWidth.toString() + ' / height=' + cellHeight.toString());
final List<Widget> cells = [];
for (var y = 0; y < rowsCount; y++) {
for (var x = 0; x < columnsCount; x++) {
final GameDataItem item = this.gameData.board[y][x];
final Widget cellContent = CustomPaint(
size: Size(cellWidth, cellHeight),
willChange: false,
painter: CellPainter(value: item.value),
);
final Widget widget = Positioned(
left: (x * cellWidth).toDouble(),
top: (y * cellHeight).toDouble(),
child: Container(
width: cellWidth,
height: cellHeight,
color: Colors.deepPurpleAccent,
child: cellContent,
),
);
cells.add(widget);
}
}
return Container(
width: staticBoardWidth.toDouble(),
height: staticBoardHeight.toDouble(),
color: Colors.grey,
child: Stack(
children: cells,
),
);
}
}
......@@ -3,7 +3,7 @@ description: A random application, for testing purpose only.
publish_to: 'none'
version: 1.0.37+38
version: 1.0.38+39
environment:
sdk: '^3.0.0'
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment