本节内容,主要学习闪电攻击魔法。闪电攻击又名为闪电链,就是在几个敌人之间产生不断跳动的闪电攻击效果。本节主要实现的是单击鼠标右键,会在敌人之间产生随机的闪电链条,效果如下:
一、基本闪电的建立
新建2D场景,命名为Lightning,添加子节点Sprite2D命名为light,目录结构如下:
将我们事先准备好的闪电蔬菜拖入到light的Texture属性。在其Region属性下将Enabled开启,如图所示:
同时开启图片无缝重复功能,开启方式如下图:
为根节点添加LightningSprite脚本,编写如下代码:
extends Node2D
@onready var lsprite = $light #获取闪电图片
@export var waittime:float=0.05 #动画间隔时间
#释放闪电函数,一个参数表示第一个物体,参数二表示第二个物体,这样会在两个物体间产生一条闪电。
func flicker(objectone,objecttwo):
position = objectone.position#设置闪电起始位置为第一个物体
var vector2:Vector2 = objectone.position - objecttwo.position#计算连个物体间有关向量
set_deferred("rotation",vector2.angle() - PI/2.1) #设置闪电旋转角度
var length = vector2.length() #计算闪电长度
lsprite.show() #显示闪电
playLightiingAnima(length) #播放闪电动画
#闪电动画,主要原理是对图片素材进行剪切,每个一段时间播放一张图片
func playLightiingAnima(length:float):
chargeSize(Rect2(3,0,11,length)) #切割素材图片,选取其中一部分
await get_tree().create_timer(waittime).timeout #等待一段时间进行下一部分图片显示
chargeSize(Rect2(20,0,11,length))
await get_tree().create_timer(waittime).timeout
chargeSize(Rect2(35,0,11,length))
await get_tree().create_timer(waittime).timeout
chargeSize(Rect2(51,0,11,length))
await get_tree().create_timer(waittime).timeout
chargeSize(Rect2(65,0,11,length))
await get_tree().create_timer(waittime).timeout
queue_free()
#切割素材图片,选取其中一部分
func chargeSize(RegionBox:Rect2):
lsprite.offset= Vector2(0,RegionBox.size.y/2*-1) #移到图片素材的对应位置
lsprite.region_rect = RegionBox #切割的具体图片大小
二、场景建立魔法管理
新建2D场景,命名为light_sence。拖入敌人的素材,然后添加分组enemy。如下:
添加Node2d节点,命名为SkillManger,并添加如下代码:
extends Node2D
#预加载闪电场景
@onready var ligtningO:PackedScene = preload("res://Scenes/lightning_sprite.tscn")
#释放闪电函数 第一个参数表示释放闪电的物体数组,第二个参数表示释放深度,也就是可以释放几条闪电链
func castLigtning(enemyObject:Array,depth:int):
if enemyObject.size()==0: #没有释放物体直接退出
return
if enemyObject.size()==1:
print("长度为1")#如果只有一个物体不会释放闪电链,咱可以释放闪电球
return
if enemyObject.size()==2:#两个物体直接释放一条闪电链条
var lightskill = ligtningO.instantiate()
add_child(lightskill)
lightskill.flicker(enemyObject[0],enemyObject[1])
else:
#随机排列数组
var array_length = enemyObject.size()
# 随机排列数组
for i in range(array_length):
# 获取一个随机索引
var random_index = randi_range(0, array_length - 1)
# 交换当前索引和随机索引的元素
var temp = enemyObject[i]
enemyObject[i] = enemyObject[random_index]
enemyObject[random_index] = temp
#如果物体的数量多余或等于释放深度,根据深度进行如下释放闪电链
if enemyObject.size()>=depth:
for i in depth:
var lightskill = ligtningO.instantiate()
add_child(lightskill)
lightskill.flicker(enemyObject[i],enemyObject[i+1])
await get_tree().create_timer(.1).timeout #间隔0.1秒释放下一闪电链
else:#如果物体的数量多余或等于释放深度,根据物体数量进行如下释放闪电链
var index:int = 0
for child in enemyObject:
if index>=enemyObject.size()-1:
return
else:
var lightskill = ligtningO.instantiate()
add_child(lightskill)
lightskill.flicker(enemyObject[index],enemyObject[index+1])
index =index+1
await get_tree().create_timer(.05).timeout
为根节点添加代码如下:
extends Node2D
@onready var skill_manger = $SkillManger #获取技能管理节点
func _input(event):
if event.is_action_pressed("sword"):#如果按下鼠标攻击键
var enemyList = get_tree().get_nodes_in_group("enemy") #通过分组获取敌人
skill_manger.castLigtning(enemyList,randi_range(1,3)) #释放闪电技能,随机产生闪电链深度
这里重点说明一下 event.is_action_pressed(“sword”)是我们以前设置好的攻击键,这里用的是鼠标单击左键。这个映射是在菜单栏项目下的项目设置里面进行的设置,如下:
最后我们看一下最后效果: