【Godot4自学手册】第二十节增加游戏的打击感,镜头震颤、冻结帧和死亡特效

这节我主要学习增加游戏的打击感。我们通过镜头震颤、冻结帧、增加攻击点特效,增加死亡。开始了。

一、添加攻击点特效

增加攻击点特效就是,在攻击敌人时,会在敌人受击点显示一个受击动画。

1.添加动画。

第一步先做个受击点动画。切换到Enemy场景,给根节点添加AnimatedSprite2D节点,命名为HiteffectAnima。在其检查器Animation->Sprite Frames 属性选择新建SpriteFrames。过程如下:

在动画帧面板中选择从精灵表中添加按钮,在弹出的对话框中选择我们提前做好的图片素材HitParticle.png,然后在选择帧面板中水平设置4,垂直设置为1,然后单击全选,最后单击添加4帧按钮。

然后在动画帧面板中将动画命名为"Default",动画速度设置10FPS,取消动画循环。

这样我们的动画就做好了。

2.编写代码

首先需要获取动画结点,代码如下:

复制代码
@onready var hiteffect_anima = $HiteffectAnima

然后编写hitHide函数,代码如下:

复制代码
func hitHide():
	hiteffect_anima.hide()

编写hitPlay函数,代码如下:

复制代码
func hitPlay():
	var ran = RandomNumberGenerator.new()
	var jiaodu = ran.randi_range(1,30) #产生个1到30随机数
	hiteffect_anima.rotation=TAU/jiaodu 
	#TAU示一个弧度值,改行代码表示该动画随机旋转一个角度
	hiteffect_anima.show()  #动画显示
	hiteffect_anima.play("Default")  #播放Default动画

敌人刚开始载入时需要隐藏受击点动画的,所以_ready函数调用hitPlay()函数,代码如下:

复制代码
func _ready():
	hitHide()

敌人受击时,要调用hitPlay()函数,现在我们敌人受击代码已经很丰富了,如下:

复制代码
func hurt_state():	#受伤状态
	stats.health -=10  #受伤一次减去10点血量
	var dir = hurtdirecion.direction_to(global_position).normalized()
	if abs(dir.x)>abs(dir.y):
		if dir.x<0:
			velocity.x =-knockback
		else :
			velocity.x =knockback
	else:
		if dir.y<0:
			velocity.y =-knockback
		else :
			velocity.y =knockback
	anima_p.play("TakeHit")
	hitPlay()  #播放受击点动画
	await  anima_p.animation_finished	
	if stats.health<=0:#血量小于等于零时,敌人进入死亡状态
		state=DEATH
	else:
		velocity = Vector2.ZERO
		state=CHASE

选择HiteffectAnima结点,在结点面板双击nimation_finished(),在弹出的对话框中选择enemy结点,然后单击链接按钮。

在代码中添加如下代码,表示动画播放完成后隐藏

复制代码
func _on_hiteffect_animation_finished():
	hitHide()

二、添加死亡动画

1.添加动画。

新建Node2D场景,命名为animations,保存到Scenes目录下。给animations结点添加AnimatedSprite2D结点,命名为anima。添加动画过程与第一点中的添加动画大同小异。只需要添加我们事先准备好的动画精灵,最后动画帧面板如下:

2.添加代码

为该场景根节点添加animations代码,并保存到Scripts文件夹下,具体代码如下:

复制代码
extends Node2D
# Called when the node enters the scene tree for the first time.
func _ready():
	self.hide() #隐藏动画
	pass # Replace with function body.

'''
options.box 动画父类
options.ani_name 动画名称
options.position 动画生成坐标
opions.scale 动画缩放
'''
func run_animation(options):
	var ani_temp = self.duplicate() #复制本身动画
	options.box.add_child(ani_temp) #作为options.box的子节点
	ani_temp.show()  #显示动画
	ani_temp.scale= options.scale if options.has("scale") else Vector2(1,1) 
	#三项条件,当参数有scale属性的时候,动画设置为scale没有的时候设置为不缩放
	ani_temp.position = options.position#设置动画位置
	ani_temp.get_node("anima").play("Dealth")#播放Dealth动画
	pass


func _on_anima_animation_finished():#动画播放完毕
	self.queue_free() #释放该节点
	pass 
3.全局变量

切换到全局变量globals,添加如下代码

复制代码
extends Node
var last_Player
var animation_scene = preload("res://Scenes/animations.tscn")#预加载动画
var animation_scene_obj=null #场景对象
var duplicate_node = null

func _ready():
	animation_scene_obj = animation_scene.instantiate() #实例化animation_scene动画场景
	add_child(animation_scene_obj) #添加到场景中	
	var node2d = Node2D.new() #新建Node2D结点
	node2d.name ="anima_node"#结点名称为duplicate_node
	get_window().add_child.call_deferred(node2d)#将node2d结点添加到主场景的最后位置
	duplicate_node=node2d #将该节点复制给duplicate_node
	pass
4.添加死亡代码

切换到敌人代码中,对死亡代码进行修改如下:

复制代码
func death_state():		
	Globals.animation_scene_obj.run_animation({
		"box":Globals.duplicate_node,
		"ani_name":"Dealth",
		"position":self.global_position,
		"scale":Vector2(1,1)
	})
	self.queue_free()

这样就完成了敌人的死亡动画调用。

三、添加镜头震颤和冻结帧

1.给相机添加代码

切换到Player场景,给Camera2D添加代码,存在Scriptes目录下命名为HitEffect.gd,具体代码如下:

复制代码
extends Camera2D
	
func _hit(_scale,_offset):#震颤效果
	var tween= create_tween()
	tween.tween_property(self,"offset",Vector2.ZERO,0.12).from(_offset)
	#偏移量从_offset到ector2.ZERO,需要0.12秒
	tween.parallel().tween_property(self,"zoom",Vector2(2.00,2.00),0.12).from(_scale)
	#缩放从_scale到Vector2(2.00,2.00),需要0.12秒,这里面为啥是2不是1,是因为我本身就给主人公放大二倍显示
func frameFreeze(time_scale,duration):#冻结帧
	Engine.time_scale = time_scale 
	#控制游戏中的时钟与现实生活中的时钟的快慢。默认值为 1.0。值为 2.0 意味着游戏的移动速度是现实生活的两倍,
	#而值为 0.5 意味着游戏的移动速度是常规速度的一半
	await get_tree().create_timer(duration*time_scale).timeout
	Engine.time_scale=1
2.给Player代码中添加函数

切换到Player代码,添加hit_effect函数

复制代码
func hit_effect():
	$Camera2D._hit(Vector2(1.99,1.99),Vector2(7,-9))
	$Camera2D.frameFreeze(0.1,0.09)
3.敌人受伤时调用

切换到Enemy场景,选择HurtBox节点,在其结点信号面板中双击area_enterd(area:Area2D)信号,在弹出框选择Enemy结点,并在脚本中添加如下代码:

复制代码
func _on_hurt_box_area_entered(area):	#进入受伤范围
	hurtdirecion = area.owner.global_position
	area.owner.hit_effect()
	state = HURT

这样我们这节就OK了,需要源代码的同学请在顶端下载下载。

相关推荐
狂人开飞机1 小时前
21、游戏架构设计模式
游戏·游戏引擎·godot
烛阴13 小时前
Godot 4 入门(04):CharacterBody2D 实现八方向移动
godot
bj_bluewei_tech17 小时前
拯救者游戏本维修卡 logo 无限重启,确认显卡虚焊故障
游戏·电脑
Jae den2 天前
网络延迟为什么会影响游戏和实时业务?
网络·游戏
思盛iOS签名上架2 天前
ipa企业签名闪退是什么原因?
游戏·ios·testfight
狂人开飞机2 天前
14、游戏手感与视觉打磨
游戏·游戏引擎·godot
狂人开飞机2 天前
15、音频系统
游戏引擎·godot
狂人开飞机2 天前
16、粒子线条与视觉特效
游戏引擎·godot
心前阳光3 天前
Unity发布PC软件图标不能改变
unity·游戏引擎
笨鸟先飞的橘猫3 天前
系统设计第十七天决策卡
学习·游戏