Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • android/org.benoitharrault.puzzlegame
1 result
Show changes
......@@ -4,7 +4,6 @@
command -v inkscape >/dev/null 2>&1 || { echo >&2 "I require inkscape but it's not installed. Aborting."; exit 1; }
command -v scour >/dev/null 2>&1 || { echo >&2 "I require scour 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; }
command -v convert >/dev/null 2>&1 || { echo >&2 "I require convert (imagemagick) but it's not installed. Aborting."; exit 1; }
CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
BASE_DIR="$(dirname "${CURRENT_DIR}")"
......
#! /bin/bash
# Check dependencies
command -v inkscape >/dev/null 2>&1 || { echo >&2 "I require inkscape but it's not installed. Aborting."; exit 1; }
command -v scour >/dev/null 2>&1 || { echo >&2 "I require scour 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)"
BASE_DIR="$(dirname "${CURRENT_DIR}")"
OPTIPNG_OPTIONS="-preserve -quiet -o7"
# optimize svg
function optimize_svg() {
SOURCE="$1"
cp ${SOURCE} ${SOURCE}.tmp
scour \
--remove-descriptive-elements \
--enable-id-stripping \
--enable-viewboxing \
--enable-comment-stripping \
--nindent=4 \
-i ${SOURCE}.tmp \
-o ${SOURCE}
rm ${SOURCE}.tmp
}
# build icons
function build_icon() {
ICON_SIZE=192
SOURCE="$1"
TARGET="$2"
optimize_svg "${SOURCE}"
inkscape \
--export-width=${ICON_SIZE} \
--export-height=${ICON_SIZE} \
--export-filename=${TARGET} \
${SOURCE}
optipng ${OPTIPNG_OPTIONS} ${TARGET}
}
# Game icons
build_icon ${CURRENT_DIR}/button_back.svg ${BASE_DIR}/assets/icons/button_back.png
build_icon ${CURRENT_DIR}/button_shuffle.svg ${BASE_DIR}/assets/icons/button_shuffle.png
build_icon ${CURRENT_DIR}/difficulty_3x3.svg ${BASE_DIR}/assets/icons/difficulty_3x3.png
build_icon ${CURRENT_DIR}/difficulty_4x4.svg ${BASE_DIR}/assets/icons/difficulty_4x4.png
build_icon ${CURRENT_DIR}/difficulty_5x5.svg ${BASE_DIR}/assets/icons/difficulty_5x5.png
<?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"><path d="m46.834 11.248c-19.624 0-35.588 15.964-35.588 35.592 0 19.624 15.964 35.588 35.588 35.588s35.584-15.964 35.584-35.588c0-19.629-15.96-35.592-35.584-35.592zm0 63.607c-15.471 0-28.02-12.544-28.02-28.014 0-15.477 12.549-28.019 28.02-28.019s28.018 12.541 28.018 28.019c0 15.471-12.547 28.014-28.018 28.014z" stroke-width=".75985"/><path d="m55.403 64.285c0.85468 0.85879 3.0403 0.85879 3.0403 0v-34.893c0-0.85985-2.1908-0.85985-3.0486 0l-28.641 15.895c-0.8578 0.85468-0.87224 2.2454-0.0165 3.1032z" fill="#ed9138" stroke-width="1.031"/></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"><path d="m83.437 0.38264h-73.092c-5.6481 0-9.9672 4.3191-9.9672 9.9672v73.092c0 5.6481 4.3191 9.9672 9.9672 9.9672h73.092c5.6481 0 9.9672-4.3191 9.9672-9.9672v-73.092c0-5.6481-4.3191-9.9672-9.9672-9.9672zm-19.602 31.23-12.625 15.283 12.957 15.283c0.66448 0.66448 1.6612 1.329 2.6579 1.329v-3.3224c0-1.9934 1.329-3.3224 3.3224-3.3224 0.99672 0 1.6612 0.33224 2.3257 0.99672l6.977 6.3125c1.6612 1.6612 1.6612 2.3257 0 4.3191l-7.3092 7.3092c-1.329 1.329-3.3224 0.99672-4.6513-0.33224-0.33224-0.66448-0.66448-1.329-0.66448-1.9934v-3.3224h-0.33224c-2.9901 0-5.6481-1.329-7.6415-3.6546l-11.961-14.286-11.961 14.618c-1.9934 1.9934-4.6513 3.3224-7.6415 3.3224h-10.299c-1.9934 0-3.3224-1.329-3.3224-3.3224s1.329-3.3224 3.3224-3.3224h10.299c0.99672 0 1.9934-0.33224 2.6579-1.329l12.957-15.283-12.957-15.283c-0.66448-0.66448-1.6612-1.329-2.6579-1.329h-10.299c-1.9934 0-3.3224-1.329-3.3224-3.3224s1.329-3.3224 3.3224-3.3224h10.299c2.9901 0 5.6481 1.329 7.6415 3.6546l11.961 14.618 11.961-14.618c1.9934-2.3257 4.6513-3.6546 7.6415-3.6546h0.33224v-3.3224c0-1.9934 1.329-3.3224 3.3224-3.3224 0.99672 0 1.6612 0.33224 2.3257 0.99672l6.6448 6.6448c1.6612 1.6612 1.9934 2.9901 0.33224 4.9836l-6.6448 6.6448c-1.329 1.329-2.9901 1.9934-4.6513 0.66448-0.99672-0.66448-1.329-1.6612-1.329-3.6546v-2.9901s-1.9934 0-2.9901 1.329z" fill="#7a0d86" stroke-width="3.3224"/></svg>
<?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="#009d21"/><g fill="#f9f9f9" stroke="#000" stroke-width="2" aria-label="3x3"><path d="m19.443 43.965-7.5195-1.3477q0.9375-3.5938 3.5938-5.5078 2.6758-1.9141 7.5586-1.9141 5.6055 0 8.1055 2.0898t2.5 5.2539q0 1.8555-1.0156 3.3594t-3.0664 2.6367q1.6602 0.41016 2.5391 0.95703 1.4258 0.87891 2.207 2.3242 0.80078 1.4258 0.80078 3.418 0 2.5-1.3086 4.8047-1.3086 2.2852-3.7695 3.5352-2.4609 1.2305-6.4648 1.2305-3.9062 0-6.1719-0.91797-2.2461-0.91797-3.7109-2.6758-1.4453-1.7773-2.2266-4.4531l7.9492-1.0547q0.46875 2.4023 1.4453 3.3398 0.99609 0.91797 2.5195 0.91797 1.6016 0 2.6562-1.1719 1.0742-1.1719 1.0742-3.125 0-1.9922-1.0352-3.0859-1.0156-1.0938-2.7734-1.0938-0.9375 0-2.5781 0.46875l0.41016-5.6836q0.66406 0.09766 1.0352 0.09766 1.5625 0 2.5977-0.99609 1.0547-0.99609 1.0547-2.3633 0-1.3086-0.78125-2.0898t-2.1484-0.78125q-1.4062 0-2.2852 0.85938-0.87891 0.83984-1.1914 2.9688z"/><path d="m37.373 43.574h9.4336l3.3008 5.7812 3.8281-5.7812h8.7695l-7.0703 9.8828 7.5781 10.859h-9.2773l-3.8281-6.6797-4.5117 6.6797h-8.6133l7.5391-10.859z"/><path d="m72.803 43.965-7.5195-1.3477q0.9375-3.5938 3.5938-5.5078 2.6758-1.9141 7.5586-1.9141 5.6055 0 8.1055 2.0898t2.5 5.2539q0 1.8555-1.0156 3.3594t-3.0664 2.6367q1.6602 0.41016 2.5391 0.95703 1.4258 0.87891 2.207 2.3242 0.80078 1.4258 0.80078 3.418 0 2.5-1.3086 4.8047-1.3086 2.2852-3.7695 3.5352-2.4609 1.2305-6.4648 1.2305-3.9062 0-6.1719-0.91797-2.2461-0.91797-3.7109-2.6758-1.4453-1.7773-2.2266-4.4531l7.9492-1.0547q0.46875 2.4023 1.4453 3.3398 0.99609 0.91797 2.5195 0.91797 1.6016 0 2.6562-1.1719 1.0742-1.1719 1.0742-3.125 0-1.9922-1.0352-3.0859-1.0156-1.0938-2.7734-1.0938-0.9375 0-2.5781 0.46875l0.41016-5.6836q0.66406 0.09766 1.0352 0.09766 1.5625 0 2.5977-0.99609 1.0547-0.99609 1.0547-2.3633 0-1.3086-0.78125-2.0898t-2.1484-0.78125q-1.4062 0-2.2852 0.85938-0.87891 0.83984-1.1914 2.9688z"/></g></svg>
<?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="#eeb517"/><g fill="#fff" stroke="#000" stroke-width="2" aria-label="4x4"><path d="m25.303 59.209h-14.492v-6.543l14.492-17.227h6.9336v17.598h3.5938v6.1719h-3.5938v5.3516h-6.9336zm0-6.1719v-9.0039l-7.6562 9.0039z"/><path d="m37.275 43.818h9.4336l3.3008 5.7812 3.8281-5.7812h8.7695l-7.0703 9.8828 7.5781 10.859h-9.2773l-3.8281-6.6797-4.5117 6.6797h-8.6133l7.5391-10.859z"/><path d="m78.662 59.209h-14.492v-6.543l14.492-17.227h6.9336v17.598h3.5938v6.1719h-3.5938v5.3516h-6.9336zm0-6.1719v-9.0039l-7.6562 9.0039z"/></g></svg>
<?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="#d31158"/><g fill="#fff" stroke="#000" stroke-width="2" aria-label="5x5"><path d="m14.971 35.439h18.887v6.3477h-12.793l-0.68359 4.2969q1.3281-0.625 2.6172-0.9375 1.3086-0.3125 2.5781-0.3125 4.2969 0 6.9727 2.5977t2.6758 6.543q0 2.7734-1.3867 5.332-1.3672 2.5586-3.9062 3.9062-2.5195 1.3477-6.4648 1.3477-2.832 0-4.8633-0.52734-2.0117-0.54688-3.4375-1.6016-1.4062-1.0742-2.2852-2.4219-0.87891-1.3477-1.4648-3.3594l8.0469-0.87891q0.29297 1.9336 1.3672 2.9492 1.0742 0.99609 2.5586 0.99609 1.6602 0 2.7344-1.25 1.0938-1.2695 1.0938-3.7695 0-2.5586-1.0938-3.75t-2.9102-1.1914q-1.1523 0-2.2266 0.56641-0.80078 0.41016-1.7578 1.4844l-6.7773-0.97656z"/><path d="m37.393 43.33h9.4336l3.3008 5.7812 3.8281-5.7812h8.7695l-7.0703 9.8828 7.5781 10.859h-9.2773l-3.8281-6.6797-4.5117 6.6797h-8.6133l7.5391-10.859z"/><path d="m68.33 35.439h18.887v6.3477h-12.793l-0.68359 4.2969q1.3281-0.625 2.6172-0.9375 1.3086-0.3125 2.5781-0.3125 4.2969 0 6.9727 2.5977t2.6758 6.543q0 2.7734-1.3867 5.332-1.3672 2.5586-3.9062 3.9062-2.5195 1.3477-6.4648 1.3477-2.832 0-4.8633-0.52734-2.0117-0.54688-3.4375-1.6016-1.4062-1.0742-2.2852-2.4219-0.87891-1.3477-1.4648-3.3594l8.0469-0.87891q0.29297 1.9336 1.3672 2.9492 1.0742 0.99609 2.5586 0.99609 1.6602 0 2.7344-1.25 1.0938-1.2695 1.0938-3.7695 0-2.5586-1.0938-3.75t-2.9102-1.1914q-1.1523 0-2.2266 0.56641-0.80078 0.41016-1.7578 1.4844l-6.7773-0.97656z"/></g></svg>
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../provider/data.dart';
class Tile {
final Image image;
final double size;
int currentCol;
int currentRow;
final int originalCol;
final int originalRow;
Tile(
@required this.image,
@required this.size,
@required this.currentCol,
@required this.currentRow,
@required this.originalCol,
@required this.originalRow,
);
Container _tileWidget() {
return Container(
decoration: BoxDecoration(
color: Colors.black,
border: Border.all(
color: Colors.black,
width: 1,
),
),
child: Image(
image: this.image.image,
width: this.size,
height: this.size,
fit: BoxFit.fill
),
);
}
Container widget(Data myProvider) {
return Container(
child: DragTarget<List<int>>(
builder: (
BuildContext context,
List<dynamic> accepted,
List<dynamic> rejected,
) {
return Container(
height: this.size,
width: this.size,
color: Colors.cyan,
child: Draggable<List<int>>(
data: [
this.currentCol,
this.currentRow,
],
// Widget when draggable is stationary
child: this._tileWidget(),
// Widget when draggable is being dragged
feedback: this._tileWidget(),
// Widget to display on original place when being dragged
childWhenDragging: Container(
height: this.size,
width: this.size,
color: Colors.pinkAccent,
),
),
);
},
onAccept: (List<int> data) {
myProvider.swapTiles(
[this.currentCol, this.currentRow],
data
);
},
)
);
}
}
import 'package:flutter/foundation.dart';
import '../entities/tile.dart';
class Data extends ChangeNotifier {
// application configuration
int _tilesCount = 4;
// application data
List _images = [];
String _image = '';
......@@ -9,6 +14,7 @@ class Data extends ChangeNotifier {
// application state
bool _shuffling = false;
bool _displayTipImage = false;
String get image => _image;
......@@ -17,6 +23,13 @@ class Data extends ChangeNotifier {
notifyListeners();
}
int get tilesCount => _tilesCount;
set updateTilesCount(int value) {
_tilesCount = value;
notifyListeners();
}
List get images => _images;
set updateImages(List value) {
......@@ -38,6 +51,32 @@ class Data extends ChangeNotifier {
notifyListeners();
}
bool get displayTipImage => _displayTipImage;
set updateDisplayTipImage(bool value) {
_displayTipImage = value;
notifyListeners();
}
void swapTiles(List<int> tile1, List<int> tile2) {
int indexTile1 = _tiles.indexWhere((tile) => ((tile.currentCol == tile1[0]) && (tile.currentRow == tile1[1])));
int indexTile2 = _tiles.indexWhere((tile) => ((tile.currentCol == tile2[0]) && (tile.currentRow == tile2[1])));
Tile swap = _tiles[indexTile1];
_tiles[indexTile1] = _tiles[indexTile2];
_tiles[indexTile2] = swap;
int swapCol = _tiles[indexTile1].currentCol;
_tiles[indexTile1].currentCol = _tiles[indexTile2].currentCol;
_tiles[indexTile2].currentCol = swapCol;
int swapRow = _tiles[indexTile1].currentRow;
_tiles[indexTile1].currentRow = _tiles[indexTile2].currentRow;
_tiles[indexTile2].currentRow = swapRow;
notifyListeners();
}
void resetGame() {
_image = '';
notifyListeners();
......
import 'dart:typed_data';
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show rootBundle;
import 'package:image/image.dart' as imglib;
import 'package:provider/provider.dart';
import '../entities/tile.dart';
import '../provider/data.dart';
import '../utils/get_images_list.dart';
class Home extends StatelessWidget {
static const String id = 'home';
int _linesCount = 3;
int _columnsCount = 3;
double _selectorImageSize = 200;
Color themePrimaryColor = Colors.blue;
double _tipImageSize = 100;
double _tileImageSize = 80;
int _selectImageColumnsCount = 2;
Future<void> resetGame(Data myProvider) async {
myProvider.updateImage = '';
myProvider.updateDisplayTipImage = false;
}
void toggleDisplayTipImage(Data myProvider) {
myProvider.updateDisplayTipImage = !myProvider.displayTipImage;
}
String getImageAssetName(String imageCode) {
......@@ -32,58 +36,132 @@ class Home extends StatelessWidget {
await getImagesList.init();
if (getImagesList.images != null) {
myProvider.updateImages = getImagesList.images;
shuffleImages(myProvider);
}
}
Future<void> selectImage(Data myProvider, String imageCode) async {
Future<void> selectImage(Data myProvider, String imageCode, double tileImageSize) async {
myProvider.updateShuffling = true;
myProvider.updateImage = imageCode;
myProvider.updateTiles = await splitImageInTiles(myProvider);
myProvider.updateTiles = await splitImageInTiles(myProvider, tileImageSize);
myProvider.updateShuffling = false;
}
Container _buildImageSelectorItem(Data myProvider, String image) {
void shuffleImages(Data myProvider) {
List images = myProvider.images;
images.shuffle();
myProvider.updateImages = images;
}
Container _buildImageSelectorItem(Data myProvider, String image, double selectImageSize, double tileImageSize) {
return Container(
child: FlatButton(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
borderRadius: BorderRadius.circular(4),
border: Border.all(
color: Colors.blue[200],
width: 8,
width: 4,
),
),
margin: EdgeInsets.all(2),
child: Image(
image: AssetImage(getImageAssetName(image)),
width: _selectorImageSize,
height: _selectorImageSize,
width: selectImageSize,
height: selectImageSize,
fit: BoxFit.fill
),
),
onPressed: () { selectImage(myProvider, image); },
onPressed: () { selectImage(myProvider, image, tileImageSize); },
),
);
}
Container _buildImageSelector(Data myProvider) {
Container _buildImageSelector(Data myProvider, double size, double tileImageSize) {
if (myProvider.images.length == 0) {
getImagesList(myProvider);
}
List images = myProvider.images;
return Container(
padding: EdgeInsets.all(5),
padding: EdgeInsets.all(2),
child: ListView(
children: [
for (var image in images)
_buildImageSelectorItem(myProvider, image),
Table(
defaultColumnWidth: IntrinsicColumnWidth(),
children: [
for (var imageIndex = 0; imageIndex < images.length; imageIndex += _selectImageColumnsCount)
TableRow(
children: [
for (var columnIndex = 0; columnIndex < _selectImageColumnsCount; columnIndex++)
Column(
children: [
if (imageIndex + columnIndex < images.length)
_buildImageSelectorItem(myProvider, images[imageIndex + columnIndex], size, tileImageSize)
]
),
]
),
],
),
],
),
);
}
Future<List<Image>> splitImageInTiles(Data myProvider) async {
FlatButton _buildTilesetSizeSelectorItem(Data myProvider, int value) {
String assetName = 'assets/icons/difficulty_' + value.toString() + 'x' + value.toString() + '.png';
Color borderColor = themePrimaryColor;
if (myProvider.tilesCount == value) {
borderColor = Colors.white;
}
return FlatButton(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4),
border: Border.all(
color: borderColor,
width: 4,
),
),
margin: EdgeInsets.all(8),
child: Image(
image: AssetImage(assetName),
fit: BoxFit.fill
),
),
onPressed: () { myProvider.updateTilesCount = value; },
);
}
List<Tile> shuffleTiles(List<Tile> tiles) {
var random = new Random();
int tilesCount = tiles.length;
for (int i = 0; i < (10 * tilesCount); i++) {
int indexTile1 = random.nextInt(tilesCount);
int indexTile2 = random.nextInt(tilesCount);
Tile swap = tiles[indexTile1];
tiles[indexTile1] = tiles[indexTile2];
tiles[indexTile2] = swap;
int swapCol = tiles[indexTile1].currentCol;
tiles[indexTile1].currentCol = tiles[indexTile2].currentCol;
tiles[indexTile2].currentCol = swapCol;
int swapRow = tiles[indexTile1].currentRow;
tiles[indexTile1].currentRow = tiles[indexTile2].currentRow;
tiles[indexTile2].currentRow = swapRow;
}
return tiles;
}
Future<List<Tile>> splitImageInTiles(Data myProvider, double tileImageSize) async {
String imageAsset = getImageAssetName(myProvider.image);
Uint8List imageData = (await rootBundle.load(imageAsset))
.buffer
......@@ -91,43 +169,52 @@ class Home extends StatelessWidget {
imglib.Image image = imglib.decodeImage(imageData);
int x = 0, y = 0;
int width = (image.width / _linesCount).round();
int height = (image.height / _columnsCount).round();
int width = (image.width / myProvider.tilesCount).round();
int height = (image.height / myProvider.tilesCount).round();
List<Tile> tiles = List<Tile>();
for (int i = 0; i < myProvider.tilesCount; i++) {
for (int j = 0; j < myProvider.tilesCount; j++) {
tiles.add(
Tile(
Image.memory(
imglib.encodeJpg(
imglib.copyCrop(image, x, y, width, height)
)
),
tileImageSize,
j, i,
j, i,
)
);
List<imglib.Image> parts = List<imglib.Image>();
for (int i = 0; i < _linesCount; i++) {
for (int j = 0; j < _columnsCount; j++) {
parts.add(imglib.copyCrop(image, x, y, width, height));
x += width;
}
x = 0;
y += height;
}
List<Image> tiles = List<Image>();
for (var img in parts) {
tiles.add(Image.memory(imglib.encodeJpg(img)));
}
return tiles;
return shuffleTiles(tiles);
}
Container _buildImageTileItem(Image tile) {
return Container(
child: Image(
image: tile.image,
width: _tileImageSize,
height: _tileImageSize,
fit: BoxFit.fill
)
);
bool _checkTilesetIsOrdered(List<Tile> tiles) {
for (Tile tile in tiles) {
if (
(tile.currentRow != tile.originalRow)
||
(tile.currentCol != tile.originalCol)
) {
return false;
}
}
return true;
}
Container _buildTilesetWidget(Data myProvider) {
List tiles = myProvider.tiles;
tiles.shuffle();
Color borderColor = _checkTilesetIsOrdered(tiles) ? Colors.green : Colors.orange;
int tileIndex = 0;
Table tileset = Table(
......@@ -139,33 +226,23 @@ class Home extends StatelessWidget {
width: 2,
),
children: [
TableRow(children: [
Column(children: [_buildImageTileItem(tiles[tileIndex++])]),
Column(children: [_buildImageTileItem(tiles[tileIndex++])]),
Column(children: [_buildImageTileItem(tiles[tileIndex++])]),
]),
TableRow(children: [
Column(children: [_buildImageTileItem(tiles[tileIndex++])]),
Column(children: [_buildImageTileItem(tiles[tileIndex++])]),
Column(children: [_buildImageTileItem(tiles[tileIndex++])]),
]),
TableRow(children: [
Column(children: [_buildImageTileItem(tiles[tileIndex++])]),
Column(children: [_buildImageTileItem(tiles[tileIndex++])]),
Column(children: [_buildImageTileItem(tiles[tileIndex++])]),
]),
],
for (var row = 0; row < myProvider.tilesCount; row++)
TableRow(children: [
for (var col = 0; col < myProvider.tilesCount; col++)
Column(children: [tiles[tileIndex++].widget(myProvider)]),
]),
]
);
return Container(
margin: EdgeInsets.all(4),
padding: EdgeInsets.all(4),
margin: EdgeInsets.all(8),
padding: EdgeInsets.all(8),
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(4),
color: borderColor,
borderRadius: BorderRadius.circular(8),
border: Border.all(
color: Colors.green,
width: 4,
color: borderColor,
width: 8,
),
),
child: tileset,
......@@ -174,21 +251,30 @@ class Home extends StatelessWidget {
Container _buildTipWidget(Data myProvider) {
return Container(
margin: EdgeInsets.all(4),
padding: EdgeInsets.all(4),
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(4),
border: Border.all(
color: Colors.green,
width: 4,
child: FlatButton(
child: Container(
margin: EdgeInsets.all(4),
padding: EdgeInsets.all(4),
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(4),
border: Border.all(
color: Colors.blue,
width: 4,
),
),
child: Image(
image: AssetImage(
myProvider.displayTipImage
? getImageAssetName(myProvider.image)
: 'assets/ui/tip-hidden.png'
),
width: _tipImageSize,
height: _tipImageSize,
fit: BoxFit.fill
),
),
),
child: Image(
image: AssetImage(getImageAssetName(myProvider.image)),
width: _tipImageSize,
height: _tipImageSize,
fit: BoxFit.fill
onPressed: () => toggleDisplayTipImage(myProvider),
),
);
}
......@@ -232,27 +318,56 @@ class Home extends StatelessWidget {
var content;
double _selectorImageSize = (MediaQuery.of(context).size.width - 140) / _selectImageColumnsCount;
double _tileImageSize = (MediaQuery.of(context).size.width - 70) / _myProvider.tilesCount;
if (_myProvider.shuffling) {
content = _buildShufflingIndicatorWidget();
} else {
if (_myProvider.image == '') {
content = _buildImageSelector(_myProvider);
content = _buildImageSelector(_myProvider, _selectorImageSize, _tileImageSize);
} else {
content = _buildGameWidget(_myProvider);
}
}
List<Widget> menuActions = [
_buildTilesetSizeSelectorItem(_myProvider, 3),
_buildTilesetSizeSelectorItem(_myProvider, 4),
_buildTilesetSizeSelectorItem(_myProvider, 5),
FlatButton(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4),
border: Border.all(
color: themePrimaryColor,
width: 4,
),
),
margin: EdgeInsets.all(8),
child: Image(
image: AssetImage('assets/icons/button_shuffle.png'),
fit: BoxFit.fill
),
),
onPressed: () => shuffleImages(_myProvider),
),
];
List<Widget> gameActions = [
FlatButton(
child: Image(
image: AssetImage('assets/icons/button_back.png'),
fit: BoxFit.fill
),
onPressed: () => resetGame(_myProvider),
),
];
return Scaffold(
appBar: AppBar(
title: Text('Puzzle'),
actions: <Widget>[
_myProvider.image == ''
? Text('')
: IconButton(
icon: const Icon(Icons.arrow_left_outlined),
onPressed: () => resetGame(_myProvider),
),
],
backgroundColor: themePrimaryColor,
actions: _myProvider.image == '' ? menuActions : gameActions,
),
body: SafeArea(
child: Center(
......
......@@ -20,4 +20,6 @@ flutter:
uses-material-design: true
assets:
- assets/files/
- assets/icons/
- assets/images/
- assets/ui/
......@@ -10,8 +10,8 @@ IMAGES_RAW_FOLDER="${IMAGES_CACHE_FOLDER}/01_raw_images"
IMAGES_OPTIMIZED_FOLDER="${IMAGES_CACHE_FOLDER}/02_optimized_images"
RESIZE_OPTION="640x640"
CROP_PARAMETERS="-auto-orient -trim +repage -gravity center -background white -extent ${RESIZE_OPTION}^"
CONVERT_OPTIONS="-alpha off +dither -colors 256 -depth 4"
CROP_PARAMETERS="-auto-orient +repage -gravity center -background white -extent ${RESIZE_OPTION}^"
CONVERT_OPTIONS="-alpha off -dither FloydSteinberg -colors 256 -depth 4"
OPTIPNG_OPTIONS="-preserve -quiet -o7"
......@@ -26,8 +26,10 @@ IMAGES="$(find "${IMAGES_RAW_FOLDER}" -type f -name "*.??g" | sort)"
while read -r INPUT_FILE; do
if [[ -n "${INPUT_FILE}" ]]; then
CATEGORY="$(basename "$(dirname "${INPUT_FILE}")")"
echo "CATEGORY: ${CATEGORY}"
HASH="$(echo "${INPUT_FILE%.*}" | md5sum | cut -c1-32)"
OUTPUT_FILE="${IMAGES_OPTIMIZED_FOLDER}/${HASH}.png"
OUTPUT_FILE="${IMAGES_OPTIMIZED_FOLDER}/${CATEGORY}_${HASH}.png"
echo " OUTPUT_FILE: ${OUTPUT_FILE}"
if [[ -f "${OUTPUT_FILE}" ]]; then
......