各位同学大家好,前面我们学习了敌人的攻击动画,但是没有真正意义上实现攻击功能。今天我们将要学习敌人的攻击和主任的受伤功能的实现,其实原理很简单我们以前都学过,主要是给敌人添加一个Area2D子节点,这个结点用于与主任公发生碰撞达到进攻记录的目的;给主人公添加一个Area2D子节点用于接收敌人的进攻。开始吧。

一、敌人的进攻

1.结点布置。

在Enemy场景中添加Area2D结点,命名为HitBox,在该节点下添加CollisionShape2D结点,该节点用于敌人攻击与主任公发生碰撞的位置,在检测其中将Shape选择矩形碰撞,属性Disabled启用,这样的目的是禁用改碰撞默认启用,后面只有在敌人进攻的时候启用。
请添加图片描述

2.适当调整碰撞位置。

单击AnimationP结点,在动画面板中,选择Attack动画,切换到第七帧,根据动画调整HitBox到合适位置,整个过程如下:
请添加图片描述

3.停用启用碰撞

切换到动画面板,然后选择Attack动画,将播放位置拖到第一帧,然后在Hitbox子节点CollisionShape2D的检查器中,属性Disabled启用后单击后面的关键帧,这样会在动画第一帧中添加一个启用Disable的关键帧。如下:
请添加图片描述

同理,在Attack动画的第七帧添加一个不启用Disable的关键帧,在最后一帧添加启用Disable的关键帧,最终动画设置如下:
请添加图片描述

这样,只用敌人进攻时,碰撞才起作用。

4.修改代码

在Enemy代码中,完善代码一是翻转攻击碰撞HitBox,攻击框随着敌人的翻转而翻转;二是添加敌人攻击力。
攻击框翻转代码如下:

@onready var hit_box = $HitBox #获取攻击框
#chase_state函数中,hit_box.scale.x =-1翻转碰撞框
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)

敌人攻击力代码简单的写一行,以后会逐步完善,代码如下:

var hitCount=2

目前,整个敌人的代码如下:

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 = $HitBox

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 attack_state():		
	anima.play("Attack")	
	await  anima.animation_finished
	state = IDLE
	await  get_tree().create_timer(1).timeout
	state = ATTACK
func hurt_state():
	pass
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" :
		state = IDLE


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


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

二、碰撞层的设置

单击菜单栏中的项目,然后选择项目设置,在项目设置对话框中选择层名称->2D物理层,在第5层中输入HitEnemy,这个层用于与敌人发生碰撞。
请添加图片描述

进入Enemy场景选择HitBox结点,在检查器中Collision属性中将Layer设置为HitEnemy,Mask不进行设置,这样HitBox会位于HitEnemy层,为下一步碰撞做好准备。如下:
请添加图片描述

三、设置主人公受伤

1.搭建子节点。

进入Player场景,在跟场景添加Area2D结点,命名为HurtBox。为HurtBox添加子节点CollisionShape2D,形状选择胶囊碰撞,在检查器中Collision属性中将Layer不进行设置,Mask设置为HitEnemy,这样表示该节点与HitEnemy发生碰撞,设置如下:
请添加图片描述

2.设置受伤动画

进入主人公场景,选择AnimatedSprite2D结点,在动画帧控制面板中,新建两个动画一个是Hurt_Left,一个是Hurt_Right,操作如下:
请添加图片描述

然后单击从精灵表中添加帧,然后选择Playerer素材,在弹出的选择帧对话框中,水平设置4,垂直设为2,前两张图片添加到Hurt_Left动画,后两张图片添加到Hurt_Right动画,如下:
请添加图片描述

切换到AnimationPlayer结点,在检查器中单击导入按钮,将AnimatedSprite2D导入到该节点下,操作如下:
请添加图片描述

在动画面板中将Hurt_Left动画时长设置0.2,并调整动画帧到0.2秒内,如下:
请添加图片描述

同理,Hurt_Right进行同样设置。
切换到AnimationTree结点,在动画树面板中选择创建新节点按钮,命名为Hurt,然后单击后面的小笔图标。如下所示:
请添加图片描述

在Hurt面板内选择创建点按钮,然后在最左侧单击按钮选择添加动画->Hurt_Left,在最右侧添加Hurt_Right;最后选择混合模式选择离散模式,而不是连续模式。操作如下:
请添加图片描述

3.添加信号编写代码

在Player场景中,给Player结点添加Area2D结点,命名为HurtBox。给HurtBox结点添加CollisionShape2D子节点,检查器中shape中选择椭圆形碰撞结点,根据主人公调整大小。如下:
请添加图片描述

选择HurtBox结点,切换到信号,双击area_entered信号在弹出信号连接对话框中选择Player,单击链接按钮,操作如下:
请添加图片描述

切换Enemy代码,编写代码如下:

func _on_hurt_box_area_entered(area):
	state=HURT	#切换到HURT状态
	enemyPositon = area.owner.global_position #敌人位置

func hurt_state():	
	var dir = enemyPositon.direction_to(global_position).normalized()
	#判断攻击方向
	anima_tree.set("parameters/Hurt/blend_position",dir.x)
	anima_tree["parameters/playback"].travel("Hurt")
	#播放受伤动画
	if dir.x>0:
		velocity.x +=10
	else :
		velocity.x -=10
	#击退效果
	await anima_tree.animation_finished
	state=WALK
	velocity = Vector2.ZERO
	#动画播放完成后,人物状态切换到WALK状态,速度降为0

最终效果如下:
请添加图片描述

这节就到这,还有许多问题需要完善,我们下节完善吧。同学们,下次再见!

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐