diff --git a/android/gradle.properties b/android/gradle.properties index 135006f9c1386c8757595c43e890e911f732f5a3..85b94f88ee157e1d1b3cec184c8948902443d36f 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=0.0.6 -app.versionCode=6 +app.versionName=0.0.7 +app.versionCode=7 diff --git a/assets/icons/skin_default.png b/assets/icons/skin_default.png deleted file mode 100644 index fbe9cb151a27e54b848f7cd48e397cd308f51dad..0000000000000000000000000000000000000000 Binary files a/assets/icons/skin_default.png and /dev/null differ diff --git a/assets/skins/default_0.png b/assets/skins/default_0.png deleted file mode 100644 index e543c1a9c0a2f38128c5a48437dcb75ceeaa23e2..0000000000000000000000000000000000000000 Binary files a/assets/skins/default_0.png and /dev/null differ diff --git a/assets/skins/default_1.png b/assets/skins/default_1.png deleted file mode 100644 index 50ac7e9dc99ea6cf1e0a0126615e0217ec140023..0000000000000000000000000000000000000000 Binary files a/assets/skins/default_1.png and /dev/null differ diff --git a/assets/skins/default_2.png b/assets/skins/default_2.png deleted file mode 100644 index cca70ea9b7cb61319c79a07d8567ae9707f29a8a..0000000000000000000000000000000000000000 Binary files a/assets/skins/default_2.png and /dev/null differ diff --git a/assets/skins/default_3.png b/assets/skins/default_3.png deleted file mode 100644 index 9e4ccd82edd6dea24e3f73a9794d735a268cc11b..0000000000000000000000000000000000000000 Binary files a/assets/skins/default_3.png and /dev/null differ diff --git a/assets/skins/default_4.png b/assets/skins/default_4.png deleted file mode 100644 index 86a9c87e0459697060a91571714765c0078a1403..0000000000000000000000000000000000000000 Binary files a/assets/skins/default_4.png and /dev/null differ diff --git a/assets/skins/default_5.png b/assets/skins/default_5.png deleted file mode 100644 index 7c4f1cb57586355b4e443d8e6e4d17fc7053f2d1..0000000000000000000000000000000000000000 Binary files a/assets/skins/default_5.png and /dev/null differ diff --git a/assets/skins/default_6.png b/assets/skins/default_6.png deleted file mode 100644 index 4a620e27de46cc9db3742e7d60a5d2e4c8094a4e..0000000000000000000000000000000000000000 Binary files a/assets/skins/default_6.png and /dev/null differ diff --git a/assets/skins/default_7.png b/assets/skins/default_7.png deleted file mode 100644 index 988d6fc485453b4f4c0c5c306809eec93a611718..0000000000000000000000000000000000000000 Binary files a/assets/skins/default_7.png and /dev/null differ diff --git a/assets/skins/default_8.png b/assets/skins/default_8.png deleted file mode 100644 index 1f5cc615ca867c90f0004097308dc83d9ae496df..0000000000000000000000000000000000000000 Binary files a/assets/skins/default_8.png and /dev/null differ diff --git a/fastlane/metadata/android/en-US/changelogs/7.txt b/fastlane/metadata/android/en-US/changelogs/7.txt new file mode 100644 index 0000000000000000000000000000000000000000..69bf9840f104282555abab3614e0af3eb7e082eb --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/7.txt @@ -0,0 +1 @@ +Fully draw board without asset images, improve cells borders diff --git a/fastlane/metadata/android/fr-FR/changelogs/7.txt b/fastlane/metadata/android/fr-FR/changelogs/7.txt new file mode 100644 index 0000000000000000000000000000000000000000..548a09811960dd6c1f78585692139202d9dd260b --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/7.txt @@ -0,0 +1 @@ +Dessine le jeu au lieu d'utiliser des images, amélioration des bordures de cellules diff --git a/icons/build_game_icons.sh b/icons/build_game_icons.sh index b76b62867716279b7a29197581a669474da3f2b4..08f5571f42f74293ef170e2eac8e7cc59f740670 100755 --- a/icons/build_game_icons.sh +++ b/icons/build_game_icons.sh @@ -32,24 +32,6 @@ AVAILABLES_GAME_SETTINGS=" colors:5,6,7,8 " -# Skins -AVAILABLE_SKINS=" - default -" - -# Images per skin -SKIN_IMAGES=" - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 -" - ####################################################### # optimize svg @@ -105,19 +87,6 @@ function build_settings_icons() { done } -function build_icon_for_skin() { - SKIN_CODE="$1" - - # skin main image - build_icon ${CURRENT_DIR}/skin_${SKIN_CODE}.svg ${ASSETS_DIR}/icons/skin_${SKIN_CODE}.png - - # skin images - for SKIN_IMAGE in ${SKIN_IMAGES} - do - build_icon ${CURRENT_DIR}/skins/${SKIN_CODE}/${SKIN_IMAGE}.svg ${ASSETS_DIR}/skins/${SKIN_CODE}_${SKIN_IMAGE}.png - done -} - ####################################################### # Create output folders @@ -139,9 +108,3 @@ for GAME_SETTING in ${AVAILABLES_GAME_SETTINGS} do build_settings_icons "${GAME_SETTING}" done - -# build skins images -for SKIN in ${AVAILABLE_SKINS} -do - build_icon_for_skin "${SKIN}" -done diff --git a/icons/skins/default/0.svg b/icons/skins/default/0.svg deleted file mode 100644 index c55c649001b0dca8cbbafc1642dfbadceee2acda..0000000000000000000000000000000000000000 --- a/icons/skins/default/0.svg +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><rect width="100" height="100" fill="#fff" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width="2.6"/></svg> diff --git a/icons/skins/default/1.svg b/icons/skins/default/1.svg deleted file mode 100644 index 8381dc683edf57b61a76592657048ade871d5d2b..0000000000000000000000000000000000000000 --- a/icons/skins/default/1.svg +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><rect width="100" height="100" fill="#E63A3F" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width="2.6"/></svg> diff --git a/icons/skins/default/2.svg b/icons/skins/default/2.svg deleted file mode 100644 index 8306614e2c8e5e185dbda8a4beda053e997c1253..0000000000000000000000000000000000000000 --- a/icons/skins/default/2.svg +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><rect width="100" height="100" fill="#708CFD" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width="2.6"/></svg> diff --git a/icons/skins/default/3.svg b/icons/skins/default/3.svg deleted file mode 100644 index 5b6298b56f9ecd3a5246089baa7160f5703ff11e..0000000000000000000000000000000000000000 --- a/icons/skins/default/3.svg +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><rect width="100" height="100" fill="#359C35" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width="2.6"/></svg> diff --git a/icons/skins/default/4.svg b/icons/skins/default/4.svg deleted file mode 100644 index b48f42546499c1814212276aff6b246184aac69e..0000000000000000000000000000000000000000 --- a/icons/skins/default/4.svg +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><rect width="100" height="100" fill="#FFCE2C" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width="2.6"/></svg> diff --git a/icons/skins/default/5.svg b/icons/skins/default/5.svg deleted file mode 100644 index 68b76105c5f6d865e00d35f0818c0d0479fb9217..0000000000000000000000000000000000000000 --- a/icons/skins/default/5.svg +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><rect width="100" height="100" fill="#FF6F43" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width="2.6"/></svg> diff --git a/icons/skins/default/6.svg b/icons/skins/default/6.svg deleted file mode 100644 index da1c8ae7de74db75f978e8dd601ad54d6bcd8752..0000000000000000000000000000000000000000 --- a/icons/skins/default/6.svg +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><rect width="100" height="100" fill="#A13CB1" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width="2.6"/></svg> diff --git a/icons/skins/default/7.svg b/icons/skins/default/7.svg deleted file mode 100644 index da0f69c5ee5270e1ebd493aca091ca884a5c5db8..0000000000000000000000000000000000000000 --- a/icons/skins/default/7.svg +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><rect width="100" height="100" fill="#38FFFF" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width="2.6"/></svg> diff --git a/icons/skins/default/8.svg b/icons/skins/default/8.svg deleted file mode 100644 index 0b637b32322121de2d1cd1f4b717443f3674d10b..0000000000000000000000000000000000000000 --- a/icons/skins/default/8.svg +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><rect width="100" height="100" fill="#F2739D" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".5" stroke-width="2.6"/></svg> diff --git a/lib/entities/cell.dart b/lib/entities/cell.dart index d5f45d912e86655d41637524ded1168c722b96db..669d9fe59e12eaeea807baf314a941f7056c2ee2 100644 --- a/lib/entities/cell.dart +++ b/lib/entities/cell.dart @@ -1,49 +1,7 @@ -import 'package:flutter/material.dart'; -import 'package:jeweled_game/provider/data.dart'; -import 'package:jeweled_game/utils/board_utils.dart'; - class Cell { String value = '0'; Cell( this.value, ); - - /* - * Build widget for board cell, with interactions - * @TODO: remove parameters - */ - Container widget(Data myProvider, int row, int col) { - String imageAsset = this.getImageAssetName(myProvider); - - return Container( - child: GestureDetector( - child: AnimatedSwitcher( - duration: const Duration(milliseconds: 100), - transitionBuilder: (Widget child, Animation<double> animation) { - return ScaleTransition(child: child, scale: animation); - }, - child: Image( - image: AssetImage(imageAsset), - fit: BoxFit.fill, - key: ValueKey<int>(imageAsset.hashCode), - ), - ), - onTap: () { - if (!myProvider.isGameFinished) { - BoardUtils.tapOnCell(myProvider, row, col); - } - }, - ), - ); - } - - /* - * Compute image asset name, from skin and cell value/state - */ - String getImageAssetName(Data myProvider) { - String imageAsset = 'assets/skins/' + myProvider.parameterSkin + '_' + this.value + '.png'; - - return imageAsset; - } } diff --git a/lib/layout/board.dart b/lib/layout/board.dart index 8d207d1ab50f7c5dcabd99cddaf90d1625c2ecdd..4cf8f3c5b276527a10b54623c4eab7bda61c8a47 100644 --- a/lib/layout/board.dart +++ b/lib/layout/board.dart @@ -1,38 +1,38 @@ import 'package:flutter/material.dart'; +import 'package:jeweled_game/layout/board_painter.dart'; import 'package:jeweled_game/provider/data.dart'; +import 'package:jeweled_game/utils/board_utils.dart'; class Board { - static Container buildGameBoard(Data myProvider) { + static Container buildGameBoard(Data myProvider, double boardWidth) { return Container( margin: EdgeInsets.all(4), padding: EdgeInsets.all(4), child: Column( children: [ - buildGameTileset(myProvider), + Container( + child: Center( + child: GestureDetector( + onTapUp: (details) { + double xTap = details.localPosition.dx; + double yTap = details.localPosition.dy; + int col = xTap ~/ (boardWidth / myProvider.sizeHorizontal); + int row = yTap ~/ (boardWidth / myProvider.sizeVertical); + BoardUtils.tapOnCell(myProvider, row, col); + }, + child: Container( + child: CustomPaint( + size: Size(boardWidth, boardWidth), + willChange: false, + painter: BoardPainter(myProvider), + isComplex: true, + ), + ), + ), + ), + ) ], ), ); } - - static Table buildGameTileset(Data myProvider) { - int boardSizeHorizontal = myProvider.sizeHorizontal; - int boardSizeVertical = myProvider.sizeVertical; - - return Table( - defaultColumnWidth: IntrinsicColumnWidth(), - children: [ - for (var row = 0; row < boardSizeVertical; row++) - TableRow( - children: [ - for (var col = 0; col < boardSizeHorizontal; col++) - Column( - children: [ - myProvider.getCell(row, col).widget(myProvider, row, col), - ], - ), - ], - ), - ], - ); - } } diff --git a/lib/layout/board_painter.dart b/lib/layout/board_painter.dart new file mode 100644 index 0000000000000000000000000000000000000000..a758d3785b3ff877b02437d2c96fe8a2a749665f --- /dev/null +++ b/lib/layout/board_painter.dart @@ -0,0 +1,88 @@ +import 'dart:math'; + +import 'package:flutter/material.dart'; +import 'package:jeweled_game/entities/cell.dart'; +import 'package:jeweled_game/layout/color_theme.dart'; +import 'package:jeweled_game/provider/data.dart'; + +class BoardPainter extends CustomPainter { + const BoardPainter(this.myProvider); + + final Data myProvider; + + @override + void paint(Canvas canvas, Size size) { + int sizeHorizontal = myProvider.sizeHorizontal; + int sizeVertical = myProvider.sizeVertical; + + List cells = myProvider.cells; + double cellSize = size.width / (max(sizeHorizontal, sizeVertical)); + + // background + for (var row = 0; row < sizeVertical; row++) { + double y = cellSize * row; + for (var col = 0; col < sizeHorizontal; col++) { + double x = cellSize * col; + + final Cell cell = cells[row][col]; + final String cellValue = cell.value; + final int colorCode = ColorTheme.getColorCode(myProvider.parameterSkin, cellValue); + + final cellPaintBackground = Paint(); + cellPaintBackground.color = Color(colorCode); + cellPaintBackground.style = PaintingStyle.fill; + + final Rect cellBackground = + Rect.fromPoints(Offset(x - 1, y - 1), Offset(x + cellSize + 2, y + cellSize + 2)); + + canvas.drawRect(cellBackground, cellPaintBackground); + } + } + + // borders + double borderSize = 4; + final cellPaintBorder = Paint(); + cellPaintBorder.color = Colors.black; + cellPaintBorder.strokeWidth = borderSize; + cellPaintBorder.strokeCap = StrokeCap.round; + + for (var row = 0; row < sizeVertical; row++) { + double y = cellSize * row; + for (var col = 0; col < sizeHorizontal; col++) { + double x = cellSize * col; + + final Cell cell = cells[row][col]; + final String cellValue = cell.value; + + if ((row == 0) || (row > 1 && cellValue != myProvider.getCellValue(row - 1, col))) { + Offset borderStart = Offset(x, y); + Offset borderStop = Offset(x + cellSize, y); + canvas.drawLine(borderStart, borderStop, cellPaintBorder); + } + if ((row == sizeVertical - 1) || + ((row + 1) < sizeVertical && cellValue != myProvider.getCellValue(row + 1, col))) { + Offset borderStart = Offset(x, y + cellSize); + Offset borderStop = Offset(x + cellSize, y + cellSize); + canvas.drawLine(borderStart, borderStop, cellPaintBorder); + } + if ((col == 0) || (col > 1 && cellValue != myProvider.getCellValue(row, col - 1))) { + Offset borderStart = Offset(x, y); + Offset borderStop = Offset(x, y + cellSize); + canvas.drawLine(borderStart, borderStop, cellPaintBorder); + } + if ((col == sizeHorizontal - 1) || + ((col + 1) < sizeHorizontal && + cellValue != myProvider.getCellValue(row, col + 1))) { + Offset borderStart = Offset(x + cellSize, y); + Offset borderStop = Offset(x + cellSize, y + cellSize); + canvas.drawLine(borderStart, borderStop, cellPaintBorder); + } + } + } + } + + @override + bool shouldRepaint(CustomPainter oldDelegate) { + return false; + } +} diff --git a/lib/layout/color_theme.dart b/lib/layout/color_theme.dart new file mode 100644 index 0000000000000000000000000000000000000000..ebc2309c91c0eea47a3827f328f4e07cb4e69503 --- /dev/null +++ b/lib/layout/color_theme.dart @@ -0,0 +1,26 @@ +class ColorTheme { + static Map<String, Map<String, int>> borderColors = { + 'default': { + '0': 0xffffff, + '1': 0xe63a3f, + '2': 0x708cfd, + '3': 0x359c35, + '4': 0xffce2c, + '5': 0xff6f43, + '6': 0xa13cb1, + '7': 0x38ffff, + '8': 0xf2739d, + }, + }; + static int defaultBorderColor = 0x808080; + + static int getColorCode(String skin, String value) { + if (borderColors.containsKey(skin) && null != borderColors[skin]) { + Map<String, int>? skinColors = borderColors[skin]; + if (null != skinColors && skinColors.containsKey(value) && null != skinColors[value]) { + return (skinColors[value] ?? defaultBorderColor) | 0xFF000000; + } + } + return defaultBorderColor | 0xFF000000; + } +} diff --git a/lib/layout/game.dart b/lib/layout/game.dart index 12df4e31f338377d6ccb7888d77ac36534fa4778..4360e6a29564252b57fb47dd05f76814224f849f 100644 --- a/lib/layout/game.dart +++ b/lib/layout/game.dart @@ -4,7 +4,7 @@ import 'package:jeweled_game/provider/data.dart'; import 'package:jeweled_game/utils/game_utils.dart'; class Game { - static Container buildGameWidget(Data myProvider) { + static Container buildGameWidget(Data myProvider, double boardWidth) { bool gameIsFinished = myProvider.isGameFinished; return Container( @@ -16,7 +16,7 @@ class Game { Game.buildTopIndicatorWidget(myProvider), SizedBox(height: 2), Expanded( - child: Board.buildGameBoard(myProvider), + child: Board.buildGameBoard(myProvider, boardWidth), ), SizedBox(height: 2), Container( diff --git a/lib/provider/data.dart b/lib/provider/data.dart index bbeabe581bfbbcd9c8ad5317ae2be7321dac704e..c07515902c44a6bfe3bed62ec778cdf58e389cd1 100644 --- a/lib/provider/data.dart +++ b/lib/provider/data.dart @@ -34,7 +34,6 @@ class Data extends ChangeNotifier { String get parameterSkin => _parameterSkin; // Game data - bool _assetsPreloaded = false; bool _gameIsRunning = false; bool _gameIsFinished = false; int _sizeVertical = 0; @@ -261,11 +260,6 @@ class Data extends ChangeNotifier { return {}; } - bool get assetsPreloaded => _assetsPreloaded; - void updateAssetsPreloaded(bool assetsPreloaded) { - _assetsPreloaded = assetsPreloaded; - } - List<List<Cell>> get cells => _cells; void updateCells(List<List<Cell>> cells) { _cells = cells; diff --git a/lib/screens/home.dart b/lib/screens/home.dart index ca3fb6d8119092b52d20bf7df20a69d2da5e434d..6db733efe8f6c85a698d18edd50483590afdd585 100644 --- a/lib/screens/home.dart +++ b/lib/screens/home.dart @@ -23,51 +23,10 @@ class _HomeState extends State<Home> { myProvider.loadCurrentSavedState(); } - List getImagesAssets(Data myProvider) { - List assets = []; - - List gameImages = [ - 'button_back', - 'button_delete_saved_game', - 'button_resume_game', - 'button_start', - 'game_fail', - 'game_win', - 'placeholder', - ]; - myProvider.availableLevelValues.forEach((level) => gameImages.add('level_' + level)); - myProvider.availableSizeValues.forEach((size) => gameImages.add('size_' + size)); - myProvider.availableSkinValues.forEach((skin) => gameImages.add('skin_' + skin)); - - gameImages.forEach((image) => assets.add('assets/icons/' + image + '.png')); - - List skinImages = [ - '0', - '1', - '2', - '3', - '4', - '5', - '6', - '7', - '8', - ]; - - myProvider.availableSkinValues.forEach((skin) => skinImages - .forEach((image) => assets.add('assets/skins/' + skin + '_' + image + '.png'))); - - return assets; - } - @override Widget build(BuildContext context) { Data myProvider = Provider.of<Data>(context); - - if (!myProvider.assetsPreloaded) { - List assets = getImagesAssets(myProvider); - assets.forEach((asset) => precacheImage(AssetImage(asset), context)); - myProvider.updateAssetsPreloaded(true); - } + double boardWidth = MediaQuery.of(context).size.width; List<Widget> menuActions = []; @@ -100,7 +59,7 @@ class _HomeState extends State<Home> { body: SafeArea( child: Center( child: myProvider.isGameRunning - ? Game.buildGameWidget(myProvider) + ? Game.buildGameWidget(myProvider, boardWidth) : Parameters.buildParametersSelector(myProvider), ), ),