Lay foundation for promotions.
This commit is contained in:
parent
52540ec96c
commit
3bec7a84d8
@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:mchess/chess_bloc/chess_bloc.dart';
|
import 'package:mchess/chess_bloc/chess_bloc.dart';
|
||||||
|
import 'package:mchess/chess_bloc/promotion_bloc.dart';
|
||||||
import 'package:mchess/connection_cubit/connection_cubit.dart';
|
import 'package:mchess/connection_cubit/connection_cubit.dart';
|
||||||
import 'package:mchess/utils/chess_router.dart';
|
import 'package:mchess/utils/chess_router.dart';
|
||||||
|
|
||||||
@ -9,17 +10,24 @@ class ChessApp extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return MultiBlocProvider(
|
||||||
create: (_) => ConnectionCubit.getInstance(),
|
providers: [
|
||||||
child: BlocProvider(
|
BlocProvider(
|
||||||
create: (_) => ChessBloc.getInstance(),
|
create: (_) => ConnectionCubit.getInstance(),
|
||||||
child: MaterialApp.router(
|
|
||||||
theme: ThemeData.dark(
|
|
||||||
useMaterial3: true,
|
|
||||||
),
|
|
||||||
routerConfig: ChessAppRouter.getInstance().router,
|
|
||||||
title: 'mChess',
|
|
||||||
),
|
),
|
||||||
|
BlocProvider(
|
||||||
|
create: (context) => ChessBloc.getInstance(),
|
||||||
|
),
|
||||||
|
BlocProvider(
|
||||||
|
create: (context) => PromotionUiBloc.getInstance(),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
child: MaterialApp.router(
|
||||||
|
theme: ThemeData.dark(
|
||||||
|
useMaterial3: true,
|
||||||
|
),
|
||||||
|
routerConfig: ChessAppRouter.getInstance().router,
|
||||||
|
title: 'mChess',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ import 'package:flutter/foundation.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:mchess/chess_bloc/chess_bloc.dart';
|
import 'package:mchess/chess_bloc/chess_bloc.dart';
|
||||||
|
import 'package:mchess/chess_bloc/promotion_bloc.dart';
|
||||||
|
|
||||||
import '../chess_bloc/chess_events.dart';
|
import '../chess_bloc/chess_events.dart';
|
||||||
import '../utils/chess_utils.dart';
|
import '../utils/chess_utils.dart';
|
||||||
@ -58,7 +59,7 @@ class ChessSquare extends StatelessWidget {
|
|||||||
draggableFdbSize = 0.15 * windowHeight;
|
draggableFdbSize = 0.15 * windowHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
return DragTarget<PieceMovedFrom>(
|
return DragTarget<PieceDragged>(
|
||||||
onWillAccept: (move) {
|
onWillAccept: (move) {
|
||||||
if (move?.fromSquare == coordinate) {
|
if (move?.fromSquare == coordinate) {
|
||||||
return false;
|
return false;
|
||||||
@ -66,9 +67,17 @@ class ChessSquare extends StatelessWidget {
|
|||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
onAccept: (move) {
|
onAccept: (move) {
|
||||||
if (coordinate != move.fromSquare) {
|
// Replace the dummy value with the actual target of the move.
|
||||||
|
move.toSquare = coordinate;
|
||||||
|
|
||||||
|
if (isPromotionMove(move)) {
|
||||||
|
PromotionUiBloc.getInstance().add(PawnMovedToPromotionField(
|
||||||
|
endSquare: move.toSquare, colorMoved: ChessBloc.myColor!));
|
||||||
|
} else if (coordinate != move.fromSquare) {
|
||||||
ChessBloc.getInstance().add(OwnPieceMoved(
|
ChessBloc.getInstance().add(OwnPieceMoved(
|
||||||
startSquare: move.fromSquare, endSquare: coordinate));
|
startSquare: move.fromSquare,
|
||||||
|
endSquare: move.toSquare,
|
||||||
|
piece: containedPiece!));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
builder: (context, candidateData, rejectedData) {
|
builder: (context, candidateData, rejectedData) {
|
||||||
@ -79,9 +88,9 @@ class ChessSquare extends StatelessWidget {
|
|||||||
color: color,
|
color: color,
|
||||||
width: ChessSquare.pieceWidth,
|
width: ChessSquare.pieceWidth,
|
||||||
height: ChessSquare.pieceWidth,
|
height: ChessSquare.pieceWidth,
|
||||||
child: Draggable<PieceMovedFrom>(
|
child: Draggable<PieceDragged>(
|
||||||
/* We create the move with the startSquare == endSquare. The receiving widget will give the correct value to end square. */
|
/* We create the move with the startSquare == endSquare. The receiving widget will give the correct value to end square. */
|
||||||
data: PieceMovedFrom(coordinate, containedPiece),
|
data: PieceDragged(coordinate, coordinate, containedPiece),
|
||||||
maxSimultaneousDrags: maxDrags,
|
maxSimultaneousDrags: maxDrags,
|
||||||
feedback: FractionalTranslation(
|
feedback: FractionalTranslation(
|
||||||
translation: const Offset(-0.5, -0.75),
|
translation: const Offset(-0.5, -0.75),
|
||||||
@ -100,4 +109,28 @@ class ChessSquare extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isPromotionMove(PieceDragged move) {
|
||||||
|
bool isPromotion = false;
|
||||||
|
if (move.movedPiece!.pieceClass != ChessPieceClass.pawn) {
|
||||||
|
return isPromotion;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (ChessBloc.myColor) {
|
||||||
|
case ChessColor.black:
|
||||||
|
if (move.toSquare.row == 1) {
|
||||||
|
isPromotion = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ChessColor.white:
|
||||||
|
if (move.toSquare.row == 8) {
|
||||||
|
isPromotion = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case null:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isPromotion;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import 'dart:developer';
|
|||||||
class ChessBloc extends Bloc<ChessEvent, ChessBoardState> {
|
class ChessBloc extends Bloc<ChessEvent, ChessBoardState> {
|
||||||
static final ChessBloc _instance = ChessBloc._internal();
|
static final ChessBloc _instance = ChessBloc._internal();
|
||||||
static ChessColor turnColor = ChessColor.white;
|
static ChessColor turnColor = ChessColor.white;
|
||||||
static ChessColor? myColor;
|
static ChessColor? myColor = ChessColor.white;
|
||||||
|
|
||||||
static ChessColor? getSidesColor() {
|
static ChessColor? getSidesColor() {
|
||||||
return myColor;
|
return myColor;
|
||||||
@ -94,8 +94,13 @@ class ChessBloc extends Bloc<ChessEvent, ChessBoardState> {
|
|||||||
|
|
||||||
void invalidMoveHandler(
|
void invalidMoveHandler(
|
||||||
InvalidMovePlayed event, Emitter<ChessBoardState> emit) {
|
InvalidMovePlayed event, Emitter<ChessBoardState> emit) {
|
||||||
emit(ChessBoardState(state.bottomColor, turnColor,
|
emit(
|
||||||
ChessPosition.getInstance().currentPosition));
|
ChessBoardState(
|
||||||
|
state.bottomColor,
|
||||||
|
turnColor,
|
||||||
|
ChessPosition.getInstance().currentPosition,
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,8 +12,12 @@ class ReceivedMove extends ChessEvent {
|
|||||||
class OwnPieceMoved extends ChessEvent {
|
class OwnPieceMoved extends ChessEvent {
|
||||||
final ChessCoordinate startSquare;
|
final ChessCoordinate startSquare;
|
||||||
final ChessCoordinate endSquare;
|
final ChessCoordinate endSquare;
|
||||||
|
final ChessPiece piece;
|
||||||
|
|
||||||
OwnPieceMoved({required this.startSquare, required this.endSquare});
|
OwnPieceMoved(
|
||||||
|
{required this.startSquare,
|
||||||
|
required this.endSquare,
|
||||||
|
required this.piece});
|
||||||
}
|
}
|
||||||
|
|
||||||
class InitBoard extends ChessEvent {
|
class InitBoard extends ChessEvent {
|
||||||
|
@ -30,45 +30,47 @@ class ChessPosition {
|
|||||||
ChessPositionType pos = {};
|
ChessPositionType pos = {};
|
||||||
|
|
||||||
for (int i = 1; i <= 8; i++) {
|
for (int i = 1; i <= 8; i++) {
|
||||||
pos[ChessCoordinate(i, 7)] =
|
// pos[ChessCoordinate(i, 7)] =
|
||||||
ChessPiece(ChessPieceName.blackPawn, ChessColor.black);
|
// ChessPiece(ChessPieceName.blackPawn, ChessColor.black);
|
||||||
pos[ChessCoordinate(i, 2)] =
|
// pos[ChessCoordinate(i, 2)] =
|
||||||
ChessPiece(ChessPieceName.whitePawn, ChessColor.white);
|
// ChessPiece(ChessPieceName.whitePawn, ChessColor.white);
|
||||||
}
|
}
|
||||||
|
pos[ChessCoordinate(1, 7)] =
|
||||||
|
ChessPiece(ChessPieceClass.pawn, ChessColor.white);
|
||||||
|
|
||||||
pos[ChessCoordinate(1, 8)] =
|
// pos[ChessCoordinate(1, 8)] =
|
||||||
ChessPiece(ChessPieceName.blackRook, ChessColor.black);
|
// ChessPiece(ChessPieceName.blackRook, ChessColor.black);
|
||||||
pos[ChessCoordinate(2, 8)] =
|
// pos[ChessCoordinate(2, 8)] =
|
||||||
ChessPiece(ChessPieceName.blackKnight, ChessColor.black);
|
// ChessPiece(ChessPieceName.blackKnight, ChessColor.black);
|
||||||
pos[ChessCoordinate(3, 8)] =
|
// pos[ChessCoordinate(3, 8)] =
|
||||||
ChessPiece(ChessPieceName.blackBishop, ChessColor.black);
|
// ChessPiece(ChessPieceName.blackBishop, ChessColor.black);
|
||||||
pos[ChessCoordinate(4, 8)] =
|
// pos[ChessCoordinate(4, 8)] =
|
||||||
ChessPiece(ChessPieceName.blackQueen, ChessColor.black);
|
// ChessPiece(ChessPieceName.blackQueen, ChessColor.black);
|
||||||
pos[ChessCoordinate(5, 8)] =
|
// pos[ChessCoordinate(5, 8)] =
|
||||||
ChessPiece(ChessPieceName.blackKing, ChessColor.black);
|
// ChessPiece(ChessPieceName.blackKing, ChessColor.black);
|
||||||
pos[ChessCoordinate(6, 8)] =
|
// pos[ChessCoordinate(6, 8)] =
|
||||||
ChessPiece(ChessPieceName.blackBishop, ChessColor.black);
|
// ChessPiece(ChessPieceName.blackBishop, ChessColor.black);
|
||||||
pos[ChessCoordinate(7, 8)] =
|
// pos[ChessCoordinate(7, 8)] =
|
||||||
ChessPiece(ChessPieceName.blackKnight, ChessColor.black);
|
// ChessPiece(ChessPieceName.blackKnight, ChessColor.black);
|
||||||
pos[ChessCoordinate(8, 8)] =
|
// pos[ChessCoordinate(8, 8)] =
|
||||||
ChessPiece(ChessPieceName.blackRook, ChessColor.black);
|
// ChessPiece(ChessPieceName.blackRook, ChessColor.black);
|
||||||
|
|
||||||
pos[ChessCoordinate(1, 1)] =
|
// pos[ChessCoordinate(1, 1)] =
|
||||||
ChessPiece(ChessPieceName.whiteRook, ChessColor.white);
|
// ChessPiece(ChessPieceName.whiteRook, ChessColor.white);
|
||||||
pos[ChessCoordinate(2, 1)] =
|
// pos[ChessCoordinate(2, 1)] =
|
||||||
ChessPiece(ChessPieceName.whiteKnight, ChessColor.white);
|
// ChessPiece(ChessPieceName.whiteKnight, ChessColor.white);
|
||||||
pos[ChessCoordinate(3, 1)] =
|
// pos[ChessCoordinate(3, 1)] =
|
||||||
ChessPiece(ChessPieceName.whiteBishop, ChessColor.white);
|
// ChessPiece(ChessPieceName.whiteBishop, ChessColor.white);
|
||||||
pos[ChessCoordinate(4, 1)] =
|
// pos[ChessCoordinate(4, 1)] =
|
||||||
ChessPiece(ChessPieceName.whiteQueen, ChessColor.white);
|
// ChessPiece(ChessPieceName.whiteQueen, ChessColor.white);
|
||||||
pos[ChessCoordinate(5, 1)] =
|
// pos[ChessCoordinate(5, 1)] =
|
||||||
ChessPiece(ChessPieceName.whiteKing, ChessColor.white);
|
// ChessPiece(ChessPieceName.whiteKing, ChessColor.white);
|
||||||
pos[ChessCoordinate(6, 1)] =
|
// pos[ChessCoordinate(6, 1)] =
|
||||||
ChessPiece(ChessPieceName.whiteBishop, ChessColor.white);
|
// ChessPiece(ChessPieceName.whiteBishop, ChessColor.white);
|
||||||
pos[ChessCoordinate(7, 1)] =
|
// pos[ChessCoordinate(7, 1)] =
|
||||||
ChessPiece(ChessPieceName.whiteKnight, ChessColor.white);
|
// ChessPiece(ChessPieceName.whiteKnight, ChessColor.white);
|
||||||
pos[ChessCoordinate(8, 1)] =
|
// pos[ChessCoordinate(8, 1)] =
|
||||||
ChessPiece(ChessPieceName.whiteRook, ChessColor.white);
|
// ChessPiece(ChessPieceName.whiteRook, ChessColor.white);
|
||||||
|
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
49
lib/chess_bloc/promotion_bloc.dart
Normal file
49
lib/chess_bloc/promotion_bloc.dart
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:mchess/utils/chess_utils.dart';
|
||||||
|
|
||||||
|
class PromotionUiBloc extends Bloc<PromotionEvent, PromotionUiState> {
|
||||||
|
static final PromotionUiBloc _instance = PromotionUiBloc._internal();
|
||||||
|
|
||||||
|
PromotionUiBloc._internal() : super(PromotionUiState.init()) {
|
||||||
|
on<PawnMovedToPromotionField>(promotionMoveHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
void promotionMoveHandler(
|
||||||
|
PawnMovedToPromotionField event,
|
||||||
|
Emitter<PromotionUiState> emit,
|
||||||
|
) {
|
||||||
|
emit(PromotionUiState(
|
||||||
|
showPromotionDialog: true, colorMoved: event.colorMoved));
|
||||||
|
}
|
||||||
|
|
||||||
|
factory PromotionUiBloc.getInstance() {
|
||||||
|
return PromotionUiBloc();
|
||||||
|
}
|
||||||
|
|
||||||
|
factory PromotionUiBloc() {
|
||||||
|
return _instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class PromotionEvent {}
|
||||||
|
|
||||||
|
class PawnMovedToPromotionField extends PromotionEvent {
|
||||||
|
final ChessCoordinate endSquare;
|
||||||
|
final ChessColor colorMoved;
|
||||||
|
|
||||||
|
PawnMovedToPromotionField(
|
||||||
|
{required this.endSquare, required this.colorMoved});
|
||||||
|
}
|
||||||
|
|
||||||
|
class PromotionUiState {
|
||||||
|
final bool showPromotionDialog;
|
||||||
|
final ChessColor colorMoved;
|
||||||
|
|
||||||
|
PromotionUiState(
|
||||||
|
{required this.showPromotionDialog, required this.colorMoved});
|
||||||
|
|
||||||
|
factory PromotionUiState.init() {
|
||||||
|
return PromotionUiState(
|
||||||
|
showPromotionDialog: false, colorMoved: ChessColor.white);
|
||||||
|
}
|
||||||
|
}
|
@ -6,6 +6,9 @@ import 'package:mchess/chess_bloc/chess_bloc.dart';
|
|||||||
|
|
||||||
import 'package:mchess/chess/chess_board.dart';
|
import 'package:mchess/chess/chess_board.dart';
|
||||||
import 'package:mchess/chess/turn_indicator_widget.dart';
|
import 'package:mchess/chess/turn_indicator_widget.dart';
|
||||||
|
import 'package:mchess/chess_bloc/promotion_bloc.dart';
|
||||||
|
import 'package:mchess/utils/chess_utils.dart';
|
||||||
|
import 'package:mchess/utils/widgets/promotion_dialog.dart';
|
||||||
import 'package:mchess/utils/widgets/server_log_widget.dart';
|
import 'package:mchess/utils/widgets/server_log_widget.dart';
|
||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
@ -32,23 +35,32 @@ class _ChessGameState extends State<ChessGame> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: FittedBox(
|
body: Center(
|
||||||
fit: BoxFit.contain,
|
child: FittedBox(
|
||||||
child: Column(
|
fit: BoxFit.contain,
|
||||||
children: [
|
child: Column(
|
||||||
if (kDebugMode) const ServerLogWidget(textColor: Colors.white),
|
children: [
|
||||||
Container(
|
if (kDebugMode) const ServerLogWidget(textColor: Colors.white),
|
||||||
margin: const EdgeInsets.all(20),
|
Container(
|
||||||
child: BlocBuilder<ChessBloc, ChessBoardState>(
|
margin: const EdgeInsets.all(20),
|
||||||
builder: (context, state) {
|
child: BlocListener<PromotionUiBloc, PromotionUiState>(
|
||||||
return ChessBoard(
|
listener: (context, state) {
|
||||||
bState: state,
|
if (state.showPromotionDialog) {
|
||||||
);
|
promotionDialogBuilder(context, state.colorMoved);
|
||||||
},
|
}
|
||||||
|
},
|
||||||
|
child: BlocBuilder<ChessBloc, ChessBoardState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
return ChessBoard(
|
||||||
|
bState: state,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
if (kDebugMode) const TurnIndicator(),
|
||||||
if (kDebugMode) const TurnIndicator(),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
floatingActionButton: FloatingActionButton(
|
floatingActionButton: FloatingActionButton(
|
||||||
@ -59,6 +71,18 @@ class _ChessGameState extends State<ChessGame> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> promotionDialogBuilder(BuildContext context, ChessColor color) {
|
||||||
|
return showDialog<void>(
|
||||||
|
context: context,
|
||||||
|
barrierDismissible: false,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return PromotionDialog(
|
||||||
|
sideColor: color,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChessGameArguments {
|
class ChessGameArguments {
|
||||||
|
@ -1,23 +1,38 @@
|
|||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:mchess/api/move.dart';
|
import 'package:mchess/api/move.dart';
|
||||||
import 'package:mchess/api/websocket_message.dart';
|
import 'package:mchess/api/websocket_message.dart';
|
||||||
import 'package:quiver/core.dart';
|
import 'package:quiver/core.dart';
|
||||||
|
|
||||||
enum ChessPieceName {
|
enum ChessPieceClass {
|
||||||
none,
|
none,
|
||||||
whitePawn,
|
pawn,
|
||||||
whiteBishop,
|
bishop,
|
||||||
whiteKnight,
|
knight,
|
||||||
whiteRook,
|
rook,
|
||||||
whiteQueen,
|
queen,
|
||||||
whiteKing,
|
king,
|
||||||
blackPawn,
|
}
|
||||||
blackBishop,
|
|
||||||
blackKnight,
|
class ChessPieceAssetKey {
|
||||||
blackRook,
|
final ChessPieceClass pieceClass;
|
||||||
blackQueen,
|
final ChessColor color;
|
||||||
blackKing,
|
|
||||||
|
ChessPieceAssetKey({required this.pieceClass, required this.color});
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return (other is ChessPieceAssetKey &&
|
||||||
|
(pieceClass == other.pieceClass) &&
|
||||||
|
(color == other.color));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
return hash2(pieceClass, color);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ChessColor {
|
enum ChessColor {
|
||||||
@ -33,36 +48,114 @@ enum ChessColor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<ChessPieceName, String> chessPiecesAssets = {
|
Map<ChessPieceAssetKey, String> chessPiecesAssets = {
|
||||||
ChessPieceName.whitePawn: 'assets/pieces/white/pawn.svg',
|
ChessPieceAssetKey(
|
||||||
ChessPieceName.whiteBishop: 'assets/pieces/white/bishop.svg',
|
pieceClass: ChessPieceClass.pawn,
|
||||||
ChessPieceName.whiteKnight: 'assets/pieces/white/knight.svg',
|
color: ChessColor.white,
|
||||||
ChessPieceName.whiteRook: 'assets/pieces/white/rook.svg',
|
): 'assets/pieces/white/pawn.svg',
|
||||||
ChessPieceName.whiteQueen: 'assets/pieces/white/queen.svg',
|
ChessPieceAssetKey(
|
||||||
ChessPieceName.whiteKing: 'assets/pieces/white/king.svg',
|
pieceClass: ChessPieceClass.bishop,
|
||||||
ChessPieceName.blackPawn: 'assets/pieces/black/pawn.svg',
|
color: ChessColor.white,
|
||||||
ChessPieceName.blackBishop: 'assets/pieces/black/bishop.svg',
|
): 'assets/pieces/white/bishop.svg',
|
||||||
ChessPieceName.blackKnight: 'assets/pieces/black/knight.svg',
|
ChessPieceAssetKey(
|
||||||
ChessPieceName.blackRook: 'assets/pieces/black/rook.svg',
|
pieceClass: ChessPieceClass.knight,
|
||||||
ChessPieceName.blackQueen: 'assets/pieces/black/queen.svg',
|
color: ChessColor.white,
|
||||||
ChessPieceName.blackKing: 'assets/pieces/black/king.svg',
|
): 'assets/pieces/white/knight.svg',
|
||||||
ChessPieceName.none: 'assets/empty.svg',
|
ChessPieceAssetKey(
|
||||||
|
pieceClass: ChessPieceClass.rook,
|
||||||
|
color: ChessColor.white,
|
||||||
|
): 'assets/pieces/white/rook.svg',
|
||||||
|
ChessPieceAssetKey(
|
||||||
|
pieceClass: ChessPieceClass.queen,
|
||||||
|
color: ChessColor.white,
|
||||||
|
): 'assets/pieces/white/queen.svg',
|
||||||
|
ChessPieceAssetKey(
|
||||||
|
pieceClass: ChessPieceClass.king,
|
||||||
|
color: ChessColor.white,
|
||||||
|
): 'assets/pieces/white/king.svg',
|
||||||
|
ChessPieceAssetKey(
|
||||||
|
pieceClass: ChessPieceClass.pawn,
|
||||||
|
color: ChessColor.black,
|
||||||
|
): 'assets/pieces/black/pawn.svg',
|
||||||
|
ChessPieceAssetKey(
|
||||||
|
pieceClass: ChessPieceClass.bishop,
|
||||||
|
color: ChessColor.black,
|
||||||
|
): 'assets/pieces/black/bishop.svg',
|
||||||
|
ChessPieceAssetKey(
|
||||||
|
pieceClass: ChessPieceClass.knight,
|
||||||
|
color: ChessColor.black,
|
||||||
|
): 'assets/pieces/black/knight.svg',
|
||||||
|
ChessPieceAssetKey(
|
||||||
|
pieceClass: ChessPieceClass.rook,
|
||||||
|
color: ChessColor.black,
|
||||||
|
): 'assets/pieces/black/rook.svg',
|
||||||
|
ChessPieceAssetKey(
|
||||||
|
pieceClass: ChessPieceClass.queen,
|
||||||
|
color: ChessColor.black,
|
||||||
|
): 'assets/pieces/black/queen.svg',
|
||||||
|
ChessPieceAssetKey(
|
||||||
|
pieceClass: ChessPieceClass.king,
|
||||||
|
color: ChessColor.black,
|
||||||
|
): 'assets/pieces/black/king.svg',
|
||||||
|
ChessPieceAssetKey(
|
||||||
|
pieceClass: ChessPieceClass.none,
|
||||||
|
color: ChessColor.black,
|
||||||
|
): 'assets/empty.svg',
|
||||||
};
|
};
|
||||||
|
|
||||||
Map<ChessPieceName, String> chessPiecesShortName = {
|
Map<ChessPieceAssetKey, String> chessPiecesShortName = {
|
||||||
ChessPieceName.whitePawn: 'P',
|
ChessPieceAssetKey(
|
||||||
ChessPieceName.whiteBishop: 'B',
|
pieceClass: ChessPieceClass.pawn,
|
||||||
ChessPieceName.whiteKnight: 'N',
|
color: ChessColor.white,
|
||||||
ChessPieceName.whiteRook: 'R',
|
): 'P',
|
||||||
ChessPieceName.whiteQueen: 'Q',
|
ChessPieceAssetKey(
|
||||||
ChessPieceName.whiteKing: 'K',
|
pieceClass: ChessPieceClass.bishop,
|
||||||
ChessPieceName.blackPawn: 'p',
|
color: ChessColor.white,
|
||||||
ChessPieceName.blackBishop: 'b',
|
): 'B',
|
||||||
ChessPieceName.blackKnight: 'n',
|
ChessPieceAssetKey(
|
||||||
ChessPieceName.blackRook: 'r',
|
pieceClass: ChessPieceClass.knight,
|
||||||
ChessPieceName.blackQueen: 'q',
|
color: ChessColor.white,
|
||||||
ChessPieceName.blackKing: 'k',
|
): 'N',
|
||||||
ChessPieceName.none: 'X',
|
ChessPieceAssetKey(
|
||||||
|
pieceClass: ChessPieceClass.rook,
|
||||||
|
color: ChessColor.white,
|
||||||
|
): 'R',
|
||||||
|
ChessPieceAssetKey(
|
||||||
|
pieceClass: ChessPieceClass.queen,
|
||||||
|
color: ChessColor.white,
|
||||||
|
): 'Q',
|
||||||
|
ChessPieceAssetKey(
|
||||||
|
pieceClass: ChessPieceClass.king,
|
||||||
|
color: ChessColor.white,
|
||||||
|
): 'K',
|
||||||
|
ChessPieceAssetKey(
|
||||||
|
pieceClass: ChessPieceClass.pawn,
|
||||||
|
color: ChessColor.black,
|
||||||
|
): 'p',
|
||||||
|
ChessPieceAssetKey(
|
||||||
|
pieceClass: ChessPieceClass.bishop,
|
||||||
|
color: ChessColor.black,
|
||||||
|
): 'b',
|
||||||
|
ChessPieceAssetKey(
|
||||||
|
pieceClass: ChessPieceClass.knight,
|
||||||
|
color: ChessColor.black,
|
||||||
|
): 'n',
|
||||||
|
ChessPieceAssetKey(
|
||||||
|
pieceClass: ChessPieceClass.rook,
|
||||||
|
color: ChessColor.black,
|
||||||
|
): 'r',
|
||||||
|
ChessPieceAssetKey(
|
||||||
|
pieceClass: ChessPieceClass.queen,
|
||||||
|
color: ChessColor.black,
|
||||||
|
): 'q',
|
||||||
|
ChessPieceAssetKey(
|
||||||
|
pieceClass: ChessPieceClass.king,
|
||||||
|
color: ChessColor.black,
|
||||||
|
): 'k',
|
||||||
|
ChessPieceAssetKey(
|
||||||
|
pieceClass: ChessPieceClass.none,
|
||||||
|
color: ChessColor.black,
|
||||||
|
): '-',
|
||||||
};
|
};
|
||||||
|
|
||||||
class ChessCoordinate {
|
class ChessCoordinate {
|
||||||
@ -140,24 +233,26 @@ class ChessCoordinate {
|
|||||||
|
|
||||||
class ChessPiece extends StatelessWidget {
|
class ChessPiece extends StatelessWidget {
|
||||||
final ChessColor color;
|
final ChessColor color;
|
||||||
final ChessPieceName pieceName;
|
final ChessPieceClass pieceClass;
|
||||||
final String shortName;
|
final String shortName;
|
||||||
final Widget? pieceImage;
|
final Widget? pieceImage;
|
||||||
|
|
||||||
const ChessPiece._(
|
const ChessPiece._(
|
||||||
this.pieceName, this.color, this.pieceImage, this.shortName);
|
this.pieceClass, this.color, this.pieceImage, this.shortName);
|
||||||
|
|
||||||
factory ChessPiece(ChessPieceName name, ChessColor color) {
|
factory ChessPiece(ChessPieceClass pieceClass, ChessColor color) {
|
||||||
Widget? pieceImage;
|
Widget? pieceImage;
|
||||||
String pieceAssetUrl = chessPiecesAssets[name]!;
|
String pieceAssetUrl = chessPiecesAssets[
|
||||||
String shortName = chessPiecesShortName[name]!;
|
ChessPieceAssetKey(pieceClass: pieceClass, color: color)]!;
|
||||||
|
String shortName = chessPiecesShortName[
|
||||||
|
ChessPieceAssetKey(pieceClass: pieceClass, color: color)]!;
|
||||||
|
|
||||||
pieceImage = SvgPicture.asset(pieceAssetUrl);
|
pieceImage = SvgPicture.asset(pieceAssetUrl);
|
||||||
return ChessPiece._(name, color, pieceImage, shortName);
|
return ChessPiece._(pieceClass, color, pieceImage, shortName);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ChessPiece.none({super.key})
|
const ChessPiece.none({super.key})
|
||||||
: pieceName = ChessPieceName.none,
|
: pieceClass = ChessPieceClass.none,
|
||||||
color = ChessColor.white,
|
color = ChessColor.white,
|
||||||
pieceImage = null,
|
pieceImage = null,
|
||||||
shortName = "-";
|
shortName = "-";
|
||||||
@ -194,9 +289,10 @@ class ChessMove {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PieceMovedFrom {
|
class PieceDragged {
|
||||||
ChessCoordinate fromSquare;
|
ChessCoordinate fromSquare;
|
||||||
|
ChessCoordinate toSquare;
|
||||||
ChessPiece? movedPiece;
|
ChessPiece? movedPiece;
|
||||||
|
|
||||||
PieceMovedFrom(this.fromSquare, this.movedPiece);
|
PieceDragged(this.fromSquare, this.toSquare, this.movedPiece);
|
||||||
}
|
}
|
||||||
|
47
lib/utils/widgets/promotion_dialog.dart
Normal file
47
lib/utils/widgets/promotion_dialog.dart
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
import 'package:mchess/utils/chess_utils.dart';
|
||||||
|
|
||||||
|
class PromotionDialog extends StatelessWidget {
|
||||||
|
final ChessColor sideColor;
|
||||||
|
const PromotionDialog({required this.sideColor, super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Card(
|
||||||
|
child: Column(children: [
|
||||||
|
Expanded(
|
||||||
|
flex: 1,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {},
|
||||||
|
child: SvgPicture.asset(chessPiecesAssets[ChessPieceAssetKey(
|
||||||
|
pieceClass: ChessPieceClass.queen, color: sideColor)]!),
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {},
|
||||||
|
child: SvgPicture.asset(chessPiecesAssets[ChessPieceAssetKey(
|
||||||
|
pieceClass: ChessPieceClass.rook, color: sideColor)]!),
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {},
|
||||||
|
child: SvgPicture.asset(chessPiecesAssets[ChessPieceAssetKey(
|
||||||
|
pieceClass: ChessPieceClass.knight, color: sideColor)]!),
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {},
|
||||||
|
child: SvgPicture.asset(chessPiecesAssets[ChessPieceAssetKey(
|
||||||
|
pieceClass: ChessPieceClass.bishop, color: sideColor)]!),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Expanded(
|
||||||
|
flex: 3,
|
||||||
|
child: ColoredBox(color: Colors.red),
|
||||||
|
)
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user