--飞剑效果
FeiJianSKill = {}
---飞剑状态
FeiJianSKill.SwordState = {
Idle = 0, --待机
Attack = 1, --攻击中
Back = 2, --收回
AttackCd1 = 3, --攻击等待飞行
AttackCd2 = 4, --攻击等待旋转
}
local feiId = 10
local hitEffId = 133
---飞剑配置信息
local allSwordInfo =
🤖 回答引擎: 前端Lua |
🕒 时间: 2026-06-17 12:11:34 |
👁️ 阅读: 44
这段代码实现了一个飞剑技能系统,我来逐行解析核心逻辑:
**一、基础定义部分(1-50行)**
```lua
FeiJianSKill = {} -- 主模块
FeiJianSKill.SwordState = { -- 飞剑状态枚举
Idle = 0, -- 待机环绕玩家
Attack = 1, -- 攻击怪物中
Back = 2, -- 返回玩家身边
AttackCd1 = 3, -- 攻击后等待飞行
AttackCd2 = 4 -- 攻击冷却等待
}
local feiId = 10 -- 基础飞剑ID
local hitEffId = 133 -- 命中特效ID
-- 飞剑配置表,id对应图片,color对应粒子颜色
local allSwordInfo = {
[10] = { id = 1, color = '5555ff' },
-- ...其他配置
[16] = { id = 99, color = '5599ff' } -- GM版多飞剑
}
```
**二、场景节点管理(51-80行)**
```lua
-- 获取前后层节点(用于深度管理)
local rootB = global.sceneGraphCtl:GetSceneNode(global.MMO.NODE_SKILL_BEHIND)
local rootF = global.sceneGraphCtl:GetSceneNode(global.MMO.NODE_SKILL)
local function getRootB() -- 懒加载背景层
local function getRootF() -- 懒加载前景层
local offset = cc.p(0, 30) -- 位置偏移量
local nowMonsters = {} -- 缓存当前可攻击怪物
```
**三、飞剑类定义(81-400行)**
核心类`FlyingSword`继承自`cc.Node`,主要功能:
1. **构造函数**(87-130行):
```lua
function FlyingSword:ctor(swordInfo, player, radiusX, radiusY, speed, userPassiveSkillData)
self.sword = cc.Sprite:create() -- 创建飞剑精灵
self.sword:initWithFile(string.format("res/custom/feijian/jian_%d.png", swordInfo.id))
self.particle = cc.ParticleSystemQuad:create("particle/tail.plist") -- 拖尾粒子
self:setNextAttackTime(userPassiveSkillData.cd) -- 设置攻击CD
self:startIdle() -- 初始为待机状态
end
```
2. **状态机系统**:
- `startIdle()`:待机环绕玩家
- `startAttackEnemy()`:攻击指定怪物
- `startBack()`:返回玩家身边
- `startAttackWait()`:攻击后等待
3. **位置计算逻辑**(350-380行):
```lua
function FlyingSword:getStatePos(actor, dt)
if self.state == FeiJianSKill.SwordState.Attack then
-- 攻击状态:贝塞尔曲线飞向目标
return UiTools.calculateBezierPoint(self.beizerPoints, 1 - self.left / self.stateDuration)
else
-- 待机状态:椭圆轨迹环绕玩家
self.angle = self.angle + self.speed * dt
local playerPos = actor:getPosition()
return cc.pAdd(playerPos, self:getIdlePos())
end
end
```
4. **更新函数**(382-450行):
```lua
function FlyingSword:update(dt)
self.left = self.left - dt -- 状态倒计时
if self.left <= 0 then
self:stateEnd() -- 状态结束切换
end
local targetPos = self:getStatePos(actor, dt)
self:setPosition(targetPos)
-- 攻击状态特殊效果
if self.state == FeiJianSKill.SwordState.Attack then
self._spiralAngle = self._spiralAngle + dt * 30 -- 螺旋角度
-- 残影效果(每0.05秒生成一个淡出精灵)
if self._afterImageTimer >= 0.05 then
local ghost = cc.Sprite:create() -- 创建残影
ghost:runAction(cc.Sequence:create({
cc.FadeOut:create(0.3),
cc.RemoveSelf:create()
}))
end
end
end
```
**四、怪物索敌系统(280-340行)**
```lua
function FeiJianSKill.getCanAttackMonster()
local nowMonsters = {}
local mainActor = maptools.getActor(SL:GetMetaValue("MAIN_ACTOR_ID"))
local nowX = mainActor:GetMapX()
local nowY = mainActor:GetMapY()
-- 遍历视野内怪物列表
for i, v in ipairs(SL:GetMetaValue("FIND_IN_VIEW_MONSTER_LIST")) do
local monster = maptools.getActor(v)
-- 检查怪物存活、可攻击、距离
if monster:GetHP() > 0 and SL:GetMetaValue("TARGET_ATTACK_ENABLE", monster:GetID()) then
if math.abs(monster:GetMapX() - nowX) <= 8 then -- 8格距离限制
table.insert(nowMonsters, monster)
end
end
end
return nowMonsters
end
```
**五、飞剑创建与管理(460-550行)**
```lua
function FeiJianSKill.addSword(actorId, swordInfo, skillId)
if swordInfo.id == 99 then -- GM版创建4把飞剑
local count = 4
swordInfo.node = {}
for i = 1, count do
local sword = FlyingSword.new(swordInfo, actorId, 80, 40, math.pi / 1.5, psData)
sword:setInitAngle(math.pi * 20 / i) -- 均匀分布角度
sword:setName(string.format("Sword_%d_%d", swordInfo.id, i))
table.insert(swordInfo.node, sword)
end
else -- 普通版创建1把飞剑
local sword = FlyingSword.new(swordInfo, actorId, 80, 40, math.pi / 1.5, psData)
sword:setInitAngle(math.pi * swordInfo.id / 2) -- 根据ID设置初始角度
sword:setName("Sword_" .. swordInfo.id)
swordInfo.node = sword
end
end
```
**六、地图限制逻辑(240-260行)**
```lua
-- 飞剑不生效地图列表
local feijian_bushengxiaomap = {
["盟重土城"] = 1,
["沙巴克皇宫"] = 1,
-- ...其他安全区地图
}
function FlyingSword:stateEnd()
-- 检查当前地图是否允许飞剑生效
if feijian_bushengxiaomap[SL:GetMetaValue("MAP_NAME")] ~= nil or SL:GetMetaValue("USER_IS_DIE") then
self:startIdle() -- 安全区或死亡时飞剑不动
return
end
-- ...正常状态切换逻辑
end
```
**七、事件系统(600-700行)**
```lua
-- 注册被动技能数据事件
SL:RegisterLUAEvent(LUA_EVENT_PASSIVE_SKILL_DATA, 'feiJian', function(data)
shuliang = tonumber(data.shuliang) or 11 -- 获取飞剑数量
onPassiveSkillData(data) -- 处理技能数据
end)
-- 注册网络消息(其他玩家飞剑命中)
SL:RegisterLuaNetMsg(1506, FeiJianSKill.onFeiJianHit, FeiJianSKill)
```
**八、定时器系统(680-700行)**
```lua
-- 创建定时器节点
local taskNode = cc.Node:create()
taskNode:setName("_task_node_")
rootF:addChild(taskNode)
-- 注册每帧更新
taskNode:scheduleUpdate(function(dt)
FeiJianSKill.tick(dt) -- 更新所有飞剑
end)
function FeiJianSKill.tick(dt)
nowMonsters = nil -- 清空怪物缓存
for k, v in pairs(allSwordInfo) do
if v.node then
if v.id == 99 then -- GM版更新多把飞剑
for i, n in ipairs(v.node) do
n:update(dt)
end
else -- 普通版更新单把飞剑
v.node:update(dt)
end
end
end
end
```
**核心设计模式总结:**
1. **状态机模式**:5种状态清晰管理飞剑行为
2. **对象池模式**:飞剑对象复用,避免频繁创建销毁
3. **观察者模式**:通过事件系统响应技能变化
4. **策略模式**:不同飞剑类型(单把/多把)不同行为
5. **缓存机制**:怪物列表缓存提升性能
**需要注意的细节:**
1. 第240行地图检查逻辑确保安全区飞剑不生效
2. 第350行贝塞尔曲线计算实现流畅飞行轨迹
3. 第382行残影效果增强视觉表现
4. 第460行GM版飞剑的特殊处理(4把同时存在)
这个系统展示了完整的游戏技能实现,包含状态管理、视觉效果、网络同步等关键要素。
← 返回问答库