-
Benoît Harrault authoredBenoît Harrault authored
home.dart 12.14 KiB
import 'dart:async';
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';
Color themePrimaryColor = Colors.blue;
double _tipImageSize = 100;
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) {
return 'assets/images/'+imageCode+'.png';
}
Future<void> getImagesList(Data myProvider) async {
GetImagesList getImagesList;
getImagesList = GetImagesList();
await getImagesList.init();
if (getImagesList.images != null) {
myProvider.updateImages = getImagesList.images;
shuffleImages(myProvider);
}
}
Future<void> selectImage(Data myProvider, String imageCode, double tileImageSize) async {
myProvider.updateIsShufflingBoard = true;
myProvider.updateImage = imageCode;
Timer timer = new Timer(new Duration(seconds: 1), () {
splitImageInTiles(myProvider, tileImageSize);
});
}
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(4),
border: Border.all(
color: Colors.blue[200],
width: 4,
),
),
margin: EdgeInsets.all(2),
child: Image(
image: AssetImage(getImageAssetName(image)),
width: selectImageSize,
height: selectImageSize,
fit: BoxFit.fill
),
),
onPressed: () { selectImage(myProvider, image, tileImageSize); },
),
);
}
Container _buildImageSelector(Data myProvider, double size, double tileImageSize) {
if (myProvider.images.length == 0) {
getImagesList(myProvider);
}
List images = myProvider.images;
return Container(
padding: EdgeInsets.all(2),
child: ListView(
children: [
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)
]
),
]
),
],
),
],
),
);
}
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<void> splitImageInTiles(Data myProvider, double tileImageSize) async {
String imageAsset = getImageAssetName(myProvider.image);
Uint8List imageData = (await rootBundle.load(imageAsset))
.buffer
.asUint8List();
imglib.Image image = imglib.decodeImage(imageData);
int x = 0, y = 0;
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,
)
);
x += width;
}
x = 0;
y += height;
}
myProvider.updateTiles = shuffleTiles(tiles);
myProvider.updateIsShufflingBoard = false;
}
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;
Color borderColor = _checkTilesetIsOrdered(tiles) ? Colors.green : Colors.orange;
int tileIndex = 0;
Table tileset = Table(
defaultColumnWidth: IntrinsicColumnWidth(),
border: TableBorder.all(
color: Colors.black,
style: BorderStyle.solid,
width: 2,
),
children: [
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(8),
padding: EdgeInsets.all(8),
decoration: BoxDecoration(
color: borderColor,
borderRadius: BorderRadius.circular(8),
border: Border.all(
color: borderColor,
width: 8,
),
),
child: tileset,
);
}
Container _buildTipWidget(Data myProvider) {
return Container(
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
),
),
onPressed: () => toggleDisplayTipImage(myProvider),
),
);
}
Container _buildGameWidget(Data myProvider) {
return Container(
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
_buildTilesetWidget(myProvider),
SizedBox(height: 20),
_checkTilesetIsOrdered(myProvider.tiles) ? _buildWinMessage(myProvider) : _buildTipWidget(myProvider),
],
),
);
}
Container _buildWinMessage(Data myProvider) {
return Container(
margin: EdgeInsets.all(2),
padding: EdgeInsets.all(2),
child: Table(
defaultColumnWidth: IntrinsicColumnWidth(),
children: [
TableRow(
children: [
Column(
children: [
Image(
image: AssetImage('assets/icons/game_win.png'),
fit: BoxFit.fill
),
]
),
Column(
children: [
FlatButton(
child: Container(
child: Image(
image: AssetImage('assets/icons/button_back.png'),
fit: BoxFit.fill
),
),
onPressed: () => resetGame(myProvider),
),
]
),
Column(
children: [
Image(
image: AssetImage('assets/icons/game_win.png'),
fit: BoxFit.fill
),
]
),
],
),
]
)
);
}
Container _buildShufflingIndicatorWidget() {
return Container(
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'⏳',
style: TextStyle(
fontSize: 60,
fontWeight: FontWeight.w600,
color: Colors.black,
),
),
SizedBox(height: 20),
CircularProgressIndicator(),
],
),
);
}
@override
Widget build(BuildContext context) {
Data _myProvider = Provider.of<Data>(context);
var content;
double _selectorImageSize = (MediaQuery.of(context).size.width - 140) / _selectImageColumnsCount;
double _tileImageSize = (MediaQuery.of(context).size.width - 70) / _myProvider.tilesCount;
if (_myProvider.isShufflingBoard) {
content = _buildShufflingIndicatorWidget();
} else {
if (_myProvider.image == '') {
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: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4),
border: Border.all(
color: Colors.blue,
width: 4,
),
),
margin: EdgeInsets.all(8),
child: Image(
image: AssetImage('assets/icons/button_back.png'),
fit: BoxFit.fill
),
),
onPressed: () => resetGame(_myProvider),
),
];
return Scaffold(
appBar: AppBar(
backgroundColor: themePrimaryColor,
actions: _myProvider.image == '' ? menuActions : gameActions,
),
body: SafeArea(
child: Center(
child: content
),
)
);
}
}