【语法算法】
上个月一场闪了全屏的事故成了组里的教材:受击闪白上线第一天,玩家一挨打整个界面白一遍——血条、按钮、聊天框全泡在白光里,半秒后才缓过来。追到底是白层的父节点挂错了地方:白层本该叠在怪的身上,结果挂在了全屏层,怪一挨打全屏陪闪。修完立了规矩:白层的父节点必须挂在怪的挂点上,范围跟怪走。这篇把整改后的整套写法拆开:配置表、白层创建、叠层结算、渐隐推进、定时器、调试按钮,一段一段照抄能跑。
一、效果演示:叠加渐隐的一层白
演示场一只蓝色轮廓的怪。点「打一下」:白层当场叠上怪的轮廓——只盖怪,一点不外溢,透明度从高点一路往下衰减,一秒半内渐隐归零。连着快点:白层一层叠一层,透明度往上抬但封死在一,连续挨打的怪白得更实、褪得更匀。左上角实时播报白层的透明度读数。演示里试两笔账:叠层连打和单发的白层留存时间——叠层的白是续命不是重置,连打不闪瞎眼。受击闪白教的是克制:白是反馈,不是闪光弹——反馈的分寸感,全在这一层白的厚薄和褪速里。
flowchart TD
A[命中发生] --> B[白层透明度加一档]
B --> C{超过封顶一了吗}
C -- 是 --> D[钉死在一]
C -- 否 --> E[逐拍渐隐]
D --> E
E --> F{透明度归零}
F -- 否 --> E
F -- 是 --> G[白层歇着 待下次命中]
fx-flashwhite
二、底层原理:一次叠层结算加一阶透明渐隐
模块的机关是一对搭档。叠层结算:命中的那一拍白层透明度往上涨一档——涨有封顶,封顶之后多挨的刀只续不叠,白得实但不会白成一片空白。透明渐隐:白层每一拍按固定的速率往下衰减——衰减是线性的,从峰值到归零一秒半,褪得匀才不闪眼。和特效类闪光的分野在"闪白是一层覆盖不是一次爆发":爆闪是亮一下就完,闪白是一层白盖上去慢慢褪——反馈的强度可以叠,褪去的速度始终匀速,眼睛才不累——眼睛是这套纹的唯一裁判,护住眼睛就护住了手感。
透明度为什么封顶在一?不封顶的版本白层叠加往上是加法,连打十刀白层指数涨,直接糊成过曝的一片;封顶一之后叠层的收益只有"白得更久",视觉的上限锁死在一,怎么打都不糊屏——封顶是这套纹最省心的保险,装上就不想拆。
三、核心代码:完整模块(上·骨架)
-- @file FlashWhite.lua
-- 受击闪白 —— 叠加渐隐的一层白
local FlashWhite = {}
local CONST = {
HIT_STEP = 0.35,
ALPHA_CAP = 1.0,
FADE_SPEED = 1.5,
AUTOINC_BASE = 1156000,
}
local _alpha = 0
local _whiteFx = nil
local _hostNode = nil
local _scheduler = nil
local _autoInc = 0
local function GenID(prefix)
_autoInc = _autoInc + 1
return string.format("%s_%d", prefix or "FWS",
CONST.AUTOINC_BASE + _autoInc)
end
local function ShowTip(msg)
if msg and msg ~= "" then SL:ShowSystemTips(msg) end
end
function FlashWhite.Alpha()
return _alpha
end
function FlashWhite.BindHost(node)
_hostNode = node
end
local function EnsureLayer()
if _whiteFx and not GUI:Widget_IsNull(_whiteFx) then
return
end
if not _hostNode or GUI:Widget_IsNull(_hostNode) then
return
end
_whiteFx = GUI:Layout_Create(_hostNode,
GenID("White"), 0, 0, 0, 0, false)
GUI:setLocalZOrder(_whiteFx, 200)
GUI:setContentSize(_whiteFx,
GUI:getContentSize(_hostNode))
end
四、核心代码:完整模块(下·叠层结算与渐隐推进)
-- 叠层结算:命中那一拍白层涨一档
SL:RegisterLUAEvent(LUA_EVENT_HURT_TAKEN, "FWS_Hit", function()
EnsureLayer()
if not _whiteFx then return 0 end
_alpha = math.min(CONST.ALPHA_CAP, _alpha + CONST.HIT_STEP)
return 0
end)
-- 渐隐推进:白层每一拍匀速往下褪
if not _scheduler then
_scheduler = SL:Schedule(function(dt)
if _alpha <= 0 then return end
_alpha = math.max(0, _alpha - CONST.FADE_SPEED * dt)
if _whiteFx and not GUI:Widget_IsNull(_whiteFx) then
GUI:setOpacity(_whiteFx,
math.floor(_alpha * 255))
end
if _alpha <= 0 then
SafeRemove(_whiteFx)
_whiteFx = nil
end
end, 0.02)
end
local function SafeRemove(node)
if node and not GUI:Widget_IsNull(node) then
GUI:removeFromParent(node)
end
end
SL:ScheduleOnce(function()
SL:BindDebugButton("打一下", function()
FlashWhite.Hit()
end)
ShowTip("技能已加载: 受击闪白 (调试按钮触发)")
end, 1.0)
function FlashWhite.Hit()
SL:FireEvent(LUA_EVENT_HURT_TAKEN)
end
function FlashWhite.Unload()
if _scheduler then SL:Unschedule(_scheduler) end
SafeRemove(_whiteFx)
_alpha = 0
end
return FlashWhite
五、机制问答
问:白层的父节点为什么必须挂在怪身上?
答:范围跟怪走——挂全屏层的版本怪一挨打全屏陪闪,那场事故的根就是父节点挂高了,白层的活动范围永远跟着宿主。
问:连打十刀会白成一团吗?
答:不会——透明度封顶在一,叠层只续时长不涨亮度,白得实但永远透得出怪的轮廓。
问:渐隐的速度能快过打击频率吗?
答:能——衰减速率独立于命中频率,刀快就白层不断,刀慢就白层断续,节奏自然跟着战斗走——刀快白密,刀慢白疏,闪白的呼吸和战局的呼吸是同一口气。
问:白层会挡住怪的血条吗?
答:看层级——白层的层级压在血条之下就互不干扰,层级挂错了血条也被刷白,这也是挂点检查的一部分——白层压谁不压谁,挂的那一拍就要想清楚。
问:同一帧挨两刀会叠两档吗?
答:会——同帧的两刀各涨一档,封顶兜着不会爆,这也是连打的白更实的由来。
六、调参与实战怎么用
第四笔是挂点的父节点:白层必须挂在怪的挂点下是那场全屏事故的整改——挂点检查要写进创建的第一行,白层的活动范围跟着宿主走,出了宿主的白层都是事故。第三笔是渐隐的速度:一秒半褪完是"看得见褪"的速率——褪太快白层像没有,太慢连打几刀屏上常年蒙白,一秒半刚好在两刀的间隙里褪干净。第二笔是叠层的封顶:透明度钉死在一是最便宜的保险——封顶的意义在锁死视觉上限,叠多少刀都不糊屏。第一笔是白层的范围:白层尺寸随宿主内容尺寸初始化——范围写死的话换一只大怪就盖不全,范围跟宿主走才叫叠在身上。常见坑三个:白层父节点挂全屏的全屏陪闪事故;透明度叠加无封顶的过曝;白层残件没摘导致怪死后悬空一层白。
实战里受击闪白是打击反馈的标配三件头之一:顿帧管节奏、闪白管确认、击退管位移,三件各管一段互不抢戏。组里的约定是:凡是要"让玩家确认打中了"的表现,闪白是第一顺位——便宜、直接、不抢镜。这篇的模块照抄能跑,改的就是 CONST 那张表。
写完留一句给做反馈系的同学:受击闪白卖的是"打中的那一眼确认"——那层只盖在怪身上渐隐的白,是把命中从数据变成肉眼可见的一层薄薄的白。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
【语法算法】 上一版的炮台索敌逻辑有个隐蔽报错:炮台永远打同一个怪——即使那只怪已经死了,索敌的游标也不挪窝。追到底索敌的游…
【语法算法】 先抛一个坑:打不完的火系怪怎么办?火抗怪火打不动,换冰系技能要切装备要换面板——切完黄花菜都凉了。元素转换的答…
【语法算法】 上个月的事故复盘会上有个数字被念了三遍:四成——策划写的是"同伴陪疼四成",代码落下去成了"陪疼四十点",两只…
【语法算法】 单行代码拆解:弹射初速=-420——弹射的全部动力就这一行的负初速。负号朝上、四百二十是弹射的初速大小——踩上…
【语法算法】 上一版的减速类模块全按"乘以零点五"来写,帧率无关的版本照搬了这套写法——结果高帧率机上减速效果好,低帧率机上…
【语法算法】 先抛一个坑:怎么把散在四处的怪聚到一起打?逐个拉是笨办法,一个范围技又只能打一片——引力球的答案是一个会动的吸…