Compare commits

...

1 Commits
v0.0.4 ... main

Author SHA1 Message Date
ZZY
e16f76e11f refactor(重构): 重构了事件驱动的代码体系,使用全新命名和版本,以及测试套件的初试
- 移除了.csproj文件
- 更新了.gitignore,添加了.editorconfig
- 重构了IBoard和IPiece接口,引入了新的事件处理机制
- 优化了CCBoard、CCPiece等类的实现,使用新的事件驱动模型
- 删除了冗余代码,提高了代码的可读性和可维护性
2024-11-24 15:42:30 +08:00
18 changed files with 416 additions and 274 deletions

1
.gitignore vendored
View File

@ -25,6 +25,7 @@ bin/
*.sln *.sln
*.error *.error
*.key* *.key*
.editorconfig
# cs project files # cs project files
!*.csproj !*.csproj

View File

@ -1,8 +1,6 @@
<Project Sdk="Godot.NET.Sdk/4.3.0"> <Project Sdk="Godot.NET.Sdk/4.3.0">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<TargetFramework Condition=" '$(GodotTargetPlatform)' == 'android' ">net7.0</TargetFramework>
<TargetFramework Condition=" '$(GodotTargetPlatform)' == 'ios' ">net8.0</TargetFramework>
<EnableDynamicLoading>true</EnableDynamicLoading> <EnableDynamicLoading>true</EnableDynamicLoading>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>

View File

@ -1,3 +1,4 @@
#nullable disable
using Godot; using Godot;
using Godot.Collections; using Godot.Collections;
using ChineseChess; using ChineseChess;
@ -39,15 +40,15 @@ public partial class ChessGame : Node2D {
sideOpposite = ChessCore.TurnsSideType.Red; sideOpposite = ChessCore.TurnsSideType.Red;
} }
if (isSession) { // if (isSession) {
Game = new(ChessCore.Mode.MultiMode, sideSelf); // Game = new(ChessCore.Mode.MultiMode, sideSelf);
} else { // } else {
Game = new(ChessCore.Mode.SingleMode, sideSelf); // Game = new(ChessCore.Mode.SingleMode, sideSelf);
} // }
board.LoadBoard(Game.board); Game = new(isSession ? ChessCore.Mode.MultiMode : ChessCore.Mode.SingleMode, sideSelf, board);
Game.Init(); Game.Init();
Game.board.OnStepsChanged += (sender, e) => { board.OnStepsChanged += (sender, e) => {
turnSideEdit.Text = Game.GetTurnsType() == ChessCore.TurnsSideType.Red ? "red" : "black"; turnSideEdit.Text = Game.GetTurnsType() == ChessCore.TurnsSideType.Red ? "red" : "black";
}; };

View File

@ -1,3 +1,4 @@
#nullable disable
using Godot; using Godot;
using Godot.Collections; using Godot.Collections;

View File

@ -4,12 +4,14 @@ using Godot;
using ChineseChess; using ChineseChess;
using Godot.Collections; using Godot.Collections;
public partial class ChessBoard : Node2D { using static IBoard;
public event EventHandler<Vector2> OnMouseClicked; public partial class ChessBoard : Node2D, ICCBoardOn {
public event EventHandler<Vector2> OnPosClicked; public event EventHandler<Vector2>? OnMouseClicked;
public event EventHandler<Vector2>? OnPosClicked;
public event EventHandler<int>? OnStepsChanged;
public Vector2 from = Vector2.Inf, to = Vector2.Inf; public Vector2 from = Vector2.Inf, to = Vector2.Inf;
public Array<Vector2> canMovePos = new(); public Array<Vector2> canMovePos = [];
public override void _Ready() { public override void _Ready() {
} }
@ -19,29 +21,39 @@ public partial class ChessBoard : Node2D {
QueueRedraw(); QueueRedraw();
} }
public void LoadBoard(CCBoard board) { void IBoardOn.OnInsert(object self, IPiece piece) {
board.OnRemove += (sender, piece) => { ChessPiece? node = piece.On as ChessPiece;
if (piece?.Data.TryGetValue("Godot", out object node) ?? false) { // throw new InvalidOperationException();
RemoveChild(node as Node); node ??= new ChessPiece((CCPiece)piece);
} node.ShowBehindParent = true;
}; AddChild(node);
board.OnInsert += (sender, piece) => { // ChessPiece chessPiece = null;
ChessPiece chessPiece = null; // if (piece.Data.TryGetValue("Godot", out object node)) {
if (piece.Data.TryGetValue("Godot", out object node)) { // chessPiece = node as ChessPiece;
chessPiece = node as ChessPiece; // } else {
} else { // chessPiece = new((CCPiece)piece);
chessPiece = new((CCPiece)piece); // }
// chessPiece.ShowBehindParent = true;
// AddChild(chessPiece);
} }
chessPiece.ShowBehindParent = true;
AddChild(chessPiece);
};
board.OnMove += (sender, vals) => { void IBoardOn.OnRemove(object self, IPiece piece) {
if (piece.On is not ChessPiece node) {
throw new InvalidOperationException();
}
RemoveChild(node);
}
void IBoardOn.OnMove(object self, IBoardOn.MoveEventArgs vals) {
from = PosTrans.transArrToPix * new Vector2(vals.From.X, vals.From.Y); from = PosTrans.transArrToPix * new Vector2(vals.From.X, vals.From.Y);
to = PosTrans.transArrToPix * new Vector2(vals.To.X, vals.To.Y); to = PosTrans.transArrToPix * new Vector2(vals.To.X, vals.To.Y);
QueueRedraw(); QueueRedraw();
}; }
void ICCBoardOn.OnSteps(object _self, int oldSteps) {
if (_self is not CCBoard self) return;
OnStepsChanged?.Invoke(self, self.Steps);
} }
public override void _Draw() { public override void _Draw() {

View File

@ -4,37 +4,31 @@ using ChineseChess;
using System.Linq; using System.Linq;
using System; using System;
public partial class ChessPiece : Sprite2D { using static IPiece;
public partial class ChessPiece : Sprite2D, IPieceOn {
[Export] [Export]
public string PieceLabel { get; set; } = null; public string? PieceLabel { get; set; } = null;
// Text Color (Can Export for Editor Adjust) // Text Color (Can Export for Editor Adjust)
[Export] [Export]
public Color LabelColor { get; set; } = new Color("white"); public Color LabelColor { get; set; } = new Color("white");
private Vector2 textureSize; private Vector2 textureSize;
private Label? labelOfChessName;
private Label labelOfChessName; void IPieceOn.OnPos(object _self, Vector.Vector2I oldPos) {
private readonly IPiece piece; if (_self is not CCPiece self) return;
public IPiece GetVirtualPiece() {
return piece;
}
private void OnPos(object _self, Vector.Vector2I oldPos) {
CCPiece self = (CCPiece)_self;
Position = ChessBoard.PosTrans.transArrToPix * new Vector2(self.Pos.X, self.Pos.Y); Position = ChessBoard.PosTrans.transArrToPix * new Vector2(self.Pos.X, self.Pos.Y);
} }
public void OnSelected(object _self, bool oldIsSelected) { void IPieceOn.OnSelected(object _self, bool oldIsSelected) {
CCPiece self = (CCPiece)_self; if (GetParent() is not ChessBoard chessBoard || _self is not CCPiece self) return;
ChessBoard chessBoard = GetParent() as ChessBoard;
if (self.IsSelected) { if (self.IsSelected) {
GD.Print($"{piece.Pos} is selected"); GD.Print($"{self.Pos} is selected");
Transform *= transToSeleted; Transform *= transToSeleted;
foreach (var item in self.CanMoveAllPos()) { foreach (var item in self.CanMoveAllPos()) {
chessBoard.canMovePos.Add(ChessBoard.PosTrans.transArrToPix * new Vector2(item.X, item.Y)); chessBoard.canMovePos.Add(ChessBoard.PosTrans.transArrToPix * new Vector2(item.X, item.Y));
} }
} else { } else {
GD.Print($"{piece.Pos} is deselected"); GD.Print($"{self.Pos} is deselected");
Transform *= transToSeleted.AffineInverse(); Transform *= transToSeleted.AffineInverse();
foreach (var item in self.CanMoveAllPos()) { foreach (var item in self.CanMoveAllPos()) {
chessBoard.canMovePos.Remove(ChessBoard.PosTrans.transArrToPix * new Vector2(item.X, item.Y)); chessBoard.canMovePos.Remove(ChessBoard.PosTrans.transArrToPix * new Vector2(item.X, item.Y));
@ -49,17 +43,15 @@ public partial class ChessPiece : Sprite2D {
new Vector2(0, 0) new Vector2(0, 0)
); );
public ChessPiece() : this(new CCPiece()){ public ChessPiece() : this(new CCPiece()) {
} }
public ChessPiece(CCPiece piece) { public ChessPiece(CCPiece piece) {
PieceLabel = piece.CNName; PieceLabel = piece.CNName;
this.piece = piece;
LabelColor = piece.TurnsSide == ChessCore.TurnsSideType.Red ? new Color("red") : new Color("black"); LabelColor = piece.TurnsSide == ChessCore.TurnsSideType.Red ? new Color("red") : new Color("black");
piece.OnPos += OnPos; piece.On = this;
piece.OnSelected += OnSelected;
// Must Be Call for init Pos // Must Be Call for init Pos
OnPos(piece, piece.Pos); piece.On.OnPos(piece, piece.Pos);
piece.Data.TryAdd("Godot", this); piece.Data.TryAdd("Godot", this);
} }

View File

@ -1,9 +1,9 @@
#nullable disable
using System.Collections.Generic; using System.Collections.Generic;
using Godot; using Godot;
using RPPackage; using RPPackage;
public partial class Global : Node public partial class Global : Node {
{
public RPClientEDWS RPClient = new(); public RPClientEDWS RPClient = new();
public string sessionId; public string sessionId;
public Node CurrentScene { get; set; } public Node CurrentScene { get; set; }
@ -21,8 +21,7 @@ public partial class Global : Node
}; };
// Called when the node enters the scene tree for the first time. // Called when the node enters the scene tree for the first time.
public override void _Ready() public override void _Ready() {
{
if (OS.GetName() == "Android") { if (OS.GetName() == "Android") {
bool ret = OS.RequestPermissions(); bool ret = OS.RequestPermissions();
GD.Print($"RequestPermissions ret is {ret}"); GD.Print($"RequestPermissions ret is {ret}");
@ -43,8 +42,7 @@ public partial class Global : Node
SetProcess(false); SetProcess(false);
} }
public void ConfigFlush() public void ConfigFlush() {
{
int font_size = (int)GlobalConfigDict["font_size"]; int font_size = (int)GlobalConfigDict["font_size"];
GlobalTheme.DefaultFontSize = font_size; GlobalTheme.DefaultFontSize = font_size;
// GlobalTheme?.SetFontSize("font_size", "Label", font_size); // GlobalTheme?.SetFontSize("font_size", "Label", font_size);
@ -54,24 +52,20 @@ public partial class Global : Node
// CurrentScene.GetWindow().AddThemeFontSizeOverride("Control", (int)GlobalConfigDict["font_size"]); // CurrentScene.GetWindow().AddThemeFontSizeOverride("Control", (int)GlobalConfigDict["font_size"]);
} }
private void OnGotoScene() private void OnGotoScene() {
{
ConfigFlush(); ConfigFlush();
} }
public void SaveConfig() public void SaveConfig() {
{
GlobalConfig.SaveConfig("Global", GlobalConfigDict); GlobalConfig.SaveConfig("Global", GlobalConfigDict);
} }
// Called every frame. 'delta' is the elapsed time since the previous frame. // Called every frame. 'delta' is the elapsed time since the previous frame.
public override void _Process(double delta) public override void _Process(double delta) {
{
RPClient.PollEx(delta); RPClient.PollEx(delta);
} }
public override void _Notification(int what) public override void _Notification(int what) {
{
if (what == NotificationWMCloseRequest) { if (what == NotificationWMCloseRequest) {
// SaveConfig(); // SaveConfig();
RPClient.Close(); RPClient.Close();
@ -81,8 +75,7 @@ public partial class Global : Node
public delegate void ChangeSceneCallback(Node newSence); public delegate void ChangeSceneCallback(Node newSence);
private static ChangeSceneCallback changeSceneCallback = null; private static ChangeSceneCallback changeSceneCallback = null;
public void GotoScene(string path, ChangeSceneCallback callback = null) public void GotoScene(string path, ChangeSceneCallback callback = null) {
{
// This function will usually be called from a signal callback, // This function will usually be called from a signal callback,
// or some other function from the current scene. // or some other function from the current scene.
// Deleting the current scene at this point is // Deleting the current scene at this point is
@ -100,8 +93,7 @@ public partial class Global : Node
changeSceneCallback = null; changeSceneCallback = null;
} }
public void DeferredGotoScene(string path, Callable onLoaded) public void DeferredGotoScene(string path, Callable onLoaded) {
{
// It is now safe to remove the current scene. // It is now safe to remove the current scene.
CurrentScene.Free(); CurrentScene.Free();

View File

@ -1,32 +1,20 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using Vector2I = Vector.Vector2I; using Vector2I = Vector.Vector2I;
using static IBoard; using static IBoard;
public abstract class AbstractBoard : IBoard { public abstract class AbstractBoard(int rows, int cols, int maxRecords = int.MaxValue,
private readonly int rows; IBoardOn? on = null) : IBoard {
private readonly int cols; private readonly int rows = rows;
protected readonly IPiece?[,] pieces; private readonly int cols = cols;
protected readonly List<MoveRecord> moveRecords = new(); protected readonly IPiece?[,] pieces = new IPiece[rows, cols];
protected readonly int MAX_RECORDS; protected readonly List<MoveRecord> moveRecords = [];
protected readonly int MAX_RECORDS = maxRecords;
public int Rows => rows; public int Rows => rows;
public int Cols => cols; public int Cols => cols;
protected IBoardOn? on = on;
public event EventHandler<SetPieceEventArgs>? OnSetPiece; public virtual IBoardOn? On { get => on; set => on = value; }
public event EventHandler<IPiece>? OnInsert;
public event EventHandler<IPiece>? OnRemove;
public event EventHandler<MoveEventArgs>? OnMove;
public event EventHandler<MoveRecord>? OnAddRecord;
public event EventHandler<MoveRecord>? OnUndoRecord;
public AbstractBoard(int rows, int cols, int maxRecords = int.MaxValue) {
this.rows = rows;
this.cols = cols;
pieces = new IPiece[rows, cols];
MAX_RECORDS = maxRecords;
}
public virtual bool IsPosOutOfRange(Vector2I arrayPos) { public virtual bool IsPosOutOfRange(Vector2I arrayPos) {
return arrayPos.X < 0 || arrayPos.X >= Rows || arrayPos.Y < 0 || arrayPos.Y >= Cols; return arrayPos.X < 0 || arrayPos.X >= Rows || arrayPos.Y < 0 || arrayPos.Y >= Cols;
@ -42,19 +30,20 @@ public abstract class AbstractBoard : IBoard {
IPiece? oldPiece = pieces[pos.X, pos.Y]; IPiece? oldPiece = pieces[pos.X, pos.Y];
pieces[pos.X, pos.Y] = piece; pieces[pos.X, pos.Y] = piece;
if (piece != null) piece.Pos = pos; if (piece is not null) piece.Pos = pos;
// if (oldPiece != null) oldPiece.Pos = Vector2I.Zero; // if (oldPiece != null) oldPiece.Pos = Vector2I.Zero;
OnSetPiece?.Invoke(this, new SetPieceEventArgs { OldPiece = oldPiece, NewPiece = piece, Pos = pos }); on?.OnSetPieceInteral(this, new IBoardOn.SetPieceEventArgs
(oldPiece, piece, pos));
return oldPiece; return oldPiece;
} }
public virtual bool InsertPiece(IPiece piece, Vector2I pos) { public virtual bool InsertPiece(IPiece piece, Vector2I pos) {
if (GetPiece(pos) != null && piece == null) { if (GetPiece(pos) is not null && piece == null) {
return false; return false;
} }
OnInsert?.Invoke(this, piece); on?.OnInsert(this, piece);
SetPiece(piece, pos); SetPiece(piece, pos);
return true; return true;
} }
@ -65,11 +54,11 @@ public abstract class AbstractBoard : IBoard {
} }
IPiece? piece = GetPiece(from); IPiece? piece = GetPiece(from);
if (GetPiece(to) != null || piece == null) { if (GetPiece(to) is not null || piece is null) {
return false; return false;
} }
OnMove?.Invoke(this, new MoveEventArgs { From = from, To = to, Piece = piece }); on?.OnMove(this, new IBoardOn.MoveEventArgs(piece, from, to));
SetPiece(null, from); SetPiece(null, from);
SetPiece(piece, to); SetPiece(piece, to);
return true; return true;
@ -77,8 +66,9 @@ public abstract class AbstractBoard : IBoard {
public virtual IPiece? RemovePiece(Vector2I pos) { public virtual IPiece? RemovePiece(Vector2I pos) {
IPiece? piece = GetPiece(pos); IPiece? piece = GetPiece(pos);
if (piece == null) return null; if (piece is null) return null;
OnRemove?.Invoke(this, piece);
on?.OnRemove(this, piece);
return SetPiece(null, pos); return SetPiece(null, pos);
} }
@ -103,7 +93,7 @@ public abstract class AbstractBoard : IBoard {
} }
MoveRecord record = new(From, To, FromPos, ToPos); MoveRecord record = new(From, To, FromPos, ToPos);
OnAddRecord?.Invoke(this, record); on?.OnAddRecord(this, record);
moveRecords.Add(record); moveRecords.Add(record);
} }
@ -113,29 +103,15 @@ public abstract class AbstractBoard : IBoard {
moveRecords.RemoveAt(moveRecords.Count - 1); moveRecords.RemoveAt(moveRecords.Count - 1);
// 恢复新位置的棋子order is very inmportant // 恢复新位置的棋子order is very inmportant
if (record.From != null) { if (record.From is not null) {
MovePiece(record.ToPos, record.FromPos); MovePiece(record.ToPos, record.FromPos);
} }
// 恢复旧位置的棋子 // 恢复旧位置的棋子
if (record.To != null) { if (record.To is not null) {
InsertPiece(record.To, record.ToPos); InsertPiece(record.To, record.ToPos);
} }
OnUndoRecord?.Invoke(this, record); on?.OnUndoRecord(this, record);
}
public class MoveRecord {
public IPiece? From { get; }
public IPiece? To { get; }
public Vector2I FromPos { get; }
public Vector2I ToPos { get; }
public MoveRecord(IPiece? From, IPiece? To, Vector2I FromPos, Vector2I ToPos) {
this.From = From;
this.To = To;
this.ToPos = ToPos;
this.FromPos = FromPos;
}
} }
} }

View File

@ -1,62 +1,61 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using Vector2I = Vector.Vector2I; using Vector2I = Vector.Vector2I;
public abstract class AbstractPiece : IPiece { using static IPiece;
private Vector2I pos; // 注意这个坐标的非像素坐标而是棋盘坐标 public abstract class AbstractPiece(string name = "", Vector2I? pos = null,
IPieceOn? on = null) : IPiece {
private Vector2I pos = pos ?? new(); // 注意这个坐标的非像素坐标而是棋盘坐标
private bool isSelected = false; private bool isSelected = false;
protected string name; protected string name = name;
private Dictionary<string, object> data = new(); private Dictionary<string, object> data = [];
protected IPieceOn? on = on;
public Vector2I Pos { public virtual IPieceOn? On { get => on; set => on = value; }
public virtual Vector2I Pos {
get => pos; get => pos;
set { set {
if (pos != value) { if (pos != value) {
var oldPos = pos; var oldPos = pos;
pos = value; pos = value;
OnPos?.Invoke(this, oldPos); on?.OnPos(this, oldPos);
} }
} }
} }
public bool IsSelected { public virtual bool IsSelected {
get => isSelected; get => isSelected;
set { set {
if (isSelected != value) { if (isSelected != value) {
var oldIsSelected = isSelected; var oldIsSelected = isSelected;
isSelected = value; isSelected = value;
OnSelected?.Invoke(this, oldIsSelected); on?.OnSelected(this, oldIsSelected);
} }
} }
} }
public string Name { public virtual string Name {
get => name; get => name;
set { set {
if (name != value) { if (name != value) {
var oldName = name; var oldName = name;
name = value; name = value;
OnName?.Invoke(this, oldName); on?.OnName(this, oldName);
} }
} }
} }
public Dictionary<string, object> Data { public virtual Dictionary<string, object> Data {
get => data; get => data;
set => data = value; set => data = value;
} }
public event EventHandler<Vector2I>? OnPos;
public event EventHandler<Vector2I>? OnMove;
public event EventHandler<bool>? OnSelected;
public event EventHandler<string>? OnName;
public virtual bool Move(Vector2I pos) { public virtual bool Move(Vector2I pos) {
if (!CanMove(pos)) { if (!CanMove(pos)) {
return false; return false;
} }
Pos = pos; Pos = pos;
OnMove?.Invoke(this, pos); on?.OnMove(this, pos);
return true; return true;
} }
@ -65,9 +64,4 @@ public abstract class AbstractPiece : IPiece {
public override string ToString() { public override string ToString() {
return $"{Name} at {pos}"; return $"{Name} at {pos}";
} }
public AbstractPiece(string name = "", Vector2I? pos = null) {
this.name = name;
this.pos = pos ?? new();
}
} }

View File

@ -1,24 +1,29 @@
using System;
using System.Collections; using System.Collections;
using static ChineseChess.ChessCore; using static ChineseChess.ChessCore;
using Vector2I = Vector.Vector2I; using Vector2I = Vector.Vector2I;
namespace ChineseChess; namespace ChineseChess;
public class CCBoard : AbstractBoard public interface ICCBoardOn : IBoard.IBoardOn {
{ void OnSteps(object self, int oldSteps) {}
public event EventHandler<int>? OnStepsChanged; }
public class CCBoard(ICCBoardOn? on = null) : AbstractBoard(9, 10, on: on) {
private int steps = 0; private int steps = 0;
protected new ICCBoardOn? on = on;
// public virtual IPieceOn? On { get => on; set => on = value; }
public new ICCBoardOn? On { get => on; set {
on = value; base.on = value;} }
public int Steps { public int Steps {
get => steps; get => steps;
protected set { protected set {
if (steps != value) { if (steps != value) {
var oldSteps = steps;
steps = value; steps = value;
OnStepsChanged?.Invoke(this, steps); on?.OnSteps(this, oldSteps);
} }
} }
} }
public CCBoard() : base(9, 10) {
}
public override void AddRecord(IPiece? From, IPiece? To, Vector2I FromPos, Vector2I ToPos) { public override void AddRecord(IPiece? From, IPiece? To, Vector2I FromPos, Vector2I ToPos) {
base.AddRecord(From, To, FromPos, ToPos); base.AddRecord(From, To, FromPos, ToPos);
@ -32,65 +37,49 @@ public class CCBoard : AbstractBoard
public (ArrayList, ArrayList) InitGame() { public (ArrayList, ArrayList) InitGame() {
Steps = 0; Steps = 0;
// ArrayList blackPart = InitOnePartPieces(TurnsSideType.Black, new[] { ArrayList blackPart = InitOnePartPieces(TurnsSideType.Black, [
// new CCChariot(TurnsSideType.Black, "black chariot 0", 0, 0), new CCChariot (this, TurnsSideType.Black, new Vector2I( 4, 0)),
// ("车", 0, 0), ("马", 1, 0), ("象", 2, 0), new CCHorse (this, TurnsSideType.Black, new Vector2I( 3, 0)),
// ("士", 3, 0), ("将", 4, 0), ("士", 5, 0), new CCElephant(this, TurnsSideType.Black, new Vector2I( 2, 0)),
// ("象", 6, 0), ("马", 7, 0), ("车", 8, 0), new CCAdvisor (this, TurnsSideType.Black, new Vector2I( 1, 0)),
// ("炮", 1, 2), ("炮", 7, 2), new CCGeneral (this, TurnsSideType.Black, new Vector2I( 0, 0)),
// ("卒", 0, 3), ("卒", 2, 3), ("卒", 4, 3), ("卒", 6, 3), ("卒", 8, 3) new CCAdvisor (this, TurnsSideType.Black, new Vector2I(-1, 0)),
// }); new CCElephant(this, TurnsSideType.Black, new Vector2I(-2, 0)),
new CCHorse (this, TurnsSideType.Black, new Vector2I(-3, 0)),
new CCChariot (this, TurnsSideType.Black, new Vector2I(-4, 0)),
new CCCannon (this, TurnsSideType.Black, new Vector2I( 3, 2)),
new CCCannon (this, TurnsSideType.Black, new Vector2I(-3, 2)),
new CCPawn (this, TurnsSideType.Black, new Vector2I(-4, 3)),
new CCPawn (this, TurnsSideType.Black, new Vector2I(-2, 3)),
new CCPawn (this, TurnsSideType.Black, new Vector2I( 0, 3)),
new CCPawn (this, TurnsSideType.Black, new Vector2I( 2, 3)),
new CCPawn (this, TurnsSideType.Black, new Vector2I( 4, 3)),
]);
// ArrayList redPart = InitOnePartPieces(TurnsSideType.Red, new[] { ArrayList redPart = InitOnePartPieces(TurnsSideType.Red, [
// ("车", 0, -0), ("马", 1, -0), ("象", 2, -0), new CCChariot (this, TurnsSideType.Red, new Vector2I( 4, 0)),
// ("士", 3, -0), ("将", 4, -0), ("士", 5, -0), new CCHorse (this, TurnsSideType.Red, new Vector2I( 3, 0)),
// ("象", 6, -0), ("马", 7, -0), ("车", 8, -0), new CCElephant(this, TurnsSideType.Red, new Vector2I( 2, 0)),
// ("炮", 1, -2), ("炮", 7, -2), new CCAdvisor (this, TurnsSideType.Red, new Vector2I( 1, 0)),
// ("卒", 0, -3), ("卒", 2, -3), ("卒", 4, -3), ("卒", 6, -3), ("卒", 8, -3) new CCGeneral (this, TurnsSideType.Red, new Vector2I( 0, 0)),
// }); new CCAdvisor (this, TurnsSideType.Red, new Vector2I(-1, 0)),
ArrayList blackPart = InitOnePartPieces(TurnsSideType.Black, new CCPiece[] { new CCElephant(this, TurnsSideType.Red, new Vector2I(-2, 0)),
new CCChariot (this, TurnsSideType.Black, new Vector2I( 4, 0)), // 4,0 new CCHorse (this, TurnsSideType.Red, new Vector2I(-3, 0)),
new CCHorse (this, TurnsSideType.Black, new Vector2I( 3, 0)), // 3,0 new CCChariot (this, TurnsSideType.Red, new Vector2I(-4, 0)),
new CCElephant(this, TurnsSideType.Black, new Vector2I( 2, 0)), // 2,0 new CCCannon (this, TurnsSideType.Red, new Vector2I( 3, 2)),
new CCAdvisor (this, TurnsSideType.Black, new Vector2I( 1, 0)), // 1,0 new CCCannon (this, TurnsSideType.Red, new Vector2I(-3, 2)),
new CCGeneral (this, TurnsSideType.Black, new Vector2I( 0, 0)), // 0,0 new CCPawn (this, TurnsSideType.Red, new Vector2I(-4, 3)),
new CCAdvisor (this, TurnsSideType.Black, new Vector2I(-1, 0)), // -1,0 new CCPawn (this, TurnsSideType.Red, new Vector2I(-2, 3)),
new CCElephant(this, TurnsSideType.Black, new Vector2I(-2, 0)), // -2,0 new CCPawn (this, TurnsSideType.Red, new Vector2I( 0, 3)),
new CCHorse (this, TurnsSideType.Black, new Vector2I(-3, 0)), // -3,0 new CCPawn (this, TurnsSideType.Red, new Vector2I( 2, 3)),
new CCChariot (this, TurnsSideType.Black, new Vector2I(-4, 0)), // -4,0 new CCPawn (this, TurnsSideType.Red, new Vector2I( 4, 3)),
new CCCannon (this, TurnsSideType.Black, new Vector2I( 3, 2)), // 3,2 ]);
new CCCannon (this, TurnsSideType.Black, new Vector2I(-3, 2)), // -3,2
new CCPawn (this, TurnsSideType.Black, new Vector2I(-4, 3)), // -4,3
new CCPawn (this, TurnsSideType.Black, new Vector2I(-2, 3)), // -2,3
new CCPawn (this, TurnsSideType.Black, new Vector2I( 0, 3)), // 0,3
new CCPawn (this, TurnsSideType.Black, new Vector2I( 2, 3)), // -4,3
new CCPawn (this, TurnsSideType.Black, new Vector2I( 4, 3)) // 4,3
});
ArrayList redPart = InitOnePartPieces(TurnsSideType.Red, new CCPiece[] {
new CCChariot (this, TurnsSideType.Red, new Vector2I( 4, 0)), // 4,0
new CCHorse (this, TurnsSideType.Red, new Vector2I( 3, 0)), // 3,0
new CCElephant(this, TurnsSideType.Red, new Vector2I( 2, 0)), // 2,0
new CCAdvisor (this, TurnsSideType.Red, new Vector2I( 1, 0)), // 1,0
new CCGeneral (this, TurnsSideType.Red, new Vector2I( 0, 0)), // 0,0
new CCAdvisor (this, TurnsSideType.Red, new Vector2I(-1, 0)), // -1,0
new CCElephant(this, TurnsSideType.Red, new Vector2I(-2, 0)), // -2,0
new CCHorse (this, TurnsSideType.Red, new Vector2I(-3, 0)), // -3,0
new CCChariot (this, TurnsSideType.Red, new Vector2I(-4, 0)), // -4,0
new CCCannon (this, TurnsSideType.Red, new Vector2I( 3, 2)), // 3,2
new CCCannon (this, TurnsSideType.Red, new Vector2I(-3, 2)), // -3,2
new CCPawn (this, TurnsSideType.Red, new Vector2I(-4, 3)), // -4,3
new CCPawn (this, TurnsSideType.Red, new Vector2I(-2, 3)), // -2,3
new CCPawn (this, TurnsSideType.Red, new Vector2I( 0, 3)), // 0,3
new CCPawn (this, TurnsSideType.Red, new Vector2I( 2, 3)), // 2,3
new CCPawn (this, TurnsSideType.Red, new Vector2I( 4, 3)) // 4,3
});
return (blackPart, redPart); return (blackPart, redPart);
} }
private ArrayList InitOnePartPieces(TurnsSideType side, CCPiece[] pieces) { private ArrayList InitOnePartPieces(TurnsSideType side, CCPiece[] pieces) {
ArrayList list = new(); ArrayList list = [];
foreach (var piece in pieces) { foreach (var piece in pieces) {
list.Add(piece); list.Add(piece);
InsertPiece(piece, piece.Pos); InsertPiece(piece, piece.Pos);

View File

@ -1,6 +1,8 @@
using Vector2 = Vector.Vector2I; using Vector2 = Vector.Vector2I;
using System; using System;
using System.Collections; using System.Collections;
using static IBoard.IBoardOn;
namespace ChineseChess; namespace ChineseChess;
public class ChessCore { public class ChessCore {
@ -23,17 +25,18 @@ public class ChessCore {
private TurnsSideType sideType = TurnsSideType.Red; private TurnsSideType sideType = TurnsSideType.Red;
private readonly TurnsSideType selfSide; private readonly TurnsSideType selfSide;
public readonly CCBoard board = new(); public readonly CCBoard board;
private readonly Player playerSelf; private readonly Player playerSelf;
private readonly Player playerOpponent; private readonly Player playerOpponent;
// public EventHandler<IBoard.MoveEventArgs> OnMove; // public EventHandler<IBoard.MoveEventArgs> OnMove;
public ChessCore(Mode mode, TurnsSideType selfSide) { public ChessCore(Mode mode, TurnsSideType selfSide, ICCBoardOn? boardOn = null) {
this.selfSide = selfSide; this.selfSide = selfSide;
board = new(boardOn);
playerSelf = new(board, Player.PlayerType.Human); playerSelf = new(board, Player.PlayerType.Human);
playerOpponent = new(board, Player.PlayerType.Human); playerOpponent = new(board, Player.PlayerType.Human);
void func(object? _self, IBoard.MoveEventArgs record) { void func(object? _self, MoveEventArgs record) {
// 防止 Undo 时 Selected Clear 出现 Null Pointer Exception // 防止 Undo 时 Selected Clear 出现 Null Pointer Exception
playerSelf.SelectedClear(); playerSelf.SelectedClear();
playerOpponent.SelectedClear(); playerOpponent.SelectedClear();

View File

@ -1,6 +1,5 @@
namespace ChineseChess; namespace ChineseChess;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Vector; using Vector;
@ -20,12 +19,15 @@ public class CCPiece : AbstractPiece {
string name = "", Vector2I? pos = null) : base(name) { string name = "", Vector2I? pos = null) : base(name) {
this.board = board ?? new(); this.board = board ?? new();
TurnsSide = turnsSide; TurnsSide = turnsSide;
OnPos += (sender, args) => {
localPos = Global2Local(Pos);
};
Pos = pos is not null ? Local2Global(pos) : Vector2I.Zero; Pos = pos is not null ? Local2Global(pos) : Vector2I.Zero;
}
public override Vector2I Pos {
get => base.Pos; set {
base.Pos = value;
localPos = Global2Local(Pos); localPos = Global2Local(Pos);
} }
}
public override bool CanMove(Vector2I to) { public override bool CanMove(Vector2I to) {
return CanMoveAllPos().Any(item => item == to); return CanMoveAllPos().Any(item => item == to);
@ -44,17 +46,17 @@ public class CCPiece : AbstractPiece {
} }
public virtual List<Vector2I> CanMoveAllPosSelf() { public virtual List<Vector2I> CanMoveAllPosSelf() {
return new List<Vector2I>(); return [];
} }
public IEnumerable<Vector2I> CanMoveAllPosLocal() { public IEnumerable<Vector2I> CanMoveAllPosLocal() {
var self = CanMoveAllPosSelf().Select(item => item + localPos);// 转换局部坐标 var self = CanMoveAllPosSelf().Select(item => item + localPos);
var ret = self.Where(item => { var ret = self.Where(item => {
CCPiece? piece = GetCCPieceLocal(item); CCPiece? piece = GetCCPieceLocal(item);
bool ret = piece is null || piece.TurnsSide != TurnsSide; bool ret = piece is null || piece.TurnsSide != TurnsSide;
// Console.WriteLine($"{item} can move: {ret}"); // Console.WriteLine($"{item} can move: {ret}");
return ret; return ret;
}); // 过滤无效位置 });
// Console.WriteLine("localPos: {0}", localPos); // Console.WriteLine("localPos: {0}", localPos);
// Console.WriteLine("CanMoveAllPosSelf: {0}", string.Join(",", self)); // Console.WriteLine("CanMoveAllPosSelf: {0}", string.Join(",", self));
@ -64,7 +66,7 @@ public class CCPiece : AbstractPiece {
public IEnumerable<Vector2I> CanMoveAllPos() { public IEnumerable<Vector2I> CanMoveAllPos() {
var ret = CanMoveAllPosLocal() var ret = CanMoveAllPosLocal()
.Select(item => Local2Global(item)); // 转换为全局坐标 .Select(item => Local2Global(item));
// Console.WriteLine("CanMoveAllPos: {0}", string.Join(",", ret)); // Console.WriteLine("CanMoveAllPos: {0}", string.Join(",", ret));
return ret; return ret;
} }

View File

@ -3,11 +3,12 @@ using System.Collections;
using Vector2I = Vector.Vector2I; using Vector2I = Vector.Vector2I;
namespace ChineseChess; namespace ChineseChess;
using static IBoard.IBoardOn;
public class Player { public class Player {
private readonly CCBoard board; private readonly CCBoard board;
private readonly SelectedPiece selectedNode; private readonly SelectedPiece selectedNode;
public EventHandler<IBoard.MoveEventArgs>? OnMove; public EventHandler<MoveEventArgs>? OnMove;
public bool CanMove { get; set; } = true; public bool CanMove { get; set; } = true;
public enum PlayerType { public enum PlayerType {
@ -15,8 +16,7 @@ public class Player {
AI AI
} }
public Player(CCBoard board, PlayerType type = PlayerType.Human) public Player(CCBoard board, PlayerType type = PlayerType.Human) {
{
this.board = board; this.board = board;
this.selectedNode = new SelectedPiece(board); this.selectedNode = new SelectedPiece(board);
} }
@ -56,8 +56,8 @@ public class Player {
} }
// MUST BE THERE !!! 防止删除节点后在启动回调导致错误 // MUST BE THERE !!! 防止删除节点后在启动回调导致错误
OnMove?.Invoke(this, new IBoard.MoveEventArgs OnMove?.Invoke(this, new MoveEventArgs
{ From = fromPos, To = toPos, Piece = fromChess });; (fromChess, fromPos, toPos));
if (toChess != null) { if (toChess != null) {
board.RemovePiece(toPos); board.RemovePiece(toPos);

View File

@ -1,32 +1,33 @@
using System; using System;
using Godot;
using Vector2I = Vector.Vector2I; using Vector2I = Vector.Vector2I;
public interface IBoard { public interface IBoard {
public interface IBoardOn {
void OnInsert(object self, IPiece piece) {}
void OnRemove(object self, IPiece piece) {}
void OnMove(object self, MoveEventArgs args) {}
void OnAddRecord(object self, MoveRecord record) {}
void OnUndoRecord(object self, MoveRecord record) {}
void OnSetPieceInteral(object self, SetPieceEventArgs args) {}
record SetPieceEventArgs(IPiece? OldPiece, IPiece? NewPiece, Vector2I Pos);
record MoveEventArgs(IPiece? Piece, Vector2I From, Vector2I To);
}
public IBoardOn? On { get; protected set; }
public int Rows { get; } public int Rows { get; }
public int Cols { get; } public int Cols { get; }
public class SetPieceEventArgs : EventArgs {
public IPiece? OldPiece { get; set; }
public IPiece? NewPiece { get; set; }
public Vector2I Pos { get; set; } = new();
}
public class MoveEventArgs : EventArgs {
public IPiece? Piece { get; set; }
public Vector2I From { get; set; } = new();
public Vector2I To { get; set; } = new();
}
event EventHandler<IPiece> OnInsert;
event EventHandler<IPiece> OnRemove;
event EventHandler<MoveEventArgs> OnMove;
event EventHandler<SetPieceEventArgs> OnSetPiece;
bool IsPosOutOfRange(Vector2I pos); bool IsPosOutOfRange(Vector2I pos);
IPiece? GetPiece(Vector2I pos); IPiece? GetPiece(Vector2I pos);
IPiece? SetPiece(IPiece piece, Vector2I pos); IPiece? SetPiece(IPiece? piece, Vector2I pos);
bool InsertPiece(IPiece piece, Vector2I pos); bool InsertPiece(IPiece piece, Vector2I pos);
bool MovePiece(Vector2I from, Vector2I to); bool MovePiece(Vector2I from, Vector2I to);
IPiece? RemovePiece(Vector2I pos); IPiece? RemovePiece(Vector2I pos);
void Clear(); void Clear(bool clearRecords);
void AddRecord(IPiece? From, IPiece? To, Vector2I FromPos, Vector2I ToPos);
void UndoRecord();
record MoveRecord(IPiece? From, IPiece? To, Vector2I FromPos, Vector2I ToPos);
} }

View File

@ -2,17 +2,21 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using Vector2I = Vector.Vector2I; using Vector2I = Vector.Vector2I;
public interface IPiece { public interface IPiece {
public interface IPieceOn {
void OnPos(object self, Vector2I oldPos) {}
void OnMove(object self, Vector2I oldPos) {}
void OnSelected(object self, bool oldIsSelected) {}
void OnName(object self, string oldName) {}
}
IPieceOn? On { get; protected set; }
Vector2I Pos { get; set; } Vector2I Pos { get; set; }
string Name { get; set; } string Name { get; set; }
bool IsSelected { get; set; } bool IsSelected { get; set; }
Dictionary<string, object> Data { get; set; } Dictionary<string, object> Data { get; set; }
event EventHandler<Vector2I> OnPos;
event EventHandler<Vector2I> OnMove;
event EventHandler<bool> OnSelected;
event EventHandler<string> OnName;
bool CanMove(Vector2I to); bool CanMove(Vector2I to);
bool Move(Vector2I pos); bool Move(Vector2I pos);
} }

View File

@ -21,11 +21,11 @@
<Using Include="NUnit.Framework" /> <Using Include="NUnit.Framework" />
</ItemGroup> </ItemGroup>
<!-- <ItemGroup>
<ProjectReference Include="..\Chinese_Chess.csproj" />
</ItemGroup> -->
<ItemGroup> <ItemGroup>
<Compile Include="..\Scripts\Src\*.cs" /> <ProjectReference Include="..\*.csproj" />
</ItemGroup> </ItemGroup>
<!-- <ItemGroup>
<Compile Include="..\Scripts\Src\*.cs" />
</ItemGroup> -->
</Project> </Project>

View File

@ -1,21 +1,147 @@
using Vector; using Vector;
namespace Test; namespace Test.Vector;
public class TestsVector public class TestsVector2I {
{
[SetUp] [SetUp]
public void Setup() public void Setup() {
{
} }
[Test] [Test]
public void Test1() public void TestVector2I_Constructors() {
{ // Arrange & Act
var v1 = new Vector2I();
var v2 = new Vector2I(1, 2);
var v3 = new Vector2I(v2);
// Assert
Assert.Multiple(() => {
Assert.That(v1.X, Is.EqualTo(0));
Assert.That(v1.Y, Is.EqualTo(0));
Assert.That(v2.X, Is.EqualTo(1));
Assert.That(v2.Y, Is.EqualTo(2));
Assert.That(v3.X, Is.EqualTo(1));
Assert.That(v3.Y, Is.EqualTo(2));
});
}
[Test]
public void TestVector2I_Operators() {
// Arrange
var v1 = new Vector2I(1, 2);
var v2 = new Vector2I(3, 4);
// Act
var v3 = v1 + v2;
var v4 = v1 - v2;
var v5 = v1 * v2;
// Assert
Assert.Multiple(() => {
Assert.That(v3, Is.EqualTo(new Vector2I(4, 6)));
Assert.That(v4, Is.EqualTo(new Vector2I(-2, -2)));
Assert.That(v5, Is.EqualTo(new Vector2I(3, 8)));
});
}
[Test]
public void TestVector2I_DotProduct() {
// Arrange
var v1 = new Vector2I(1, 2);
var v2 = new Vector2I(3, 4);
// Act
var dotProduct = v1.Dot(v2);
// Assert
Assert.That(dotProduct, Is.EqualTo(11));
}
[Test]
public void TestVector2I_ParameterModification() {
// Arrange
var v1 = new Vector2I(1, 2);
var v2 = new Vector2I(3, 4);
// Act
var v3 = v1 + v2;
var v4 = v1 - v2;
var v5 = v1 * v2;
// Assert
Assert.Multiple(() => {
Assert.That(v1, Is.EqualTo(new Vector2I(1, 2)), "v1 should not be modified");
Assert.That(v2, Is.EqualTo(new Vector2I(3, 4)), "v2 should not be modified");
});
}
[Test]
public void TestVector2I_Equality() {
// Arrange
var v1 = new Vector2I(1, 2);
var v2 = new Vector2I(1, 2);
var v3 = new Vector2I(3, 4);
// Act & Assert
Assert.Multiple(() => {
Assert.That(v1, Is.EqualTo(v2));
Assert.That(v1, Is.Not.EqualTo(v3));
});
}
[Test]
public void TestVector2I_HashCode() {
// Arrange
var v1 = new Vector2I(1, 2);
var v2 = new Vector2I(1, 2);
var v3 = new Vector2I(3, 4);
// Act & Assert
Assert.Multiple(() => {
Assert.That(v1.GetHashCode(), Is.EqualTo(v2.GetHashCode()));
Assert.That(v1.GetHashCode(), Is.Not.EqualTo(v3.GetHashCode()));
});
}
[Test]
public void TestVector2I_BoundaryValues() {
// Arrange
var v1 = new Vector2I(0, 0);
var v2 = new Vector2I(-1, -2);
var v3 = new Vector2I(int.MaxValue, int.MaxValue);
var v4 = new Vector2I(int.MinValue, int.MinValue);
// Act
var v5 = v1 + v2;
var v6 = v1 - v2;
var v7 = v1 * v2;
var v8 = v3 + v4;
var v9 = v3 - v4;
var v10 = v3 * v4;
// Assert
Assert.Multiple(() => {
Assert.That(v5, Is.EqualTo(new Vector2I(-1, -2)));
Assert.That(v6, Is.EqualTo(new Vector2I(1, 2)));
Assert.That(v7, Is.EqualTo(new Vector2I(0, 0)));
Assert.That(v8, Is.EqualTo(new Vector2I(-1, -1)));
// Assert.That(v9, Is.EqualTo(new Vector2I(2 * int.MaxValue - 1, 2 * int.MaxValue - 1)));
// Assert.That(v10, Is.EqualTo(new Vector2I(int.MaxValue * int.MinValue, int.MaxValue * int.MinValue)));
});
}
}
public class TestsTrans2DI {
[SetUp]
public void Setup() {
}
[Test]
public void Test1() {
Assert.Pass(); Assert.Pass();
} }
[Test] [Test]
public void TestVector2I_Constructors() public void TestVector2I_Constructors() {
{
// Arrange & Act // Arrange & Act
var v1 = new Vector2I(); var v1 = new Vector2I();
var v2 = new Vector2I(1, 2); var v2 = new Vector2I(1, 2);
@ -31,8 +157,7 @@ public class TestsVector
} }
[Test] [Test]
public void TestVector2I_Operators() public void TestVector2I_Operators() {
{
// Arrange // Arrange
var v1 = new Vector2I(1, 2); var v1 = new Vector2I(1, 2);
var v2 = new Vector2I(3, 4); var v2 = new Vector2I(3, 4);
@ -49,8 +174,7 @@ public class TestsVector
} }
[Test] [Test]
public void TestTrans2DI_Constructors() public void TestTrans2DI_Constructors() {
{
// Arrange & Act // Arrange & Act
var t1 = new Trans2DI(); var t1 = new Trans2DI();
var t2 = new Trans2DI(new Vector2I(1, 0), new Vector2I(0, 1), new Vector2I(0, 0)); var t2 = new Trans2DI(new Vector2I(1, 0), new Vector2I(0, 1), new Vector2I(0, 0));
@ -76,8 +200,7 @@ public class TestsVector
} }
[Test] [Test]
public void TestTrans2DI_Operators() public void TestTrans2DI_Operators() {
{
// Arrange // Arrange
var t1 = new Trans2DI(new Vector2I(1, 0), new Vector2I(0, 1), new Vector2I(1, 2)); var t1 = new Trans2DI(new Vector2I(1, 0), new Vector2I(0, 1), new Vector2I(1, 2));
var v1 = new Vector2I(3, 4); var v1 = new Vector2I(3, 4);
@ -90,4 +213,51 @@ public class TestsVector
Assert.That(v2, Is.EqualTo(new Vector2I(4, 6))); Assert.That(v2, Is.EqualTo(new Vector2I(4, 6)));
Assert.That(v3, Is.EqualTo(new Vector2I(2, 2))); Assert.That(v3, Is.EqualTo(new Vector2I(2, 2)));
} }
[Test]
public void TestTrans2DI_BoundaryValues() {
// Arrange
var t1 = new Trans2DI(new Vector2I(int.MaxValue, 0), new Vector2I(0, int.MaxValue), new Vector2I(0, 0));
var t2 = new Trans2DI(new Vector2I(int.MinValue, 0), new Vector2I(0, int.MinValue), new Vector2I(0, 0));
var v1 = new Vector2I(1, 1);
// Act
var v2 = t1 * v1;
var v3 = t2 * v1;
// Assert
Assert.That(v2, Is.EqualTo(new Vector2I(int.MaxValue, int.MaxValue)));
Assert.That(v3, Is.EqualTo(new Vector2I(int.MinValue, int.MinValue)));
}
[Test]
public void TestTrans2DI_SpecialValues() {
// Arrange
var t1 = new Trans2DI(new Vector2I(0, 0), new Vector2I(0, 0), new Vector2I(0, 0));
var t2 = new Trans2DI(new Vector2I(1, 0), new Vector2I(0, 1), new Vector2I(0, 0));
var v1 = new Vector2I(1, 1);
// Act
var v2 = t1 * v1;
var v3 = t2 * v1;
// Assert
Assert.That(v2, Is.EqualTo(new Vector2I(0, 0)));
Assert.That(v3, Is.EqualTo(new Vector2I(1, 1)));
}
[Test]
public void TestTrans2DI_Multiplication() {
// Arrange
var t1 = new Trans2DI(new Vector2I(1, 0), new Vector2I(0, 1), new Vector2I(1, 2));
var t2 = new Trans2DI(new Vector2I(2, 0), new Vector2I(0, 2), new Vector2I(3, 4));
// Act
var t3 = t1 * t2;
// Assert
Assert.That(t3.XAxis, Is.EqualTo(new Vector2I(2, 0)));
Assert.That(t3.YAxis, Is.EqualTo(new Vector2I(0, 2)));
Assert.That(t3.Origin, Is.EqualTo(new Vector2I(5, 8)));
}
} }

View File

@ -10,10 +10,11 @@ config_version=5
[application] [application]
config/name="Chinese_Chess" config/name="ChessGame"
config/version="0.0.5"
run/main_scene="res://Main.tscn" run/main_scene="res://Main.tscn"
config/features=PackedStringArray("4.3", "C#", "Mobile") config/features=PackedStringArray("4.3", "C#", "Mobile")
config/icon="res://icon.svg" config/icon="res://Asserts/icon.svg"
[autoload] [autoload]
@ -28,7 +29,12 @@ window/handheld/orientation=1
[dotnet] [dotnet]
project/assembly_name="Chinese_Chess" project/assembly_name="ChessGame"
[navigation]
2d/name_localized={}
2d/version="0.0."
[rendering] [rendering]