这节中,我将利用组合思想进一步优化构建怪物。计算机中的“组合”指的是在编程和算法设计中使用的一种技术,它涉及将多个元素或部分以特定方式结合在一起,以创建更复杂的数据结构或处理流程。我把不同对象的共有功能抽象为一个个组件,当构建某一个特定的的对象时再讲这些组件组合到一起。例如:主人公、敌人共有的功能一个是生命、攻击和碰撞,就可以抽象出三个组件,如果我们构建一颗子弹,这颗子弹只有攻击和碰撞,所以我们可以组成这两个组件,如果我们构建一棵树木,这棵树木有生命和碰撞功能,我们可以用这两个组件构成树木的一部分。开始吧。
一、构建生命组件
1.节点布局
新建Node2D场景命名为HealthComponent,保存到新建的Component文件夹内。一是新建TextureProgressBar节点用于血量显示,命名为HealthBar。为其添加TextureProgressBar子节点,命名为BackBar。二是为根节点添加Label子节点,命名为ChargeHealth,用于显示血量减少的数值。三是为根节点添加AnimationPlayer子节点,用于播放血量减少的动画。最终节点目录情况如下:
2.节点属性设置
(1)血量显示节点HealthBar的属性配置。
选择该节点,然后在其检查器中设置Textures属性,Over属性对应设置边框背景,Progress对应选择黄色背景图片素材;Range属性中Min Value:0,Max Value:100;Value:100。
选择该节点的子节点BackBar,在其检查器中将Progress对应选择红色背景图片素材,然后开启CanvasItem->Visibility->Show Behind Paren把其放在黄色背景的下面,目的是黄色血量有变化立即减少,这个红色血量有个减少的过程。如果不会设置属性的请参考【Godot4自学手册】第十八节主人公的血量显示这一节有详细的介绍。
(2)掉血显示节点ChargeHealth配置。
将ChargeHealth移动到血条的正上方,然后修改对象的旋转轴心。很简单,只需要选中该节点单击上方的修改对象的旋转轴心按钮,移动轴心位置即可。
(3)掉血显示动画配置。
选择该节点在其动画面板中新建动画命名为damage,动画时长设置为0.7。position设置: 0秒设置(10,-26),0.1秒设置(10,-53),0.3秒设置(10,-60)。
scale设置: 0秒设置(1,1),0.1秒设置(3,3),0.3秒设置(1,1)。
modulate设置: 0秒,0.4秒不透明度设为1,0.7秒不透明度设为0。
如果不知道具体设置的请参考【Godot4自学手册】第十九节敌人的血量显示及掉血特效_godot textureprogressbar-优快云博客中序号一、创建敌人的血条下面的小4设置文字动画。
3.编写代码
为根节点添加代码,存在Component目录下,命名为HealthComponent.gd,代码如下:
extends Node2D
class_name HealthComponent #类名
@onready var health_bar = $HealthBar #获取血量显示节点
@onready var back_bar = $HealthBar/BackBar #获取血量显示背景节点
@onready var charge_health = $ChargeHealth #获取掉血量显示节点
@onready var animation_player = $AnimationPlayer #获取掉血动画播放器
@export var MAX_HEALTH:=100.0 #定义最大血量
var health:float #定义当前血量
func _ready():
health = MAX_HEALTH #初始化时,当前血量等于最大血量
health_bar.value = health #将血量显示节点设置为当前血量 黄色血条
back_bar.value = health #将血量显示背景节点设置为当前血量 红色血条
### 受伤函数
func damage(attack:Attack):
charge_health.text = str("-") + str(attack.attack_damage) #将当前掉血量赋值给掉血量显示节点
health -=attack.attack_damage #计算当前血量
health_bar.value = health #更新血量条
var tween = get_tree().create_tween() #创建create_tween类
tween.tween_property(back_bar,"value",health,0.5) #将血量显示背景血量条调整到当前血量,0.5秒的一个减血过程
animation_player.play("damage") #播放掉血量动画
if health<0: #如果当前血量小于0,销毁当前对象的父对象
get_parent().queue_free()
二、构建碰撞组件
新建Area2D场景命名为HitboxComponent,保存到新建的Component文件夹内。为根据点添加如下代码:
extends Area2D
class_name HitboxComponent #类名
@export var health_component:HealthComponent #定义HealthComponent组件
func damage(attack:Attack): #攻击函数
if health_component:
health_component.damage(attack) #调用HealthComponent组件的受伤函数
三、调用构建组件
切换到Monster场景,选中根节点,单击实例化子场景,将我们刚才新建的两个组件实例化到场景中。选中HitboxComponent节点,在检查器中在health_component属性后面选择指定按钮,在弹出的对话框选择HealthComponent。
然后在Collison中layer设置Enemy图层,mask不选择。
四、定义攻击类
定义攻击类Attack,主要用来传递参数等。代码如下:
class_name Attack #定义类
var attack_damage:float #攻击力
var konckback_force:float #攻击后退理论
var attack_position:Vector2 #攻击位置
五、设置主人公的碰撞
切换到Player场景,选择结点,Collison中layer设置HitPlayer图层,mask设置为Enemy层。
让后切换到信号选项卡,双击area_entered(area:Area2D),在弹出对话框中选择Player,为Player添加信号。
在信号中,填写如下代码:
var attack_damage :=20.0 #攻击力
var knockback_force :=100.0 #击退力量
func _on_hit_box_area_entered(area):
if area.has_method("damage"):
var attack = Attack.new()
attack.attack_damage = attack_damage
attack.konckback_force = knockback_force
area.damage(attack)
看一下效果: