Select Git revision
game_board.dart
-
Benoît Harrault authoredBenoît Harrault authored
game_board.dart 5.19 KiB
import 'package:flutter/material.dart';
import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
import 'package:random/cubit/activity/activity_cubit.dart';
import 'package:random/models/activity/activity.dart';
import 'package:random/models/settings/settings_activity.dart';
import 'package:random/ui/painters/cell_painter.dart';
import 'package:random/ui/widgets/game/game_score.dart';
class GameBoardWidget extends StatefulWidget {
const GameBoardWidget({
super.key,
required this.activity,
required this.widgetSize,
});
final Activity activity;
final Size widgetSize;
@override
State<GameBoardWidget> createState() => _GameBoardWidget();
}
class _GameBoardWidget extends State<GameBoardWidget> with TickerProviderStateMixin {
List<List<Animation<double>?>> animations = [];
void resetAnimations(ActivitySettings activitySettings) {
final int boardSize = activitySettings.boardSizeValue;
animations = List.generate(
boardSize,
(i) => List.generate(
boardSize,
(i) => null,
),
);
}
void removeCell(BuildContext context, int x, int y) {
final ActivityCubit activityCubit = BlocProvider.of<ActivityCubit>(context);
final Activity updatedGame = activityCubit.state.currentActivity;
// "remove" cell, update counters
updatedGame.increaseScore(updatedGame.getCellValue(x, y));
updatedGame.increaseMovesCount();
updatedGame.updateCellValue(x, y, null);
setState(() {});
// "move down" cells
final controller = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 750),
)..addListener(() {
if (mounted) {
setState(() {});
}
});
if (mounted) {
setState(() {});
}
Animation<double> animation = Tween(
begin: 0.0,
end: 1.0,
).animate(CurvedAnimation(
curve: Curves.bounceOut,
parent: controller,
))
..addStatusListener((status) {
if (status == AnimationStatus.completed) {
// Update cell values
for (var i = 0; i < y; i++) {
updatedGame.updateCellValue(x, (y - i), updatedGame.getCellValue(x, (y - i) - 1));
}
updatedGame.setRandomCellValue(x, 0, updatedGame.activitySettings);
resetAnimations(updatedGame.activitySettings);
setState(() {});
controller.dispose();
}
});
for (var i = 0; i < y; i++) {
animations[(y - i) - 1][x] = animation;
}
controller.forward().orCancel;
}
Widget buildBoard() {
final double widgetWidth = widget.widgetSize.width;
final double widgetHeight = widget.widgetSize.height;
final int rowsCount = widget.activity.activitySettings.boardSizeValue;
final int columnsCount = widget.activity.activitySettings.boardSizeValue;
final double cellWidth = widgetWidth / columnsCount;
final double cellHeight = widgetHeight / rowsCount;
if (animations.isEmpty) {
resetAnimations(widget.activity.activitySettings);
}
final List<Widget> cells = [];
for (var y = 0; y < rowsCount; y++) {
for (var x = 0; x < columnsCount; x++) {
final int? value = widget.activity.getCellValue(x, y);
if (value != null) {
final Animation<double>? translation = animations[y][x];
final Widget cellContent = CustomPaint(
size: Size(cellWidth, cellHeight),
willChange: false,
painter: CellPainter(value: value),
);
final Widget cellWidget = Positioned(
left: (x * cellWidth).toDouble(),
top: ((y + (translation?.value ?? 0)) * cellHeight).toDouble(),
child: SizedBox(
width: cellWidth,
height: cellHeight,
child: cellContent,
),
);
cells.add(cellWidget);
}
}
}
return Container(
width: widgetWidth,
height: widgetHeight,
color: Colors.black,
child: Stack(
children: cells,
),
);
}
Widget interactiveBoard(BuildContext context) {
final double widgetWidth = widget.widgetSize.width;
final double widgetHeight = widget.widgetSize.height;
final int rowsCount = widget.activity.activitySettings.boardSizeValue;
final int columnsCount = widget.activity.activitySettings.boardSizeValue;
return GestureDetector(
child: buildBoard(),
onTapUp: (details) {
bool canRemoveCell = true;
for (var row in animations) {
for (var cell in row) {
if (cell != null) {
canRemoveCell = false;
}
}
}
if (canRemoveCell) {
double xTap = details.localPosition.dx;
double yTap = details.localPosition.dy;
int x = (xTap / widgetWidth * columnsCount).toInt();
int y = (yTap / widgetHeight * rowsCount).toInt();
printlog('[$x,$y]');
removeCell(context, x, y);
} else {
printlog('animation in progress...');
}
},
);
}
@override
Widget build(BuildContext context) {
return Column(
children: [
interactiveBoard(context),
GameScoreWidget(activity: widget.activity),
],
);
}
}