Implement moves by tapping the squares
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.
This commit is contained in:
parent
dfd9f09ee6
commit
2a4da9a1af
@ -2,6 +2,7 @@ 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/chess_bloc/promotion_bloc.dart';
|
||||||
|
import 'package:mchess/chess_bloc/tap_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';
|
||||||
|
|
||||||
@ -16,18 +17,21 @@ class ChessApp extends StatelessWidget {
|
|||||||
create: (_) => ConnectionCubit.getInstance(),
|
create: (_) => ConnectionCubit.getInstance(),
|
||||||
),
|
),
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
create: (context) => ChessBloc.getInstance(),
|
create: (_) => ChessBloc.getInstance(),
|
||||||
),
|
),
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
create: (context) => PromotionBloc.getInstance(),
|
create: (_) => PromotionBloc.getInstance(),
|
||||||
)
|
),
|
||||||
|
BlocProvider(
|
||||||
|
create: (_) => TapBloc.getInstance(),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
child: MaterialApp.router(
|
child: MaterialApp.router(
|
||||||
theme: ThemeData.dark(
|
theme: ThemeData.dark(
|
||||||
useMaterial3: true,
|
useMaterial3: true,
|
||||||
),
|
),
|
||||||
routerConfig: ChessAppRouter.getInstance().router,
|
routerConfig: ChessAppRouter.getInstance().router,
|
||||||
title: 'mChess 0.1.1340',
|
title: 'mChess 0.9.115',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,8 @@ class ChessBoard extends StatelessWidget {
|
|||||||
|
|
||||||
const ChessBoard._({required this.bState, required this.squares});
|
const ChessBoard._({required this.bState, required this.squares});
|
||||||
|
|
||||||
factory ChessBoard({required ChessBoardState boardState}) {
|
factory ChessBoard(
|
||||||
|
{required ChessBoardState boardState, ChessCoordinate? tappedSquare}) {
|
||||||
List<ChessSquare> squares = List.empty(growable: true);
|
List<ChessSquare> squares = List.empty(growable: true);
|
||||||
for (int i = 0; i < 64; i++) {
|
for (int i = 0; i < 64; i++) {
|
||||||
var column = (i % 8) + 1;
|
var column = (i % 8) + 1;
|
||||||
@ -24,16 +25,16 @@ class ChessBoard extends StatelessWidget {
|
|||||||
bool squareWasPartOfLastMove = false;
|
bool squareWasPartOfLastMove = false;
|
||||||
if ((boardState.lastMove.to == ChessCoordinate(column, row) ||
|
if ((boardState.lastMove.to == ChessCoordinate(column, row) ||
|
||||||
boardState.lastMove.from == ChessCoordinate(column, row)) &&
|
boardState.lastMove.from == ChessCoordinate(column, row)) &&
|
||||||
boardState.positionAckdByServer) {
|
boardState.colorLastMove) {
|
||||||
squareWasPartOfLastMove = true;
|
squareWasPartOfLastMove = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
squares.add(
|
squares.add(
|
||||||
ChessSquare(
|
ChessSquare(
|
||||||
ChessCoordinate(column, row),
|
ChessCoordinate(column, row),
|
||||||
piece,
|
piece,
|
||||||
squareWasPartOfLastMove,
|
squareWasPartOfLastMove,
|
||||||
),
|
tappedSquare == ChessCoordinate(column, row)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
||||||
import 'package:mchess/chess/chess_square_outer_dragtarget.dart';
|
import 'package:mchess/chess/chess_square_outer_dragtarget.dart';
|
||||||
import 'package:mchess/chess_bloc/chess_bloc.dart';
|
import 'package:mchess/chess_bloc/tap_bloc.dart';
|
||||||
import '../utils/chess_utils.dart';
|
import '../utils/chess_utils.dart';
|
||||||
|
|
||||||
class ChessSquare extends StatefulWidget {
|
class ChessSquare extends StatefulWidget {
|
||||||
@ -18,13 +17,18 @@ class ChessSquare extends StatefulWidget {
|
|||||||
required this.color,
|
required this.color,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory ChessSquare(
|
factory ChessSquare(ChessCoordinate coord, ChessPiece? piece,
|
||||||
ChessCoordinate coord, ChessPiece? piece, bool wasPartOfLastMove) {
|
bool wasPartOfLastMove, bool wasTapped) {
|
||||||
Color lightSquaresColor =
|
Color lightSquaresColor =
|
||||||
wasPartOfLastMove ? Colors.green.shade200 : Colors.brown.shade50;
|
wasPartOfLastMove ? Colors.green.shade200 : Colors.brown.shade50;
|
||||||
Color darkSquaresColor =
|
Color darkSquaresColor =
|
||||||
wasPartOfLastMove ? Colors.green.shade300 : Colors.brown.shade400;
|
wasPartOfLastMove ? Colors.green.shade300 : Colors.brown.shade400;
|
||||||
|
|
||||||
|
if (wasTapped) {
|
||||||
|
lightSquaresColor = Colors.red.shade200;
|
||||||
|
darkSquaresColor = Colors.red.shade300;
|
||||||
|
}
|
||||||
|
|
||||||
Color squareColor;
|
Color squareColor;
|
||||||
|
|
||||||
if (coord.row % 2 == 0) {
|
if (coord.row % 2 == 0) {
|
||||||
@ -53,31 +57,19 @@ class ChessSquare extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _ChessSquareState extends State<ChessSquare> {
|
class _ChessSquareState extends State<ChessSquare> {
|
||||||
late Color squareColor;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
squareColor = widget.color;
|
|
||||||
super.initState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocListener<ChessBloc, ChessBoardState>(
|
return GestureDetector(
|
||||||
listenWhen: (previous, current) {
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
listener: (context, state) {
|
|
||||||
setState(() {
|
|
||||||
squareColor = Colors.red;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
child: Container(
|
child: Container(
|
||||||
color: widget.color,
|
color: widget.color,
|
||||||
child: ChessSquareOuterDragTarget(
|
child: ChessSquareOuterDragTarget(
|
||||||
coordinate: widget.coordinate,
|
coordinate: widget.coordinate,
|
||||||
containedPiece: widget.containedPiece ?? const ChessPiece.none()),
|
containedPiece: widget.containedPiece ?? const ChessPiece.none()),
|
||||||
),
|
),
|
||||||
|
onTap: () {
|
||||||
|
TapBloc().add(SquareTappedEvent(
|
||||||
|
tapped: widget.coordinate, pieceOnSquare: widget.containedPiece));
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ import 'package:flutter/foundation.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:mchess/chess/chess_square.dart';
|
import 'package:mchess/chess/chess_square.dart';
|
||||||
import 'package:mchess/chess_bloc/chess_bloc.dart';
|
import 'package:mchess/chess_bloc/chess_bloc.dart';
|
||||||
|
import 'package:mchess/chess_bloc/tap_bloc.dart';
|
||||||
import 'package:mchess/utils/chess_utils.dart';
|
import 'package:mchess/utils/chess_utils.dart';
|
||||||
|
|
||||||
class ChessSquareInnerDraggable extends StatelessWidget {
|
class ChessSquareInnerDraggable extends StatelessWidget {
|
||||||
@ -48,7 +49,9 @@ class ChessSquareInnerDraggable extends StatelessWidget {
|
|||||||
dragAnchorStrategy: pointerDragAnchorStrategy,
|
dragAnchorStrategy: pointerDragAnchorStrategy,
|
||||||
child: containedPiece ?? Container(),
|
child: containedPiece ?? Container(),
|
||||||
onDragCompleted: () {},
|
onDragCompleted: () {},
|
||||||
onDragStarted: () {},
|
onDragStarted: () {
|
||||||
|
TapBloc().add(CancelTapEvent());
|
||||||
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -25,16 +25,19 @@ class ChessSquareOuterDragTarget extends StatelessWidget {
|
|||||||
// Replace the dummy value with the actual target of the move.
|
// Replace the dummy value with the actual target of the move.
|
||||||
pieceDragged.toSquare = coordinate;
|
pieceDragged.toSquare = coordinate;
|
||||||
|
|
||||||
if (isPromotionMove(pieceDragged)) {
|
if (isPromotionMove(
|
||||||
|
pieceDragged.movedPiece!.pieceClass,
|
||||||
|
ChessBloc.myColor!,
|
||||||
|
pieceDragged.toSquare,
|
||||||
|
)) {
|
||||||
var move = ChessMove(
|
var move = ChessMove(
|
||||||
from: pieceDragged.fromSquare, to: pieceDragged.toSquare);
|
from: pieceDragged.fromSquare, to: pieceDragged.toSquare);
|
||||||
PromotionBloc.getInstance().add(PawnMovedToPromotionField(
|
PromotionBloc().add(PawnMovedToPromotionField(
|
||||||
move: move, colorMoved: ChessBloc.myColor!));
|
move: move, colorMoved: ChessBloc.myColor!));
|
||||||
} else if (coordinate != pieceDragged.fromSquare) {
|
} else if (coordinate != pieceDragged.fromSquare) {
|
||||||
ChessBloc.getInstance().add(OwnPieceMoved(
|
ChessBloc().add(OwnPieceMoved(
|
||||||
startSquare: pieceDragged.fromSquare,
|
startSquare: pieceDragged.fromSquare,
|
||||||
endSquare: pieceDragged.toSquare,
|
endSquare: pieceDragged.toSquare));
|
||||||
piece: pieceDragged.movedPiece!));
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
builder: (context, candidateData, rejectedData) {
|
builder: (context, candidateData, rejectedData) {
|
||||||
@ -45,28 +48,4 @@ class ChessSquareOuterDragTarget 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,6 @@ class ChessBloc extends Bloc<ChessEvent, ChessBoardState> {
|
|||||||
on<OwnPieceMoved>(ownMoveHandler);
|
on<OwnPieceMoved>(ownMoveHandler);
|
||||||
on<OwnPromotionPlayed>(ownPromotionHandler);
|
on<OwnPromotionPlayed>(ownPromotionHandler);
|
||||||
on<InvalidMovePlayed>(invalidMoveHandler);
|
on<InvalidMovePlayed>(invalidMoveHandler);
|
||||||
on<BoardStatusReceived>(boardStatusHandler);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
factory ChessBloc.getInstance() {
|
factory ChessBloc.getInstance() {
|
||||||
@ -112,8 +111,14 @@ class ChessBloc extends Bloc<ChessEvent, ChessBoardState> {
|
|||||||
tempPosition[move.from] = const ChessPiece.none();
|
tempPosition[move.from] = const ChessPiece.none();
|
||||||
|
|
||||||
emit(
|
emit(
|
||||||
ChessBoardState(state.bottomColor, turnColor, tempPosition, move, false,
|
ChessBoardState(
|
||||||
ChessCoordinate.none()),
|
state.bottomColor,
|
||||||
|
turnColor,
|
||||||
|
tempPosition,
|
||||||
|
ChessPositionManager.getInstance().lastMove,
|
||||||
|
true,
|
||||||
|
ChessCoordinate.none(),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,31 +143,18 @@ class ChessBloc extends Bloc<ChessEvent, ChessBoardState> {
|
|||||||
|
|
||||||
void invalidMoveHandler(
|
void invalidMoveHandler(
|
||||||
InvalidMovePlayed event, Emitter<ChessBoardState> emit) {
|
InvalidMovePlayed event, Emitter<ChessBoardState> emit) {
|
||||||
|
var move = ChessPositionManager.getInstance().lastMove;
|
||||||
emit(
|
emit(
|
||||||
ChessBoardState(
|
ChessBoardState(
|
||||||
state.bottomColor,
|
state.bottomColor,
|
||||||
turnColor,
|
turnColor,
|
||||||
ChessPositionManager.getInstance().currentPosition,
|
ChessPositionManager.getInstance().currentPosition,
|
||||||
ChessMove.none(),
|
move,
|
||||||
false,
|
true,
|
||||||
event.squareInCheck,
|
event.squareInCheck,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void boardStatusHandler(
|
|
||||||
BoardStatusReceived event, Emitter<ChessBoardState> emit) {
|
|
||||||
emit(
|
|
||||||
ChessBoardState(
|
|
||||||
event.myColor,
|
|
||||||
event.whoseTurn,
|
|
||||||
event.pos,
|
|
||||||
ChessMove.none(),
|
|
||||||
false,
|
|
||||||
ChessCoordinate.none(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChessBoardState {
|
class ChessBoardState {
|
||||||
@ -170,7 +162,7 @@ class ChessBoardState {
|
|||||||
final ChessColor newTurnColor;
|
final ChessColor newTurnColor;
|
||||||
final ChessPosition position;
|
final ChessPosition position;
|
||||||
final ChessMove lastMove;
|
final ChessMove lastMove;
|
||||||
final bool positionAckdByServer;
|
final bool colorLastMove;
|
||||||
final ChessCoordinate squareInCheck;
|
final ChessCoordinate squareInCheck;
|
||||||
|
|
||||||
ChessBoardState._(
|
ChessBoardState._(
|
||||||
@ -178,7 +170,7 @@ class ChessBoardState {
|
|||||||
this.newTurnColor,
|
this.newTurnColor,
|
||||||
this.position,
|
this.position,
|
||||||
this.lastMove,
|
this.lastMove,
|
||||||
this.positionAckdByServer,
|
this.colorLastMove,
|
||||||
this.squareInCheck,
|
this.squareInCheck,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -22,12 +22,8 @@ class ReceivedBoardState 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(
|
OwnPieceMoved({required this.startSquare, required this.endSquare});
|
||||||
{required this.startSquare,
|
|
||||||
required this.endSquare,
|
|
||||||
required this.piece});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class OwnPromotionPlayed extends ChessEvent {
|
class OwnPromotionPlayed extends ChessEvent {
|
||||||
@ -56,15 +52,3 @@ class InvalidMovePlayed extends ChessEvent {
|
|||||||
required this.squareInCheck,
|
required this.squareInCheck,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class BoardStatusReceived extends ChessEvent {
|
|
||||||
final ChessPosition pos;
|
|
||||||
final ChessColor myColor;
|
|
||||||
final ChessColor whoseTurn;
|
|
||||||
|
|
||||||
BoardStatusReceived({
|
|
||||||
required this.pos,
|
|
||||||
required this.myColor,
|
|
||||||
required this.whoseTurn,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
109
lib/chess_bloc/tap_bloc.dart
Normal file
109
lib/chess_bloc/tap_bloc.dart
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:mchess/chess_bloc/chess_bloc.dart';
|
||||||
|
import 'package:mchess/chess_bloc/chess_events.dart';
|
||||||
|
import 'package:mchess/chess_bloc/promotion_bloc.dart';
|
||||||
|
import 'package:mchess/utils/chess_utils.dart';
|
||||||
|
|
||||||
|
class TapBloc extends Bloc<TapEvent, TapState> {
|
||||||
|
static final TapBloc _instance = TapBloc._internal();
|
||||||
|
|
||||||
|
static TapBloc getInstance() {
|
||||||
|
return _instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
factory TapBloc() {
|
||||||
|
return _instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
TapBloc._internal() : super(TapState.init()) {
|
||||||
|
on<SquareTappedEvent>(handleTap);
|
||||||
|
on<CancelTapEvent>(cancelTap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleTap(SquareTappedEvent event, Emitter<TapState> emit) {
|
||||||
|
ChessCoordinate? firstTappedSquare, secondTappedSquare;
|
||||||
|
ChessPiece? piece;
|
||||||
|
|
||||||
|
if (ChessBloc.myColor != ChessBloc.turnColor) return;
|
||||||
|
|
||||||
|
if (state.firstSquareTapped == null) {
|
||||||
|
//first tap
|
||||||
|
if (event.pieceOnSquare == null) return;
|
||||||
|
if (event.pieceOnSquare != null &&
|
||||||
|
ChessBloc.myColor != event.pieceOnSquare!.color) return;
|
||||||
|
firstTappedSquare = event.tapped;
|
||||||
|
piece = event.pieceOnSquare;
|
||||||
|
} else {
|
||||||
|
//second tap
|
||||||
|
if (event.pieceOnSquare?.color == ChessBloc.myColor) {
|
||||||
|
emit(TapState(
|
||||||
|
firstSquareTapped: event.tapped,
|
||||||
|
pieceOnFirstTappedSquare: event.pieceOnSquare,
|
||||||
|
secondSquareTapped: null));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
secondTappedSquare = event.tapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.firstSquareTapped != null &&
|
||||||
|
state.firstSquareTapped != event.tapped) {
|
||||||
|
if (isPromotionMove(
|
||||||
|
state.pieceOnFirstTappedSquare!.pieceClass,
|
||||||
|
ChessBloc.myColor!,
|
||||||
|
event.tapped,
|
||||||
|
)) {
|
||||||
|
PromotionBloc().add(PawnMovedToPromotionField(
|
||||||
|
move: ChessMove(from: state.firstSquareTapped!, to: event.tapped),
|
||||||
|
colorMoved: ChessBloc.myColor!));
|
||||||
|
emit(TapState.init());
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
ChessBloc().add(OwnPieceMoved(
|
||||||
|
startSquare: state.firstSquareTapped!, endSquare: event.tapped));
|
||||||
|
emit(TapState.init());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log("handleTap() in TapBloc is called");
|
||||||
|
emit(TapState(
|
||||||
|
firstSquareTapped: firstTappedSquare,
|
||||||
|
pieceOnFirstTappedSquare: piece,
|
||||||
|
secondSquareTapped: secondTappedSquare));
|
||||||
|
}
|
||||||
|
|
||||||
|
void cancelTap(CancelTapEvent event, Emitter<TapState> emit) {
|
||||||
|
emit(TapState.init());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class TapEvent {}
|
||||||
|
|
||||||
|
class SquareTappedEvent extends TapEvent {
|
||||||
|
ChessCoordinate tapped;
|
||||||
|
ChessPiece? pieceOnSquare;
|
||||||
|
|
||||||
|
SquareTappedEvent({required this.tapped, required this.pieceOnSquare});
|
||||||
|
}
|
||||||
|
|
||||||
|
class CancelTapEvent extends TapEvent {}
|
||||||
|
|
||||||
|
class TapState {
|
||||||
|
ChessCoordinate? firstSquareTapped;
|
||||||
|
ChessPiece? pieceOnFirstTappedSquare;
|
||||||
|
|
||||||
|
ChessCoordinate? secondSquareTapped;
|
||||||
|
|
||||||
|
TapState(
|
||||||
|
{required this.firstSquareTapped,
|
||||||
|
required this.pieceOnFirstTappedSquare,
|
||||||
|
required this.secondSquareTapped});
|
||||||
|
|
||||||
|
factory TapState.init() {
|
||||||
|
return TapState(
|
||||||
|
firstSquareTapped: null,
|
||||||
|
pieceOnFirstTappedSquare: null,
|
||||||
|
secondSquareTapped: null);
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,5 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
import 'package:flutter/foundation.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:mchess/chess_bloc/chess_bloc.dart';
|
import 'package:mchess/chess_bloc/chess_bloc.dart';
|
||||||
@ -40,11 +39,7 @@ class ServerConnection {
|
|||||||
|
|
||||||
void connect(String playerID, lobbyID, String? passphrase) {
|
void connect(String playerID, lobbyID, String? passphrase) {
|
||||||
String url;
|
String url;
|
||||||
if (kDebugMode) {
|
url = 'wss://chess.sw-gross.de:9999/api/ws';
|
||||||
url = 'ws://localhost:8080/api/ws';
|
|
||||||
} else {
|
|
||||||
url = 'wss://chess.sw-gross.de:9999/api/ws';
|
|
||||||
}
|
|
||||||
channel = WebSocketChannel.connect(Uri.parse(url));
|
channel = WebSocketChannel.connect(Uri.parse(url));
|
||||||
|
|
||||||
send(
|
send(
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_web_plugins/url_strategy.dart';
|
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:mchess/chess/chess_app.dart';
|
import 'package:mchess/chess/chess_app.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
GoRouter.optionURLReflectsImperativeAPIs = true;
|
GoRouter.optionURLReflectsImperativeAPIs = true;
|
||||||
setUrlStrategy(PathUrlStrategy());
|
|
||||||
|
|
||||||
runApp(const ChessApp());
|
runApp(const ChessApp());
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ 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_bloc/promotion_bloc.dart';
|
import 'package:mchess/chess_bloc/promotion_bloc.dart';
|
||||||
|
import 'package:mchess/chess_bloc/tap_bloc.dart';
|
||||||
import 'package:mchess/utils/chess_utils.dart';
|
import 'package:mchess/utils/chess_utils.dart';
|
||||||
import 'package:mchess/utils/widgets/promotion_dialog.dart';
|
import 'package:mchess/utils/widgets/promotion_dialog.dart';
|
||||||
import 'package:universal_platform/universal_platform.dart';
|
import 'package:universal_platform/universal_platform.dart';
|
||||||
@ -25,10 +26,7 @@ class ChessGame extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _ChessGameState extends State<ChessGame> {
|
class _ChessGameState extends State<ChessGame> {
|
||||||
@override
|
ChessCoordinate? tappedSquare;
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -48,18 +46,26 @@ class _ChessGameState extends State<ChessGame> {
|
|||||||
body: Center(
|
body: Center(
|
||||||
child: Container(
|
child: Container(
|
||||||
margin: const EdgeInsets.all(10),
|
margin: const EdgeInsets.all(10),
|
||||||
child: BlocListener<PromotionBloc, PromotionState>(
|
child: BlocListener<TapBloc, TapState>(
|
||||||
listener: (listenerContext, state) {
|
listener: (context, state) {
|
||||||
if (state.showPromotionDialog) {
|
setState(() {
|
||||||
promotionDialogBuilder(listenerContext, state.colorMoved);
|
tappedSquare = state.firstSquareTapped;
|
||||||
}
|
});
|
||||||
},
|
},
|
||||||
child: BlocBuilder<ChessBloc, ChessBoardState>(
|
child: BlocListener<PromotionBloc, PromotionState>(
|
||||||
builder: (context, state) {
|
listener: (listenerContext, state) {
|
||||||
return ChessBoard(
|
if (state.showPromotionDialog) {
|
||||||
boardState: state,
|
promotionDialogBuilder(listenerContext, state.colorMoved);
|
||||||
);
|
}
|
||||||
},
|
},
|
||||||
|
child: BlocBuilder<ChessBloc, ChessBoardState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
return ChessBoard(
|
||||||
|
boardState: state,
|
||||||
|
tappedSquare: tappedSquare,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
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:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
@ -101,11 +100,7 @@ class _HostGameWidgetState extends State<HostGameWidget> {
|
|||||||
String addr;
|
String addr;
|
||||||
Response response;
|
Response response;
|
||||||
|
|
||||||
if (kDebugMode) {
|
addr = 'https://chess.sw-gross.de:9999/api/hostPrivate';
|
||||||
addr = 'http://localhost:8080/api/hostPrivate';
|
|
||||||
} else {
|
|
||||||
addr = 'https://chess.sw-gross.de:9999/api/hostPrivate';
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
response = await http
|
response = await http
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
@ -157,11 +156,7 @@ class _LobbySelectorState extends State<LobbySelector> {
|
|||||||
var info = PlayerInfo(
|
var info = PlayerInfo(
|
||||||
playerID: null, lobbyID: null, passphrase: phraseController.text);
|
playerID: null, lobbyID: null, passphrase: phraseController.text);
|
||||||
|
|
||||||
if (kDebugMode) {
|
addr = 'https://chess.sw-gross.de:9999/api/joinPrivate';
|
||||||
addr = 'http://localhost:8080/api/joinPrivate';
|
|
||||||
} else {
|
|
||||||
addr = 'https://chess.sw-gross.de:9999/api/joinPrivate';
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
response = await http.post(Uri.parse(addr),
|
response = await http.post(Uri.parse(addr),
|
||||||
|
@ -363,3 +363,26 @@ class PieceDragged {
|
|||||||
|
|
||||||
PieceDragged(this.fromSquare, this.toSquare, this.movedPiece);
|
PieceDragged(this.fromSquare, this.toSquare, this.movedPiece);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isPromotionMove(
|
||||||
|
ChessPieceClass pieceMoved, ChessColor myColor, ChessCoordinate toSquare) {
|
||||||
|
bool isPromotion = false;
|
||||||
|
if (pieceMoved != ChessPieceClass.pawn) {
|
||||||
|
return isPromotion;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (myColor) {
|
||||||
|
case ChessColor.black:
|
||||||
|
if (toSquare.row == 1) {
|
||||||
|
isPromotion = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ChessColor.white:
|
||||||
|
if (toSquare.row == 8) {
|
||||||
|
isPromotion = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isPromotion;
|
||||||
|
}
|
||||||
|
20
pubspec.lock
20
pubspec.lock
@ -236,10 +236,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: path_provider_platform_interface
|
name: path_provider_platform_interface
|
||||||
sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c"
|
sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.1"
|
version: "2.1.2"
|
||||||
path_provider_windows:
|
path_provider_windows:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -324,10 +324,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: shared_preferences_platform_interface
|
name: shared_preferences_platform_interface
|
||||||
sha256: d4ec5fc9ebb2f2e056c617112aa75dcf92fc2e4faaf2ae999caa297473f75d8a
|
sha256: "22e2ecac9419b4246d7c22bfbbda589e3acf5c0351137d87dd2939d984d37c3b"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.1"
|
version: "2.3.2"
|
||||||
shared_preferences_web:
|
shared_preferences_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -433,26 +433,26 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: vector_graphics
|
name: vector_graphics
|
||||||
sha256: "0f0c746dd2d6254a0057218ff980fc7f5670fd0fcf5e4db38a490d31eed4ad43"
|
sha256: "18f6690295af52d081f6808f2f7c69f0eed6d7e23a71539d75f4aeb8f0062172"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.9+1"
|
version: "1.1.9+2"
|
||||||
vector_graphics_codec:
|
vector_graphics_codec:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: vector_graphics_codec
|
name: vector_graphics_codec
|
||||||
sha256: "0edf6d630d1bfd5589114138ed8fada3234deacc37966bec033d3047c29248b7"
|
sha256: "531d20465c10dfac7f5cd90b60bbe4dd9921f1ec4ca54c83ebb176dbacb7bb2d"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.9+1"
|
version: "1.1.9+2"
|
||||||
vector_graphics_compiler:
|
vector_graphics_compiler:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: vector_graphics_compiler
|
name: vector_graphics_compiler
|
||||||
sha256: d24333727332d9bd20990f1483af4e09abdb9b1fc7c3db940b56ab5c42790c26
|
sha256: "03012b0a33775c5530576b70240308080e1d5050f0faf000118c20e6463bc0ad"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.9+1"
|
version: "1.1.9+2"
|
||||||
vector_math:
|
vector_math:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
Loading…
Reference in New Issue
Block a user