【游戏功能】
单体射击的瓶颈是"只有一路"。分裂箭把一路变三路:主箭半途裂成三支扇面,左中右各十二——打在一只身上三十六集中输出,打在三只身上各十二分兵扫场。这篇的核心代码照引擎技能脚本的全规格写:配置表、主箭构件、分裂分叉、定时器、调试按钮。
一、效果演示:一支出去,三支回来
演示场点「分裂箭!」:主箭搭弦射出——半场的中间点箭身一亮"分裂!",一支变三支:左箭偏上、中箭直走、右箭偏下,扇面铺开。三支各十二齐扎在大怪身上——三十六的集中账。演示里看三支箭的扇面张角:中间那支笔直、两翼各偏十五度——扇面的宽度就是覆盖的范围,三路齐发对单体的爆发和对群体的覆盖是同一个技能的两副面孔。扇面的宽度就是覆盖的范围,分裂的中点取两座的中点——裂点离怪越近扇面越窄、三支越容易全中,裂点离怪越远扇面越散。三路齐发对单体的爆发和对群体的覆盖是同一个技能的两副面孔——中箭直走的二十五如果全中是集中输出,三支散开就是覆盖输出,打一只还是打三只看站位。扇面的三支箭各自独立命中——中箭笔直打脸、两翼各扎侧腰,三支全中的账面是集中三十六,只中一支是分散十二。
fx-splitarrow
二、底层原理:一支主箭加一次分叉
模块的机关是两段。主箭段:单支箭从玩家出手直线飞——飞到两座中点触发分叉。分叉段:主箭出表、三支子箭入表——子箭各带横速相同纵速不同的速度向量,中箭笔直、两翼各偏一个纵速。分裂点的判定写 "主箭横坐标过中点即裂"——裂点的位置由两座间的中点决定,站位远近改变的是裂点距怪的距离,扇面的张角不变。子箭的命中各自独立结算——三支全中是集中三十六,只中一支是分散十二,命中数玩家自己控制。
三、核心代码:完整模块(上·骨架)
--------------------------------------------------------------------------------
-- @file SplitArrow.lua
-- @brief 分裂箭 —— 一支裂三支,扇面三路齐发
-- 客户端表现模块:配置表 / 箭矢构件 / 分叉状态机 / 定时器
--------------------------------------------------------------------------------
local SplitArrow = {}
--------------------------------------------------------------------------------
-- 配置与常量
--------------------------------------------------------------------------------
local CONST = {
SPLIT_CD = 3.5, -- 分裂箭冷却
ARROW_SPEED = 320, -- 箭速三百二
SUB_DMG = 12, -- 子箭十二
FAN_SPREAD = 90, -- 两翼纵速差九十
AUTO_DMG = 10, -- 平射十
-- 颜色
COLOR_ARROW = "#d8c078", -- 分裂金
COLOR_DEEP = "#6b5a2b", -- 深金
COLOR_GHOST = "#f5eed8", -- 箭白
ZORDER_GROUND = 118,
ZORDER_ARROW = 133,
ZORDER_EFFECT = 135,
AUTOINC_BASE = 965000,
}
--------------------------------------------------------------------------------
-- 模块内部状态
--------------------------------------------------------------------------------
local _arrows = {} -- 箭表
local _cdLeft = 0
local _autoT = 0
local _scheduler = nil
local _autoInc = 0
local m_cos = math.cos
local m_sin = math.sin
--------------------------------------------------------------------------------
-- 辅助函数
--------------------------------------------------------------------------------
local function GenID(prefix)
_autoInc = _autoInc + 1
return string.format("%s_%d", prefix or "SPA", CONST.AUTOINC_BASE + _autoInc)
end
local function GetActorPos(actorID)
if not actorID then return nil end
local x = SL:GetValue("ACTOR_POSITION_X", actorID)
local y = SL:GetValue("ACTOR_POSITION_Y", actorID)
if not x or not y then return nil end
return { x = x, y = y }
end
local function SafeRemove(node)
if node and not GUI:Widget_IsNull(node) then
GUI:removeFromParent(node)
end
end
local function ShowTip(msg)
if msg and msg ~= "" then SL:ShowSystemTips(msg) end
end
---箭矢构件:主箭金杆、子箭白杆
local function CreateArrowNode(isMain)
local node = GUI:Layout_Create(GUI:Attach_SceneF(), GenID(isMain and "Main" or "Sub"),
0, 0, 0, 0, false)
GUI:setLocalZOrder(node, CONST.ZORDER_ARROW)
local col = isMain and CONST.COLOR_ARROW or CONST.COLOR_GHOST
GUI:DrawLine_Create(node, "shaft", 0, 0, 2, -10, 0, 10, 0, col, 240)
GUI:DrawLine_Create(node, "head", 0, 0, 3, 10, 0, 5, -3, col, 240)
GUI:DrawLine_Create(node, "head2", 0, 0, 3, 10, 0, 5, 3, col, 240)
return node
end
骨架的三处立规。箭表的主箭和子箭共用一张表——主箭裂的时候从表里删自己、往表里塞三支子箭,进出同一张表分叉才不会漏箭。箭矢构件的箭头用两笔斜线画——三角箭头加一笔箭杆就是箭,画得太复杂飞行时看不清。分裂的中点取两座的中点——裂点距离怪三十步左右,三支子箭刚好在怪的碰撞盒上散开。
四、核心代码:完整模块(下·定时器与分裂分叉)
--------------------------------------------------------------------------------
-- 分裂箭入口
--------------------------------------------------------------------------------
function SplitArrow.Cast()
if _cdLeft > 0 then return end
_cdLeft = CONST.SPLIT_CD
local mp = GetActorPos(SL:GetValue("USER_ID"))
local tp = GetActorPos(SL:GetValue("MARK_TARGET_ID"))
if not mp or not tp then return end
local midX = (mp.x + tp.x) / 2
table.insert(_arrows, { x = mp.x + 16, y = mp.y - 58,
vx = CONST.ARROW_SPEED, vy = 0, main = true, mid = midX,
node = CreateArrowNode(true) })
ShowTip("主箭出去了——半途裂三支")
end
--------------------------------------------------------------------------------
-- 定时器:主箭推进、分叉与子箭结算
--------------------------------------------------------------------------------
if not _scheduler then
_scheduler = SL:Schedule(function(dt)
_cdLeft = math.max(0, _cdLeft - dt)
for i = #_arrows, 1, -1 do
local a = _arrows[i]
a.x = a.x + a.vx * dt
a.y = a.y + a.vy * dt
if a.main and a.x >= a.mid then
SafeRemove(a.node)
table.remove(_arrows, i)
for s = -1, 1 do
table.insert(_arrows, { x = a.mid, y = a.y,
vx = CONST.ARROW_SPEED, vy = s * CONST.FAN_SPREAD,
main = false, node = CreateArrowNode(false) })
end
SL:TipAboveAt(a.mid, "分裂!")
elseif not a.main then
local tid = SL:GetValue("MARK_TARGET_ID")
local tp = tid and GetActorPos(tid)
if tp and math.abs(a.x - tp.x) < 18 and math.abs(a.y - (tp.y - 50)) < 50 then
SL:ActorHurt(tid, CONST.SUB_DMG)
SL:TipAbove(tid, "-" .. CONST.SUB_DMG)
SafeRemove(a.node)
table.remove(_arrows, i)
end
end
if a.x > 700 then
SafeRemove(a.node)
table.remove(_arrows, i)
end
end
end, 0.02)
end
SL:ScheduleOnce(function()
ShowTip("技能已加载: 分裂箭 (调试按钮触发)")
end, 1.0)
return SplitArrow
下半场的分叉是全模块的开关:主箭横坐标过中点的判定一行——过了就自删、塞三支子箭、弹分裂提示,三步一口气。子箭的命中走独立的碰撞盒——纵速不同导致三支箭的飞行轨迹各不相同,各自的碰撞各自查。出界的子箭走横坐标超限的分支清理——三支箭各飞各的,哪支出界哪支删,不因为其他两支还在飞而留着。
五、调参指南与商业服怎么用
调参三笔账。子箭十二对三支全中三十六——集中产值为平射的一点二倍,倍率太低玩家只用平射,太高平射被淘汰;一点二倍是"值得按但不强制"的甜区。扇面纵速差九十对半场宽度是三路的覆盖范围——纵速差太大三支箭散出屏外,太小三支箭叠成一团。扇面纵速差九十对半场宽度是三路的覆盖范围——纵速差太大三支箭散出屏外,太小三支箭叠成一团。分裂箭的音效也要分主箭和子箭——主箭一声弦响、子箭三声破空,听声就知道裂了几支。分裂中点取两座中点——中点近怪则三支同时扎到,中点远怪则扇面散开只中一支,裂点的远近就是集中与分散的旋钮。常见坑三个:分叉的瞬间主箭没删干净,主箭继续飞变成四支;子箭的纵速只加了正号,扇面只往上半开;分裂的提示和音效共用主箭的,主箭和子箭分不清。
商业服里分裂箭是"弓手流派"的第一课:单体平射和分裂扇面两种模式教会弓手"什么时候该分散",弓手的操作深度从第一支分裂箭开始。弓手的操作深度从第一支分裂箭开始。分裂箭的冷却三点五秒对平射一点四秒留两秒的回档——分裂箭是重拳、平射是轻拍,轻重交替才是弓手的完整循环。分裂箭是"弓手流派"的第一课:单体平射和分裂扇面两种模式教会弓手"什么时候该分散",弓手的操作深度从第一支分裂箭开始。分裂箭的箭羽音效也要分主箭和子箭——主箭一声闷、子箭三声脆,听声就知道箭裂了。商城里分裂箭的箭羽做成品级——白羽、凤羽、龙羽,三支扇面齐发的那一帧就是箭羽的海报帧。变体做成五路分裂:五支扇面覆盖更大但单支伤害砍半——覆盖与集中之间多了一档选择。这一篇的演示和整套模块照抄能跑,改的就是 CONST 那张表。
写完留一句给做投射系的同学:分裂箭卖的是"一支变三支的展开感"——扇面张开的那个瞬间,玩家的输出从一条线变成了一张网。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
【游戏功能】 控制技能的镜像问题是:锁住了怪,自己是不是也闲着?影锁把这道两难摆上台面:影锁四秒,它动不了、你也动不了——它…
【游戏功能】 打断为什么只有"清读条"一种?震魂偏要反过来——不清招、不断势,打在它读条半途的那一劲顺着招震进腑——中劲十秒…
【游戏功能】 蜂群为什么总是一只一只出?蜂王偏要让它们进化:放一只蜂王出来,杀掉小怪喂它——喂三只升一阶,三阶蜂王的毒刺一秒…
【游戏功能】 技能为什么总是不扣自己的血?血刃偏要反着来:开着血刃的每一刀先扣自己二血、命中回三血——净赚一但要打得中,空刀…
【游戏功能】 bn.t = bn.t - dt ——一行旗面倒计时的代码,撑起了破军旗全部的紧迫感:旗立三秒、圈内加攻三成,…
【游戏功能】 淬毒为什么要一毒到底?淬毒刃偏要一层一层叠:一刀淬一层毒、毒层一秒六地烂,六层封顶之后一刀下去毒伤三十六——叠…