【Godot4自学手册】第十七节主人公的攻击和敌人的受伤

news2024/10/5 14:00:50

本节主要学习主人公是如何向敌人发起进攻的,敌人是如何受伤的,受伤时候动画显示,击退效果等。其原理和上一节内容相同,不过有许多细节需要关注和完善。

一、修改Bug

在本节学习之前,我将要对上一节的代码进行完善,修改一些Bug。

1.第一个Bug是敌人攻击动画没有播放完整。

主要原因是:但敌人动画底6帧攻击主人公HitBox起作用后,将会将主人公向后击退一部分距离,离开了HitArea碰撞区域会立即执行_on_hit_area_body_exited内代码,状态会改变为 CHASE。所以,第一要断开hit_area_body_exited信号,并删除下面的代码:

func _on_hit_area_body_exited(body):
	if body.name=="Player" :
		state = CHASE

第二删除代码后,需要将attack_state代码修改如下:

func attack_state():		
	anima.play("Attack")		
	await  anima.animation_finished
	state = IDLE
	$TraceArea/Trace_Collsion.disabled=true
	$TraceArea/Trace_Collsion.disabled=false
	$HitArea/HitArea_Collsion.disabled=true
	$HitArea/HitArea_Collsion.disabled=false

这段代码表示敌人攻击动画完成后切换敌人状态到IDLE,同时跟踪、攻击碰撞重新停止和启动,来判断目前敌人需要进入的状态,如果在跟踪区域,就进行跟踪;如果在攻击区域就进行攻击。

2.主人公进入敌人跟踪区域,停止移动,敌人跟踪到攻击范围,发起攻击,主人公闪白效果不对应

主要原因是:在动画树中,我在制作主人公受伤的动画时用了BlendSpace1D,只有两个方向上的受伤动画。所以进行如下修改:第一在动画树中删除Hurt节点,新建BlendSpace2D节点,命名为Hurt,进入节点内部建立四个方向的受伤动画。第二修改代码。首先在walk_state()中添加如下代码:

anima_tree.set("parameters/Hurt/blend_position",Vector2(playerdirection.x*-1,playerdirection.y))

这段代码表示最后主人公的在那个方向收到的攻击。然后修改func hurt_state()代码如下:

func hurt_state():	
	var dir = enemyPositon.direction_to(global_position).normalized()
	anima_tree["parameters/playback"].travel("Hurt")
	if dir.x>0:
		velocity.x +=10
	else :
		velocity.x -=10
	#await  get_tree().create_timer(.4).timeout	
	await anima_tree.animation_finished
	state=WALK
	velocity = Vector2.ZERO
3.如果主人公进入敌人跟踪区域,在敌人上方停止移动,敌人跟踪到攻击范围,攻击敌人还是左右方向,并未与主人公发生碰撞

主要原因是:我们的敌人攻击动画只有左右连个方向,攻击范围用的是圆形碰撞体,在整改圆形区域任何边缘都会发生碰撞,所以将攻击范围的圆形碰撞体改为矩形,保持左右方向,这样就可以了,效果如下:
请添加图片描述

如果我们的敌人动画时四个方向的攻击,我们可以将HitArea节点下添加连个矩形碰撞,即可时限四个方向的攻击。

二、主人公的攻击

1.添加攻击节点。

在Player场景中,给Player节点添加一个Area2D节点,命名为HitBox;给HitBox节点添加CollisionShape2D节点,命名为DownCollision,检查器中shape设置为RectangleShape2D,方形碰撞;Disabled属性启用;根据Attack_Down动画挥刀位置调整节点DownCollision位置,过程如下:
请添加图片描述

2.调整攻击动画。

切换到AnimationPlayer节点,在动画面板中第一帧添加DownCollision节点Disabled属性未启用关键帧;第四帧添加DownCollision节点Disabled属性启用关键帧;第五帧添加DownCollision节点Disabled属性未启用关键帧。最后效果如上图的动画面板所示。
同理,在HitBox节点依次添加3个CollisionShape2D节点,名称分别命名为LeftCollision、RightCollision、UpCollision,然后对着动画依次调整位置和Disabled属性。这里着重强调一下,LeftCollision等3个节点,选择矩形碰撞后还要选择唯一化,这样避免调整其中一个碰撞图形大小影响到其它节点碰撞图形,唯一化操作如下图所示。
请添加图片描述

3.设置碰撞层。

新建第6物理层,命名为HitPlayer,将HitBox节点collision中的layer设置在HitPlayer层,Mask不进行设置,结果如下:
请添加图片描述

三、敌人的受伤

1.添加受伤结点

在Enemy场景中给Eneymy节点添加子结点Area2D,命名为HurtBox。给HurtBox节点添加子节点CollisionShape2D,在检查器中shape属性选择CapsuleShape2D椭圆形碰撞,表示敌人受伤碰撞,根据敌人形状调整碰撞大小。新建Node2D结点,命名为CheckBox,将HitArea、HitBox、HurtBox、TraceArea结点拖至子节点。效果如下:
请添加图片描述

2.修改碰撞层

将HurtBox节点collision中的layer设置为空,Mask设置HitPlayer,表示受伤层主动与主人公发生碰撞,结果如下:
请添加图片描述

3.修改信号,编辑代码

首先将HurtBox结点area_entered信号添加到Enemy代码中,并完善代码如下:

func _on_hurt_box_area_entered(area):
	state = HURT
	hurtdirecion = area.owner.global_position

修改hurt_state代码如下:

func hurt_state():	
	$CheckBox.process_mode=Node.PROCESS_MODE_DISABLED	
	var dir = hurtdirecion.direction_to(global_position).normalized()
	if abs(dir.x)>abs(dir.y):
		if dir.x<0:
			velocity.x =-200
		else :
			velocity.x =200
	else:
		if dir.y<0:
			velocity.y =-200
		else :
			velocity.y =200			
	await  get_tree().create_timer(.05).timeout	
	velocity = Vector2.ZERO
	anima.play("TakeHit")
	await  anima.animation_finished
	state=IDLE
	$CheckBox.process_mode=Node.PROCESS_MODE_INHERIT

这段代码首先当敌人受伤时所有碰撞检测代码全部失效,敌人后退200后播放受伤动画,播放完毕所有碰撞检测代码恢复正常。
修改attack_state代码如下:

func attack_state():		
	anima.play("Attack")		
	await  anima.animation_finished
	state = IDLE
	$CheckBox.process_mode=Node.PROCESS_MODE_DISABLED
	await  get_tree().create_timer(.5).timeout	
	$CheckBox.process_mode=Node.PROCESS_MODE_INHERIT

这段代码主要修复了有碰撞检测代码全部失效和恢复功能。
修改_on_trace_area_body_exited代码如下:

func _on_trace_area_body_exited(body):	
		if body.name=="Player" :
			if state != HURT:
				state = IDLE

这样敌人的整改代码如下:

extends CharacterBody2D
enum {
	IDLE,
	CHASE,
	ATTACK,
	HURT,
	DEATH
}
const SPEED = 1.0
var hitCount=2
@onready var anima = $AnimaP
@onready var animaS =$AnimaS
@onready var hit_box = $CheckBox/HurtBox
var hurtdirecion

var state = IDLE

func _physics_process(delta):
	match state:
			IDLE:
				idle_state()
			CHASE:
				chase_state()
			ATTACK:
				attack_state()
			HURT:
				hurt_state()
			DEATH:
				death_state()
	move_and_slide()
	
	
func idle_state():
	anima.play("Idle")

func chase_state():
	anima.play("Run")
	var direction =  Globals.last_Player-global_position
	if direction.x<0:
		animaS.flip_h=true
		hit_box.scale.x =-1
	else:
		animaS.flip_h = false
		hit_box.scale.x=1
	global_position = global_position.move_toward(Globals.last_Player,SPEED)

func finattack():
	state=IDLE
	
func attack_state():		
	anima.play("Attack")		
	await  anima.animation_finished
	state = IDLE
	$CheckBox.process_mode=Node.PROCESS_MODE_DISABLED
	await  get_tree().create_timer(.5).timeout	
	$CheckBox.process_mode=Node.PROCESS_MODE_INHERIT
func hurt_state():	
	$CheckBox.process_mode=Node.PROCESS_MODE_DISABLED	
	var dir = hurtdirecion.direction_to(global_position).normalized()
	if abs(dir.x)>abs(dir.y):
		if dir.x<0:
			velocity.x =-200
		else :
			velocity.x =200
	else:
		if dir.y<0:
			velocity.y =-200
		else :
			velocity.y =200			
	await  get_tree().create_timer(.05).timeout	
	velocity = Vector2.ZERO
	anima.play("TakeHit")
	await  anima.animation_finished
	state=IDLE
	$CheckBox.process_mode=Node.PROCESS_MODE_INHERIT


func death_state():	
	pass

func _on_trace_area_body_entered(body):
	if body.name=="Player" :
		state = CHASE


func _on_trace_area_body_exited(body):	
		if body.name=="Player" :
			if state != HURT:
				state = IDLE

func _on_hit_area_body_entered(body):
	if body.name=="Player" :
		state = ATTACK

func _on_hurt_box_area_entered(area):
	state = HURT
	hurtdirecion = area.owner.global_position


最后我们预览一下效果如下:
请添加图片描述

这一节就到这了,同学们下节再见!
需要源代码的同学,请单击下载。下载源代码

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基础小白快速入门Python------>模块的作用和意义

模块&#xff0c; 这个词听起来是如此的高大威猛&#xff0c;以至于萌新小白见了瑟瑟发抖&#xff0c;本草履虫见了都直摇头&#xff0c;好像听上去很难的样子&#xff0c;但是但是&#xff0c;年轻人&#xff0c;请听本少年细细讲述&#xff0c;他只是看起来很难&#xff0c;实…

MySql安全加固:可信IP地址访问控制 设置密码复杂度

MySql安全加固&#xff1a;可信IP地址访问控制 & 设置密码复杂度 1.1 可信IP地址访问控制1.2 设置密码复杂度 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 1.1 可信IP地址访问控制 当您在创建用户时使用’%作为主机部分&#xff0c;…

【爬虫逆向实战 逆向滑块 Python+Node】今天逆向的网站有点嘿嘿,还是仅供学习,别瞎搞

逆向日期&#xff1a;2024.03.01 使用工具&#xff1a;Node.js、Python 加密方法&#xff1a;AES标准算法 文章全程已做去敏处理&#xff01;&#xff01;&#xff01; 【需要做的可联系我】 AES解密处理&#xff08;直接解密即可&#xff09;&#xff08;crypto-js.js 标准算…

大模型生成,Open API调用

大模型是怎么生成结果的 通俗原理 其实&#xff0c;它只是根据上文&#xff0c;猜下一个词&#xff08;的概率&#xff09;…… OpenAI 的接口名就叫【completion】&#xff0c;也证明了其只会【生成】的本质。 下面用程序演示【生成下一个字】。你可以自己修改 prompt 试试…

Appium移动端自动化测试-(Java)

目录 环境搭建ADB调试工具adb构成adb工作原理adb常用命令电脑连接多个设备跟模拟器使用adb包名与界面名的概念如何获取包名和界面名文件传输获取app启动时间获取手机日志其他命令 Appium全自动化测试框架&#xff08;python&#xff09;冲错了序言 环境搭建Appium客户端安装App…

IDEA切换 Springboot初始化 URL

&#x1f339;作者主页&#xff1a;青花锁 &#x1f339;简介&#xff1a;Java领域优质创作者&#x1f3c6;、Java微服务架构公号作者&#x1f604; &#x1f339;简历模板、学习资料、面试题库、技术互助 &#x1f339;文末获取联系方式 &#x1f4dd; 往期热门专栏回顾 专栏…

【矩阵】【方向】【素数】3044 出现频率最高的素数

作者推荐 动态规划的时间复杂度优化 本文涉及知识点 素数 矩阵 方向 LeetCode 3044 出现频率最高的素数 给你一个大小为 m x n 、下标从 0 开始的二维矩阵 mat 。在每个单元格&#xff0c;你可以按以下方式生成数字&#xff1a; 最多有 8 条路径可以选择&#xff1a;东&am…

C语言基础(三)——函数

六、函数 6.1 函数的声明与定义—嵌套调用 6.1.1 函数的声明与定义 函数间的调用关系是&#xff0c;由主函数调用其他函数&#xff0c;其他函数也可以互相调用&#xff0c;同一个函数可以背一个或多个函数调用任意次。 下例中有两个c文件, func.c是子函数printstar和print_me…

光伏气象站的组成

TH-FGF9光伏气象站主要由以下几个部分组成&#xff1a; 光伏组件&#xff1a;光伏组件是光伏气象站的核心部分&#xff0c;其主要功能是将太阳能转化为电能&#xff0c;为气象站的各项设备提供电源。光伏组件通常由多个光伏电池板组成&#xff0c;能够有效地吸收并利用太阳能。…

C++:String类的使用

创作不易&#xff0c;感谢三连&#xff01;&#xff01; 在C语言中&#xff0c;我们想要存储字符串的话必须要用字符数组 char str[]"hello world"这其实是将在常量区的常量字符串拷贝到数组中&#xff0c;我们会在数组的结尾多开一个空间存储\0&#xff0c;这样我…

pyuic生成py文件到指定文件夹

pyuic生成py文件到指定文件夹 关于如何在pycharm配置外部工具的方法这里不做赘述&#xff0c;本文主要说明&#xff0c;如何利用pyuic将ui文件生成到指定的项目目录中。 前提条件&#xff1a;已配置的pyuic工具可以正常使用生成文件到目录中。 一、打开外部工具配置页面 打开…

吸猫毛空气净化器哪个好?推荐除猫毛好的宠物空气净化器品牌

如今&#xff0c;越来越多的家庭选择养宠物&#xff01;虽然家里变得更加温馨&#xff0c;但养宠可能会带来异味和空气中的毛发增多可能会引发健康问题&#xff0c;这也是一个大问题。 但我不想家里到处都是异味&#xff0c;尤其是便便的味道&#xff0c;所以很需要一款能够处…

android Service 与 activity 通信 并不断传数据

注&#xff1a;这只是个Demo 以下载为案例&#xff0c;实现开启下载&#xff0c;暂停下载&#xff0c;下载进度不断发送给activity class DownloadService : Service() {override fun onBind(intent: Intent?): IBinder? {return MyBinder()}inner class MyBinder : Binder…

mysql学习--binlog与gtid主从同步

基础环境 基于centOS7-MySQL8.0.35版本 我们先准备一台主服务器两台从服务器来实现我们主从同步的诉求 Master&#xff1a;192.168.75.142 slave1:192.168.75.143 slave&#xff1a;192.168.75.145 binlog主从同步 主库配置 #我们需要在主从库中都需要添加server_id&am…

如何学习、上手点云算法(一):点云基础

写在前面 本文内容 点云算法的学习基础&#xff0c;入门方法&#xff0c;相关领域&#xff0c;资源&#xff0c;开源库&#xff0c;算法等的介绍&#xff1b; 以Open3D和PCL等为基础工具的点云处理代码讲解、实现&#xff1b; 文中涉及的参考以链接形式给出&#xff0c;涉及文…

综合练习(二)

目录 列出薪金比 SMITH 或 ALLEN 多的所有员工的编号、姓名、部门名称、领导姓名、部门人数&#xff0c;以及所在部门的平均工资、最高和最低工资 补充 spool Oracle从入门到总裁:https://blog.csdn.net/weixin_67859959/article/details/135209645 列出薪金比 SMITH 或 AL…

探索数据结构:解锁计算世界的密码

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;数据结构与算法 贝蒂的主页&#xff1a;Betty‘s blog 前言 随着应用程序变得越来越复杂和数据越来越丰富&#xff0c;几百万、…

LabVIEW最佳传输系统设计

LabVIEW最佳传输系统设计 介绍了基于LabVIEW软件开发的最佳基带传输系统和最佳带通传输系统的设计。通过软件仿真实现了脉冲成形滤波器和匹配滤波器的设计&#xff0c;证明了系统在消除码间干扰和抗噪声方面的优异性能。此设计不仅激发了学生的学习兴趣&#xff0c;还有助于提…

kubernetes最新版安装单机版v1.21.5

k8s集群由Master节点和Node&#xff08;Worker&#xff09;节点组成。 1.环境 环境&#xff1a;centos 7资源配置&#xff1a;2c4g &#xff08;CPU最少2c&#xff0c;不然k8s起不来&#xff09;docker&#xff1a;25.0.3k8s&#xff1a;1.21.5 2.安装前置环境 [rootbertra…

【Android开发】01-第一个Android APP

一、改MainActivity class MainActivity : AppCompatActivity() {/*因Android的app有生命周期&#xff0c;故入口是OnCreate而不是main函数*/override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main…