【游戏功能】
隐蔽报错引入:一个很隐蔽的报错——壶明明还在半空飞着,落地的水花已经溅了,地上的壶影甚至比壶先落地。壶的飞行、壶影、落地的水花,三样各走各的表。抛物道具的三样画面必须一根线串着:影在壶下、花在壶落、账在花溅。这篇把掷壶溅纹整套写法重写成篇:高抛出手、壶影追地、落地开花、湿身加痛,一段一段照抄能跑。
一、效果演示
演示场是泥沼边的战场。点「掷壶!」:酒壶高高抛出,划一道大弧,地上的壶影追着壶跑——影到壶到,落地一声炸开,二十点水花拍在怪身上,还溅它一身湿。湿着的五秒里,你的每一刀都多八点——湿皮嫩肉,刀刀入得深。六秒一壶,掐着湿身的五秒打,湿干之前多砍两刀。
flowchart TD
A[点掷壶] --> B[壶出手高抛]
B --> C[壶影追地]
C --> D{影到壶到了吗}
D -- 到了 --> E[落地开花]
E --> F[二十入账]
F --> G[溅湿五秒]
G --> H[湿身挨刀多八]
H --> I[晾干回原价]
I --> A
fx-crest-jar
二、底层原理
掷壶系统的机关是"三样一根线"——壶身、壶影、水花共用同一根进度线:进度走一成,壶飞一成、影挪一成,进度走满,花才溅、账才落。那场影先落地的报错就是三样三张表:壶按抛物线走、影按自己的速度跑、水花按心情炸。正解是一根进度管三样,谁也不许自己掐表。
湿身是掷壶的后手账:砸二十是明账,溅湿的五秒里刀刀加八是暗账——明账管当下,暗账管接下来五秒的打法。湿身的画面语言要足:怪身上一层蓝汪汪的光晕,湿字倒计时挂在头上,玩家一看就知道这几刀该抠着湿身打。幂尔框架这边进度线收在出壶口,落地那一拍同时炸花、落账、盖湿——三件事一根线,谁也不抢跑。
这套玩法的代码量不到八十行,难的不是抛物线而是三样一根线——影比壶快半步,戏就穿帮了。
再看壶影为什么要画在地上追着跑——抛物道具最怕的是"高度错觉":壶飞得高,玩家不知道它会落在哪。壶影就是落点的预告:影在哪壶就往哪落,落地时影壶重合——玩家从壶出手那一瞬就能预判落点,闪不闪得开心里有数。投影预告是抛物道具的礼数:落点不告诉人,砸中了也砸得糊涂。
三、核心代码:完整模块(上·骨架)
-- @file CrestJar.lua
-- 掷壶溅纹 —— 壶落开花 湿身挨刀更疼
local CrestJar = {}
local CONST = {
FLY_TIME = 0.9,
JAR_DMG = 20,
WET_TIME = 5,
WET_BONUS = 8,
DMG_BASE = 14,
JAR_CD = 6,
AUTOINC_BASE = 1203900,
}
local _flying = false
local _flyT = 0
local _wet = 0
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 CrestJar.Wet() return _wet end
function CrestJar.Dmg()
if _wet > 0 then return CONST.DMG_BASE + CONST.WET_BONUS end
return CONST.DMG_BASE
end
四、核心代码:完整模块(下·推进与卸载)
-- 掷壶: 一根进度管三样
function CrestJar.Throw()
if _cd > 0 then
ShowTip("壶还没出手——再等" .. math.ceil(_cd) .. "秒")
return
end
_cd = CONST.JAR_CD
_flying = true
_flyT = CONST.FLY_TIME
ShowTip("壶出手——高抛看落点")
end
-- 落地那一拍: 炸花 落账 盖湿 同一拍
function CrestJar.OnLand()
_wet = CONST.WET_TIME
ShowTip("壶落开花——溅湿" .. CONST.WET_TIME
.. "秒,湿身挨刀多" .. CONST.WET_BONUS)
return CONST.JAR_DMG
end
if not _ticker then
_ticker = SL:Schedule(function(dt)
if _cd > 0 then _cd = _cd - dt end
if _wet > 0 then _wet = _wet - dt end
if not _flying then return end
_flyT = _flyT - dt
if _flyT <= 0 then
_flying = false
CrestJar.OnLand()
end
end, 0.02)
end
SL:ScheduleOnce(function()
SL:BindDebugButton("掷壶!", function()
CrestJar.Throw()
end)
ShowTip("技能已加载: 掷壶溅纹")
end, 1.0)
function CrestJar.Unload()
if _ticker then SL:Unschedule(_ticker) end
_flying = false
_wet = 0
end
return CrestJar
五、机制问答
问:影子比壶先落地的戏穿在哪?
答:壶身壶影水花三张表——正解是一根进度管三样,谁也不许自己掐表。
问:壶影追地追的是什么?
答:落点的预告——影在哪壶往哪落,玩家从出手那瞬就能预判,砸得明白。
问:湿身的五秒给了玩家什么?
答:暗账——砸二十是明账,湿着的刀刀加八是接下来五秒的打法。
问:湿身的画面语言做足了吗?
答:蓝光晕加倒计时——玩家一看就知道这几刀该抠着湿身打。
问:湿身的效果能叠吗?
答:不能——五秒没晾干再泼一壶,湿从头算不叠加,账面永远只有一层湿。
问:落地那一拍同时做三件事,顺序怎么排?
答:炸花、落账、盖湿同一拍——一根线的三样,谁也不抢跑。
六、调参与实战怎么用
参数层面三个量——飞行时长、湿身时长、湿身加痛。九分之一的抛弧高度配五秒湿身是标准壶:弧太高等得烦,湿太短追不上。壶的出手高度也照着画面上沿留余地:弧顶快要顶出画框的壶,砸得再准也像在打画外音。实战里这套一根线的骨架能搬去火油罐、毒葫芦、震天雷,全是高抛、追影、同拍落账一条线。常见坑两个:三样三张表互相抢跑;落点不预告,砸中也是糊涂账。
补充一个设计层面的思考——出招的动作语言要和招的性质说一回事:绳就该有绳的弧线、壶就该有壶的抛物线、浪就该有浪的推进,玩家看动作就能猜到招怎么算。动作和数值两张皮是最伤的——看着是重锤结果是挠痒,看着是轻挑结果瞬杀,玩家对出招的信任就这么散的。
补充一个维护层面的思考——动作进行中的状态(飞行中的壶、钻地的一半、索飞的半程)要在换怪和重开时收干净:飞到一半的壶落地不落账、钻到一半的人卡在土里,都是阶段切换没扫尾。每一类飞行物配一句"到点没对象就作废"的清理,换多少次场都不留悬案。
补充一个工程层面的思考——位移类的演出要让位移的起点和终点都有交代:从哪起、到哪落、落地站哪,三问各有答案再动手。位移是所有演出里最容易穿模穿边界的,起落说不清的位移宁可拆成两段演,也别让人物在两帧之间瞬移到图外面去。
写完留一句给做抛物系的同学:玩家追的是壶也是那道追地的影——一根进度管三样,落点预告了,砸才砸得明明白白。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
接手二开的兄弟几乎都撞过同一堵墙:玩家嫌走路"一格一格像机器人",老板拍板要"丝滑移动",改服务端速度?不对。改客户端动画帧…
【游戏功能】 先看一个熟场面:法师的火球特效挂在怪的脚后跟上,明明技能说明写着"焚烧其面",火星子却在地上打滚。群里有位策划…
【游戏功能】 上周有个开服的老板在群里发了一段录屏:他的战士明明刀刀都砍中了,观众却一片"这刀挥空了吧"。他原话是"判定日志…
【游戏功能】 先说结论放在开头:怪的皮一会儿绿一会儿红,不是美术换了几套贴图,是染色系统在怪身上盖了一层"色镜"。开服群里有…
前两天群里有个架设的朋友问了个需求:中毒的人要变绿、每两秒掉一次血、毒还能叠五层,问是不是要在服务端把整套状态机重写。我说你…
【游戏功能】 先抛一个坑:五口钟一模一样大,为什么一口比一口疼?先后次序动不得吗?倒过来敲会怎样?这篇把编钟纹整套写法拆开:…