【Godot4自学手册】第十八节主人公的血量显示

今天,我主要学习主人公的血量显示,在屏幕的左上角,会显示主人公的头像,后面会显示血量进度条,当主人公受到伤害时,血量会实时变动,显示绿色血条减少,后是红色血量逐渐减少到正确位置,效果如下:
请添加图片描述

一、修改BUG

再开始今天的学习之前,修改以前的一些Bug,在敌人攻击和受伤,主人公的攻击和受伤学习中又许多Bug,主要是因为我把需要执行一次的状态代码和需要执行一段时间的代码全都写到_physics_process函数的原因,所以我将需要执行一次的代码加到state状态的set(v):函数内执行一次;把需要多次执行的代码加到了_physics_process函数内。

1.Player代码修改如下:
extends CharacterBody2D
@onready var anima_tree=$AnimationTree
@onready var animation_player = $AnimationPlayer
@onready var stats = $Stats
@onready var direcion = Vector2.ZERO
enum {IDLE,WALK,SWORD,HURT
}
var state = IDLE:set(v):state=vmatch  state:IDLE:idle_state()WALK:walk_state()SWORD:sword_state()HURT:hurt_state()const SPEED = 120.0
var enemyPositon
var knockback=200func _ready():Globals.last_Player = positionfunc _physics_process(delta):	direcion = Vector2.ZEROdirecion.x = Input.get_axis("left", "right")direcion.y = Input.get_axis("up", "down")if state!=SWORD and state!=HURT:if direcion:anima_tree.set("parameters/Idle/blend_position",direcion)anima_tree.set("parameters/Walk/blend_position",direcion)anima_tree.set("parameters/Sword/blend_position",direcion)anima_tree.set("parameters/Hurt/blend_position",Vector2(direcion.x*-1,direcion.y))state = WALKelse:velocity=Vector2.ZEROstate=IDLEif Input.is_action_just_pressed("sword"):velocity= Vector2.ZEROstate = SWORDGlobals.last_Player = positionmove_and_slide()	func idle_state():#待机状态anima_tree["parameters/playback"].travel("Idle")
func walk_state():#行走状态anima_tree["parameters/playback"].travel("Walk")velocity = direcion * SPEED	func sword_state():#进攻状态anima_tree["parameters/playback"].travel("Sword")await anima_tree.animation_finished	state=IDLEfunc hurt_state():#受伤状态var dir = enemyPositon.direction_to(global_position).normalized()anima_tree["parameters/playback"].travel("Hurt")if dir.x>0:velocity.x +=knockbackelse :velocity.x -=knockbackawait anima_tree.animation_finishedstats.health -=10	state=WALKfunc _on_hurt_box_area_entered(area):enemyPositon = area.owner.global_positionstate=HURT	
2.Enemy代码修改如下:
extends CharacterBody2D
enum {IDLE,CHASE,ATTACK,HURT,DEATH
}
const SPEED = 1.0
var hitCount=2
@onready var anima_s = $AnimaS
@onready var anima_p = $AnimaP
@onready var hit_box = $CheckBox/HitBox
@onready var trace_collsion = $CheckBox/TraceArea/Trace_Collsionvar knockback=300
var hurtdirecionvar state = IDLE:set(v):state = vmatch state:IDLE:idle_state()CHASE:chase_state()ATTACK:attack_state()HURT:hurt_state()DEATH:death_state()func _physics_process(delta):	var direction =  Globals.last_Player-global_positionif direction.x<0:anima_s.flip_h=truehit_box.scale.x =-1else:anima_s.flip_h = falsehit_box.scale.x=1if state==CHASE:		global_position = global_position.move_toward(Globals.last_Player,SPEED)move_and_slide()func idle_state():#待机状态anima_p.play("Idle")func chase_state():#跟踪状态anima_p.play("Run")func attack_state():#攻击状态anima_p.play("Attack")	await  anima_p.animation_finishedstate = CHASEfunc hurt_state():	#受伤状态var dir = hurtdirecion.direction_to(global_position).normalized()if abs(dir.x)>abs(dir.y):if dir.x<0:velocity.x =-knockbackelse :velocity.x =knockbackelse:if dir.y<0:velocity.y =-knockbackelse :velocity.y =knockbackanima_p.play("TakeHit")await  anima_p.animation_finished	velocity = Vector2.ZEROstate=CHASEfunc death_state():	passfunc _on_trace_area_body_entered(body):if body.name=="Player" and state!=HURT and state!=ATTACK:state = CHASEfunc _on_trace_area_body_exited(body):	if body.name=="Player" and state!=HURT and state!=ATTACK:state = IDLEfunc _on_hit_area_body_entered(body):#进入攻击范围if body.name=="Player" :state = ATTACKfunc _on_hurt_box_area_entered(area):	#进入受伤范围hurtdirecion = area.owner.global_positionstate = HURT

二、新建血量显示场景

1.新建场景。

单击新建场景按钮,选择其它节点,在创建Node对话框中,选择HBoxContainer节点,单击创建按钮,创建新的场景,如下:
请添加图片描述

将新场景保存到Scenes文件夹下,命名为:StatusUI。
将根节点重新命名为StatusPanel,检查器中将Transform->Size重置为0,0。

2.添加节点

首先为根节点添加PanelContainer子节点,再为PanelContainer添加TextureRect子节点,显示头像。为根节点添加TextureProgressBar子节点,显示血量,最终效果如下:
请添加图片描述

最后将PanelContainer命名为HeadBox;将TextureRect命名为Head;将TextureProgressBar命名为HeadthBar。

3.设置人物头像背景框

将HeadBox检查器中Theme Overrides->style->Panel属性设置为StyleBoxTextture。并将我们事先做好的背景边框图片结合托人到Texture内。
请添加图片描述

单击Sub-Region属性,展开界面选择编辑区域,在区域编辑框中选择像素吸附,画出图像背景框,然后选择关闭按钮,如下:
请添加图片描述

检查器中Custom Minimum Size属性设置为23,23,表示图像框的大小为23.如下:
请添加图片描述

检查器中Theme Overrides->Styles->Content Margins中,Left,Top,Right,Bottom均设置为3,表示填充边框为3,如下:
请添加图片描述

4.设置头像

切换到Head节点,在检查器中Texture选择AtlasTexture图集纹理,将主人公的Player.png图片拖入到Atlas属性,如下:
请添加图片描述

在检查器中选择Region,单击下面的编辑区域按钮,在弹出的区域编辑框中选择像素吸附,选取主人公正面头像,然后关闭。
请添加图片描述

head检查器中Stretch Mode属性选择 Keep Aspect Centered,表示图像保持比例缩放,居中。如下:
请添加图片描述

最后的头像效果如下:
请添加图片描述

5.设置血量显示条

切换到HealthBar节点,在检查器中Textures展开属性,在Progress选择AtlasTexture,将HUD.png拖入到Atlas中,如下:
请添加图片描述

在Region属性下单击编辑按钮,在区域编辑框中选择自动剪裁,然后选择绿色图片,最后单击关闭。
请添加图片描述

然后突出Progress属性,在HealthBar检查器中Range属性中Max Value设置为1,step设置为0,Value设置为1,如下所示:
请添加图片描述

同样方法设置Texture下的Over,图片选择黑色背景边框,然后设置Progress Offset设置为1,1,这样保证绿色图片在黑色背景边框中间,设置如下所示:
请添加图片描述

在HealthBar的检查器中Control->Layout->Container Sizing->Vertical属性选择居中收缩。如下:
请添加图片描述

最后显示效果如下:
请添加图片描述

6.设置红色血量显示调

复制HealthBar命名为HealthBarRead,并将其设为HealthBar的子节点,如下所示:
请添加图片描述

在其检查器中Textures属性重置Over属性,Progress属性选择唯一化,然后从新编辑区域,选择红色血条,效果如下:
请添加图片描述

然后在编辑器上方控制节点锚点和偏移值的预设中选择整个矩形,这样红色血量和绿色血量最终重合,如下:
请添加图片描述

然后在检查器中找到Visibility->Show Behind Parent并启用,这样绿色血量将会在红色血量的上方。
请添加图片描述

通过以上步骤所有节点都已布置完成,先忙开始编写代码。

三、编写代码

1.抽象状态类。

无论是敌人还是主人公都有一些相同状态,如血量,我把这些相同的状态定义成一个类,需要的时候继承就好了。首先切换到脚本,单击文件新建脚本,新建Class文件夹,将新建的脚步保存到Class文件夹内,命名为Status。编写如下脚本:

class_name Stats
extends Node
signal  health_changed@export var max_health: int = 100
@onready var health: int = max_health:set(v):v = clampi(v, 0, max_health)if health == v:returnhealth = vhealth_changed.emit()  #发出信号

第一行代码主要把该脚本命名为Stats类,这样的目的是,把所有跟敌人或者主人公有关状态的量抽象一个类,复用。
第二行代码说明该类继承了Node节点,Node节点的方法和属性都可以使用。
第三行定义了一个信号,表示当血量发生变化时,出现该信号。
第四行定义了最大血量,默认是100,@export表示该变量可以在编辑器中看到和修改。
第五行定义了当前血量,@onready表示该变量会在Node节点就绪状态时赋值,默认赋值为最大血量。
第六行表示当给health变量赋值时,发生。
第七行表示给health复制时,取值范围为0到max_health,当超过这个范围会自动变换到这个范围。
第八行、第九行表示如果复完值就跳出该方法。
第十行表示把用户输入的值付给health。
第十一行表示复完值后发出血量变化信号。

2.StatusUI场景代码

切换到StatusUI场景,选择根节点,单击创建脚本按钮,将代码保存到Scripts文件夹内,命名为StatusUI。如下:
请添加图片描述

编写如下代码:

extends HBoxContainer
@export var stats:Stats
@onready var health_bar = $HealthBar
@onready var health_bar_red = $HealthBar/HealthBarREDfunc _ready():stats.health_changed.connect(update_health)  #血量变化信号连接到血量更新UIupdate_health()func update_health()->void:var percentage :=stats.health/ float(stats.max_health)health_bar.value = percentagecreate_tween().tween_property(health_bar_red,"value",percentage,.3)

这段代码中第二行定义了一个状态变量,继承Stats。
第三至四行代码表示获取绿色血量和红色血量节点。
_ready函数中的stats.health_changed.connect(update_health)代码表示血量变化信号发生后会调用update_health函数。
update_health自定义函数表示血量发生变化后血量显示进度条适时变化。该函数前两行代码对绿色血量进行调整,后一行代码表示红色血量变化会在0.3秒内完成,并显示间补动画,就是红色血量有个减少过程,绿色血量直接发生变化。
这里面有个引擎自带函数tween_propert方法解释一下。create_tween()表示创建一个间补动画,tween_property方法第一个参数表示要发生变化的对象,第二个参数表示该对象的哪个属性发生变化,第三个参数表示该属性到达的最后状态,第四个参数表示达到最后状态需要的持续时间。

四、给主人公添加血量显示

1.添加状态类

切换到Player场景,选择根节点,然后点击添加节点按钮,选择Stats,我们自己编写的类,如下:
请添加图片描述

单击Stats节点,在其检查器中,我们会看到我们编写该类时,暴漏的max_health的变量,我们可以在检查器中进行修改。
请添加图片描述

2.添加StatusUI场景到Player场景

切换到Player场景,选择根节点,单击实例化子场景按钮,在实例化子场景中选择StatusUI点击打开,就把StatusUI场景加入到Player场景内了,重名为PlayerStatus,然后适当调整位置。
请添加图片描述

在PlayerStatus节点单击右键选择重设父节点为新节点,在对话框中选择CanvasLayer节点,这样的目的是把主人公的血条显示固定在一个位置。操作如下:
请添加图片描述

调整PlayerStatus节点位置到屏幕的左上角,如下:
请添加图片描述

在检查器中将Stats选择Stats,操作如下:
请添加图片描述

ok,这样就应该好了,看一下最终效果:
请添加图片描述

注意观看左上角的血量变化。今天就到这,下节见,同学们。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/499019.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大环境不好,测试人员如何提高核心竞争力?

测试人员如何提升核心竞争力 作为一个测试工程师&#xff0c;自动化测试已经是必须要掌握的技能了。学习自动化测试有两个难点&#xff0c;除了其本身拥有一定的技术门槛之外&#xff0c;实战经验才是学习自动化测试的最大难点。部分初中级测试工程师往往在掌握了基本的编程与…

Unity 佳能SDK 及数据获取

1. 填写信息跟官方申请SDK,大概1-2个工作日会邮件回复你 佳能(中国)- 佳定制(佳能影像产品),SDK,EDSDK,CCAPI,软件开发包下载 2. 将SDK这两个文件放到 Unity Plugins文件夹 3. 把CameraControl 下面只要是绿色的 .cs 文件都复制到Unity 中

Linux之定时任务02

一、什么是crond Linux 中 crond 就是定时任务&#xff0c;即根据 crond 指定的时间&#xff0c;由系统按指定的时间&#xff0c;周期性&#xff0c;自动触发的事件。 crond 服务在默认的情况下会每分钟检查系统中是否有定时任务&#xff0c;如果有且符合触发条件&#xff0c;…

哈工大中文mistral介绍(Chinese-Mixtral-8x7B)

Chinese-Mixtral-8x7B基于Mistral发布的模型Mixtral-8x7B进行了中文扩词表增量预训练。扩充后的词表显著提高了模型对中文的编解码效率&#xff0c;并通过大规模开源语料对扩词表模型进行增量预训练&#xff0c;使模型具备了强大的中文生成和理解能力。 开源地址见https://gith…

从单体服务到微服务:多模式 Web 应用开发记录<三>预初始化属性

相关文章&#xff1a; 多模式 Web 应用开发记录<一>背景&全局变量优化多模式 Web 应用开发记录<二>自己动手写一个 Struts 开头先看一个简单的例子&#xff0c;这是 ftl 文件的一个表单&#xff1a; <form id"validateForm" action"#&quo…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的水果质量识别系统(Python+PySide6界面+训练代码)

摘要&#xff1a;本篇博客详尽介绍了一套基于深度学习的水果质量识别系统及其实现代码。系统采用了尖端的YOLOv8算法&#xff0c;并与YOLOv7、YOLOv6、YOLOv5等前代算法进行了详细的性能对比分析&#xff0c;提供在识别图像、视频、实时视频流和批量文件中水果方面的高效准确性…

SpringBoot接收参数的几种形式

SpringBoot接收参数的几种形式 在SpringBoot中获取参数基本方式有5种,需要都掌握. 这里需要记住一个技术术语或概念 API接口: 你写好的那个URL地址,就被称为API接口 1. 接收常规参数 给/param/demo1这个URL接口发送id, name两个参数 以上是以GET请求类型进行发送,实际发送…

EasyX的使用(详解版)

EasyX的基础概念&#xff1a; 图形化——EasyX的安装-CSDN博客 创建图形化窗口 #include<graphics.h> #include<conio.h> int main() {//创建绘图窗口&#xff0c;大小为100x100像素。//更改为大窗口&#xff0c;像素增大&#xff1b;更改为小窗口&#xff0c;像素…

Jenkins笔记(一)

个人学习笔记&#xff08;整理不易&#xff0c;有帮助点个赞&#xff09; 笔记目录&#xff1a;学习笔记目录_pytest和unittest、airtest_weixin_42717928的博客-CSDN博客 目录 一&#xff1a;简单了解 二&#xff1a;什么是DevOps 三&#xff1a;安装Jenkins 四&#xff1…

HarmonyOS—端云一体化组件

概述 DevEco Studio还为您提供多种端云一体化组件。集成端云一体化组件后&#xff0c;您只需进行简单配置即可向应用用户提供登录、支付等众多功能。 登录组件 您可使用端云一体化登录组件向应用用户提供登录和登出功能&#xff0c;目前支持帐号密码登录、手机验证码登录、以…

喜报|迪捷软件入选工信部“2023年信息技术应用创新解决方案”

为进一步推进信创生态建设&#xff0c;激发产业自主创新活力&#xff0c;高效促进供需协同发展&#xff0c;加强区域联动和资源整合&#xff0c;国家工业和信息化部网络安全产业发展中心&#xff08;工业和信息化部信息中心&#xff09;联合相关单位&#xff0c;遴选了一批可复…

idea集成git详解教程(实用篇)

0.Git常用命令 Git常用命令-CSDN博客 1.下载git Git - Downloads 一路傻瓜式安装即可&#xff08;NEXT&#xff09; 2.软件测试 在Windows桌面空白处&#xff0c;点击鼠标右键&#xff0c;弹出右键菜单 Git软件安装后&#xff0c;会在右键菜单中增加两个菜单 Git GUI He…