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

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

一、修改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_finishedstate = 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 +=10else :velocity.x -=10#await  get_tree().create_timer(.4).timeout	await anima_tree.animation_finishedstate=WALKvelocity = 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 = HURThurtdirecion = 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 =-200else :velocity.x =200else:if dir.y<0:velocity.y =-200else :velocity.y =200			await  get_tree().create_timer(.05).timeout	velocity = Vector2.ZEROanima.play("TakeHit")await  anima.animation_finishedstate=IDLE$CheckBox.process_mode=Node.PROCESS_MODE_INHERIT

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

func attack_state():		anima.play("Attack")		await  anima.animation_finishedstate = IDLE$CheckBox.process_mode=Node.PROCESS_MODE_DISABLEDawait  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 hurtdirecionvar state = IDLEfunc _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_positionif direction.x<0:animaS.flip_h=truehit_box.scale.x =-1else:animaS.flip_h = falsehit_box.scale.x=1global_position = global_position.move_toward(Globals.last_Player,SPEED)func finattack():state=IDLEfunc attack_state():		anima.play("Attack")		await  anima.animation_finishedstate = IDLE$CheckBox.process_mode=Node.PROCESS_MODE_DISABLEDawait  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 =-200else :velocity.x =200else:if dir.y<0:velocity.y =-200else :velocity.y =200			await  get_tree().create_timer(.05).timeout	velocity = Vector2.ZEROanima.play("TakeHit")await  anima.animation_finishedstate=IDLE$CheckBox.process_mode=Node.PROCESS_MODE_INHERITfunc death_state():	passfunc _on_trace_area_body_entered(body):if body.name=="Player" :state = CHASEfunc _on_trace_area_body_exited(body):	if body.name=="Player" :if state != HURT:state = IDLEfunc _on_hit_area_body_entered(body):if body.name=="Player" :state = ATTACKfunc _on_hurt_box_area_entered(area):state = HURThurtdirecion = area.owner.global_position

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

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

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

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

相关文章

androidframework开发面试,阿里P8成长路线

字节跳动Android面经 一面问的 Java 和 Android 基础 1、Jvm虚拟机 2、messageQueue会不会阻塞ui线程 3、对象锁和类锁 4、之字形打印树 5、还有其他的 《Android学习笔记总结最新移动架构视频大厂安卓面试真题项目实战源码讲义》 **完整开源项目&#xff1a;docs.qq.com/doc…

【leetcode】破解闯关密码 模板字符串

/*** param {number[]} password* return {string}*/ var crackPassword function(password) {return minNumspassword.sort((a,b)>{if(${a}${b}-${b}${a}>0){return 1;}else{return -1;}}).join(""); };巧用模板字符串对数组进行排序

二、TensorFlow结构分析(2)

目录 1、会话 1.1 __init__(target,graphNone,configNone) 1.2 会话的run() 1.3 feed操作 TF数据流图图与TensorBoard会话张量变量OP高级API 1、会话 1.1 __init__(target,graphNone,configNone) def session_demo():# 会话的演示# Tensorflow实现加法运算a_t tf.constan…

Vue+SpringBoot打造音乐偏好度推荐系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、系统设计2.1 功能模块设计2.1.1 音乐档案模块2.1.2 我的喜好模块2.1.3 每日推荐模块2.1.4 通知公告模块 2.2 用例图设计2.3 实体类设计2.4 数据库设计 三、系统展示3.1 登录注册3.2 音乐档案模块3.3 音乐每日推荐模块3.4 通知公告模…

继承-学习2

this关键字&#xff1a;指向调用该方法的对象&#xff0c;一般我们是在当前类中使用this关键字&#xff0c;所以我们常说代表本类对象的引用 super关键字&#xff1a;代表父类存储空间的标识(可看作父类对象的引用) 父类&#xff1a; package ven;public class Fu {//父类成员…

【云原生】Spring Cloud Gateway的底层原理与实践方法探究

&#x1f389;&#x1f389;欢迎光临&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;特别推荐给大家我的最新专栏《Spring 狂野之旅&#xff1a;从入门到入魔》 &#x1f680; 本…

Win32汇编ListView控件学习

此控件比较复杂&#xff1b;和基础win32控件不同&#xff1b;需要先初始化Windows公共控件库&#xff0c; invoke InitCommonControls 之后才可使用&#xff1b; lvdemo.asm&#xff0c; .386.model flat, stdcalloption casemap :none ; case sensitiveinclude window…

Windows Docker 部署 SQL Server

部署 SQL Server 打开 Docker Desktop&#xff0c;切换到 Linux 内核。然后在 PowerShell 执行下面命令&#xff0c;即可启动一个 SQL Server 服务&#xff0c;这里安装的是 2022 年版本 docker run -e "ACCEPT_EULAY" -e "MSSQL_SA_PASSWORDSQL123abcABC!&qu…

VR全景HDR拍摄教程

什么是HDR&#xff1f; HDR可以用在哪里&#xff1f; 书面解释&#xff1a;HDR&#xff08;高动态范围 High Dynamic Range&#xff09;摄影&#xff0c;是摄影领域广泛使用的一种技术。 是不是有点懵&#xff1f; 我们来看一个实际的拍摄现场环境&#xff0c;你就懂了 我们…

电商网站数据采集配合socks5代理ip怎么进行?

电商网站数据采集是一项重要的任务&#xff0c;可以帮助企业了解市场需求、竞品分析、用户行为等方面。在进行电商网站数据采集时&#xff0c;有时需要配合使用socks5代理IP。本文将介绍如何进行电商网站数据采集配合socks5代理IP。 一、代理IP介绍 代理IP是一种可以隐藏用户真…

Ps:明度直方图

明度 Luminosity直方图显示了图像中各个亮度级别的像素分布情况。 与 RGB 直方图不同&#xff0c;“明度”直方图专注于图像的亮度信息&#xff0c;而不是单独的颜色信息。 在“直方图”面板的通道中选择“明度”。 “明度”直方图提供了一种量化的方式来理解图像的整体明暗结构…

内衣洗衣机希亦、RUUFFY、由利强势对决,实测数据谁能赢?

对于那些追求品质生活、分类洗涤的用户而言&#xff0c;小型洗衣机可以满足我们对不同类型衣物分开洗涤的需求&#xff0c;例如将内衣、袜子等小件衣物与外套等分开洗涤&#xff0c;以保持衣物的清洁和卫生。并且如果您家中有宝宝&#xff0c;或者您对个人卫生和健康有较高要求…