【Godot4.2】环形阵列子节点和控件环形阵列容器

概述

今天(2024年4月13日)在群里收到群友的提问,它想实现子节点的环形排布,当然按他的说法,它实际想要实现的是一个自动环形排列子控件的自定义容器

image.png

好在我之前有自定义容器的经验,也马上想到可以用向量旋转获取圆上的定位。

实现2D节点环形阵列

在实现环形阵列容器之前,我首先测试了2D节点的子节点环形阵列。
创建如下场景:

image.png

  • 以一个Node2D为根节点,添加6个Sprite2D,并赋予不同的图片,这里我以以前编写骰子组件使用的骰子6面图片+问号图片举例
  • 将根节点尽量移动到视口矩形的中心,对所有Sprite2D进行了适当的等比缩放

根节点添加代码如下:

extends Node2D

var r:= 100.0   # 圆半径


func _ready() -> void:
  var step = get_child_count()   # 阵列的元素数目
	var t = Transform2D().translated(Vector2.RIGHT * r)   # 初始向量
	var ang = TAU/step             # 间隔角度
	
	for i in range(step):
		t = t.rotated(ang)   # 旋转向量
		get_child(i).transform = t * get_child(i).transform

上面代码中:

  • 用根节点的一级子节点数目作为阵列的步骤数step,并计算出每次要旋转的角度ang
  • 构造了一个变换t,它实际上是将某个点的位置向右移动到Vector2.RIGHT * r距离。
  • 然后for循环遍历step次,每次对变换t施加旋转ang的操作
  • 然后将当前变换实施到对应顺序的子节点上。

完成后的效果:

image.png

环形阵列容器

如果要应用于Control节点,则用上述方法则可能无法实现想要的结果。而且Control节点一般不需要旋转,只需要将矩形中心位移到相应的圆上就行。

所以这里我们自定义一个环形阵列容器CircleArrayContainer,用来自动化的环形排列其一级子控件。

完整代码如下:

@tool
extends Container
class_name CircleArrayContainer   # 环形阵列容器

var r:= 100.0:  # 圆半径
	set(val):
		r = val
		queue_sort()

func _init() -> void:
	# 容器尺寸发生变化时
	connect("resized",func():
		set("r",get_rect().size.y/2.0)  # 修改半径为1/2的高
	)

func _notification(what):
	var center = get_rect().get_center() # 容器中心点
	var a = Vector2.RIGHT * r
	match what:
		NOTIFICATION_SORT_CHILDREN:
			var step = get_child_count()   # 阵列的元素数目
			var ang = TAU/step             # 间隔角度
			for i in range(step):
				var b = a.rotated(ang * i)   # 旋转向量
				get_child(i).position = center + b - get_child(i).size/2.0

效果:

image.png

  • 你可以通过“添加节点”对话框,实例化CircleArrayContainer容器,并直接在其下添加子控件。
  • 容器会自动根据子控件的数目,环形排列它们,圆的半径等于容器矩形尺寸的一半。
  • 修改容器尺寸时会自动更新圆的半径

环形阵列容器1.gif

总结

  • 这是一次很好的自定义容器尝试,证明了Godot可以实现特殊的布局容器
  • 当然这种做法可能不算符合Godot容器的定义规范,对于子控件将无法再使用size_flags来实现动态大小,控件将自动被压缩至最小尺寸,除非定义了custom_minimum_size
  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

巽星石

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值