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

Refactor / normalize layout

parent 2101251b
No related branches found
No related tags found
1 merge request!46Resolve "Normalize layout"
Pipeline #3085 passed
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true
app.versionName=0.0.44
app.versionCode=44
app.versionName=0.0.45
app.versionCode=45
Improve / normalize display and layout
Amélioration / standardisation de l'affichage
import 'package:flutter/material.dart';
import 'tile.dart';
import '../provider/data.dart';
import 'package:puzzlegame/entities/tile.dart';
import 'package:puzzlegame/provider/data.dart';
class MovingTile extends Tile {
int currentCol;
......
import 'package:flutter/material.dart';
import '../provider/data.dart';
import 'package:puzzlegame/provider/data.dart';
class Tile {
final Image image;
......
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import 'provider/data.dart';
import 'screens/home.dart';
import 'package:puzzlegame/provider/data.dart';
import 'package:puzzlegame/screens/home.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
......
import 'package:flutter/foundation.dart';
import '../entities/moving_tile.dart';
import 'package:puzzlegame/entities/moving_tile.dart';
class Data extends ChangeNotifier {
// application configuration
......
import 'package:flutter/material.dart';
import 'package:puzzlegame/entities/moving_tile.dart';
import 'package:puzzlegame/provider/data.dart';
import 'package:puzzlegame/utils/game_utils.dart';
class Game {
static void toggleDisplayTipImage(Data myProvider) {
myProvider.updateDisplayTipImage = !myProvider.displayTipImage;
}
static Container buildTilesetWidget(Data myProvider) {
List<MovingTile> tiles = myProvider.tiles;
Color borderColor = GameUtils.checkTilesetIsCleared(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,
);
}
static Container buildTipWidget(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/images/placeholder.png'),
fit: BoxFit.fill,
),
],
),
Column(
children: [
TextButton(
child: Container(
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(4),
border: Border.all(
color: Colors.blue,
width: 4,
),
),
child: Image(
image: AssetImage(
myProvider.displayTipImage
? GameUtils.getImageAssetName(myProvider.image)
: 'assets/icons/tip_hidden.png',
),
fit: BoxFit.contain,
),
),
onPressed: () => Game.toggleDisplayTipImage(myProvider),
),
],
),
Column(
children: [
Image(
image: AssetImage('assets/images/placeholder.png'),
fit: BoxFit.fill,
),
],
),
],
),
],
),
);
}
static Container buildGameWidget(Data myProvider) {
return Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(height: 8),
buildTopIndicatorWidget(myProvider),
SizedBox(height: 2),
Expanded(
child: buildGameBoard(myProvider),
),
SizedBox(height: 2),
Container(
child: GameUtils.checkTilesetIsCleared(myProvider.tiles)
? Game.buildWinMessage(myProvider)
: Game.buildTipWidget(myProvider),
),
],
),
);
}
static Container buildGameBoard(Data myProvider) {
return Container(
margin: EdgeInsets.all(4),
padding: EdgeInsets.all(4),
child: Column(
children: [
buildTilesetWidget(myProvider),
],
),
);
}
static Widget buildTopIndicatorWidget(Data myProvider) {
return Table(
children: [
TableRow(
children: [
Column(children: []),
Column(children: []),
],
),
],
);
}
static 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: [
TextButton(
child: Container(
child: Image(
image: AssetImage('assets/icons/button_back.png'),
fit: BoxFit.fill,
),
),
onPressed: () => GameUtils.resetGame(myProvider),
),
],
),
Column(
children: [
Image(
image: AssetImage('assets/icons/game_win.png'),
fit: BoxFit.fill,
),
],
),
],
),
],
),
);
}
static 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(),
],
),
);
}
}
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 '../entities/moving_tile.dart';
import '../provider/data.dart';
import '../utils/get_images_list.dart';
import 'package:provider/provider.dart';
import 'package:puzzlegame/provider/data.dart';
import 'package:puzzlegame/screens/game.dart';
import 'package:puzzlegame/utils/game_utils.dart';
import 'package:puzzlegame/utils/get_images_list.dart';
class Home extends StatelessWidget {
static const String id = 'home';
......@@ -18,38 +14,23 @@ class Home extends StatelessWidget {
final Color themePrimaryColor = Colors.blue;
final int _selectImageColumnsCount = 3;
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.isNotEmpty) {
myProvider.updateImages = getImagesList.images;
shuffleImages(myProvider);
shuffleAvailableImages(myProvider);
}
}
Future<void> selectImage(Data myProvider, String imageCode, double tileImageSize) async {
myProvider.updateIsShufflingBoard = true;
myProvider.updateImage = imageCode;
new Timer(new Duration(seconds: 1), () {
splitImageInTiles(myProvider, tileImageSize);
});
GameUtils.startGame(myProvider, tileImageSize);
}
void shuffleImages(Data myProvider) {
void shuffleAvailableImages(Data myProvider) {
List images = myProvider.images;
images.shuffle();
myProvider.updateImages = images;
......@@ -70,7 +51,7 @@ class Home extends StatelessWidget {
),
),
child: Image(
image: AssetImage(getImageAssetName(image)),
image: AssetImage(GameUtils.getImageAssetName(image)),
fit: BoxFit.fill,
),
),
......@@ -146,257 +127,6 @@ class Home extends StatelessWidget {
);
}
List<MovingTile> shuffleMovingTiles(List<MovingTile> 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);
MovingTile 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) ?? imglib.Image.fromBytes(1, 1, []);
int x = 0, y = 0;
int width = (image.width / myProvider.tilesCount).round();
int height = (image.height / myProvider.tilesCount).round();
List<MovingTile> tiles = [];
for (int i = 0; i < myProvider.tilesCount; i++) {
for (int j = 0; j < myProvider.tilesCount; j++) {
Uint8List tileData = new Uint8List.fromList(imglib.encodeJpg(imglib.copyCrop(
image,
x,
y,
width,
height,
)));
tiles.add(MovingTile(
Image.memory(tileData),
tileImageSize,
j,
i,
j,
i,
));
x += width;
}
x = 0;
y += height;
}
myProvider.updateTiles = shuffleMovingTiles(tiles);
myProvider.updateIsShufflingBoard = false;
}
bool _checkTilesetIsCleared(List<MovingTile> tiles) {
for (Tile tile in tiles) {
if (!tile.isCorrect()) {
return false;
}
}
return true;
}
Container _buildTilesetWidget(Data myProvider) {
List<MovingTile> tiles = myProvider.tiles;
Color borderColor = _checkTilesetIsCleared(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(
margin: EdgeInsets.all(2),
padding: EdgeInsets.all(2),
child: Table(
defaultColumnWidth: IntrinsicColumnWidth(),
children: [
TableRow(
children: [
Column(
children: [
Image(
image: AssetImage('assets/images/placeholder.png'),
fit: BoxFit.fill,
),
],
),
Column(
children: [
TextButton(
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/icons/tip_hidden.png',
),
fit: BoxFit.contain,
),
),
onPressed: () => toggleDisplayTipImage(myProvider),
),
],
),
Column(
children: [
Image(
image: AssetImage('assets/images/placeholder.png'),
fit: BoxFit.fill,
),
],
),
],
),
],
),
);
}
Container _buildGameWidget(Data myProvider) {
return Container(
child: Column(
children: [
_buildTilesetWidget(myProvider),
SizedBox(height: 20),
_checkTilesetIsCleared(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: [
TextButton(
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);
......@@ -406,13 +136,13 @@ class Home extends StatelessWidget {
double _tileImageSize = (MediaQuery.of(context).size.width - 70) / _myProvider.tilesCount;
if (_myProvider.isShufflingBoard) {
content = _buildShufflingIndicatorWidget();
content = Game.buildShufflingIndicatorWidget();
precacheImage(new AssetImage('assets/icons/game_win.png'), context);
} else {
if (_myProvider.image == '') {
content = _buildImageSelector(_myProvider, _tileImageSize);
} else {
content = _buildGameWidget(_myProvider);
content = Game.buildGameWidget(_myProvider);
}
}
......@@ -434,7 +164,7 @@ class Home extends StatelessWidget {
fit: BoxFit.fill,
),
),
onPressed: () => shuffleImages(_myProvider),
onPressed: () => shuffleAvailableImages(_myProvider),
),
];
......@@ -453,7 +183,7 @@ class Home extends StatelessWidget {
fit: BoxFit.fill,
),
),
onPressed: () => resetGame(_myProvider),
onPressed: () => GameUtils.resetGame(_myProvider),
),
];
......
import 'dart:async';
import 'dart:math';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show rootBundle;
import 'package:image/image.dart' as imglib;
import 'package:puzzlegame/entities/moving_tile.dart';
import 'package:puzzlegame/entities/tile.dart';
import 'package:puzzlegame/provider/data.dart';
class GameUtils {
static String getImageAssetName(String imageCode) {
return 'assets/images/' + imageCode + '.png';
}
static startGame(Data myProvider, double tileImageSize) {
new Timer(new Duration(seconds: 1), () {
GameUtils.splitImageInTiles(myProvider, tileImageSize);
});
}
static Future<void> resetGame(Data myProvider) async {
myProvider.updateImage = '';
myProvider.updateDisplayTipImage = false;
}
static bool checkTilesetIsCleared(List<MovingTile> tiles) {
for (Tile tile in tiles) {
if (!tile.isCorrect()) {
return false;
}
}
return true;
}
static List<MovingTile> shuffleMovingTiles(List<MovingTile> 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);
MovingTile 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;
}
static 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) ?? imglib.Image.fromBytes(1, 1, []);
int x = 0, y = 0;
int width = (image.width / myProvider.tilesCount).round();
int height = (image.height / myProvider.tilesCount).round();
List<MovingTile> tiles = [];
for (int i = 0; i < myProvider.tilesCount; i++) {
for (int j = 0; j < myProvider.tilesCount; j++) {
Uint8List tileData = new Uint8List.fromList(imglib.encodeJpg(imglib.copyCrop(
image,
x,
y,
width,
height,
)));
tiles.add(MovingTile(
Image.memory(tileData),
tileImageSize,
j,
i,
j,
i,
));
x += width;
}
x = 0;
y += height;
}
myProvider.updateTiles = shuffleMovingTiles(tiles);
myProvider.updateIsShufflingBoard = false;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment