parent
f5feea1db6
commit
67797ec2bc
|
@ -34,7 +34,7 @@ class Game {
|
|||
void init() {
|
||||
// TODO: [Leptopoda] _position is already initialized with Position(). seems like duplicate code
|
||||
_position = Position();
|
||||
focusIndex = blurIndex = invalidIndex;
|
||||
focusIndex = blurIndex = null;
|
||||
}
|
||||
|
||||
void start() {
|
||||
|
@ -47,7 +47,7 @@ class Game {
|
|||
position.phase = Phase.ready;
|
||||
start();
|
||||
position.init();
|
||||
focusIndex = blurIndex = invalidIndex;
|
||||
focusIndex = blurIndex = null;
|
||||
moveHistory = [""];
|
||||
sideToMove = PieceColor.white;
|
||||
}
|
||||
|
@ -64,8 +64,8 @@ class Game {
|
|||
Position _position = Position();
|
||||
Position get position => _position;
|
||||
|
||||
int focusIndex = invalidIndex;
|
||||
int blurIndex = invalidIndex;
|
||||
int? focusIndex;
|
||||
int? blurIndex;
|
||||
|
||||
Map<String, bool> isSearching = {
|
||||
PieceColor.white: false,
|
||||
|
@ -113,7 +113,7 @@ class Game {
|
|||
|
||||
void select(int pos) {
|
||||
focusIndex = pos;
|
||||
blurIndex = invalidIndex;
|
||||
blurIndex = null;
|
||||
}
|
||||
|
||||
Future<bool> doMove(String move) async {
|
||||
|
|
|
@ -522,7 +522,7 @@ class Position {
|
|||
} else {
|
||||
changeSideToMove();
|
||||
}
|
||||
gameInstance.focusIndex = squareToIndex[s] ?? invalidIndex;
|
||||
gameInstance.focusIndex = squareToIndex[s];
|
||||
await Audios.playTone(Sound.place);
|
||||
} else {
|
||||
pieceToRemoveCount = rule.mayRemoveMultiple ? n : 1;
|
||||
|
@ -558,7 +558,7 @@ class Position {
|
|||
action = Act.remove;
|
||||
}
|
||||
|
||||
gameInstance.focusIndex = squareToIndex[s] ?? invalidIndex;
|
||||
gameInstance.focusIndex = squareToIndex[s];
|
||||
await Audios.playTone(Sound.mill);
|
||||
}
|
||||
} else if (phase == Phase.moving) {
|
||||
|
@ -606,14 +606,14 @@ class Position {
|
|||
if (isGameOver()) {
|
||||
return true;
|
||||
} else {
|
||||
gameInstance.focusIndex = squareToIndex[s] ?? invalidIndex;
|
||||
gameInstance.focusIndex = squareToIndex[s];
|
||||
await Audios.playTone(Sound.place);
|
||||
}
|
||||
} else {
|
||||
pieceToRemoveCount = rule.mayRemoveMultiple ? n : 1;
|
||||
updateKeyMisc();
|
||||
action = Act.remove;
|
||||
gameInstance.focusIndex = squareToIndex[s] ?? invalidIndex;
|
||||
gameInstance.focusIndex = squareToIndex[s];
|
||||
await Audios.playTone(Sound.mill);
|
||||
}
|
||||
} else {
|
||||
|
@ -716,7 +716,7 @@ class Position {
|
|||
|
||||
currentSquare = sq;
|
||||
action = Act.place;
|
||||
gameInstance.blurIndex = squareToIndex[sq]!;
|
||||
gameInstance.blurIndex = squareToIndex[sq];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -301,8 +301,6 @@ int makeMove(int from, int to) {
|
|||
return (from << 8) + to;
|
||||
}
|
||||
|
||||
const invalidIndex = -1;
|
||||
|
||||
Map<int, int> squareToIndex = {
|
||||
8: 17,
|
||||
9: 18,
|
||||
|
|
|
@ -40,17 +40,12 @@ import 'package:sanmill/shared/custom_spacer.dart';
|
|||
import 'package:sanmill/shared/dialog.dart';
|
||||
import 'package:sanmill/shared/game_toolbar/game_toolbar.dart';
|
||||
import 'package:sanmill/shared/number_picker.dart';
|
||||
import 'package:sanmill/shared/painters/painters.dart';
|
||||
import 'package:sanmill/shared/snackbar.dart';
|
||||
import 'package:sanmill/shared/theme/app_theme.dart';
|
||||
import 'package:stack_trace/stack_trace.dart';
|
||||
|
||||
part 'package:sanmill/screens/game_page/board.dart';
|
||||
part 'package:sanmill/shared/painters/board_painter.dart';
|
||||
part 'package:sanmill/shared/painters/painter_base.dart';
|
||||
part 'package:sanmill/shared/painters/pieces_painter.dart';
|
||||
|
||||
// TODO: [Leptopoda] remove variables that are not part of an object
|
||||
double boardWidth = 0.0;
|
||||
|
||||
class GamePage extends StatefulWidget {
|
||||
final EngineType engineType;
|
||||
|
@ -77,6 +72,8 @@ class _GamePageState extends State<GamePage>
|
|||
late Animation<double> animation;
|
||||
bool disposed = false;
|
||||
late bool ltr;
|
||||
late double boardWidth;
|
||||
|
||||
static const String _tag = "[game_page]";
|
||||
|
||||
Future<void> _setReadyState() async {
|
||||
|
|
|
@ -1,314 +0,0 @@
|
|||
/*
|
||||
This file is part of Sanmill.
|
||||
Copyright (C) 2019-2021 The Sanmill developers (see AUTHORS file)
|
||||
|
||||
Sanmill is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Sanmill is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
part of 'package:sanmill/screens/game_page/game_page.dart';
|
||||
|
||||
class BoardPainter extends PiecesBasePainter {
|
||||
BoardPainter({required double width}) : super(width: width);
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
doPaint(
|
||||
canvas,
|
||||
thePaint,
|
||||
gridWidth,
|
||||
squareWidth,
|
||||
offsetX: AppTheme.boardPadding + squareWidth / 2,
|
||||
offsetY: AppTheme.boardPadding + squareWidth / 2,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(CustomPainter oldDelegate) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static void doPaint(
|
||||
Canvas canvas,
|
||||
Paint paint,
|
||||
double gridWidth,
|
||||
double squareWidth, {
|
||||
required double offsetX,
|
||||
required double offsetY,
|
||||
}) {
|
||||
paint.color = LocalDatabaseService.colorSettings.boardLineColor;
|
||||
paint.style = PaintingStyle.stroke;
|
||||
|
||||
final left = offsetX;
|
||||
final top = offsetY;
|
||||
|
||||
paint.strokeWidth = LocalDatabaseService.display.boardBorderLineWidth;
|
||||
|
||||
if (LocalDatabaseService.display.isPieceCountInHandShown) {
|
||||
var pieceInHandCount =
|
||||
gameInstance.position.pieceInHandCount[PieceColor.black];
|
||||
|
||||
if (gameInstance.position.pieceOnBoardCount[PieceColor.white] == 0 &&
|
||||
gameInstance.position.pieceOnBoardCount[PieceColor.black] == 0) {
|
||||
pieceInHandCount = LocalDatabaseService.rules.piecesCount;
|
||||
}
|
||||
|
||||
var pieceInHandCountStr = "";
|
||||
|
||||
// TODO: [Leptopoda] only paint it when the phase is placing.
|
||||
if (gameInstance.position.phase == Phase.placing) {
|
||||
pieceInHandCountStr = pieceInHandCount.toString();
|
||||
}
|
||||
|
||||
final TextSpan textSpan = TextSpan(
|
||||
style: TextStyle(
|
||||
fontSize: 48,
|
||||
color: LocalDatabaseService.colorSettings.boardLineColor,
|
||||
), // TODO
|
||||
text: pieceInHandCountStr,
|
||||
);
|
||||
|
||||
final TextPainter textPainter = TextPainter(
|
||||
text: textSpan,
|
||||
textAlign: TextAlign.center,
|
||||
textDirection: TextDirection.ltr,
|
||||
);
|
||||
|
||||
textPainter.layout();
|
||||
|
||||
textPainter.paint(
|
||||
canvas,
|
||||
Offset(
|
||||
left + squareWidth * 3 - textPainter.width / 2,
|
||||
top + squareWidth * 3 - textPainter.height / 2,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if (LocalDatabaseService.display.isNotationsShown) {
|
||||
const String verticalNotations = "abcdefg";
|
||||
const String horizontalNotations = "7654321";
|
||||
String notationV = "";
|
||||
String notationH = "";
|
||||
|
||||
for (int i = 0; i < 7; i++) {
|
||||
notationV = verticalNotations[i];
|
||||
notationH = horizontalNotations[i];
|
||||
|
||||
final TextSpan notationSpanV = TextSpan(
|
||||
style: AppTheme.notationTextStyle, // TODO
|
||||
text: notationV,
|
||||
);
|
||||
|
||||
final TextSpan notationSpanH = TextSpan(
|
||||
style: AppTheme.notationTextStyle, // TODO
|
||||
text: notationH,
|
||||
);
|
||||
|
||||
final TextPainter notationPainterV = TextPainter(
|
||||
text: notationSpanV,
|
||||
textAlign: TextAlign.center,
|
||||
textDirection: TextDirection.ltr,
|
||||
);
|
||||
|
||||
final TextPainter notationPainterH = TextPainter(
|
||||
text: notationSpanH,
|
||||
textAlign: TextAlign.center,
|
||||
textDirection: TextDirection.ltr,
|
||||
);
|
||||
|
||||
notationPainterV.layout();
|
||||
notationPainterH.layout();
|
||||
|
||||
final offset = (boardWidth - squareWidth * 6) / 4;
|
||||
|
||||
// Show notations "a b c d e f" on board
|
||||
|
||||
if (LocalDatabaseService.preferences.developerMode) {
|
||||
notationPainterV.paint(
|
||||
canvas,
|
||||
Offset(
|
||||
left + squareWidth * i - notationPainterV.width / 2,
|
||||
top - offset - notationPainterV.height / 2,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
notationPainterV.paint(
|
||||
canvas,
|
||||
Offset(
|
||||
left + squareWidth * i - notationPainterV.width / 2,
|
||||
top + squareWidth * 6 + offset - notationPainterV.height / 2,
|
||||
),
|
||||
);
|
||||
|
||||
// Show notations "1 2 3 4 5 6 7" on board
|
||||
|
||||
notationPainterH.paint(
|
||||
canvas,
|
||||
Offset(
|
||||
left - offset - notationPainterH.width / 2,
|
||||
top + squareWidth * i - notationPainterH.height / 2,
|
||||
),
|
||||
);
|
||||
|
||||
if (LocalDatabaseService.preferences.developerMode) {
|
||||
notationPainterH.paint(
|
||||
canvas,
|
||||
Offset(
|
||||
left + squareWidth * 6 + offset - notationPainterH.width / 2,
|
||||
top + squareWidth * i - notationPainterH.height / 2,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// File C
|
||||
canvas.drawRect(
|
||||
Rect.fromLTWH(left, top, squareWidth * 6, squareWidth * 6),
|
||||
paint,
|
||||
);
|
||||
|
||||
paint.strokeWidth = LocalDatabaseService.display.boardInnerLineWidth;
|
||||
final double bias = paint.strokeWidth / 2;
|
||||
|
||||
// File B
|
||||
canvas.drawRect(
|
||||
Rect.fromLTWH(
|
||||
left + squareWidth * 1,
|
||||
top + squareWidth * 1,
|
||||
squareWidth * 4,
|
||||
squareWidth * 4,
|
||||
),
|
||||
paint,
|
||||
);
|
||||
|
||||
// File A
|
||||
canvas.drawRect(
|
||||
Rect.fromLTWH(
|
||||
left + squareWidth * 2,
|
||||
top + squareWidth * 2,
|
||||
squareWidth * 2,
|
||||
squareWidth * 2,
|
||||
),
|
||||
paint,
|
||||
);
|
||||
|
||||
// Middle horizontal lines (Left to Right)
|
||||
|
||||
canvas.drawLine(
|
||||
Offset(left - bias, top + squareWidth * 3),
|
||||
Offset(left + squareWidth * 2 + bias, top + squareWidth * 3),
|
||||
paint,
|
||||
);
|
||||
|
||||
canvas.drawLine(
|
||||
Offset(left + squareWidth * 4 - bias, top + squareWidth * 3),
|
||||
Offset(left + squareWidth * 6 + bias, top + squareWidth * 3),
|
||||
paint,
|
||||
);
|
||||
|
||||
// Middle horizontal lines (Top to Bottom)
|
||||
|
||||
canvas.drawLine(
|
||||
Offset(left + squareWidth * 3, top - bias),
|
||||
Offset(left + squareWidth * 3, top + squareWidth * 2 + bias),
|
||||
paint,
|
||||
);
|
||||
|
||||
canvas.drawLine(
|
||||
Offset(left + squareWidth * 3, top + squareWidth * 4 - bias),
|
||||
Offset(left + squareWidth * 3, top + squareWidth * 6 + bias),
|
||||
paint,
|
||||
);
|
||||
|
||||
// Point
|
||||
if (LocalDatabaseService.display.pointStyle != 0) {
|
||||
if (LocalDatabaseService.display.pointStyle == 1) {
|
||||
paint.style = PaintingStyle.fill;
|
||||
} else if (LocalDatabaseService.display.pointStyle == 2) {
|
||||
paint.style = PaintingStyle.stroke; // TODO: WIP
|
||||
}
|
||||
|
||||
final double pointRadius = LocalDatabaseService.display.pointWidth;
|
||||
|
||||
final points = [
|
||||
[0, 0],
|
||||
[0, 3],
|
||||
[0, 6],
|
||||
[1, 1],
|
||||
[1, 3],
|
||||
[1, 5],
|
||||
[2, 2],
|
||||
[2, 3],
|
||||
[2, 4],
|
||||
[3, 0],
|
||||
[3, 1],
|
||||
[3, 2],
|
||||
[3, 4],
|
||||
[3, 5],
|
||||
[3, 6],
|
||||
[4, 2],
|
||||
[4, 3],
|
||||
[4, 4],
|
||||
[5, 1],
|
||||
[5, 3],
|
||||
[5, 5],
|
||||
[6, 0],
|
||||
[6, 3],
|
||||
[6, 6],
|
||||
];
|
||||
|
||||
for (final point in points) {
|
||||
canvas.drawCircle(
|
||||
Offset(left + squareWidth * point[0], top + squareWidth * point[1]),
|
||||
pointRadius,
|
||||
paint,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!LocalDatabaseService.rules.hasDiagonalLines) {
|
||||
return;
|
||||
}
|
||||
|
||||
// top left diagonal line
|
||||
canvas.drawLine(
|
||||
Offset(left + 0, top),
|
||||
Offset(left + squareWidth * 2, top + squareWidth * 2),
|
||||
paint,
|
||||
);
|
||||
|
||||
// lower right diagonal line
|
||||
canvas.drawLine(
|
||||
Offset(left + squareWidth * 4, top + squareWidth * 4),
|
||||
Offset(left + squareWidth * 6, top + squareWidth * 6),
|
||||
paint,
|
||||
);
|
||||
|
||||
// top right diagonal line
|
||||
canvas.drawLine(
|
||||
Offset(left + squareWidth * 6, top),
|
||||
Offset(left + squareWidth * 4, top + squareWidth * 2),
|
||||
paint,
|
||||
);
|
||||
|
||||
// lower left diagonal line
|
||||
canvas.drawLine(
|
||||
Offset(left + squareWidth * 2, top + squareWidth * 4),
|
||||
Offset(left + squareWidth * 0, top + squareWidth * 6),
|
||||
paint,
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
This file is part of Sanmill.
|
||||
Copyright (C) 2019-2021 The Sanmill developers (see AUTHORS file)
|
||||
|
||||
Sanmill is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Sanmill is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/// Although marked as a library this package is tightly integrated into the app
|
||||
library painters;
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sanmill/mill/game.dart';
|
||||
import 'package:sanmill/mill/position.dart';
|
||||
import 'package:sanmill/mill/types.dart';
|
||||
import 'package:sanmill/services/storage/storage.dart';
|
||||
import 'package:sanmill/shared/theme/app_theme.dart';
|
||||
|
||||
part 'src/board_painter.dart';
|
||||
part 'src/painter_base.dart';
|
||||
part 'src/pieces_painter.dart';
|
|
@ -1,214 +0,0 @@
|
|||
/*
|
||||
This file is part of Sanmill.
|
||||
Copyright (C) 2019-2021 The Sanmill developers (see AUTHORS file)
|
||||
|
||||
Sanmill is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Sanmill is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
part of 'package:sanmill/screens/game_page/game_page.dart';
|
||||
|
||||
class PiecePaintParam {
|
||||
final String piece;
|
||||
final Offset pos;
|
||||
final bool animated;
|
||||
PiecePaintParam({
|
||||
required this.piece,
|
||||
required this.pos,
|
||||
required this.animated,
|
||||
});
|
||||
}
|
||||
|
||||
class PiecesPainter extends PiecesBasePainter {
|
||||
final Position position;
|
||||
final int focusIndex;
|
||||
final int blurIndex;
|
||||
final double animationValue;
|
||||
|
||||
int pointStyle = 0;
|
||||
double pointWidth = 10.0;
|
||||
double pieceWidth = 0.0;
|
||||
double animatedPieceWidth = 0.0;
|
||||
|
||||
PiecesPainter({
|
||||
required double width,
|
||||
required this.position,
|
||||
this.focusIndex = invalidIndex,
|
||||
this.blurIndex = invalidIndex,
|
||||
required this.animationValue,
|
||||
}) : super(width: width) {
|
||||
pointStyle = LocalDatabaseService.display.pointStyle;
|
||||
pointWidth = LocalDatabaseService.display.pointWidth;
|
||||
pieceWidth = squareWidth * LocalDatabaseService.display.pieceWidth;
|
||||
animatedPieceWidth =
|
||||
squareWidth * LocalDatabaseService.display.pieceWidth * animationValue;
|
||||
}
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
doPaint(
|
||||
canvas,
|
||||
thePaint,
|
||||
position: position,
|
||||
gridWidth: gridWidth,
|
||||
squareWidth: squareWidth,
|
||||
pointStyle: pointStyle,
|
||||
pointWidth: pointWidth,
|
||||
pieceWidth: pieceWidth,
|
||||
animatedPieceWidth: animatedPieceWidth,
|
||||
offsetX: AppTheme.boardPadding + squareWidth / 2,
|
||||
offsetY: AppTheme.boardPadding + squareWidth / 2,
|
||||
focusIndex: focusIndex,
|
||||
blurIndex: blurIndex,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(CustomPainter oldDelegate) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static void doPaint(
|
||||
Canvas canvas,
|
||||
Paint paint, {
|
||||
required Position position,
|
||||
required double gridWidth,
|
||||
required double squareWidth,
|
||||
required int pointStyle,
|
||||
required double pointWidth,
|
||||
required double pieceWidth,
|
||||
required double animatedPieceWidth,
|
||||
required double offsetX,
|
||||
required double offsetY,
|
||||
int focusIndex = invalidIndex,
|
||||
int blurIndex = invalidIndex,
|
||||
}) {
|
||||
final left = offsetX;
|
||||
final top = offsetY;
|
||||
|
||||
final shadowPath = Path();
|
||||
final piecesToDraw = <PiecePaintParam>[];
|
||||
|
||||
late Color blurPositionColor;
|
||||
Color focusPositionColor;
|
||||
|
||||
// Draw pieces on board
|
||||
for (var row = 0; row < 7; row++) {
|
||||
for (var col = 0; col < 7; col++) {
|
||||
final index = row * 7 + col;
|
||||
final piece = position.pieceOnGrid(index); // No Pieces when initial
|
||||
|
||||
if (piece == Piece.noPiece) continue;
|
||||
|
||||
final pos = Offset(left + squareWidth * col, top + squareWidth * row);
|
||||
final animated = focusIndex == index;
|
||||
|
||||
piecesToDraw
|
||||
.add(PiecePaintParam(piece: piece, pos: pos, animated: animated));
|
||||
|
||||
shadowPath.addOval(
|
||||
Rect.fromCenter(center: pos, width: pieceWidth, height: pieceWidth),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw shadow of piece
|
||||
canvas.drawShadow(shadowPath, Colors.black, 2, true);
|
||||
|
||||
paint.style = PaintingStyle.fill;
|
||||
|
||||
for (final pps in piecesToDraw) {
|
||||
final pieceRadius = pieceWidth / 2;
|
||||
final pieceInnerRadius = pieceRadius * 0.99;
|
||||
|
||||
final animatedPieceRadius = animatedPieceWidth / 2;
|
||||
final animatedPieceInnerRadius = animatedPieceRadius * 0.99;
|
||||
|
||||
// Draw Border of Piece
|
||||
switch (pps.piece) {
|
||||
case Piece.whiteStone:
|
||||
paint.color = AppTheme.whitePieceBorderColor;
|
||||
canvas.drawCircle(
|
||||
pps.pos,
|
||||
pps.animated ? animatedPieceRadius : pieceRadius,
|
||||
paint,
|
||||
);
|
||||
paint.color = LocalDatabaseService.colorSettings.whitePieceColor;
|
||||
canvas.drawCircle(
|
||||
pps.pos,
|
||||
pps.animated ? animatedPieceInnerRadius : pieceInnerRadius,
|
||||
paint,
|
||||
);
|
||||
blurPositionColor = LocalDatabaseService.colorSettings.whitePieceColor
|
||||
.withOpacity(0.1);
|
||||
break;
|
||||
case Piece.blackStone:
|
||||
paint.color = AppTheme.blackPieceBorderColor;
|
||||
canvas.drawCircle(
|
||||
pps.pos,
|
||||
pps.animated ? animatedPieceRadius : pieceRadius,
|
||||
paint,
|
||||
);
|
||||
paint.color = LocalDatabaseService.colorSettings.blackPieceColor;
|
||||
canvas.drawCircle(
|
||||
pps.pos,
|
||||
pps.animated ? animatedPieceInnerRadius : pieceInnerRadius,
|
||||
paint,
|
||||
);
|
||||
blurPositionColor = LocalDatabaseService.colorSettings.blackPieceColor
|
||||
.withOpacity(0.1);
|
||||
break;
|
||||
case Piece.ban:
|
||||
//print("pps.piece is Ban");
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// draw focus and blur position
|
||||
|
||||
final int row = focusIndex ~/ 7;
|
||||
final int column = focusIndex % 7;
|
||||
|
||||
if (focusIndex != invalidIndex) {
|
||||
focusPositionColor =
|
||||
LocalDatabaseService.colorSettings.pieceHighlightColor;
|
||||
|
||||
paint.color = focusPositionColor;
|
||||
paint.style = PaintingStyle.stroke;
|
||||
paint.strokeWidth = 2;
|
||||
|
||||
canvas.drawCircle(
|
||||
Offset(left + column * squareWidth, top + row * squareWidth),
|
||||
animatedPieceWidth / 2,
|
||||
paint,
|
||||
);
|
||||
}
|
||||
|
||||
if (blurIndex != invalidIndex) {
|
||||
final row = blurIndex ~/ 7;
|
||||
final column = blurIndex % 7;
|
||||
|
||||
paint.color = blurPositionColor;
|
||||
paint.style = PaintingStyle.fill;
|
||||
|
||||
canvas.drawCircle(
|
||||
Offset(left + column * squareWidth, top + row * squareWidth),
|
||||
animatedPieceWidth / 2 * 0.8,
|
||||
paint,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,266 @@
|
|||
/*
|
||||
This file is part of Sanmill.
|
||||
Copyright (C) 2019-2021 The Sanmill developers (see AUTHORS file)
|
||||
|
||||
Sanmill is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Sanmill is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
part of '../painters.dart';
|
||||
|
||||
class BoardPainter extends PiecesBasePainter {
|
||||
BoardPainter({required double width}) : super(width: width);
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) => _doPaint(canvas, thePaint);
|
||||
|
||||
@override
|
||||
bool shouldRepaint(CustomPainter oldDelegate) => false;
|
||||
|
||||
void _doPaint(Canvas canvas, Paint paint) {
|
||||
paint.strokeWidth = LocalDatabaseService.display.boardBorderLineWidth;
|
||||
paint.color = LocalDatabaseService.colorSettings.boardLineColor;
|
||||
paint.style = PaintingStyle.stroke;
|
||||
|
||||
if (LocalDatabaseService.display.isPieceCountInHandShown &&
|
||||
gameInstance.position.phase == Phase.placing) {
|
||||
final int pieceInHandCount;
|
||||
if (gameInstance.position.pieceOnBoardCount[PieceColor.white] == 0 &&
|
||||
gameInstance.position.pieceOnBoardCount[PieceColor.black] == 0) {
|
||||
pieceInHandCount = LocalDatabaseService.rules.piecesCount;
|
||||
} else {
|
||||
pieceInHandCount =
|
||||
gameInstance.position.pieceInHandCount[PieceColor.black]!;
|
||||
}
|
||||
|
||||
final TextSpan textSpan = TextSpan(
|
||||
style: TextStyle(
|
||||
fontSize: 48,
|
||||
color: LocalDatabaseService.colorSettings.boardLineColor,
|
||||
), // TODO
|
||||
text: pieceInHandCount.toString(),
|
||||
);
|
||||
|
||||
final TextPainter textPainter = TextPainter(
|
||||
text: textSpan,
|
||||
textAlign: TextAlign.center,
|
||||
textDirection: TextDirection.ltr,
|
||||
);
|
||||
|
||||
textPainter.layout();
|
||||
|
||||
textPainter.paint(
|
||||
canvas,
|
||||
_offset.translate(
|
||||
_squareWidth * 3 - textPainter.width / 2,
|
||||
_squareWidth * 3 - textPainter.height / 2,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if (LocalDatabaseService.display.isNotationsShown) {
|
||||
const String verticalNotations = "abcdefg";
|
||||
const String horizontalNotations = "7654321";
|
||||
|
||||
for (int i = 0; i < 7; i++) {
|
||||
final String notationV = verticalNotations[i];
|
||||
final String notationH = horizontalNotations[i];
|
||||
|
||||
final TextSpan notationSpanV = TextSpan(
|
||||
style: AppTheme.notationTextStyle, // TODO
|
||||
text: notationV,
|
||||
);
|
||||
|
||||
final TextSpan notationSpanH = TextSpan(
|
||||
style: AppTheme.notationTextStyle, // TODO
|
||||
text: notationH,
|
||||
);
|
||||
|
||||
final TextPainter notationPainterV = TextPainter(
|
||||
text: notationSpanV,
|
||||
textAlign: TextAlign.center,
|
||||
textDirection: TextDirection.ltr,
|
||||
);
|
||||
|
||||
final TextPainter notationPainterH = TextPainter(
|
||||
text: notationSpanH,
|
||||
textAlign: TextAlign.center,
|
||||
textDirection: TextDirection.ltr,
|
||||
);
|
||||
|
||||
notationPainterV.layout();
|
||||
notationPainterH.layout();
|
||||
|
||||
final offset = (width - _squareWidth * 6) / 4;
|
||||
|
||||
// Show notations "a b c d e f" on board
|
||||
if (LocalDatabaseService.preferences.developerMode) {
|
||||
notationPainterV.paint(
|
||||
canvas,
|
||||
_offset.translate(
|
||||
_squareWidth * i - notationPainterV.width / 2,
|
||||
-offset - notationPainterV.height / 2,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
notationPainterV.paint(
|
||||
canvas,
|
||||
_offset.translate(
|
||||
_squareWidth * i - notationPainterV.width / 2,
|
||||
_squareWidth * 6 + offset - notationPainterV.height / 2,
|
||||
),
|
||||
);
|
||||
|
||||
// Show notations "1 2 3 4 5 6 7" on board
|
||||
notationPainterH.paint(
|
||||
canvas,
|
||||
_offset.translate(
|
||||
-offset - notationPainterH.width / 2,
|
||||
_squareWidth * i - notationPainterH.height / 2,
|
||||
),
|
||||
);
|
||||
|
||||
if (LocalDatabaseService.preferences.developerMode) {
|
||||
notationPainterH.paint(
|
||||
canvas,
|
||||
_offset.translate(
|
||||
_squareWidth * 6 + offset - notationPainterH.width / 2,
|
||||
_squareWidth * i - notationPainterH.height / 2,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final points = [
|
||||
_offset + Offset(_squareWidth * 0, _squareWidth * 0), // 0
|
||||
_offset + Offset(_squareWidth * 0, _squareWidth * 3), // 1
|
||||
_offset + Offset(_squareWidth * 0, _squareWidth * 6), // 2
|
||||
_offset + Offset(_squareWidth * 1, _squareWidth * 1), // 3
|
||||
_offset + Offset(_squareWidth * 1, _squareWidth * 3), // 4
|
||||
_offset + Offset(_squareWidth * 1, _squareWidth * 5), // 5
|
||||
_offset + Offset(_squareWidth * 2, _squareWidth * 2), // 6
|
||||
_offset + Offset(_squareWidth * 2, _squareWidth * 3), // 7
|
||||
_offset + Offset(_squareWidth * 2, _squareWidth * 4), // 8
|
||||
_offset + Offset(_squareWidth * 3, _squareWidth * 0), // 9
|
||||
_offset + Offset(_squareWidth * 3, _squareWidth * 1), // 10
|
||||
_offset + Offset(_squareWidth * 3, _squareWidth * 2), // 11
|
||||
_offset + Offset(_squareWidth * 3, _squareWidth * 4), // 12
|
||||
_offset + Offset(_squareWidth * 3, _squareWidth * 5), // 13
|
||||
_offset + Offset(_squareWidth * 3, _squareWidth * 6), // 14
|
||||
_offset + Offset(_squareWidth * 4, _squareWidth * 2), // 15
|
||||
_offset + Offset(_squareWidth * 4, _squareWidth * 3), // 16
|
||||
_offset + Offset(_squareWidth * 4, _squareWidth * 4), // 17
|
||||
_offset + Offset(_squareWidth * 5, _squareWidth * 1), // 18
|
||||
_offset + Offset(_squareWidth * 5, _squareWidth * 3), // 19
|
||||
_offset + Offset(_squareWidth * 5, _squareWidth * 5), // 20
|
||||
_offset + Offset(_squareWidth * 6, _squareWidth * 0), // 21
|
||||
_offset + Offset(_squareWidth * 6, _squareWidth * 3), // 22
|
||||
_offset + Offset(_squareWidth * 6, _squareWidth * 6), // 23
|
||||
];
|
||||
|
||||
// File C
|
||||
canvas.drawRect(
|
||||
Rect.fromLTWH(_offset.dx, _offset.dy, _squareWidth * 6, _squareWidth * 6),
|
||||
paint,
|
||||
);
|
||||
|
||||
paint.strokeWidth = LocalDatabaseService.display.boardInnerLineWidth;
|
||||
final double bias = paint.strokeWidth / 2;
|
||||
|
||||
// File B
|
||||
canvas.drawRect(
|
||||
Rect.fromLTWH(
|
||||
_offset.dx + _squareWidth * 1,
|
||||
_offset.dy + _squareWidth * 1,
|
||||
_squareWidth * 4,
|
||||
_squareWidth * 4,
|
||||
),
|
||||
paint,
|
||||
);
|
||||
|
||||
// File A
|
||||
canvas.drawRect(
|
||||
Rect.fromLTWH(
|
||||
_offset.dx + _squareWidth * 2,
|
||||
_offset.dy + _squareWidth * 2,
|
||||
_squareWidth * 2,
|
||||
_squareWidth * 2,
|
||||
),
|
||||
paint,
|
||||
);
|
||||
|
||||
// Middle horizontal lines (offsetX to Right)
|
||||
canvas.drawLine(
|
||||
points[1].translate(-bias, 0),
|
||||
points[7].translate(bias, 0),
|
||||
paint,
|
||||
);
|
||||
|
||||
canvas.drawLine(
|
||||
points[16].translate(-bias, 0),
|
||||
points[22].translate(bias, 0),
|
||||
paint,
|
||||
);
|
||||
|
||||
// Middle horizontal lines (offsetY to Bottom)
|
||||
canvas.drawLine(
|
||||
points[9].translate(0, -bias),
|
||||
points[11].translate(0, bias),
|
||||
paint,
|
||||
);
|
||||
|
||||
canvas.drawLine(
|
||||
points[12].translate(0, -bias),
|
||||
points[14].translate(0, bias),
|
||||
paint,
|
||||
);
|
||||
|
||||
// TODO: [Leptopoda] use enum or so :)
|
||||
// Point
|
||||
switch (LocalDatabaseService.display.pointStyle) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
paint.style = PaintingStyle.fill;
|
||||
_drawPoint(points, canvas, paint);
|
||||
break;
|
||||
case 2:
|
||||
paint.style = PaintingStyle.stroke;
|
||||
_drawPoint(points, canvas, paint);
|
||||
}
|
||||
|
||||
if (LocalDatabaseService.rules.hasDiagonalLines) {
|
||||
// offsetY offsetX diagonal line
|
||||
canvas.drawLine(points[0], points[6], paint);
|
||||
|
||||
// lower right diagonal line
|
||||
canvas.drawLine(points[17], points[23], paint);
|
||||
|
||||
// offsetY right diagonal line
|
||||
canvas.drawLine(points[21], points[15], paint);
|
||||
|
||||
// lower offsetX diagonal line
|
||||
canvas.drawLine(points[8], points[2], paint);
|
||||
}
|
||||
}
|
||||
|
||||
static void _drawPoint(List<Offset> points, Canvas canvas, Paint paint) {
|
||||
final double pointRadius = LocalDatabaseService.display.pointWidth;
|
||||
|
||||
for (final point in points) {
|
||||
canvas.drawCircle(point, pointRadius, paint);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,16 +16,21 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
part of 'package:sanmill/screens/game_page/game_page.dart';
|
||||
part of '../painters.dart';
|
||||
|
||||
abstract class PiecesBasePainter extends CustomPainter {
|
||||
final double width;
|
||||
|
||||
final thePaint = Paint();
|
||||
final double gridWidth;
|
||||
final double squareWidth;
|
||||
late final double _squareWidth;
|
||||
late final Offset _offset;
|
||||
|
||||
PiecesBasePainter({required this.width})
|
||||
: gridWidth = width - AppTheme.boardPadding * 2,
|
||||
squareWidth = (width - AppTheme.boardPadding * 2) / 7;
|
||||
PiecesBasePainter({required this.width}) {
|
||||
_squareWidth = (width - AppTheme.boardPadding * 2) / 7;
|
||||
|
||||
// equivalent to (width + 12 * AppTheme.boardPadding) / 14
|
||||
final offset = AppTheme.boardPadding + _squareWidth / 2;
|
||||
|
||||
_offset = Offset(offset, offset);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
This file is part of Sanmill.
|
||||
Copyright (C) 2019-2021 The Sanmill developers (see AUTHORS file)
|
||||
|
||||
Sanmill is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Sanmill is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
part of '../painters.dart';
|
||||
|
||||
class _PiecePaintParam {
|
||||
final String piece;
|
||||
final Offset pos;
|
||||
final bool animated;
|
||||
|
||||
const _PiecePaintParam({
|
||||
required this.piece,
|
||||
required this.pos,
|
||||
required this.animated,
|
||||
});
|
||||
}
|
||||
|
||||
class PiecesPainter extends PiecesBasePainter {
|
||||
final Position position;
|
||||
final int? focusIndex;
|
||||
final int? blurIndex;
|
||||
final double animationValue;
|
||||
|
||||
late final int pointStyle;
|
||||
late final double pointWidth;
|
||||
late final double pieceWidth;
|
||||
late final double animatedPieceWidth;
|
||||
|
||||
PiecesPainter({
|
||||
required double width,
|
||||
required this.position,
|
||||
this.focusIndex,
|
||||
this.blurIndex,
|
||||
required this.animationValue,
|
||||
}) : super(width: width) {
|
||||
pointStyle = LocalDatabaseService.display.pointStyle;
|
||||
pointWidth = LocalDatabaseService.display.pointWidth;
|
||||
pieceWidth = _squareWidth * LocalDatabaseService.display.pieceWidth;
|
||||
animatedPieceWidth =
|
||||
_squareWidth * LocalDatabaseService.display.pieceWidth * animationValue;
|
||||
}
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) => _doPaint(canvas, thePaint);
|
||||
|
||||
@override
|
||||
bool shouldRepaint(CustomPainter oldDelegate) => true;
|
||||
|
||||
void _doPaint(Canvas canvas, Paint paint) {
|
||||
final shadowPath = Path();
|
||||
final piecesToDraw = <_PiecePaintParam>[];
|
||||
|
||||
// Draw pieces on board
|
||||
for (var row = 0; row < 7; row++) {
|
||||
for (var col = 0; col < 7; col++) {
|
||||
final index = row * 7 + col;
|
||||
final piece = position.pieceOnGrid(index); // No Pieces when initial
|
||||
|
||||
if (piece == Piece.noPiece) continue;
|
||||
|
||||
final pos = _offset.translate(_squareWidth * col, _squareWidth * row);
|
||||
final animated = focusIndex == index;
|
||||
|
||||
piecesToDraw
|
||||
.add(_PiecePaintParam(piece: piece, pos: pos, animated: animated));
|
||||
|
||||
shadowPath.addOval(
|
||||
Rect.fromCenter(center: pos, width: pieceWidth, height: pieceWidth),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw shadow of piece
|
||||
canvas.drawShadow(shadowPath, Colors.black, 2, true);
|
||||
paint.style = PaintingStyle.fill;
|
||||
|
||||
late Color blurPositionColor;
|
||||
for (final pps in piecesToDraw) {
|
||||
final pieceRadius = pieceWidth / 2;
|
||||
final pieceInnerRadius = pieceRadius * 0.99;
|
||||
|
||||
final animatedPieceRadius = animatedPieceWidth / 2;
|
||||
final animatedPieceInnerRadius = animatedPieceRadius * 0.99;
|
||||
|
||||
// TODO: [Leptopoda] move the following attributes into [_PiecePaintParam]
|
||||
// Draw Border of Piece
|
||||
late final Color border;
|
||||
late final Color piece;
|
||||
switch (pps.piece) {
|
||||
case Piece.whiteStone:
|
||||
border = AppTheme.whitePieceBorderColor;
|
||||
piece = LocalDatabaseService.colorSettings.whitePieceColor;
|
||||
blurPositionColor = LocalDatabaseService.colorSettings.whitePieceColor
|
||||
.withOpacity(0.1);
|
||||
break;
|
||||
case Piece.blackStone:
|
||||
border = AppTheme.blackPieceBorderColor;
|
||||
piece = LocalDatabaseService.colorSettings.blackPieceColor;
|
||||
blurPositionColor = LocalDatabaseService.colorSettings.blackPieceColor
|
||||
.withOpacity(0.1);
|
||||
break;
|
||||
case Piece.ban:
|
||||
//print("pps.piece is Ban");
|
||||
continue;
|
||||
}
|
||||
|
||||
paint.color = border;
|
||||
canvas.drawCircle(
|
||||
pps.pos,
|
||||
pps.animated ? animatedPieceRadius : pieceRadius,
|
||||
paint,
|
||||
);
|
||||
paint.color = piece;
|
||||
canvas.drawCircle(
|
||||
pps.pos,
|
||||
pps.animated ? animatedPieceInnerRadius : pieceInnerRadius,
|
||||
paint,
|
||||
);
|
||||
}
|
||||
|
||||
// draw focus and blur position
|
||||
if (focusIndex != null) {
|
||||
final row = focusIndex! ~/ 7;
|
||||
final column = focusIndex! % 7;
|
||||
|
||||
paint.color = LocalDatabaseService.colorSettings.pieceHighlightColor;
|
||||
paint.style = PaintingStyle.stroke;
|
||||
paint.strokeWidth = 2;
|
||||
|
||||
canvas.drawCircle(
|
||||
_offset.translate(column * _squareWidth, row * _squareWidth),
|
||||
animatedPieceWidth / 2,
|
||||
paint,
|
||||
);
|
||||
}
|
||||
|
||||
if (blurIndex != null) {
|
||||
final row = blurIndex! ~/ 7;
|
||||
final column = blurIndex! % 7;
|
||||
|
||||
paint.color = blurPositionColor;
|
||||
paint.style = PaintingStyle.fill;
|
||||
|
||||
canvas.drawCircle(
|
||||
_offset.translate(column * _squareWidth, row * _squareWidth),
|
||||
animatedPieceWidth / 2 * 0.8,
|
||||
paint,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue