本节内容,主要学习闪电攻击魔法。闪电攻击又名为闪电链,就是在几个敌人之间产生不断跳动的闪电攻击效果。本节主要实现的是单击鼠标右键,会在敌人之间产生随机的闪电链条,效果如下:
一、基本闪电的建立
新建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).timeoutchargeSize(Rect2(35,0,11,length))await get_tree().create_timer(waittime).timeoutchargeSize(Rect2(51,0,11,length))await get_tree().create_timer(waittime).timeoutchargeSize(Rect2(65,0,11,length))await get_tree().create_timer(waittime).timeoutqueue_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: #没有释放物体直接退出returnif enemyObject.size()==1:print("长度为1")#如果只有一个物体不会释放闪电链,咱可以释放闪电球returnif 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 = 0for child in enemyObject:if index>=enemyObject.size()-1:returnelse: var lightskill = ligtningO.instantiate()add_child(lightskill)lightskill.flicker(enemyObject[index],enemyObject[index+1])index =index+1await 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”)是我们以前设置好的攻击键,这里用的是鼠标单击左键。这个映射是在菜单栏项目下的项目设置里面进行的设置,如下:
最后我们看一下最后效果: