feat: 重构棋盘逻辑和游戏流程,将引擎版本提升至4.3

- 重构了 VirtualBoard 类,优化了棋盘操作和事件处理
- 重写了 ChessPiece 类,增加了事件处理和虚拟棋子逻辑
- 更新了 ChessGame 控制器,增加了结束回合功能和对话框
- 调整了场景布局和资源引用
- 清理了冗余代码和注释
This commit is contained in:
ZZY
2024-11-02 21:18:53 +08:00
parent abace89813
commit 7e2ca3948d
17 changed files with 2984 additions and 503 deletions

View File

@ -5,7 +5,10 @@ public partial class ChessGame : Node2D
{
ChessBoard board;
Global global;
ConfirmationDialog dialog;
private bool isSession = false;
private Vector2 from;
private Vector2 to;
// Called when the node enters the scene tree for the first time.
public override void _Ready()
@ -13,11 +16,17 @@ public partial class ChessGame : Node2D
// Init.Call();
global = GetNode<Global>("/root/Global");
board = GetNode<ChessBoard>("Chessboard");
// GetNode<Button>("Undo").Connect("pressed", Callable.From(board.Undo));
// GetNode<Button>("ReInit").Connect("pressed", Callable.From(board.ReInit));
// GetNode<Button>("Home").Connect("pressed", Callable.From(this.GoHome));
dialog = new ConfirmationDialog {
DialogAutowrap = true,
MinSize = new Vector2I(400, 200),
Position = new Vector2I(200, 400),
};
AddChild(dialog);
// GetNode<Button>("Undo").Connect("pressed", Callable.From(board.Undo));
// GetNode<Button>("ReInit").Connect("pressed", Callable.From(board.ReInit));
// GetNode<Button>("Home").Connect("pressed", Callable.From(this.GoHome));
if (!global.RPClient.GetIsConnected()) {
if (!global.RPClient.GetIsConnected()) {
return;
}
@ -28,6 +37,11 @@ public partial class ChessGame : Node2D
};
board.Set("Hello", Callable.From(() => {GD.PrintErr("hello");}));
board.Set("chessMoveFunc", Callable.From((Vector2 newPos, Vector2 fromPos) => {
if (from.X == fromPos.X && from.Y == fromPos.Y && to.X == newPos.X && to.Y == newPos.Y) {
return true;
}
from = fromPos;
to = newPos;
var res = global.RPClient.SendSessionToAll(global.sessionId, new Dictionary{
{"type", "move"},
{"from", fromPos},
@ -50,25 +64,58 @@ public partial class ChessGame : Node2D
}
private void SessionMsgHandle(Dictionary msg) {
// GD.PrintErr($"session msg: {msg}");
GD.PrintErr($"session msg: {msg}");
switch (msg["type"].AsString()) {
case "over":
if (global.RPClient.GetUserId() == msg["id"].AsString()) {
break;
}
dialog.Title = "Opponent Finished";
dialog.DialogText = "Turn On You\n";
dialog.Visible = true;
break;
case "move":
Vector2 to = new(GD.StrToVar(msg["toX"].ToString()).AsInt32(),
Vector2 _to = new(GD.StrToVar(msg["toX"].ToString()).AsInt32(),
GD.StrToVar(msg["toY"].ToString()).AsInt32());
Vector2 from = new(GD.StrToVar(msg["fromX"].ToString()).AsInt32(),
Vector2 _from = new(GD.StrToVar(msg["fromX"].ToString()).AsInt32(),
GD.StrToVar(msg["fromY"].ToString()).AsInt32());
board.MoveAndRecord(to, from);
if (_to.X == to.X && _to.Y == to.Y && _from.X == from.X && _from.Y == from.Y) {
return;
}
to = _to;
from = _from;
board.playerSelf.MoveAndRecord(to, from);
break;
case "undo":
board.Undo();
_Undo();
break;
case "reInit":
board.ReInit();
_ReInit();
break;
}
}
private void _Undo() {
board.playerSelf.Undo();
}
private void _ReInit() {
board.playerSelf.ReInit();
board.InitChessBoard();
}
private void BtnOver() {
GD.PrintErr($"BtnOver {isSession}");
if (isSession == false) {
return;
}
global.RPClient.SendSessionToAll(global.sessionId, new Dictionary{
{"type", "over"},
{"id", global.RPClient.GetUserId()},
});
}
public void GoHome() {
if (global.RPClient.IsOnline()) {
global.RPClient.ExitServer();
@ -79,9 +126,7 @@ public partial class ChessGame : Node2D
public void Undo() {
GD.PrintErr($"Undo {isSession}");
if (isSession == false) {
GD.PrintErr($"Undo ??");
board.Undo();
return;
_Undo();
}
global.RPClient.SendSessionToAll(global.sessionId, new Dictionary{
{"type", "undo"},
@ -91,8 +136,7 @@ public partial class ChessGame : Node2D
public void ReInit() {
GD.PrintErr($"ReInit {isSession}");
if (isSession == false) {
board.ReInit();
return;
_ReInit();
}
global.RPClient.SendSessionToAll(global.sessionId, new Dictionary{
{"type", "reInit"},

View File

@ -0,0 +1,127 @@
using Godot;
public class Player
{
private VirtualBoard board;
private SelectedPiece selectedNode;
private MoveRecords<VirtualPiece> moveRecords;
public enum PlayerType {
Human,
AI
}
public Player(VirtualBoard board, PlayerType type = PlayerType.Human)
{
this.board = board;
this.selectedNode = new SelectedPiece(board);
this.moveRecords = new MoveRecords<VirtualPiece>(onUndoRecordCallback: (newNode, oldNode, newPos, oldPos) => {
GD.Print("Undo: ", newNode, "->", oldNode, ":", newPos, "->", oldPos);
VirtualPiece newPiece = newNode;
VirtualPiece oldPiece = oldNode;
this.board.MovePiece(newPos, oldPos);
if (newPiece != null) {
this.board.InsertPiece(newPiece, newPos);
}
});
}
public void HandleBoardPosClick(Vector2 clickPos) {
if (board.ArrPosOutOfRange(clickPos)) return;
GD.Print($"VirtualBoard {clickPos} clicked");
VirtualPiece clickChess = board.GetPiece(clickPos);
if (!selectedNode.HasSelected()) {
// Select piece
if (clickChess == null) {
// selectedNode.Clear();
return;
}
selectedNode.SetPos(clickPos);
} else if (clickChess == selectedNode.GetPiece()) {
// Unselect piece
selectedNode.Clear();
} else {
// Move piece
GD.Print("default MoveFunc Move: ", selectedNode.GetPos(), "->", clickPos);
MoveAndRecord(clickPos, selectedNode.GetPos());
}
}
public void MoveAndRecord(Vector2 toPos, Vector2 fromPos) {
GD.Print($"{fromPos} move to {toPos}");
VirtualPiece toChess = board.GetPiece(toPos);
VirtualPiece fromChess = board.GetPiece(fromPos);
fromChess?.Selected(false);
VirtualPiece NowNode;
if (toChess != null) {
NowNode = toChess;
board.RemovePiece(toPos);
} else {
NowNode = toChess;
}
moveRecords.AddRecord(NowNode, fromChess, toPos, fromPos);
board.MovePiece(fromPos, toPos);
selectedNode.Clear();
}
public void Undo() {
// ChessPiece selected = selectedNode.GetPiece();
// selected?.DeSelected();
selectedNode.Clear();
moveRecords.Undo();
}
public void ReInit() {
moveRecords.Clear();
board.Clear();
selectedNode.Clear();
// board.InitChessBoard();
}
private class SelectedPiece
{
// Called when the node enters the scene tree for the first time.
private Vector2 selectedNodePos = Vector2.Inf;
private VirtualPiece piece;
private VirtualBoard board;
public SelectedPiece(VirtualBoard board)
{
this.board = board;
}
public void Clear()
{
if (selectedNodePos != Vector2.Inf) {
selectedNodePos = Vector2.Inf;
piece.Selected(false);
}
}
public void SetPos(Vector2 pos)
{
// piece = board.GetNodeFromBoard(pos) as VirtualPiece;
selectedNodePos = pos;
piece = board.GetPiece(selectedNodePos);
piece.Selected(true);
}
public VirtualPiece GetPiece()
{
return piece;
}
public Vector2 GetPos()
{
return selectedNodePos;
}
public bool HasSelected()
{
return selectedNodePos != Vector2.Inf;
}
}
}

View File

@ -2,27 +2,19 @@
using Godot;
public partial class ChessBoard : Node2D {
VirtualBoard Board = null;
MoveRecords Records = null;
// Called when the node enters the scene tree for the first time.
public Vector2 selectedNodePos = Vector2.Inf;
public VirtualBoard board = null;
public Player playerSelf = null;
public delegate bool ChessMoveFunc(Vector2 toPos, Vector2 fromPos);
public Callable chessMoveFunc { get; set; }
public override void _Ready() {
Board = new VirtualBoard(this as Node);
Records = new MoveRecords(onUndoRecordCallback: (newNode, oldNode, newPos, oldPos) => {
GD.Print("Undo: ", newNode, "->", oldNode, ":", newPos, "->", oldPos);
ChessPiece newPiece = newNode as ChessPiece;
ChessPiece oldPiece = oldNode as ChessPiece;
Board.MoveNode(oldPos, newPos);
if (newPiece != null) {
Board.InsertNode(newPiece, newPos);
}
});
Board.InitChessBoard();
// this.AddChild();
board = new VirtualBoard(9, 10);
playerSelf = new Player(board);
board.OnRemove += OnRemove;
board.OnInsert += OnInsert;
board.OnMove += OnMove;
InitChessBoard();
}
public override void _Input(InputEvent @event) {
@ -31,85 +23,286 @@ public partial class ChessBoard : Node2D {
mouseEvent.ButtonIndex == MouseButton.Left) {
// HandleMouseClick(GetGlobalTransformWithCanvas().AffineInverse() * mouseButton.Position);
HandleMouseClick(GetLocalMousePosition());
// ActionPos(
// (PosTrans.transArrToPix.AffineInverse() *
// GetLocalMousePosition()).Round()
// );
}
}
public void ActionPos(Vector2 newPos) {
}
public void MoveAndRecord(Vector2 toPos, Vector2 fromPos) {
GD.Print($"{fromPos} move to {toPos}");
ChessPiece toChess = Board.GetNodeFromBoard(toPos) as ChessPiece;
ChessPiece fromChess = Board.GetNodeFromBoard(fromPos) as ChessPiece;
if (fromChess != null) {
fromChess.DeSelected();
}
Node NowNode;
if (toChess != null) {
GD.Print("nowchess", toChess);
NowNode = toChess.Duplicate();
Board.RemoveNode(toPos);
} else {
NowNode = toChess as Node;
}
Records.AddRecord(NowNode, fromChess, toPos, fromPos);
Board.MoveNode(toPos, fromPos);
selectedNodePos = Vector2.Inf;
}
public void Undo() {
Records.Undo();
}
public void ReInit() {
Records.Clear();
Board.Clear();
selectedNodePos = Vector2.Inf;
Board.InitChessBoard();
}
private void HandleMouseClick(Vector2 clickPosition) {
Vector2 newPos = (PosTrans.transArrToPix.AffineInverse() *
clickPosition).Round();
if (VirtualBoard.ArrPosOutOfRange(newPos)) return;
GD.Print($"{newPos} mouse clicked");
ChessPiece NowChess = Board.GetNodeFromBoard(newPos) as ChessPiece;
ChessPiece SelChess = Board.GetNodeFromBoard(selectedNodePos) as ChessPiece;
if (Vector2.Inf.Equals(selectedNodePos)) {
if (NowChess == null) {
return;
}
NowChess.Selected();
selectedNodePos = newPos;
} else if (selectedNodePos == newPos) {
if (SelChess != null) {
SelChess.DeSelected();
}
selectedNodePos = Vector2.Inf;
} else {
if (chessMoveFunc.Delegate != null) {
GD.Print("chessMoveFunc Move: ", selectedNodePos, "->", newPos);
if ((bool)chessMoveFunc.Call(newPos, selectedNodePos)) {
MoveAndRecord(newPos, selectedNodePos);
}
} else {
GD.Print("default MoveFunc Move: ", selectedNodePos, "->", newPos);
MoveAndRecord(newPos, selectedNodePos);
}
// MoveAndRecord(newPos, selectedNodePos);
// GD.Print($"End: {selectedNodePos} {SelChess} move to {clickArrPos} {NowChess}");
}
}
private void HandleMouseClick(Vector2 clickPosition) {
Vector2 clickBoardPos = (PosTrans.transArrToPix.AffineInverse() *
clickPosition).Round();
playerSelf.HandleBoardPosClick(clickBoardPos);
}
void OnMove(Vector2 from, Vector2 to) {
chessMoveFunc.Call(to, from);
}
void OnRemove(VirtualPiece piece) {
// (piece.data as Node).QueueFree();
if (piece?.data != null)
RemoveChild(piece.data as Node);
}
void OnInsert(VirtualPiece piece) {
ChessPiece chess = piece.data as ChessPiece;
AddChild(chess);
}
public void InsertNode(ChessPiece node, Vector2 arrayPos) {
AddChild(node);
VirtualPiece piece = node.GetVirtualPiece();
// piece.Move(vector);
board.SetPiecePos(piece, arrayPos);
}
// using Godot;
// public enum ChessType
// {
// Carriage,
// Horse,
// Elephant,
// Advisor,
// General,
// Cannon,
// Pawn
// }
// public class VirtualBoard
// {
// // ...其他原有成员变量...
// public VirtualBoard(Node root = null)
// {
// BoardRoot = root ?? GetTree().CurrentScene; // 如果未提供root默认为当前场景
// }
// public void InitChessBoard()
// {
// // 定义黑色和红色棋子的初始位置和类型
// var positions = new (Vector2 position, ChessType type)[]
// {
// // 黑方棋子初始化...
// // 示例省略具体位置和类型,你需要根据实际情况填写
// // (new Vector2(x, y), ChessType.Pawn),
// // 红方棋子初始化...
// // 同上
// };
// // 初始化棋子
// foreach (var (position, type) in positions)
// {
// var color = position.Y == 0 ? new Color("black") : new Color("red"); // 根据行判断颜色
// var piece = CreateChessPiece(type, color);
// InsertChess(piece, position);
// }
// }
// private ChessPiece CreateChessPiece(ChessType type, Color labelColor)
// {
// // 根据ChessType创建对应的棋子实例并设置Label和颜色
// // 这里需要你实现具体的逻辑例如switch case或映射表来决定创建哪种棋子
// // 返回创建的棋子实例
// }
// // ...其他原有方法...
// }
public void InitChessBoard() {
InsertNode(new ChessPiece
{
PieceLabel = "车",
LabelColor = new Color("black"),
}, new Vector2(0, 0));
InsertNode(new ChessPiece
{
PieceLabel = "马",
LabelColor = new Color("black"),
}, new Vector2(1, 0));
InsertNode(new ChessPiece
{
PieceLabel = "象",
LabelColor = new Color("black"),
}, new Vector2(2, 0));
InsertNode(new ChessPiece
{
PieceLabel = "士",
LabelColor = new Color("black"),
}, new Vector2(3, 0));
InsertNode(new ChessPiece
{
PieceLabel = "将",
LabelColor = new Color("black"),
}, new Vector2(4, 0));
InsertNode(new ChessPiece
{
PieceLabel = "士",
LabelColor = new Color("black"),
}, new Vector2(5, 0));
InsertNode(new ChessPiece
{
PieceLabel = "象",
LabelColor = new Color("black"),
}, new Vector2(6, 0));
InsertNode(new ChessPiece
{
PieceLabel = "马",
LabelColor = new Color("black"),
}, new Vector2(7, 0));
InsertNode(new ChessPiece
{
PieceLabel = "车",
LabelColor = new Color("black"),
}, new Vector2(8, 0));
InsertNode(new ChessPiece
{
PieceLabel = "炮",
LabelColor = new Color("black"),
}, new Vector2(1, 2));
InsertNode(new ChessPiece
{
PieceLabel = "炮",
LabelColor = new Color("black"),
}, new Vector2(7, 2));
InsertNode(new ChessPiece
{
PieceLabel = "卒",
LabelColor = new Color("black"),
}, new Vector2(0, 3));
InsertNode(new ChessPiece
{
PieceLabel = "卒",
LabelColor = new Color("black"),
}, new Vector2(2, 3));
InsertNode(new ChessPiece
{
PieceLabel = "卒",
LabelColor = new Color("black"),
}, new Vector2(4, 3));
InsertNode(new ChessPiece
{
PieceLabel = "卒",
LabelColor = new Color("black"),
}, new Vector2(6, 3));
InsertNode(new ChessPiece
{
PieceLabel = "卒",
LabelColor = new Color("black"),
}, new Vector2(8, 3));
// -----------------------------------
InsertNode(new ChessPiece
{
PieceLabel = "车",
LabelColor = new Color("red"),
}, new Vector2(0, 9));
InsertNode(new ChessPiece
{
PieceLabel = "马",
LabelColor = new Color("red"),
}, new Vector2(1, 9));
InsertNode(new ChessPiece
{
PieceLabel = "象",
LabelColor = new Color("red"),
}, new Vector2(2, 9));
InsertNode(new ChessPiece
{
PieceLabel = "士",
LabelColor = new Color("red"),
}, new Vector2(3, 9));
InsertNode(new ChessPiece
{
PieceLabel = "将",
LabelColor = new Color("red"),
}, new Vector2(4, 9));
InsertNode(new ChessPiece
{
PieceLabel = "士",
LabelColor = new Color("red"),
}, new Vector2(5, 9));
InsertNode(new ChessPiece
{
PieceLabel = "象",
LabelColor = new Color("red"),
}, new Vector2(6, 9));
InsertNode(new ChessPiece
{
PieceLabel = "马",
LabelColor = new Color("red"),
}, new Vector2(7, 9));
InsertNode(new ChessPiece
{
PieceLabel = "车",
LabelColor = new Color("red"),
}, new Vector2(8, 9));
InsertNode(new ChessPiece
{
PieceLabel = "炮",
LabelColor = new Color("red"),
}, new Vector2(1, 7));
InsertNode(new ChessPiece
{
PieceLabel = "炮",
LabelColor = new Color("red"),
}, new Vector2(7, 7));
InsertNode(new ChessPiece
{
PieceLabel = "卒",
LabelColor = new Color("red"),
}, new Vector2(0, 6));
InsertNode(new ChessPiece
{
PieceLabel = "卒",
LabelColor = new Color("red"),
}, new Vector2(2, 6));
InsertNode(new ChessPiece
{
PieceLabel = "卒",
LabelColor = new Color("red"),
}, new Vector2(4, 6));
InsertNode(new ChessPiece
{
PieceLabel = "卒",
LabelColor = new Color("red"),
}, new Vector2(6, 6));
InsertNode(new ChessPiece
{
PieceLabel = "卒",
LabelColor = new Color("red"),
}, new Vector2(8, 6));
}
}

View File

@ -11,42 +11,38 @@ public partial class ChessPiece : Sprite2D {
private Vector2 textureSize;
private Label labelOfChessName;
private VirtualPiece piece;
private Vector2 arrPos = new Vector2(); // 注意这个坐标的非像素坐标而是棋盘坐标
public void movePos(Vector2 newPos) {
this.arrPos = newPos;
this.Position = PosTrans.transArrToPix * newPos;
public VirtualPiece GetVirtualPiece() {
return piece;
}
public Vector2 getPos() {
return arrPos;
private void OnMove(Vector2 newPos) {
Position = PosTrans.transArrToPix * new Vector2(newPos.X, newPos.Y);
}
public void OnSelected(bool isSelected) {
if (isSelected) {
GD.Print($"{piece.Pos()} is selected");
Transform *= transToSeleted;
} else {
GD.Print($"{piece.Pos()} is deselected");
Transform *= transToSeleted.AffineInverse();
}
}
// 是否被选中
public bool isSelected = false;
Transform2D transToSeleted = new Transform2D(
new Vector2(1.2f, 0),
new Vector2(0, 1.2f),
new Vector2(0, 0)
);
public void Selected() {
if (isSelected) {
return;
}
GD.Print($"{arrPos} is selected");
this.Transform *= transToSeleted;
this.isSelected = true;
}
public void DeSelected() {
if (!isSelected) {
return;
}
GD.Print($"{arrPos} is deselected");
this.Transform *= transToSeleted.AffineInverse();
this.isSelected = false;
public ChessPiece(string name = "", Vector2 pos = new Vector2()) {
PieceLabel = name;
piece = new VirtualPiece(name, pos);
piece.OnMove += OnMove;
piece.OnSelected += OnSelected;
piece.data = this;
}
// Called when the node enters the scene tree for the first time.
@ -56,8 +52,8 @@ public partial class ChessPiece : Sprite2D {
private void InitLabel() {
// this.Texture.ResourcePath = "res://Asserts/ChesspieceBase.tres";
this.Texture ??= (Texture2D)ResourceLoader.Load("res://Asserts/ChesspieceBase.tres");
textureSize = this.Texture.GetSize();
Texture ??= (Texture2D)ResourceLoader.Load("res://Asserts/ChesspieceBase.tres");
textureSize = Texture.GetSize();
Vector2 labalPosition = new(
-textureSize.X / 2,
-textureSize.Y / 2);
@ -72,8 +68,4 @@ public partial class ChessPiece : Sprite2D {
// labelOfChessName.SetAnchorsPreset(Control.LayoutPreset.FullRect);
AddChild(labelOfChessName);
}
interface IVarify {
bool CanMove(Vector2 newPosition);
}
}

View File

View File

@ -1,23 +1,25 @@
// using System.Numerics;
using Godot;
using System.Collections.Generic;
using System;
using Godot;
using System.Linq;
public class MoveRecords {
public class MoveRecords<T> {
private readonly LinkedList<MoveRecord> records = new LinkedList<MoveRecord>(); // 使用队列替换栈
private readonly int maxRecords; // 记录上限
private Action<Node, Node, Vector2, Vector2> onAddRecordCallback; // 添加记录时的回调
private Action<Node, Node, Vector2, Vector2> onUndoRecordCallback; // 撤销记录时的回调
private Action<T, T, Vector2, Vector2> onAddRecordCallback; // 添加记录时的回调
private Action<T, T, Vector2, Vector2> onUndoRecordCallback; // 撤销记录时的回调
public MoveRecords(
Action<Node, Node, Vector2, Vector2> onAddRecordCallback = null,
Action<Node, Node, Vector2, Vector2> onUndoRecordCallback = null,
Action<T, T, Vector2, Vector2> onAddRecordCallback = null,
Action<T, T, Vector2, Vector2> onUndoRecordCallback = null,
int maxRecords = 32) {
this.maxRecords = maxRecords;
this.onAddRecordCallback = onAddRecordCallback;
this.onUndoRecordCallback = onUndoRecordCallback;
}
public void AddRecord(Node newNode, Node oldNode, Vector2 newPos, Vector2 oldPos) {
public void AddRecord(T newNode, T oldNode, Vector2 newPos, Vector2 oldPos) {
// 达到记录上限时,移除最远的记录(队首元素)
if (records.Count >= maxRecords) {
records.RemoveFirst();
@ -42,16 +44,16 @@ public class MoveRecords {
}
private class MoveRecord {
public Node NewNode { get; }
public Node OldNode { get; }
public T NewNode { get; }
public T OldNode { get; }
public Vector2 NewPos { get; }
public Vector2 OldPos { get; }
public MoveRecord(Node newNode, Node oldNode, Vector2 newPos, Vector2 oldPos) {
this.NewNode = newNode;
this.OldNode = oldNode;
this.OldPos = oldPos;
this.NewPos = newPos;
public MoveRecord(T newNode, T oldNode, Vector2 newPos, Vector2 oldPos) {
NewNode = newNode;
OldNode = oldNode;
OldPos = oldPos;
NewPos = newPos;
}
}
}

View File

@ -1,316 +1,74 @@
// using System.Numerics;
using Godot;
using System;
class VirtualBoard {
private static readonly int boradRows = 9;
private static readonly int boradCols = 10;
private readonly Node BoardRoot;
private readonly Node[,] nodesBorad = new Node[boradRows, boradCols];
public class VirtualBoard {
private readonly int Rows;
private readonly int Cols;
private readonly VirtualPiece[,] pieces;
public static bool ArrPosOutOfRange(Vector2 arrayPos) {
return arrayPos.X < 0 || arrayPos.X >= boradRows || arrayPos.Y < 0 || arrayPos.Y >= boradCols;
// <oldPiece, newPiece>
public event Action<VirtualPiece, VirtualPiece> OnSetPiecePos;
public event Action<VirtualPiece> OnInsert;
public event Action<VirtualPiece> OnRemove;
public event Action<Vector2, Vector2> OnMove;
public VirtualBoard(int Rows, int Cols) {
this.Rows = Rows;
this.Cols = Cols;
pieces = new VirtualPiece[Rows, Cols];
}
public Node GetNodeFromBoard(Vector2 arrayPos) {
public bool ArrPosOutOfRange(Vector2 arrayPos) {
return arrayPos.X < 0 || arrayPos.X >= Rows || arrayPos.Y < 0 || arrayPos.Y >= Cols;
}
public VirtualPiece GetPiece(Vector2 arrayPos) {
if (ArrPosOutOfRange(arrayPos)) return null;
return nodesBorad[(int)arrayPos.X, (int)arrayPos.Y];
return pieces[(int)arrayPos.X, (int)arrayPos.Y];
}
public void SetNodeToBoard(Vector2 arrayPos, Node node) {
if (ArrPosOutOfRange(arrayPos)) return;
nodesBorad[(int)arrayPos.X, (int)arrayPos.Y] = node;
public VirtualPiece SetPiecePos(VirtualPiece piece, Vector2 arrayPos) {
VirtualPiece ret = null;
if (ArrPosOutOfRange(arrayPos)) return ret;
ret = pieces[(int)arrayPos.X, (int)arrayPos.Y];
pieces[(int)arrayPos.X, (int)arrayPos.Y] = piece;
OnSetPiecePos?.Invoke(ret, piece);
piece?.Move(arrayPos);
return ret;
}
public VirtualBoard(Node root = null) {
//?? //GetTree().CurrentScene; // 如果未提供root默认为当前场景
BoardRoot = root;
}
public bool MoveNode(Vector2 newPos, Vector2 oldPos) {
if (ArrPosOutOfRange(newPos) || ArrPosOutOfRange(oldPos)) {
return false;
}
if (GetNodeFromBoard(newPos) != null) {
return false;
}
if (GetNodeFromBoard(oldPos) is ChessPiece chessPiece) {
chessPiece.movePos(newPos);
public bool InsertPiece(VirtualPiece piece, Vector2 arrayPos) {
if (GetPiece(arrayPos) != null) {
return false;
}
SetNodeToBoard(newPos, GetNodeFromBoard(oldPos));
SetNodeToBoard(oldPos, null);
return true;
}
public bool RemoveNode(Vector2 arrayPos) {
if (ArrPosOutOfRange(arrayPos)) return false;
if (GetNodeFromBoard(arrayPos) is ChessPiece chessPiece) {
chessPiece.QueueFree();
}
SetNodeToBoard(arrayPos, null);
OnInsert?.Invoke(piece);
SetPiecePos(piece, arrayPos);
return true;
}
public void InsertNode(ChessPiece chess, Vector2 arrayPos) {
chess.Position = PosTrans.transArrToPix * arrayPos;
SetNodeToBoard(arrayPos, chess);
BoardRoot.AddChild(chess);
public bool MovePiece(Vector2 from, Vector2 to) {
if (ArrPosOutOfRange(to) || ArrPosOutOfRange(from)) {
return false;
}
if (GetPiece(to) != null) {
return false;
}
OnMove?.Invoke(from, to);
SetPiecePos(SetPiecePos(null, from), to);
return true;
}
public bool RemovePiece(Vector2 pos) {
OnRemove?.Invoke(GetPiece(pos));
return SetPiecePos(null, pos) != null;
}
public void Clear() {
foreach (var node in BoardRoot.GetChildren()) {
if (node is ChessPiece chessPiece) {
RemoveNode(chessPiece.getPos());
chessPiece.QueueFree();
for (int i = 0; i < Rows; i++) {
for (int j = 0; j < Cols; j++) {
RemovePiece(new Vector2(i, j));
}
}
}
// using Godot;
// public enum ChessType
// {
// Carriage,
// Horse,
// Elephant,
// Advisor,
// General,
// Cannon,
// Pawn
// }
// public class VirtualBoard
// {
// // ...其他原有成员变量...
// public VirtualBoard(Node root = null)
// {
// BoardRoot = root ?? GetTree().CurrentScene; // 如果未提供root默认为当前场景
// }
// public void InitChessBoard()
// {
// // 定义黑色和红色棋子的初始位置和类型
// var positions = new (Vector2 position, ChessType type)[]
// {
// // 黑方棋子初始化...
// // 示例省略具体位置和类型,你需要根据实际情况填写
// // (new Vector2(x, y), ChessType.Pawn),
// // 红方棋子初始化...
// // 同上
// };
// // 初始化棋子
// foreach (var (position, type) in positions)
// {
// var color = position.Y == 0 ? new Color("black") : new Color("red"); // 根据行判断颜色
// var piece = CreateChessPiece(type, color);
// InsertChess(piece, position);
// }
// }
// private ChessPiece CreateChessPiece(ChessType type, Color labelColor)
// {
// // 根据ChessType创建对应的棋子实例并设置Label和颜色
// // 这里需要你实现具体的逻辑例如switch case或映射表来决定创建哪种棋子
// // 返回创建的棋子实例
// }
// // ...其他原有方法...
// }
public void InitChessBoard() {
InsertNode(new ChessPiece
{
PieceLabel = "车",
LabelColor = new Color("black"),
}, new Vector2(0, 0));
InsertNode(new ChessPiece
{
PieceLabel = "马",
LabelColor = new Color("black"),
}, new Vector2(1, 0));
InsertNode(new ChessPiece
{
PieceLabel = "象",
LabelColor = new Color("black"),
}, new Vector2(2, 0));
InsertNode(new ChessPiece
{
PieceLabel = "士",
LabelColor = new Color("black"),
}, new Vector2(3, 0));
InsertNode(new ChessPiece
{
PieceLabel = "将",
LabelColor = new Color("black"),
}, new Vector2(4, 0));
InsertNode(new ChessPiece
{
PieceLabel = "士",
LabelColor = new Color("black"),
}, new Vector2(5, 0));
InsertNode(new ChessPiece
{
PieceLabel = "象",
LabelColor = new Color("black"),
}, new Vector2(6, 0));
InsertNode(new ChessPiece
{
PieceLabel = "马",
LabelColor = new Color("black"),
}, new Vector2(7, 0));
InsertNode(new ChessPiece
{
PieceLabel = "车",
LabelColor = new Color("black"),
}, new Vector2(8, 0));
InsertNode(new ChessPiece
{
PieceLabel = "炮",
LabelColor = new Color("black"),
}, new Vector2(1, 2));
InsertNode(new ChessPiece
{
PieceLabel = "炮",
LabelColor = new Color("black"),
}, new Vector2(7, 2));
InsertNode(new ChessPiece
{
PieceLabel = "卒",
LabelColor = new Color("black"),
}, new Vector2(0, 3));
InsertNode(new ChessPiece
{
PieceLabel = "卒",
LabelColor = new Color("black"),
}, new Vector2(2, 3));
InsertNode(new ChessPiece
{
PieceLabel = "卒",
LabelColor = new Color("black"),
}, new Vector2(4, 3));
InsertNode(new ChessPiece
{
PieceLabel = "卒",
LabelColor = new Color("black"),
}, new Vector2(6, 3));
InsertNode(new ChessPiece
{
PieceLabel = "卒",
LabelColor = new Color("black"),
}, new Vector2(8, 3));
// -----------------------------------
InsertNode(new ChessPiece
{
PieceLabel = "车",
LabelColor = new Color("red"),
}, new Vector2(0, 9));
InsertNode(new ChessPiece
{
PieceLabel = "马",
LabelColor = new Color("red"),
}, new Vector2(1, 9));
InsertNode(new ChessPiece
{
PieceLabel = "象",
LabelColor = new Color("red"),
}, new Vector2(2, 9));
InsertNode(new ChessPiece
{
PieceLabel = "士",
LabelColor = new Color("red"),
}, new Vector2(3, 9));
InsertNode(new ChessPiece
{
PieceLabel = "将",
LabelColor = new Color("red"),
}, new Vector2(4, 9));
InsertNode(new ChessPiece
{
PieceLabel = "士",
LabelColor = new Color("red"),
}, new Vector2(5, 9));
InsertNode(new ChessPiece
{
PieceLabel = "象",
LabelColor = new Color("red"),
}, new Vector2(6, 9));
InsertNode(new ChessPiece
{
PieceLabel = "马",
LabelColor = new Color("red"),
}, new Vector2(7, 9));
InsertNode(new ChessPiece
{
PieceLabel = "车",
LabelColor = new Color("red"),
}, new Vector2(8, 9));
InsertNode(new ChessPiece
{
PieceLabel = "炮",
LabelColor = new Color("red"),
}, new Vector2(1, 7));
InsertNode(new ChessPiece
{
PieceLabel = "炮",
LabelColor = new Color("red"),
}, new Vector2(7, 7));
InsertNode(new ChessPiece
{
PieceLabel = "卒",
LabelColor = new Color("red"),
}, new Vector2(0, 6));
InsertNode(new ChessPiece
{
PieceLabel = "卒",
LabelColor = new Color("red"),
}, new Vector2(2, 6));
InsertNode(new ChessPiece
{
PieceLabel = "卒",
LabelColor = new Color("red"),
}, new Vector2(4, 6));
InsertNode(new ChessPiece
{
PieceLabel = "卒",
LabelColor = new Color("red"),
}, new Vector2(6, 6));
InsertNode(new ChessPiece
{
PieceLabel = "卒",
LabelColor = new Color("red"),
}, new Vector2(8, 6));
}
}

View File

@ -0,0 +1,40 @@
// using System.Numerics;
using Godot;
using System;
public class VirtualPiece {
private Vector2 pos; // 注意这个坐标的非像素坐标而是棋盘坐标
private string name;
private bool isSelected;
public object data;
public event Action<Vector2> OnMove;
public event Action<bool> OnSelected;
public void Move(Vector2 pos) {
this.pos = pos;
OnMove?.Invoke(pos);
}
public Vector2 Pos() {
return pos;
}
public void Selected(bool isSelected) {
if (this.isSelected != isSelected) {
OnSelected?.Invoke(isSelected);
this.isSelected = isSelected;
}
}
public bool IsSelected() {
return isSelected;
}
public VirtualPiece(string name = "", Vector2 pos = new Vector2()) {
this.name = name;
this.pos = pos;
}
}