首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Godot-放置棋子,实现黑白棋翻转

Godot-放置棋子,实现黑白棋翻转

原创
作者头像
kdyonly
发布2025-07-07 23:30:49
发布2025-07-07 23:30:49
2490
举报
文章被收录于专栏:个人编程笔记个人编程笔记

前面的一节,我们发现棋盘本来应该是白色的格子,但是显示的是灰色,这里的原因是缺少光照。我们可以在主场景中添加光照的节点。

添加DirectionalLight3D平行光,Ratation(-60.0,45.0,0,0),添加一个环境光WorldEnvironment用于补光,Environment → 添加 New Environment ,AmbientLight 可以设置自己需要的属性,这里就使用默认的。

创建一个球场景

添加一个Ball.tscn,根节点维Node3D,添加子节点MeshInstance3D,Mesh设置为SphereMesh球体形状,Material Override 新建StandardMaterial3D。

添加脚本,主要实现球(棋子)的颜色变化,跳跃等动画效果,参考代码如下:

代码语言:javascript
复制
using Godot;
using System;

public partial class Ball : Node3D
{
    private StandardMaterial3D material;

    public override void _Ready()
    {
        material = new StandardMaterial3D();
    }

    public void FlipTo(Color targetColor, float duration = 0.4f)
    {
        var tween = GetTree().CreateTween();
        // 旋转动画
        tween.TweenProperty(this, "rotation_degrees", new Vector3(180, 0, 0), duration)
             .SetTrans(Tween.TransitionType.Sine)
             .SetEase(Tween.EaseType.InOut);

        // 缩放动画:放大到 1.2 再回到 1
        tween.TweenProperty(this, "scale", new Vector3(1.2f, 1.2f, 1.2f), duration / 2f)
             .SetTrans(Tween.TransitionType.Sine)
             .SetEase(Tween.EaseType.Out);
        tween.TweenProperty(this, "scale", new Vector3(1, 1, 1), duration / 2f)
             .SetTrans(Tween.TransitionType.Sine)
             .SetEase(Tween.EaseType.In);

        // 跳跃动画(Y轴偏移)
        Vector3 startPos = Position;
        Vector3 peakPos = Position + new Vector3(0, 0.2f, 0);
        tween.TweenProperty(this, "position", peakPos, duration / 2f)
             .SetTrans(Tween.TransitionType.Quad)
             .SetEase(Tween.EaseType.Out);
        tween.TweenProperty(this, "position", startPos, duration / 2f)
             .SetTrans(Tween.TransitionType.Quad)
             .SetEase(Tween.EaseType.In);

        // 颜色过渡
        Color fromColor = material.AlbedoColor;
        tween.TweenMethod(
            Callable.From((Color c) => material.AlbedoColor = c),
            fromColor,
            targetColor,
            duration
        ).SetTrans(Tween.TransitionType.Sine)
         .SetEase(Tween.EaseType.InOut);
    }
}

实现黑白棋的棋子变化游戏规则

点击单元格放置一个球,判断当前位置的8个方向的棋子是否需要翻转颜色,翻转完成之后,玩家切换为对手玩家。

添加单元格点击事件,参考代码如下:

代码语言:javascript
复制
//Cell.cs
using Godot;
using System;

public partial class Cell : Area3D
{
	public Vector2I BoardPosition{get;set;}
	[Signal]
	public delegate void CellClickedEventHandler(Vector2I boardPos);
	public override void _InputEvent(Camera3D camera, InputEvent @event, Vector3 position, Vector3 normal, int shapeIdx)
	{
		if (@event is InputEventMouseButton mb && mb.Pressed && mb.ButtonIndex == MouseButton.Left)
		{
			GD.Print($"[Cell] Clicked at {BoardPosition}");
			EmitSignal(nameof(CellClicked), BoardPosition);
		}
	}
}

点击单元格的时候放置球,获取需要翻转的棋子的位置,翻转棋子颜色,参考代码:

代码语言:javascript
复制
//Main.cs
private enum Piece { None, Black, White }
private Piece[,] boardState = new Piece[BoardSize, BoardSize];
private Piece currentPlayer = Piece.Black;

private void OnCellClicked(Vector2I position)
{
	if (boardState[position.X, position.Y] != Piece.None)
		return;

	var toFlip = GetFlippablePieces(position, currentPlayer);
	if (toFlip.Count == 0)
	{
		GD.Print("非法落子!");
		return;
	}

	// 落子
	boardState[position.X, position.Y] = currentPlayer;
	PlacePiece(position, currentPlayer);

	// 翻子
	foreach (var flipPos in toFlip)
	{
		boardState[flipPos.X, flipPos.Y] = currentPlayer;
		FlipPiece(flipPos, currentPlayer);
	}

	// 切换回合
	currentPlayer = currentPlayer == Piece.Black ? Piece.White : Piece.Black;
}
//获取需要翻转的棋子
private List<Vector2I> GetFlippablePieces(Vector2I pos, Piece player)
{
	List<Vector2I> totalToFlip = new();
	Piece opponent = (player == Piece.Black) ? Piece.White : Piece.Black;
	foreach (var dir in Directions)
	{
		List<Vector2I> toFlip = new();
		int x = pos.X + dir.X;
		int y = pos.Y + dir.Y;
		while (x >= 0 && x < BoardSize && y >= 0 && y < BoardSize)
		{
			var p = boardState[x, y];
			if (p == opponent)
			{
				toFlip.Add(new Vector2I(x, y));
			}
			else if (p == player)
			{
				if (toFlip.Count > 0)
				{
					totalToFlip.AddRange(toFlip);
				}
				break;
			}
			else // None
			{
				break;
			}
			x += dir.X;
			y += dir.Y;
		}
	}
	return totalToFlip;
}

/// <summary>
/// 放置棋子
/// </summary>
/// <param name="pos"></param>
/// <param name="piece"></param>
private void PlacePiece(Vector2I pos, Piece piece)
{
	var ball = ballScene.Instantiate<Node3D>();
	ball.Position = new Vector3(pos.X, 0.2f, pos.Y);

	var mesh = ball.GetNode<MeshInstance3D>("MeshInstance3D");
	var mat = new StandardMaterial3D();
	mat.AlbedoColor = (piece == Piece.Black) ? new Color(0, 0, 0) : new Color(1, 1, 1);
	mesh.MaterialOverride = mat;

	ball.Name = $"Piece_{pos.X}_{pos.Y}";
	boardNode.AddChild(ball);
}
/// <summary>
/// 翻转棋子
/// </summary>
/// <param name="pos"></param>
/// <param name="toColor"></param>
private void FlipPiece(Vector2I pos, Piece toColor)
{
	string nodeName = $"Piece_{pos.X}_{pos.Y}";
	if (boardNode.HasNode(nodeName))
	{
		var piece = boardNode.GetNodeOrNull<Ball>(nodeName);
		var mesh = piece.GetNode<MeshInstance3D>("MeshInstance3D");
		var mat = new StandardMaterial3D();
		mat.AlbedoColor = (toColor == Piece.Black) ? new Color(0, 0, 0) : new Color(1, 1, 1);
		mesh.MaterialOverride = mat;
		piece.FlipTo(currentPlayer == Piece.Black ? Colors.Black : Colors.White);
	}
}

效果展示

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 创建一个球场景
  • 实现黑白棋的棋子变化游戏规则
  • 效果展示
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档