feat(chess): 初始化棋盘和玩家颜色,优化代码结构,重构多人游戏代码

- 在 ChessGame 中初始化棋盘,根据玩家颜色设置棋子
- 更新 UI 显示玩家颜色
- 调整棋盘位置和 UI 布局
- 重构部分代码以提高可读性和维护性
This commit is contained in:
ZZY
2024-11-07 15:28:03 +08:00
parent d6cbb5e11d
commit 6daf09b300
11 changed files with 161 additions and 220 deletions

View File

@ -1,8 +1,8 @@
using System.Collections;
using Godot;
using Godot.Collections;
public partial class ChessGame : Node2D
{
public partial class ChessGame : Node2D {
ChessBoard board;
Global global;
ConfirmationDialog dialog;
@ -17,17 +17,14 @@ public partial class ChessGame : Node2D
// Init.Call();
global = GetNode<Global>("/root/Global");
board = GetNode<ChessBoard>("Chessboard");
isSession = global.RPClient.IsOnline();
playerSelf = new Player(board.board, Player.PlayerType.Human);
playerOpponent = new Player(board.board, Player.PlayerType.Human);
board.OnMouseClicked += (sender, clickPosition) => {
Vector2 clickBoardPos = (PosTrans.transArrToPix.AffineInverse() *
clickPosition).Round();
playerSelf.HandleBoardPosClick(clickBoardPos);
};
InitChessBoard();
GetNode<LineEdit>("Control/VBoxContainer/MarginContainer3/HFlowContainer/LineEdit")
.Text = global.GlobalData["player_color"].AsString();
GD.PrintErr("ChessGame ", global.RPClient.GetUserId(), ":",global.GlobalData["player_color"]);
dialog = new ConfirmationDialog {
DialogAutowrap = true,
@ -36,37 +33,76 @@ public partial class ChessGame : Node2D
};
AddChild(dialog);
if (!global.RPClient.GetIsConnected()) {
return;
board.OnPosClicked += (sender, pos) => {
if (isSession) {
var res = global.RPClient.SendSessionToAll(global.sessionId, new Dictionary {
{"type", "mouseClicked"},
{"X", pos.X},
{"Y", pos.Y},
{"id", global.RPClient.GetUserId()}
});
playerSelf.HandleBoardPosClick(pos);
} else {
playerSelf.HandleBoardPosClick(pos);
playerSelf.SetAllowedPieces(null);
}
};
if (isSession) {
GD.Print("ws is connected");
global.RPClient.OnPRCSessionExit += (cmd, code) => {
GoHome();
};
global.RPClient.OnPRCSessionRecv += (msg) => {
SessionMsgHandle(msg["msg"].AsGodotDictionary());
};
}
isSession = true;
GD.Print("ws is connected");
global.RPClient.OnPRCSessionExit += (cmd, code) => {
GoHome();
};
board.OnMouseClicked += (sender, clickPosition) => {
Vector2 clickBoardPos = (PosTrans.transArrToPix.AffineInverse() *
clickPosition).Round();
var res = global.RPClient.SendSessionToAll(global.sessionId, new Dictionary {
{"type", "mouseClicked"},
{"X", clickBoardPos.X},
{"Y", clickBoardPos.Y},
});
// GD.Print($"chessMoveFunc Callback {fromPos} -> {newPos} {res}");
};
global.RPClient.OnPRCSessionRecv += (msg) => {
SessionMsgHandle(msg["msg"].AsGodotDictionary());
};
}
// Called every frame. 'delta' is the elapsed time since the previous frame.
public override void _Process(double delta) {
}
public void InitChessBoard() {
ArrayList black = InitializePieces("black", 0, new[] {
("车", 0, 0), ("马", 1, 0), ("象", 2, 0),
("士", 3, 0), ("将", 4, 0), ("士", 5, 0),
("象", 6, 0), ("马", 7, 0), ("车", 8, 0),
("炮", 1, 2), ("炮", 7, 2),
("卒", 0, 3), ("卒", 2, 3), ("卒", 4, 3), ("卒", 6, 3), ("卒", 8, 3)
});
ArrayList red = InitializePieces("red", 9, new[] {
("车", 0, -0), ("马", 1, -0), ("象", 2, -0),
("士", 3, -0), ("将", 4, -0), ("士", 5, -0),
("象", 6, -0), ("马", 7, -0), ("车", 8, -0),
("炮", 1, -2), ("炮", 7, -2),
("卒", 0, -3), ("卒", 2, -3), ("卒", 4, -3), ("卒", 6, -3), ("卒", 8, -3)
});
if (global.GlobalData["player_color"].AsString() == "red") {
playerSelf.SetAllowedPieces(red);
playerOpponent.SetAllowedPieces(black);
} else {
playerSelf.SetAllowedPieces(black);
playerOpponent.SetAllowedPieces(red);
}
}
private ArrayList InitializePieces(string color, int baseY, (string label, int x, int y)[] positions) {
ArrayList list = new();
foreach (var (label, x, y) in positions) {
ChessPiece piece = new ChessPiece {
PieceLabel = label,
LabelColor = new Color(color)
};
list.Add(piece.GetVirtualPiece());
board.InsertNode(piece, new Vector2(x, baseY + y));
}
return list;
}
private void SessionMsgHandle(Dictionary msg) {
GD.PrintErr($"session msg: {msg}");
switch (msg["type"].AsString()) {
@ -79,12 +115,18 @@ public partial class ChessGame : Node2D
dialog.Visible = true;
break;
case "mouseClicked":
if (msg["id"].ToString() == global.RPClient.GetUserId()) {
break;
}
Vector2 mouseClicked = new(GD.StrToVar(msg["X"].ToString()).AsInt32(),
GD.StrToVar(msg["Y"].ToString()).AsInt32());
playerOpponent.HandleBoardPosClick(mouseClicked);
break;
case "undo":
_Undo();
if (msg["id"].ToString() == global.RPClient.GetUserId()) {
break;
}
playerOpponent.Undo();
break;
case "reInit":
_ReInit();
@ -92,13 +134,9 @@ public partial class ChessGame : Node2D
}
}
private void _Undo() {
playerSelf.Undo();
}
private void _ReInit() {
playerSelf.ReInit();
board.InitChessBoard();
InitChessBoard();
}
private void BtnOver() {
@ -123,11 +161,13 @@ public partial class ChessGame : Node2D
GD.Print($"Undo {isSession}");
if (isSession) {
playerSelf.Undo();
global.RPClient.SendSessionToAll(global.sessionId, new Dictionary{
{"type", "undo"},
{"id", global.RPClient.GetUserId()},
});
} else {
_Undo();
playerSelf.Undo();
}
}

View File

@ -10,6 +10,7 @@ public partial class GameLobby : Control {
string URL;
string userName;
bool isAcceptedPart = false;
// Called when the node enters the scene tree for the first time.
public override void _Ready() {
@ -26,8 +27,11 @@ public partial class GameLobby : Control {
global.RPClient.SessionAckCreate(dialog.GetMeta("sessionId").ToString(), false);
};
dialog.Confirmed += () => {
if (dialog.Title == "Session Created")
global.RPClient.SessionAckCreate(dialog.GetMeta("sessionId").ToString(), true);
if (dialog.Title == "Session Created") {
// FIXME
isAcceptedPart = true;
global.RPClient.SessionAckCreate(dialog.GetMeta("sessionId").ToString(), true);
}
};
global.RPClient.OnOpen += (string eventName, object[] args) => {
@ -56,7 +60,14 @@ public partial class GameLobby : Control {
dialog.Visible = true;
} else {
if (res) {
// TODO FIXME
global.sessionId = sessionId;
if (!isAcceptedPart) {
global.GlobalData["player_color"] = "red";
} else {
global.GlobalData["player_color"] = "black";
}
// GD.PrintErr("sessionId: ", reqUserId, "color: ", global.GlobalData["player_color"].AsString());
global.GotoScene("res://Scenes/ChessGame.tscn");
} else {
dialog.Title = "Failed";

View File

@ -33,9 +33,13 @@ public partial class Setting : Control
}
private void OnBack() {
global.SaveConfig();
global.GotoScene("res://Main.tscn", null);
}
private void OnSave() {
global.SaveConfig();
// OS.Alert("Saved", "Setting");
}
void OnNameChanged(string Value)
{

View File

@ -9,6 +9,7 @@ public partial class ChessBoard : Node2D {
public delegate bool ChessMoveFunc(Vector2 toPos, Vector2 fromPos);
// public Callable chessMoveFunc { get; set; }
public event EventHandler<Vector2> OnMouseClicked;
public event EventHandler<Vector2> OnPosClicked;
public override void _Ready() {
board = new VirtualBoard(9, 10);
@ -29,8 +30,6 @@ public partial class ChessBoard : Node2D {
// board.OnMove += (sender, args) => {
// // chessMoveFunc.Call(args.To, args.From);
// };
InitChessBoard();
}
public override void _Input(InputEvent @event) {
@ -40,6 +39,8 @@ public partial class ChessBoard : Node2D {
// HandleMouseClick(GetGlobalTransformWithCanvas().AffineInverse() * mouseButton.Position);
OnMouseClicked?.Invoke(this, GetLocalMousePosition());
OnPosClicked?.Invoke(this, (PosTrans.transArrToPix.AffineInverse() *
GetLocalMousePosition()).Round());
}
}
@ -49,32 +50,4 @@ public partial class ChessBoard : Node2D {
// piece.Move(vector);
board.SetPiecePos(piece, arrayPos);
}
public void InitChessBoard() {
InitializePieces("black", 0, new[] {
("车", 0, 0), ("马", 1, 0), ("象", 2, 0),
("士", 3, 0), ("将", 4, 0), ("士", 5, 0),
("象", 6, 0), ("马", 7, 0), ("车", 8, 0),
("炮", 1, 2), ("炮", 7, 2),
("卒", 0, 3), ("卒", 2, 3), ("卒", 4, 3), ("卒", 6, 3), ("卒", 8, 3)
});
InitializePieces("red", 9, new[] {
("车", 0, -0), ("马", 1, -0), ("象", 2, -0),
("士", 3, -0), ("将", 4, -0), ("士", 5, -0),
("象", 6, -0), ("马", 7, -0), ("车", 8, -0),
("炮", 1, -2), ("炮", 7, -2),
("卒", 0, -3), ("卒", 2, -3), ("卒", 4, -3), ("卒", 6, -3), ("卒", 8, -3)
});
}
private void InitializePieces(string color, int baseY, (string label, int x, int y)[] positions) {
foreach (var (label, x, y) in positions) {
ChessPiece piece = new ChessPiece {
PieceLabel = label,
LabelColor = new Color(color)
};
InsertNode(piece, new Vector2(x, baseY + y));
}
}
}

View File

@ -31,7 +31,7 @@ public partial class ChessPiece : Sprite2D {
}
}
Transform2D transToSeleted = new Transform2D(
Transform2D transToSeleted = new(
new Vector2(1.2f, 0),
new Vector2(0, 1.2f),
new Vector2(0, 0)

View File

@ -16,6 +16,10 @@ public partial class Global : Node
{"user_name", "undefined"}
};
public Dictionary<string, Variant> GlobalData = new() {
{"player_color", "red"},
};
// Called when the node enters the scene tree for the first time.
public override void _Ready()
{
@ -69,7 +73,7 @@ public partial class Global : Node
public override void _Notification(int what)
{
if (what == NotificationWMCloseRequest) {
SaveConfig();
// SaveConfig();
RPClient.Close();
GetTree().Quit(); // default behavior
}

View File

@ -15,7 +15,7 @@ public partial class RPClientBaseEDWS : EventDrivenWebSocket {
public RPClientBaseEDWS() : base() {
OnText += (text) => {
GD.Print($"response: {text}");
// GD.Print($"response: {text}");
RPMessage msg = RPHelper.HandleIncomingMessage(text);
if (msg.Code != "0000") {
OnRPCError?.Invoke(msg.Code, msg.Type, msg.Cmd, msg.Data.ToString());

View File

@ -7,7 +7,7 @@ public class Player {
private readonly SelectedPiece selectedNode;
private readonly MoveRecords<VirtualPiece> moveRecords;
public EventHandler<VirtualBoard.MoveEventArgs> OnMove;
public ArrayList pieces = new();
public enum PlayerType {
Human,
@ -86,11 +86,16 @@ public class Player {
// board.InitChessBoard();
}
public void SetAllowedPieces(ArrayList allowedPieces) {
selectedNode.allowedPieces = allowedPieces;
}
private class SelectedPiece {
// Called when the node enters the scene tree for the first time.
private Vector2 selectedNodePos = Vector2.Inf;
private VirtualPiece piece;
private readonly VirtualBoard board;
public ArrayList allowedPieces = null;
public SelectedPiece(VirtualBoard board) {
this.board = board;
@ -105,8 +110,11 @@ public class Player {
public void SetPos(Vector2 pos) {
// piece = board.GetNodeFromBoard(pos) as VirtualPiece;
piece = board.GetPiece(pos);
if (allowedPieces != null && allowedPieces.Contains(piece) == false) {
return;
}
selectedNodePos = pos;
piece = board.GetPiece(selectedNodePos);
piece.Selected(true);
}