本文整理自 CHUAN2《Lua速成班》直播课「Lua速成班 第十四课 系统函数第四节 MATH和OS库」,主讲:浮生梦。 课程体系:996 引擎传奇开发教学 · 威海旷世互娱教学基地
正弦函数用于计算物体在圆周运动中的垂直位置。返回值范围是负一到一。配合时间变量可以实现物体上下浮动效果。
想象一个摩天轮,正弦值表示座舱在垂直方向上的位置。时间乘以二派得到当前角度,sin函数将这个角度转换为位置比例。
练习题:让一个图片在3秒内上下浮动3次,浮动范围100像素
local time = 0
local startY = 450
local range = 100
function update()
time = time + 0.016
local y = startY + math.sin(time * math.pi * 6) * range
print("Y位置:", y)
end
余弦函数与正弦函数配合使用,控制物体在水平方向的位置。sin控制垂直方向,cos控制水平方向,两者结合实现圆周运动。
当角度为零时,sin值为零(中间位置),cos值为一(最右侧)。两个函数配合使用可以让物体绕圈运动。
练习题:让一个物体以屏幕中心为圆心,半径150像素做圆周运动
local time = 0
local centerX = 500
local centerY = 450
local radius = 150
function update()
time = time + 0.05
local x = centerX + math.cos(time) * radius
local y = centerY + math.sin(time) * radius
print("位置:", x, y)
end
随机函数默认每次运行产生相同序列。使用randomseed设置种子可以改变序列。通常用时间作为种子让每次运行结果不同。
random有三种用法:不传参数返回零到一小数;一个参数返回一到该参数的整数;两个参数返回指定范围的整数。
练习题:实现一个抽奖系统,30%概率获得稀有物品,70%概率获得普通物品
math.randomseed(os.time() + os.clock())
function lottery()
local roll = math.random(1, 100)
if roll <= 30 then
return "稀有物品"
else
return "普通物品"
end
end
print(lottery())
floor向下取整,舍弃小数部分;ceil向上取整,只要有小数就进位。这两个函数不是四舍五入。
游戏开发中伤害值、金币分配等都需要整数结果。根据游戏规则选择向上或向下取整。
练习题:100万金币分给37人,分别用floor和ceil计算每人分得多少
local total = 1000000
local people = 37
local per1 = math.floor(total / people)
local per2 = math.ceil(total / people)
print("向下取整每人:", per1, "剩余:", total - per1 * people)
print("向上取整每人:", per2, "会长补足:", per2 * people - total)
绝对值函数将负数转为正数,正数保持不变。用于计算距离、差值等场景。
计算两个物体距离时,不知道谁在左边谁在右边,用abs可以得到正确的距离值。
练习题:计算玩家点击位置与目标中心的距离,越近分数越高
local targetX = 500
local clickX = 450
local distance = math.abs(clickX - targetX)
local score = math.max(0, 100 - distance)
print("距离:", distance, "得分:", score)
pi是math库中的常量,约等于3.14159。用于角度和弧度的转换计算。
一圈是360度,也是2派弧度。游戏动画中常用弧度计算,因为sin和cos函数接受弧度值。
练习题:将角度转换为弧度,计算sin30度的值
local angle = 30
local radian = angle * math.pi / 180
print("30度的弧度:", radian)
print("sin30度:", math.sin(radian))
time返回当前时间戳,秒级精度;clock返回CPU运行时间,毫秒级精度。两者都用于计算耗时或设置随机种子。
测量代码执行时间时,在代码前后分别获取时间,相减得到耗时。
练习题:测量一个循环执行10000次需要多少毫秒
local start = os.clock()
for i = 1, 10000 do
local x = math.sin(i)
end
local cost = os.clock() - start
print("耗时毫秒:", cost * 1000)
ScheduleOnce用于创建延迟执行或循环执行的函数。第一个参数是回调函数,第二个参数是延迟时间。
游戏动画通过定时器不断更新物体位置实现。每次定时器触发时计算新的位置并应用。
练习题:使用定时器让一个物体在2秒内从左侧移动到右侧
local x = 100
local targetX = 700
local speed = 3
function move()
x = x + speed
if x < targetX then
SL:ScheduleOnce(move, 0.016)
end
end
move()
前端调用GUIUtil.lua
function Reload()
SL:Require("test.lua",true)
end
GUI:addKeyboardEvent("KEY_SPACE", Reload)
-- 调度器
local function onUpdate(dt)
frameCount = frameCount + 1
local elapsed = os.clock() - startTime
if elapsed >= 1.0 then
scheduler:unscheduleScriptEntry(scheduleId)
SL:print("FPS:", frameCount)
end
end
scheduleId = scheduler:scheduleScriptFunc(onUpdate, 0, false) -- COCOS 定时器 ~ C++ 语法规则!
作业一:使用sin函数制作一个物体上下浮动效果,浮动范围80像素,2秒完成一个周期
作业二:结合sin和cos让物体以屏幕中心为圆心,半径200像素做圆周运动,3秒转一圈
作业三:编写装备强化函数,成功率40%,成功加1到3点属性,失败不增加,使用random实现,尝试后端实现脚本功能!
作业四:公会分红计算,总金币888888,参与人数29人,使用floor计算每人分得多少,剩余多少存入仓库
local win = GUI:Win_Create("Win_1", 0, 0, 1136, 640)
local path = "res/custom/feijian/a/jian_6.png"
-- 缓存初始中心坐标
local startX, startY = 450, 250
local Image_bg = GUI:Image_Create(win, "Image_bg1234", startX, startY, path)
local t = 0
local overTime = 1
local radius = 110 -- 运动半径
-- 假设60 FPS
local delay = 1 / 60 -- 定时器间隔设为一帧的时间 (约 0.016)
function go()
-- 直接使用外部缓存的 startX/Y 进行计算
local x = startX + radius * math.sin(t * math.pi * 2)
local y = startY + radius * math.cos(t * math.pi * 2)
GUI:setPosition(Image_bg, x, y)
t = t + delay
if t < overTime then
SL:ScheduleOnce(go, delay)
end
end
go()
概念说明
os.clock() 获取的是当前进程消耗的CPU时间,不是真实时间。真实时间是你手表上显示的时间,CPU时间是你的程序实际占用处理器进行计算的时间。比如你从12点学习到1点,但CPU时间只计算你真正在用脑思考的那几分钟。
应用场景
用于检测程序耗时,特别是需要毫秒级精度计算的场景。
代码示例
local start = os.clock()
local n = 0
for i = 1, 10000000 do
n = n + 1
end
local endTime = os.clock() - start
print(string.format("耗时:%.4f秒", endTime))
重要提示
不同电脑的耗时结果不同,与CPU性能密切相关。i9-13900处理器可能比老旧服务器快5倍以上,涉及基础频率、内存频率、制程工艺等因素。本机测试的结果不能直接套用到服务器上。
练习题
编写一个程序,使用os.clock()测量计算1到1000000累加和的耗时,保留3位小数输出。
概念说明
os.time() 返回从1970年1月1日零点开始经过的秒数,是一个不断增长的整数。这个时间戳是全球通用的标准,每秒增加1。
两种使用形态
形态一:获取当前时间戳
local t = os.time()
print(t) -- 输出类似 1773728263
形态二:将指定时间转换为时间戳
local t = os.time({
year = 2026,
month = 5,
day = 1,
hour = 0,
min = 0,
sec = 0
})
print(t)
注意事项
练习题
获取当前时间戳,并计算距离2026年12月31日还有多少秒。
概念说明
在Lua中,当函数只有一个参数,且该参数是字符串或表时,可以省略括号直接调用。这是一种语法糖,让代码看起来更简洁,但也可能让不熟悉的人感到困惑。
字符串参数省略括号
-- 标准写法
print("1234")
-- 神仙写法(等效)
print '1234'
表参数省略括号
-- 标准写法
local t = os.time({year = 2026, month = 3, day = 17})
-- 神仙写法(等效)
local t = os.time{year = 2026, month = 3, day = 17}
连续调用的特殊玩法
当函数返回另一个函数时,可以连续使用省略括号的语法:
function a(b)
print(b)
return function(c)
print(c)
end
end
-- 标准写法
a("123")("456")
-- 神仙写法(等效)
a"123""456"
注意事项
练习题
将以下标准写法改写为省略括号的神仙写法:
print("hello world")
os.date("%Y-%m-%d")
概念说明
os.date() 用于将时间戳转换为可读的日期格式,或者获取日期的各个组成部分。
两种使用形态
形态一:获取日期字符串
local date = os.date()
print(date) -- 输出格式如:Tue Mar 17 14:30:00 2026
形态二:获取结构化日期表
local t = os.date("*t")
print(t.year, t.month, t.day)
print(t.hour, t.min, t.sec)
print(t.wday) -- 星期几,1表示周日,2表示周一,以此类推
print(t.yday) -- 当年的第几天
格式化字符串
local day = os.date("%Y-%m-%d %H:%M:%S")
print(day) -- 输出如:2026-03-17 14:30:00
常用格式符
实用技巧:中文星期显示
local now = os.date("*t")
local wday = {"日","一","二","三","四","五","六"}
local nowstr = string.format("%d年%d月%d日 星期%s", now.year, now.month, now.day, wday[now.wday])
print(nowstr)
练习题
编写程序输出当前时间的完整中文格式,例如"2026年03月17日 14时30分25秒 星期二"。
概念说明
os.difftime() 用于计算两个时间戳之间的差值,返回秒数。虽然直接用减法也能得到结果,但使用这个函数语义更清晰,表示你在计算时间差。
代码示例
local t1 = os.time()
local t2 = os.time() + 100
local diff = os.difftime(t1, t2)
print(diff) -- 输出 -100
练习题
记录程序开始和结束的时间戳,使用os.difftime()计算程序运行了多少秒。
概念说明
os.execute() 可以执行操作系统的命令行指令。这是一个非常强大的函数,但由于安全风险,在前端和后端环境中通常被禁用或阉割。
代码示例
-- 列出当前目录文件(Windows)
os.execute("dir")
-- 打开网页
os.execute("start www.qq.com")
-- 关机命令(慎用)
-- os.execute("shutdown -s -t 3")
警告
此函数可以执行任何系统命令,包括删除文件、关机、下载程序等。如果被恶意利用,可能控制用户电脑。生产环境中谨慎使用。
练习题
(理论题)为什么os.execute()函数在客户端脚本中通常被禁用?请从安全角度说明。
概念说明
os.exit() 用于立即终止当前程序运行,释放所有资源并关闭文件。
代码示例
os.exit(1) -- 参数为true或非零值时直接退出
应用场景
通常用于前端客户端中需要强制关闭程序的情况。
概念说明
os.getenv() 用于获取操作系统环境变量的值,可以获取用户名、系统类型、临时目录等信息。
代码示例
print(os.getenv("USERNAME")) -- 获取当前用户名
print(os.getenv("OS")) -- 获取操作系统类型
print(os.getenv("TEMP")) -- 获取临时文件目录
练习题
编写程序获取并显示当前操作系统的用户名和系统类型。
os.remove() 删除文件
os.remove("test.txt") -- 删除指定文件
os.rename() 重命名文件
os.rename("old.txt", "new.txt") -- 将old.txt重命名为new.txt
应用场景
可用于本地存档系统,例如玩家删号时删除本地存档文件,或者更新时重命名旧版本文件。
概念说明
os.tmpname() 生成一个唯一的临时文件名,用于创建临时文件。这些文件通常存储在系统临时目录中,重启电脑后可能自动清理。
代码示例
local file = os.tmpname()
print(file) -- 输出临时文件路径
应用场景
可用于安全执行代码:后端发送代码到前端,前端写入临时文件并加密执行,执行后删除文件,不在本地留痕迹。
练习题
使用os.tmpname()创建一个临时文件路径,并打印该路径。
概念说明
os.setlocale() 用于设置程序的区域和语言环境,影响日期、时间、数字的显示格式。
应用场景
开发海外服游戏时使用,例如为日本玩家设置日语环境,为美国玩家设置英语环境。
作业1
使用os.clock()测量一个包含1000万次循环的程序耗时,分别测试空循环和进行数学运算的循环,比较两者的耗时差异。
作业2
编写一个倒计时程序,使用os.time()获取当前时间戳,计算距离你下一个生日还有多少天、多少小时、多少分钟。
作业3
使用os.date("*t")获取当前时间的所有信息,然后格式化为以下字符串输出:"现在是2026年3月17日,今年的第76天,星期二,14时30分"。要求使用神仙语法调用os.date。
作业4
创建一个简单的日志系统:每次程序运行时,使用os.date()记录当前时间,将时间字符串追加写入log.txt文件(提示:需要结合IO库使用)。
作业5
(思考题)解释为什么os.clock()在不同电脑上测量同一程序会得到不同的结果?从CPU架构、频率、内存等方面分析。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
本文整理自 CHUAN2《Lua速成班》直播课「Lua速成班 第十三课 系统函数第三节 string库 table库」,主讲…
本文整理自 CHUAN2《Lua速成班》直播课「Lua速成班 第十四课 系统函数第四节 MATH和OS库」,主讲:浮生梦。 …
本文整理自 CHUAN2《Lua速成班》直播课「Lua速成班 第十一课 系统函数 第一节」,主讲:浮生梦。 课程体系:996…
本文整理自 CHUAN2《Lua速成班》直播课「Lua速成班 第十二课 系统函数第二节 string库」,主讲:浮生梦。 课…
本文整理自 CHUAN2《Lua速成班》直播课「Lua速成班 第九课 后端面向对象和事件推送」,主讲:浮生梦。 课程体系:9…
本文整理自 CHUAN2《Lua速成班》直播课「Lua速成班 第十课 后端面向对象 class构造」,主讲:浮生梦。 课程体…