【游戏功能】
先抛一个坑:大摆都荡完一个来回了,为什么还有人站在原地没挨刀?摆刃扫过的每一段都有它的账,站得对不对位子,决定这一刀落在谁头上。荡摆类玩法的全部学问是"读摆":摆荡到哪、下一拍扫哪,读得懂的人站进刀路里白捡,读不懂的人站着白挨。这篇把钟摆刃纹整套写法拆开:垂落起摆、荡身扫刃、来回两刀、收摆归鞘,一段一段照抄能跑。
一、效果演示
演示场钟楼的机括间里垂下一柄巨摆。点「落摆!」:巨摆从正中荡向右——摆刃扫过怪的身位一刀十四;荡到头又荡回来,回程再扫一刀,一个来回两刀二十八。摆刃的弧线贴着地皮扫过头脸的高度,怪在刀路里躲不开,站错了位子就得认。九秒一落,读摆的人掐着荡的拍子引怪进刀路。
flowchart TD
A[点落摆] --> B[巨摆垂落起摆]
B --> C[荡向右扫过身位]
C --> D{扫过怪身了吗}
D -- 扫过 --> E[一刀十四]
D -- 没扫到 --> F[荡到头折返]
E --> F
F --> G[回程再扫一刀]
G --> H[收摆 九秒后再落]
二、底层原理
钟摆的机关是"弧线扫刃"——摆刃从顶点的机括垂下,荡过一个来回,扫过怪的身位两刀。荡摆的账跟着摆角走:摆角从零荡到右极、再荡回左极,摆刃的横坐标压过怪身位的那两拍各结一账。读摆是玩家的功课:摆荡的节奏是匀的,进刀路的时机自己挑——挑回程那一刀的,是会读摆的人。
摆刃的高度是章法的细节:垂长三百年、荡到怪身位时刃口正好扫在头脸的高度——压头不压脚,刀从脸前过。机括间的铁柱背景衬出摆的分量:巨摆从楼顶垂下来,荡的就是钟楼的分量。幂尔框架这边摆角收在每拍推进里,扫中的判定读摆刃横坐标压没压过身位,两刀各结各的账不合并。
这套玩法的代码量不到八十行,难的不是荡而是读——摆的节奏匀得像钟,读得懂的人把怪引进刀路,读不懂的人自己站在刀路里。
再看回程那一刀为什么不少——单程一刀的摆只是扫堂,来回两刀的摆才读得出"摆的往复":去时一刀是明枪,回时一刀是暗箭,怪躲过去程常常栽在回程。往复的两刀也是对"读摆"功课的考试:读完去程读回程,两刀都躲开的人才配站在这间机括间里。
三、核心代码:完整模块(上·骨架)
-- @file CrestPendulum.lua
-- 钟摆刃纹 —— 大摆荡过来 站错位子挨一刀
local CrestPendulum = {}
local CONST = {
SWING_TIME = 1.6,
SWING_AMP = 0.9,
PIVOT_X = 330,
PIVOT_Y = -12,
ARM_LEN = 300,
BLADE_DMG = 14,
BLADE_BAND = 26,
PEND_CD = 9,
AUTOINC_BASE = 1206200,
}
local _on = false
local _t = 0
local _hit1 = false
local _hit2 = false
local _cd = 0
local _autoInc = 0
local function ShowTip(msg)
if msg and msg ~= "" then SL:ShowSystemTips(msg) end
end
local function GenID()
_autoInc = _autoInc + 1
return CONST.AUTOINC_BASE + _autoInc
end
function CrestPendulum.On() return _on end
-- 落摆
function CrestPendulum.Drop()
if _cd > 0 then
ShowTip("机括还在回卷——再等" .. math.ceil(_cd) .. "秒")
return
end
_cd = CONST.PEND_CD
_on = true
_t = 0
_hit1 = false
_hit2 = false
ShowTip("巨摆垂落——看准它扫过身位的时机")
end
四、核心代码:完整模块(下·推进与卸载)
-- 每拍推进: 摆角走一个来回 两刀各结各账
if not _ticker then
_ticker = SL:Schedule(function(dt)
if _cd > 0 then _cd = _cd - dt end
if not _on then return end
_t = _t + dt
local sw = math.sin(_t / CONST.SWING_TIME * 6.28)
* CONST.SWING_AMP
local bx = CONST.PIVOT_X + math.sin(sw) * CONST.ARM_LEN
local mobX = SL:GetValue("mobX") or 0
if math.abs(bx - mobX) < CONST.BLADE_BAND then
if not _hit1 and _t < CONST.SWING_TIME / 2 then
_hit1 = true
ShowTip("摆刃扫中——" .. CONST.BLADE_DMG)
end
if _hit1 and not _hit2 and _t >= CONST.SWING_TIME / 2 then
_hit2 = true
ShowTip("回摆又一刀——两刀入账")
end
end
if _t >= CONST.SWING_TIME then
_on = false
ShowTip("摆收了——九秒后再落")
end
end, 0.02)
end
SL:ScheduleOnce(function()
SL:BindDebugButton("落摆!", function()
CrestPendulum.Drop()
end)
ShowTip("技能已加载: 钟摆刃纹")
end, 1.0)
function CrestPendulum.Unload()
if _ticker then SL:Unschedule(_ticker) end
_on = false
end
return CrestPendulum
五、机制问答
问:荡完一个来回没挨刀的人做对了什么?
答:读摆——摆荡的节奏是匀的,进不进刀路自己挑,读得懂就白捡。
问:回程那一刀算什么?
答:暗箭——去时明枪回时暗箭,躲过去程常栽在回程。
问:摆刃的高度为什么定在头脸?
答:压头不压脚——刀从脸前过,荡的分量才配得上钟楼。
问:两刀为什么不合记一账?
答:去明回暗各是各的功课——合记一账,读摆的考试就少考一半。
问:九秒一落管什么?
答:巨摆的分量——落摆随便落的机括间,摆就成了背景装饰。
六、调参与实战怎么用
参数层面三个量——荡周期、摆幅、刃带宽度。一秒六荡一个来回配零点九弧度摆幅是"读得出躲得开"的线:再快成转门再慢成摇篮。实战里这套弧线扫刃的骨架能搬去吊镰、巨斧机关、城中钟摆,全是垂落、荡身、来回两账一条线。常见坑两个:两刀合一账少考一半功课;摆刃高度定在脚脖子,荡的分量全无。
补充一个设计层面的思考——攻防的账要分"压头"和"压脚"两笔:砸头脸的招吃的是措手不及,扫下盘的招吃的是站稳与否,两笔账的躲法不同、赏法也不同。一套战斗里两类招都备着,玩家才会抬头看低头看两头兼顾——只教一种躲法的战斗,练到后来只剩一种反应。
补充一个维护层面的思考——带机括节奏的招(连发、歇息、回填)要把节奏写成状态而不是写成延时串:连发是一态、歇息是一态、第二轮是一态,态与态的切换写在推进口里。串延时的版本多跑两轮就对不上拍——状态机的账怎么翻都对,延时串的账翻两页就乱。
补充一个工程层面的思考——弹道和牵引类的运动体在目标消失时要"就地收势":刃坠地、鸢归天、箭坠土,各自的收势演完账就清。运动体没收势就复用,新的一发会继承旧的残影和旧的目标——收势是运动体的卸载口,卸载口不在,运动体就是幽灵。
补充一个到达层面的思考——这六式招式各有一套到达的写法:滚石贴地碾过去、纸鸢从天上扎下来、钟摆走弧线来回扫、认踪矢拐弯追、双蛟绞着麻花游、机括匣点射轮转。到达方式就是招式的身份:改伤害容易改到达难,到达一改就成了另一个招。调招先调到达的节奏,数值放到最后一步。
写完留一句给做机关摆的同学:玩家读的是摆也是自己的位子——来回两刀各结各账,读摆的人才配站在机括间。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
【游戏功能】 隐蔽报错引入:一个很隐蔽的报错——机括匣的箭放完了还在放,匣里的箭明明只有六支,账面上却射出了第十七支:轮次的…
【游戏功能】 线上事故引入:早上水渠的双蛟出了怪相——两条蛟游着游着绞成了一股,分不出你我,双蛟的账记成了单蛟的翻倍。双蛟各…
【游戏功能】 单行代码拆解:先看一行代码: 箭头,往它那里挪一点 ——认踪矢的全部机关就这一行:箭每飞一拍,箭头的朝向往怪的…
【游戏功能】 先抛一个坑:大摆都荡完一个来回了,为什么还有人站在原地没挨刀?摆刃扫过的每一段都有它的账,站得对不对位子,决定…
【游戏功能】 隐蔽报错引入:一个很隐蔽的报错——纸鸢扎下来扎的是怪的脚后跟,明明瞄准的是头脸。鸢的俯坠路径读的是怪的脚下坐标…
【游戏功能】 线上事故引入:早上山道的滚石机关出了糗——石碾滚过去把怪顶退四十步,一步没刹住推出了战场地皮,半只身子挂在世界…