【Godot 3.5组件】简单血条组件HealthBar

说明

本文原文写自2022年,内容基于Godot3.5。是本人早期进行Godot组件化和自定义节点探索时的产物,当时的代码和思想可能不太成熟,但贴出来,供需要学习组件化基础思路的同学食用。

概述

血条作为一个非常基础和常见的组件,Godot并没有给我们提供现成的,相反我们需要通过魔改Progress节点或使用TextureProgress节点和制作一些图片来实现它们。

本篇内容介绍的是我前不久刚制作的一个简单血条组件,它是基于Progress节点和StyleBoxFlat资源修改样式制作的。灵感是Hi小胡的视频。与他一步一步教你不同,我不会教你我是如何一步步制作的。

相反,你只需要在自己的项目里创建一个Progress节点,你可以将它重命名为“HealthBar”。
image.png
为其创建脚本,并复制粘贴如下代码:

# ======================================================================
# 名称:HealthBar
# 描述:一个简单的基于ProgressBar样式修改的参数化血条组件
# 类型:UI组件,原生控件扩展
# 作者:巽星石
# Godot版本:3.5
# 创建时间:2022102422:56:00
# 最后修改时间:2022102921:12:08
# ======================================================================

tool
extends ProgressBar

signal dead()    # 已经到达最小值
signal val_changed(value)    # 血量发生变化
signal is_maxed()  # 已经到达最大值

export(Color) var bg_color = Color(0.941176, 0.043137, 0.043137) setget set_bg_color # 背景颜色
export(Color) var fg_color = Color(0.286275, 0.8, 0.258824) setget set_fg_color # 前景颜色
export(Color) var border_color = Color(0.952941, 0.952941, 0.952941) setget set_border_color       # 描边 - 颜色
export(int,0,20) var border_width = 2 setget set_border_width   # 描边 - 宽度
export(int,0,200) var corner_radius = 2 setget set_corner_radius # 圆角半径


# ========================= Setter&Getter =========================
func set_bg_color(val:Color):
	bg_color = val
	# 设置StyleBox中的属性
	var bg_style = get_bg_style_box()
	var fg_style = get_fg_style_box()
	bg_style.bg_color = val

func set_fg_color(val:Color):
	fg_color = val
	# 设置StyleBox中的属性
	var fg_style = get_fg_style_box()
	var bg_style = get_bg_style_box()
	fg_style.bg_color = val

func set_border_color(val:Color):
	border_color = val
	# 设置StyleBox中的属性
	var bg_style = get_bg_style_box()
	bg_style.border_color = val
	var fg_style = get_fg_style_box()
	var fg_border_color = Color(0,0,0,0)
	fg_style.border_color = fg_border_color
	
func set_border_width(val:int):
	border_width = val
	# 设置StyleBox中的属性
	var bg_style = get_bg_style_box()
	bg_style.border_width_bottom = val
	bg_style.border_width_left = val
	bg_style.border_width_right = val
	bg_style.border_width_top = val
	var fg_style = get_fg_style_box()
	fg_style.border_width_bottom = val
	fg_style.border_width_left = val
	fg_style.border_width_right = val
	fg_style.border_width_top = val

func set_corner_radius(val:int):
	corner_radius = val
	# 设置StyleBox中的属性
	var bg_style = get_bg_style_box()
	bg_style.corner_radius_bottom_left = val
	bg_style.corner_radius_bottom_right = val
	bg_style.corner_radius_top_left = val
	bg_style.corner_radius_top_right = val
	var fg_style = get_fg_style_box()
	fg_style.corner_radius_bottom_left = val
	fg_style.corner_radius_bottom_right = val
	fg_style.corner_radius_top_left = val
	fg_style.corner_radius_top_right = val

# ========================= 加载 =========================

func _enter_tree(): # 替换原有的stylebox
	# 背景
	var box = create_styleboxflat(bg_color,border_color,border_width,
		[corner_radius,corner_radius,corner_radius,corner_radius])
	set("custom_styles/bg",box)
	var fg_border_color = Color(0,0,0,0)
	# 前景
	var box2 = create_styleboxflat(fg_color,fg_border_color,border_width,
	[corner_radius,corner_radius,corner_radius,corner_radius])
	set("custom_styles/fg",box2)

func _ready():
	percent_visible = false  # 关闭百分比显示
	size_flags_horizontal = SIZE_EXPAND_FILL
	size_flags_vertical = SIZE_EXPAND_FILL


# ========================= 方法 =========================
# 增加血量值
func add(val:int):
	var tween = create_tween()
	tween.tween_property(self,"value",value + val,0.2)
	
# 减少血量值
func sub(val:int):
	var tween = create_tween()
	tween.tween_property(self,"value",value - val,0.2)

# ========================= 信号处理 =========================
func _on_HealthBar_value_changed(value):
	if value == min_value:
		emit_signal("dead")
	if value == max_value:
		emit_signal("is_maxed")
	emit_signal("val_changed",value)
	pass


# ========================= 底层方法 =========================
# 获取或创建背景所需的StyleBox
func get_bg_style_box() -> StyleBoxFlat:
	var box
	if get("custom_styles/bg"):
		box = get("custom_styles/bg")
	else:# 不存在
		box = create_styleboxflat(bg_color,border_color,border_width,
		[corner_radius,corner_radius,corner_radius,corner_radius])
		set("custom_styles/bg",box)
	return box

# 获取或创建前景所需的StyleBox
func get_fg_style_box() -> StyleBoxFlat:
	var box
	if get("custom_styles/fg"):
		box = get("custom_styles/fg")
	else:# 不存在
		var fg_border_color = Color(0,0,0,0)
		box = create_styleboxflat(fg_color,fg_border_color,border_width,
		[corner_radius,corner_radius,corner_radius,corner_radius])
		set("custom_styles/fg",box)
	return box

# 动态创建StyleBoxFlat
func create_styleboxflat(bg_color = ColorN("white",1),
						border_color = ColorN("gray",1),
						border_width = 0,
						corner_radius = [0,0,0,0],
						content_margin = [5,5,5,5],
						expand_margin = [0,0,0,0],
						has_shadow = false,
						shadow_size = 1,
						shadow_color = ColorN("gray",0.5),
						shadow_offset = Vector2(1,1)
						) -> StyleBoxFlat:
	var stylebox:StyleBoxFlat = StyleBoxFlat.new()
	# 背景
	stylebox.bg_color = bg_color
	# 边框
	stylebox.set_border_width_all(border_width)  # 粗细
	stylebox.border_color =  border_color  # 颜色
	# 圆角
	stylebox.set_corner_radius_individual(
		corner_radius[0],
		corner_radius[1],
		corner_radius[1],
		corner_radius[1])
	# 内容边距
	stylebox.content_margin_bottom = content_margin[0]
	stylebox.content_margin_left = content_margin[1]
	stylebox.content_margin_right = content_margin[2]
	stylebox.content_margin_top = content_margin[3]
	# 外边距
	stylebox.set_expand_margin_individual(
		expand_margin[0],
		expand_margin[1],
		expand_margin[2],
		expand_margin[3]
		)
	# 阴影
	if has_shadow:
		stylebox.shadow_size = shadow_size
		stylebox.shadow_color = shadow_color
		stylebox.shadow_offset = shadow_offset
	return stylebox

然后你就可以发现自己有了一个简单的参数化的血条组件。
image.png
当然你还要再做一件事情,手动连接一下value_changed信号到脚本。

image.png

保存和实例化

为了实现复用,你需要将这个场景保存然后关闭,然后在其他场景中实例化这个组件。
比如我们创建有一个Control根节点的场景,实例化一个HealthBar组件。
image.png

通过参数快速调整样式

实例化后的HealthBar组件就像Godot的原生控件一样,可以通过调整其属性来实现快速的样式改变。当然由于我们采用的是export var的形式,也就是“脚本变量”,所以为了区别将其称为“参数”,也可以体现参数化的理念。
image.png image.png
HealthBar组件的“自定义属性”(或叫“参数”)只有5个,但是有于它本质是继承于ProgressBar控件,所以ProgressBar控件所拥有的属性、信号、方法都可以使用。

参数值类型默认值说明
bg_colorColorColor(0.941176, 0.043137, 0.043137)背景颜色
fg_colorColorColor(0.286275, 0.8, 0.258824)前景颜色
border_colorColorColor(0.952941, 0.952941, 0.952941)描边 - 颜色
border_widthint,0,202描边 - 宽度
corner_radiusint,0,2002圆角半径

通过这些参数的设定,你可以快速创建完全不同的颜色和描边样式。
一些参数化后的实例

方法

HealthBar组件提供了两个基础的增加和减少血量的方法,并且通过Godot3.5新增的SceneTreeTween实现了动效。

add(val:int)

当前血量增加给定的数值。变化过程有一个简单的动画效果(使用SceneTreeTween实现)。
并触发val_changed(value)信号,当血量达到最大值时,触发is_maxed()信号。

sub(val:int)

当前血量减少给定的数值。变化过程有一个简单的动画效果(使用SceneTreeTween实现)。
并触发val_changed(value)信号,当血量达到最小值时,触发dead()信号。
效果:
增加和减少血量的动画效果

信号

HealthBar组件自定义了三个信号,你可以在通过节点面板或脚本进行连接。
image.png
具体描述如下。

信号描述
dead()已经到达最小值时触发
is_maxed()已经到达最大值时触发
val_changed(value)值发生变化时触发,参数value返回当前值。
  • 25
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,以下是一个简单的Viewport组件的使用案例: 1. 创建一个新的Godot项目。 2. 在场景编辑器中,创建一个Viewport节点。Viewport节点是一个可视化容器,它可以显示其他节点的视图。 3. 在Viewport节点下创建一个Sprite节点。这将是我们在Viewport中显示的图像。 4. 选择Viewport节点,在Inspector面板中,找到Viewport节点的Rect属性。这个属性决定了Viewport节点的大小和位置。你可以通过拖动Viewport节点的大小和位置来调整它。 5. 在Viewport节点的Inspector面板中,找到Viewport节点的Size属性。将这个属性设置为与Sprite节点相同的大小。这将确保Sprite节点完全显示在Viewport中。 6. 在Viewport节点的Inspector面板中,找到Viewport节点的Render Targets属性。将其勾选上,以启用Viewport节点的渲染目标。 7. 在Viewport节点的Inspector面板中,找到Viewport节点的Clear Mode属性。将其设置为“Only When Transparent”。这将确保Viewport节点只在背景透明时才清除其渲染目标。 8. 在场景编辑器中,创建一个Camera2D节点,并将其作为Viewport节点的子节点。这个节点将决定我们在Viewport中看到的图像。 9. 在Camera2D节点的Inspector面板中,找到Camera2D节点的Current属性。将其勾选上以启用相机。 10. 在Camera2D节点的Inspector面板中,找到Camera2D节点的Offset属性。通过调整这个属性,你可以在Viewport中看到我们的Sprite节点。 11. 运行游戏。你应该能够在Viewport中看到我们的Sprite节点了。 希望这个案例能够帮助你理解Viewport组件的使用方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

巽星石

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

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

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

打赏作者

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

抵扣说明:

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

余额充值