diff --git a/android/gradle.properties b/android/gradle.properties index cd511d2125450a944f1e2bd7839e9059a09ccdaa..d96c32178c38990e00612de2cd3fa50f85d88126 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,5 +1,5 @@ org.gradle.jvmargs=-Xmx1536M android.useAndroidX=true android.enableJetifier=true -app.versionName=1.0.38 -app.versionCode=39 +app.versionName=1.0.39 +app.versionCode=40 diff --git a/lib/cubit/game_cubit.dart b/lib/cubit/game_cubit.dart index 90146ddbee91b6248621d91e9f72bdec8b822329..231ed500fe9439775ae1ed1a07336c481052ba30 100644 --- a/lib/cubit/game_cubit.dart +++ b/lib/cubit/game_cubit.dart @@ -8,12 +8,12 @@ part 'game_state.dart'; class GameCubit extends HydratedCubit<GameState> { GameCubit() : super(const GameState()); - void getData(GameState state) { - emit(state); + void getData(GameState gameState) { + emit(gameState); } - void updateGameState(GameData game) { - emit(GameState(game: game)); + void updateGameState(GameData gameData) { + emit(GameState(game: gameData)); } @override diff --git a/lib/ui/painters/cell_painter.dart b/lib/ui/painters/cell_painter.dart index 26ee97ddb41f0715a238a49196c97e72f2865d09..b67c76edde50c7dce6b39e50479660ddff90dccf 100644 --- a/lib/ui/painters/cell_painter.dart +++ b/lib/ui/painters/cell_painter.dart @@ -1,6 +1,9 @@ +import 'dart:ui' as ui; + import 'package:flutter/material.dart'; import 'package:random/config/app_colors.dart'; +import 'package:random/utils/color_extensions.dart'; class CellPainter extends CustomPainter { const CellPainter({required this.value}); @@ -24,12 +27,33 @@ class CellPainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { - final paintBackground = Paint(); - paintBackground.color = getIndexedColor(value); - paintBackground.style = PaintingStyle.fill; + final baseColor = getIndexedColor(value); + + const borderWidth = 0.05; + + final Rect baseSquare = Rect.fromPoints(Offset(0, 0), Offset(size.width, size.height)); + + final paintBaseSquare = Paint() + ..style = PaintingStyle.fill + ..color = baseColor.darken(40); + + canvas.drawRect(baseSquare, paintBaseSquare); + + final Rect innerGradientBackground = Rect.fromPoints( + Offset(size.width * borderWidth, size.height * borderWidth), + Offset(size.width * (1 - borderWidth), size.height * (1 - borderWidth))); + + final paintInnerBackground = Paint() + ..shader = ui.Gradient.linear( + baseSquare.topCenter, + baseSquare.bottomCenter, + [ + baseColor.lighten(10), + baseColor.darken(20), + ], + ); - final Rect rectBackground = Rect.fromPoints(Offset(0, 0), Offset(size.width, size.height)); - canvas.drawRect(rectBackground, paintBackground); + canvas.drawRect(innerGradientBackground, paintInnerBackground); } @override diff --git a/lib/ui/screens/game_page.dart b/lib/ui/screens/game_page.dart index 8ccb67fd641d663dd02f016515e98d0ece89e3a3..faf19a310679b1e6c2b783a7832fa8f3740d9792 100644 --- a/lib/ui/screens/game_page.dart +++ b/lib/ui/screens/game_page.dart @@ -1,10 +1,10 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:unicons/unicons.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}); @@ -13,31 +13,35 @@ class GamePage extends StatefulWidget { State<GamePage> createState() => _GamePageState(); } +void createNewGame(GameCubit gameCubit, int boardSize) { + final GameData newGame = GameData.createRandom(boardSize); + gameCubit.updateGameState(newGame); +} + class _GamePageState extends State<GamePage> { @override Widget build(BuildContext context) { return BlocBuilder<GameCubit, GameState>( builder: (context, gameState) { + const boardSize = 6; + const double boardWidgetWidth = 300; + const double boardWidgetHeight = 300; + + final GameCubit gameCubit = BlocProvider.of<GameCubit>(context); + 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!, - ), + ? GameBoardWidget( + gameData: gameState.game!, + size: Size(boardWidgetWidth, boardWidgetHeight), ) : SizedBox.shrink(), IconButton( onPressed: () { - const boardSize = 6; - - final GameData newGame = GameData.createRandom(boardSize); - BlocProvider.of<GameCubit>(context).updateGameState(newGame); - print(gameState); + createNewGame(gameCubit, boardSize); }, icon: Icon(UniconsSolid.star), color: Colors.white, diff --git a/lib/ui/widgets/game_board.dart b/lib/ui/widgets/game_board.dart index 427ff46ce0685cf3e506889ebd010065af6a9c0a..30581d81eeac54524d089ba2830868182a30521b 100644 --- a/lib/ui/widgets/game_board.dart +++ b/lib/ui/widgets/game_board.dart @@ -3,29 +3,39 @@ 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}); +class GameBoardWidget extends StatefulWidget { + const GameBoardWidget({ + super.key, + required this.gameData, + required this.size, + }); final GameData gameData; + final Size size; + @override + State<GameBoardWidget> createState() => _GameBoardWidgetState(); +} + +class _GameBoardWidgetState extends State<GameBoardWidget> { @override Widget build(BuildContext context) { - const staticBoardWidth = 300; - const staticBoardHeight = 300; + final widgetWidth = widget.size.width; + final widgetHeight = widget.size.height; - final rowsCount = this.gameData.board.length; - final columnsCount = this.gameData.board[0].length; + final rowsCount = widget.gameData.board.length; + final columnsCount = widget.gameData.board[0].length; print('counts: rows=' + rowsCount.toString() + ' / columns=' + columnsCount.toString()); - final cellWidth = staticBoardWidth / columnsCount; - final cellHeight = staticBoardHeight / rowsCount; + final cellWidth = widgetWidth / columnsCount; + final cellHeight = widgetHeight / 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 GameDataItem item = widget.gameData.board[y][x]; final Widget cellContent = CustomPaint( size: Size(cellWidth, cellHeight), @@ -33,24 +43,23 @@ class GameBoardWidget extends StatelessWidget { painter: CellPainter(value: item.value), ); - final Widget widget = Positioned( + final Widget cellWidget = Positioned( left: (x * cellWidth).toDouble(), top: (y * cellHeight).toDouble(), child: Container( width: cellWidth, height: cellHeight, - color: Colors.deepPurpleAccent, child: cellContent, ), ); - cells.add(widget); + cells.add(cellWidget); } } return Container( - width: staticBoardWidth.toDouble(), - height: staticBoardHeight.toDouble(), + width: widgetWidth, + height: widgetHeight, color: Colors.grey, child: Stack( children: cells, diff --git a/lib/utils/color_extensions.dart b/lib/utils/color_extensions.dart new file mode 100644 index 0000000000000000000000000000000000000000..4e55e338f0d3ed98b233d1ef887b7b3e17e29d97 --- /dev/null +++ b/lib/utils/color_extensions.dart @@ -0,0 +1,33 @@ +import 'dart:ui'; + +extension ColorExtension on Color { + Color darken([int percent = 40]) { + assert(1 <= percent && percent <= 100); + final value = 1 - percent / 100; + return Color.fromARGB( + alpha, + (red * value).round(), + (green * value).round(), + (blue * value).round(), + ); + } + + Color lighten([int percent = 40]) { + assert(1 <= percent && percent <= 100); + final value = percent / 100; + return Color.fromARGB( + alpha, + (red + ((255 - red) * value)).round(), + (green + ((255 - green) * value)).round(), + (blue + ((255 - blue) * value)).round(), + ); + } + + Color avg(Color other) { + final red = (this.red + other.red) ~/ 2; + final green = (this.green + other.green) ~/ 2; + final blue = (this.blue + other.blue) ~/ 2; + final alpha = (this.alpha + other.alpha) ~/ 2; + return Color.fromARGB(alpha, red, green, blue); + } +} diff --git a/pubspec.yaml b/pubspec.yaml index 5e18bdd7ad704a826e15dbb34241d0ad5be3432f..a0dad971e0249c47f72502fbac5d16fb069f0192 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: A random application, for testing purpose only. publish_to: 'none' -version: 1.0.38+39 +version: 1.0.39+40 environment: sdk: '^3.0.0'