Marco
212a54612c
This adds an option to dragging-and-dropping which is slightly hard on smaller screens. Fix promotions when tapping and fix handling of subsequently tapping two pieces of your color Cancel tap if a drag is started (tapped square will not stay red in case a drag is started) Change url strategy back to the hashtag thing Change version Fix bug that would not allow a piece move if you tried to take an opponents piece. Fix the coloring of the last move after an invalid move was played. Upgrading deps
122 lines
3.7 KiB
Dart
122 lines
3.7 KiB
Dart
import 'dart:developer';
|
|
import 'dart:math' as math;
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:mchess/chess_bloc/chess_bloc.dart';
|
|
|
|
import 'chess_square.dart';
|
|
import '../utils/chess_utils.dart';
|
|
|
|
class ChessBoard extends StatelessWidget {
|
|
final ChessBoardState bState;
|
|
final List<ChessSquare> squares;
|
|
|
|
const ChessBoard._({required this.bState, required this.squares});
|
|
|
|
factory ChessBoard(
|
|
{required ChessBoardState boardState, ChessCoordinate? tappedSquare}) {
|
|
List<ChessSquare> squares = List.empty(growable: true);
|
|
for (int i = 0; i < 64; i++) {
|
|
var column = (i % 8) + 1;
|
|
var row = (i ~/ 8) + 1;
|
|
|
|
final piece = boardState.position[ChessCoordinate(column, row)];
|
|
|
|
bool squareWasPartOfLastMove = false;
|
|
if ((boardState.lastMove.to == ChessCoordinate(column, row) ||
|
|
boardState.lastMove.from == ChessCoordinate(column, row)) &&
|
|
boardState.colorLastMove) {
|
|
squareWasPartOfLastMove = true;
|
|
}
|
|
|
|
squares.add(
|
|
ChessSquare(
|
|
ChessCoordinate(column, row),
|
|
piece,
|
|
squareWasPartOfLastMove,
|
|
tappedSquare == ChessCoordinate(column, row)),
|
|
);
|
|
}
|
|
|
|
return ChessBoard._(bState: boardState, squares: squares);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
log("ChessBoard's build()");
|
|
|
|
return LayoutBuilder(builder: (context, constraints) {
|
|
/*We calculate the margins manually, because otherwise we would have
|
|
lines that are 1 pixel wide between the squares (which is ugly)*/
|
|
int smallerSize =
|
|
math.min(constraints.maxWidth.toInt(), constraints.maxHeight.toInt());
|
|
int desiredSize = smallerSize - smallerSize % 8;
|
|
int verticalMargin = constraints.maxHeight.toInt() - desiredSize;
|
|
int verticalMarginTop = verticalMargin ~/ 2;
|
|
int verticalMarginBottom = verticalMargin - verticalMarginTop;
|
|
int horizontalMargin = constraints.maxWidth.toInt() - desiredSize;
|
|
int horizontalMarginLeft = horizontalMargin ~/ 2;
|
|
int horizontalMarginRight = horizontalMargin - horizontalMarginLeft;
|
|
return Container(
|
|
margin: EdgeInsets.only(
|
|
left: horizontalMarginLeft.toDouble(),
|
|
right: horizontalMarginRight.toDouble(),
|
|
top: verticalMarginTop.toDouble(),
|
|
bottom: verticalMarginBottom.toDouble(),
|
|
),
|
|
child: FittedBox(
|
|
fit: BoxFit.contain,
|
|
child: Container(
|
|
decoration: const BoxDecoration(boxShadow: [
|
|
BoxShadow(color: Colors.black, offset: Offset(10, 10))
|
|
]),
|
|
child: _buildBoard(bState.bottomColor == ChessColor.black),
|
|
),
|
|
),
|
|
);
|
|
});
|
|
}
|
|
|
|
Row _buildChessRow(int rowNo, bool flipped) {
|
|
if (!flipped) {
|
|
return Row(
|
|
children: [
|
|
for (int i = 8 * rowNo - 8; i < 8 * rowNo; i++) squares.elementAt(i)
|
|
],
|
|
);
|
|
} else {
|
|
return Row(
|
|
children: [
|
|
for (int i = 8 * rowNo - 1; i >= 8 * rowNo - 8; i--)
|
|
squares.elementAt(i)
|
|
],
|
|
);
|
|
}
|
|
}
|
|
|
|
Column _buildBoard(bool flipped) {
|
|
List<Row> chessBoard = <Row>[];
|
|
|
|
if (!flipped) {
|
|
for (int row = 8; row > 0; row--) {
|
|
chessBoard.add(_buildChessRow(row, flipped));
|
|
}
|
|
} else {
|
|
for (int row = 1; row <= 8; row++) {
|
|
chessBoard.add(_buildChessRow(row, flipped));
|
|
}
|
|
}
|
|
|
|
return Column(children: [...chessBoard]);
|
|
}
|
|
|
|
ChessSquare getSquareAtCoordinate(ChessCoordinate coord) {
|
|
/* Calculate index in squares[] from column and row */
|
|
int index = (coord.row - 1) * 8 + (coord.column - 1);
|
|
|
|
log("getSquareAtCoordinates: index calculated to $index");
|
|
|
|
return squares.elementAt(index);
|
|
}
|
|
}
|