02 Oct, 2025

Skydimo 脚本开发完全指南

欢迎来到 Skydimo 脚本开发世界!本指南将帮助您从零开始学习如何使用 Lua 脚本创建自己的 RGB 灯效,无论您是初学者还是高级用户。该功能在 Skydimo 内测版本推出。

目录


功能概览

  • 自由创作:用 Lua 代码编写独一无二的灯效
  • AI 辅助:一句话生成专属灯效,AI 帮您编写和优化代码
  • 音频响应:让灯光随音乐律动,支持实时 FFT 频谱分析
  • 多标签管理:同时编辑多个脚本,轻松切换和组织
  • 热更新:修改即刻生效,无需重启软件
  • 导入导出:分享您的创作,或使用社区脚本
  • 完全控制:速度、亮度、色温、色调一应俱全

快速入门

第一个脚本:彩虹渐变

在 Skydimo → “脚本”页面,新建脚本并输入:

function get_color(x, y, width, height, env)
    -- 根据位置和时间生成彩虹色
    local hue = (x / width * 360 + env.time * 60) % 360
    return hsv(hue, 255, 255)
end

操作步骤:

  1. 点击右上角“注册模式”按钮(右上角按钮从左到右一次为注册模式/更新模式、恢复、注销、导出、导入)
  2. 在模式列表中找到刚注册的脚本
  3. 点击启用,设备将显示流动的彩虹渐变效果

代码解析:

  • get_color:每个像素调用的函数
  • x / width:生成 0–1 的位置比例
  • env.time:不断增长的时间值,让颜色流动
  • hsv():将色相、饱和度、亮度转换为 RGB 颜色

Lua 脚本基础

什么是 Lua?

Lua 是一种轻量级、易学的编程语言。Skydimo 使用 Lua 5.4 版本。

基本语法速查

-- 单行注释

--[[
  多行注释
  可以写多行
]]

-- 变量定义(不需要声明类型)
local speed = 100
local name = "Rainbow"
local enabled = true

-- 数学运算
local result = (10 + 5) * 2 / 3

-- 条件判断
if x > 10 then
    -- 执行代码
elseif x == 5 then
    -- 另一种情况
else
    -- 默认情况
end

-- 循环
for i = 1, 10 do
    -- 重复 10 次
end

-- 函数定义
local function calculate(a, b)
    return a + b
end

核心接口规范

必选函数:get_color(x, y, width, height, env)

作用:为每个 LED 灯珠计算颜色值(每帧调用多次)

参数:

  • xy:当前像素坐标(从 0 开始)
  • widthheight:设备总宽度/高度
  • env:环境变量对象

返回值:一个 32 位整数,格式 0x00BBGGRR(蓝绿红顺序,每通道 0–255)

示例:

function get_color(x, y, width, height, env)
    return rgb(255, 0, 0)
end

可选函数:begin_frame(env)

作用:在每帧开始前执行一次,用于预计算或初始化帧级变量。

-- 全局变量存储预计算结果
local wave_offset = 0

function begin_frame(env)
    -- 每帧计算一次波浪偏移
    wave_offset = math.sin(env.time) * 50
end

function get_color(x, y, width, height, env)
    -- 直接使用预计算的值
    local hue = (x / width * 360 + wave_offset) % 360
    return hsv(hue, 255, 255)
end

环境变量详解

在渲染周期内,运行时会注入 env 环境对象,供 begin_frameget_color 使用。常用字段如下(如有缺省,以具体版本实现为准):

  • env.time:自启动以来的累计时间(秒,浮点数)。
  • env.dt:上一帧到当前帧的时间步长(秒)。
  • env.fps:当前帧率(帧/秒)。
  • env.random:0–1 的随机数种子(每帧变化)。
  • env.bpm:节拍(Beat Per Minute),用于节奏驱动效果(可选)。
  • env.audio:音频数据对象(可选),典型结构:
    • env.audio.level:整体音量包络 0–1。
    • env.audio.fft:频谱数组,低频到高频(如 64/128/256 槽)。
    • env.audio.sampleRate:音频采样率。
    • env.audio.enabled:音频输入是否启用。

示例:

-- 根据节拍做脉冲
local pulse = 0

function begin_frame(env)
    if env.bpm then
        local beat = env.time * env.bpm / 60.0
        pulse = 0.5 + 0.5 * math.sin(beat * math.pi * 2)
    else
        pulse = 0.5 + 0.5 * math.sin(env.time)
    end
end

function get_color(x, y, width, height, env)
    local hue = (x / width * 360 + env.time * 30) % 360
    return hsv(hue, 255, math.floor(255 * pulse))
end

内置函数库

为便于编写高质量灯效,运行时提供了一组常用工具函数(以下为常见约定,最终以具体版本为准):

  • 颜色构造与变换:

    • rgb(r, g, b):返回 32 位颜色(0x00BBGGRR)。
    • hsv(h, s, v):HSV 转 RGB,h: 0–360, s/v: 0–255。
    • saturate(v):将数值夹紧到 0–1。
    • clamp(v, min, max):区间裁剪。
    • mix(a, b, t)/lerp(a, b, t):线性混合。
    • smoothstep(edge0, edge1, x):平滑阶跃。
    • map(x, inMin, inMax, outMin, outMax):区间映射。
  • 噪声与随机:

    • random():0–1 随机。
    • noise1(x)/noise2(x, y):平滑噪声(如 Perlin/Simplex 实现)。
  • 数学与常量:

    • PITAU(2π)等。

示例:

-- 使用 smoothstep 做柔和的中心高亮
function get_color(x, y, width, height, env)
    local u = x / math.max(1, width - 1)
    local v = (height > 1) and (y / (height - 1)) or 0.5
    local dx = u - 0.5
    local dy = v - 0.5
    local d = math.sqrt(dx*dx + dy*dy)
    local glow = 1.0 - smoothstep(0.2, 0.5, d)
    local hue = (env.time * 40) % 360
    return hsv(hue, 255, math.floor(glow * 255))
end

音频可视化

借助 env.audio.fft 可以实现频谱响应、低频鼓点增强等效果:

local spectrum = {}
local smoothed = {}

function begin_frame(env)
    if env.audio and env.audio.fft then
        spectrum = env.audio.fft
        -- 简单平滑
        for i = 1, #spectrum do
            local v = spectrum[i]
            smoothed[i] = smoothed[i] and (smoothed[i] * 0.7 + v * 0.3) or v
        end
    end
end

function get_color(x, y, width, height, env)
    if not smoothed or #smoothed == 0 then
        return rgb(10, 10, 10)
    end
    local band = math.max(1, math.floor((x / math.max(1, width - 1)) * #smoothed))
    local amp = smoothed[band] or 0
    local h = (band / #smoothed) * 360
    local v = math.floor(math.min(255, amp * 255 * 1.5))
    return hsv(h, 255, v)
end

实践建议:

  • 将低频(如 20–200Hz)映射到暖色,高频映射到冷色,增强声像感。
  • 对整体音量 env.audio.level 做全局亮度门限,弱音时降低功耗。
  • 做峰值保持与缓慢衰减,获得更稳定的视觉反馈。

运行机制详解

渲染循环通常遵循以下顺序:

  1. 每帧开始先调用 begin_frame(env)(如实现)。
  2. 随后对每个像素按序调用 get_color(x, y, width, height, env)
  3. 将本帧颜色缓冲提交到设备。

性能与内存建议:

  • begin_frame 中做复杂计算与缓存,避免在 get_color 内重复开销。
  • 避免创建大量临时表;复用数组、使用局部变量。
  • 合理限制 math 调用次数,优先使用预计算查表。

AI 辅助开发

在脚本编辑器中描述目标效果(例如“低频驱动暖色条形,节拍脉冲增强亮度”),AI 将生成初版代码;随后可继续对“颜色风格、速度、平滑参数”等提出修改建议,快速迭代。


实战案例

1) 频谱条形图(横向)

local smoothed = {}

function begin_frame(env)
    if not (env.audio and env.audio.fft) then return end
    local fft = env.audio.fft
    for i = 1, #fft do
        local v = fft[i]
        smoothed[i] = smoothed[i] and (smoothed[i] * 0.6 + v * 0.4) or v
    end
end

function get_color(x, y, width, height, env)
    if not smoothed or #smoothed == 0 then return rgb(0,0,0) end
    local band = math.max(1, math.floor((x / math.max(1, width - 1)) * #smoothed))
    local level = smoothed[band] or 0
    local barH = math.floor(level * height)
    if (height - 1 - y) <= barH then
        local hue = (band / #smoothed) * 360
        return hsv(hue, 255, 255)
    else
        return rgb(0, 0, 0)
    end
end

2) 流星雨(一维)

local tails = {}
local speed = 20      -- 像素/秒
local length = 10     -- 尾巴长度

function begin_frame(env)
    -- 随机生成流星
    if (env.time % 1.0) < env.dt * 2 then
        table.insert(tails, { pos = 0, hue = (env.time * 80) % 360 })
    end
    -- 更新位置
    for i = #tails, 1, -1 do
        tails[i].pos = tails[i].pos + speed * env.dt
        if tails[i].pos - length > 1000 then
            table.remove(tails, i)
        end
    end
end

function get_color(x, y, width, height, env)
    local v = 0
    local hue = 0
    for i = 1, #tails do
        local p = tails[i].pos
        local d = math.abs(x - p)
        if d < length then
            local k = 1.0 - d / length
            v = math.max(v, math.floor(k * 255))
            hue = tails[i].hue
        end
    end
    if v > 0 then return hsv(hue, 255, v) end
    return rgb(0, 0, 0)
end

3) 呼吸灯(二维)

local phase = 0

function begin_frame(env)
    phase = (phase + env.dt) % 1.0
end

function get_color(x, y, width, height, env)
    local u = x / math.max(1, width - 1)
    local v = (height > 1) and (y / (height - 1)) or 0.5
    local dx = u - 0.5
    local dy = v - 0.5
    local d = math.sqrt(dx*dx + dy*dy)
    local breathe = 0.5 + 0.5 * math.sin((phase + d) * 2 * math.pi)
    local hue = (env.time * 20) % 360
    return hsv(hue, 200, math.floor(breathe * 255))
end

最佳实践

  • 优先在 begin_frame 做重计算与数据预处理。
  • 用局部变量缓存频繁访问的全局对象(如 math, env.audio.fft)。
  • 谨慎创建临时表,循环中尽量避免 table.insert 带来的扩容开销。
  • 对参数与返回值做边界保护(如 width-1 的除零保护)。
  • 颜色与亮度范围统一(0–255),超出需裁剪。

常见问题(FAQ)

Q1:get_color 返回格式是什么?
A:返回 32 位整数,格式 0x00BBGGRR

Q2:为什么开启音频可视化没有反应?
A:检查 env.audio.enabled 与输入设备;另确认运行环境是否授予麦克风权限。

Q3:如何提高帧率?
A:减少 get_color 内的复杂计算;把可复用值放到 begin_frame;避免创建临时表。

Q4:是否支持多脚本同时运行?
A:取决于宿主实现;建议一个设备同时激活一个脚本以便调试与性能保障。


有问题或建议?点击这里快速反馈。

技术支持 | 联系我们