draw
屏幕绘制。所有 draw.* 调用打到当前帧的前景 draw list,必须在每渲染帧 event.on("frame_update") 内调用。draw list 每帧重置,漏一帧 = 屏幕上空白闪一下。详见 入门指南。
颜色参数:下文
color均是number类型(32-bit packed 颜色),由draw.rgba/draw.u8/draw.hex构造;不能直接传{r,g,b,a}table(table 形态仅用于 ESP 元素配色 opts)。
颜色构造(返 packed uint32)
draw.rgba(r, g, b, a) → uint32 —— floats 0..1
draw.u8(r, g, b, a) → uint32 —— ints 0..255
draw.hex(packed : int) → uint32 —— 直接传 0xRRGGBBAA
颜色变换(输入/输出都是 packed uint32)
不引入新类型,跟现有 rgba/u8/hex 互通。
draw.color_mod_a(col, v) → uint32
现有 alpha 乘以 v(0..1)。不是覆盖,叠加效果,适合渐隐。
local half = draw.color_mod_a(red, 0.5) -- alpha 砍半draw.color_lerp(a, b, t) → uint32
双色逐分量线性插值(包含 alpha),t 自动 saturate 到 0..1。
-- 低血从绿渐变到红
local hp_col = draw.color_lerp(draw.rgba(1,0,0,1), draw.rgba(0,1,0,1), hp / 100)draw.color_darken(col, v) → uint32
RGB × (1-v),alpha 保留。v=0.5 = 暗 50%。
draw.color_lighten(col, v) → uint32
RGB 朝 255 插值 v,alpha 保留。v=0.5 = 朝白色靠拢 50%。
draw.color_hsv(h, s, v, a?) → uint32
HSV 构造。h ∈ [0,360) 度(超出会模),s/v/a ∈ [0,1]。a 默认 1.0。
-- 彩虹流动
local hue = (time.now() * 60) % 360
local rainbow = draw.color_hsv(hue, 1.0, 1.0)形状
draw.line(x1, y1, x2, y2, color, opts?)
opts:{thickness = 1.0}
draw.rect(x1, y1, x2, y2, color, opts?)
opts:{filled = false, rounding = 0, thickness = 1, flags = 0}
draw.rect_gradient(x1, y1, x2, y2, c_tl, c_tr, c_br, c_bl)
4 角各自一色的渐变矩形。常用做渐变血条 / 渐变背景。
draw.triangle_multicolor(x1, y1, c1, x2, y2, c2, x3, y3, c3)
3 顶点各自一色,GPU 自动插值填充。适合 fade 箭头、命中标记的渐变填充。
draw.circle_multicolor(x, y, r, center_col, edge_col, opts?)
圆心 → 圆周径向渐变(圆心一色,圆周一色,中间插值)。 opts:{segments = 36}。常用做能量球、雷达 marker 发光、minimap 边缘淡出。
-- 中心亮白外圈透明的发光球
local cy = draw.rgba(1, 0.9, 0.4, 0.9)
local cx = draw.rgba(1, 0.9, 0.4, 0)
draw.circle_multicolor(x, y, 30, cy, cx)draw.circle(x, y, r, color, opts?)
opts:{filled = false, segments = 0, thickness = 1, fill = 1.0}
fill∈ [0,1] —— 顺时针扇形,从 12 点位起。fill = 1.0(默认)= 完整圆。filled = true+fill < 1.0→ 画扇形 pie(圆心 → 弧 → 圆心)filled = false+fill < 1.0→ 画弧线(不闭合)- 用于 CD 进度环 / loading spinner / 雷达扇区。
fill = 1.0走 ImGui 原生 fast path,无性能损失。
-- 75% 进度环
draw.circle(cx, cy, 30, draw.rgba(0.3,0.9,0.4,1),
{ fill = 0.75, thickness = 4 })
-- 实心扇形(pie)
draw.circle(cx, cy, 30, draw.rgba(1,0.6,0,0.4),
{ filled = true, fill = 0.5 })draw.triangle(x1, y1, x2, y2, x3, y3, color, opts?)
opts:{filled = false, thickness = 1}。适合方向箭头、FOV 三角指示、down arrow。
draw.quad(x1, y1, x2, y2, x3, y3, x4, y4, color, opts?)
opts:{filled = false, thickness = 1}。投影 3D box 的核心:玩家世界空间 8 顶点投到屏幕后顶面/底面就是 4-vertex quad。
draw.polyline(points, color, opts?)
points:点序列,两种写法都接受
- flat:
{x1, y1, x2, y2, ...}(偶数长度) - nested:
{ {x1, y1}, {x2, y2}, ... }
opts:{thickness = 1, closed = false, filled = false}
closed = true→ 末尾连回起点filled = true→ 用AddConvexPolyFilled(仅凸多边形可靠);走 filled 路径时closed/thickness都被忽略
万能兜底,能画 quad / 投影 box 的 polygonal outline / radar 形状 / FOV 弧。
阴影 + 外发光 (composite helper)
纯像素 helper —— 多圈叠加近似柔和模糊,不需要 shader。col 的 alpha 通道作为基准强度,opts.alpha 是叠加倍数(0..1)。
draw.shadow_line(x1, y1, x2, y2, color, opts?)
线段投影。 opts:{offset_x = 0, offset_y = 2, blur = 3, layers = 3, alpha = 1.0}
blur 大 → 阴影更柔;layers 越多越平滑但 batch 也增。offset_x/y 是阴影相对原始位置的偏移(模拟光源方向)。
-- 在描边文字下加暗阴影
draw.shadow_line(x, y + 12, x + w, y + 12,
draw.rgba(0, 0, 0, 0.6),
{ offset_y = 1, blur = 2 })draw.shadow_rect(x1, y1, x2, y2, color, opts?)
矩形外阴影。 opts:{spread = 6, rounding = 0, layers = 3, alpha = 1.0}
外推 spread 像素等分 layers 圈,内圈接近实色外圈淡出。rounding 跟主体 rect 圆角一致即可。layers 越大越柔但 batch 也越多,默认 3 已够看,N 玩家批量 ESP 用时建议保持默认或降到 2。
-- 给 hp bar 加底阴影,提升菜单背景对比
draw.shadow_rect(x, y, x + w, y + h,
draw.rgba(0, 0, 0, 0.5),
{ spread = 4, rounding = 2 })
draw.rect(x, y, x + w, y + h, hp_col,
{ filled = true, rounding = 2 })draw.glow_circle(x, y, r, color, opts?)
圆形外发光。 opts:{spread = 8, layers = 4, alpha = 1.0}
外推 spread 像素逐层径向衰减(平方曲线 → 中心亮边缘淡)。适合配 circle 当焦点 marker / 警示灯。layers 是性能拐点 —— 默认 4 + 平方衰减下,N 玩家 marker 批量调用仍可控。
-- 雷达 marker 高亮(发光 + 实心圆心)
draw.glow_circle(mx, my, 6, draw.rgba(1, 0.3, 0.3, 0.7))
draw.circle(mx, my, 4, draw.rgba(1, 0.3, 0.3, 1), { filled = true })文字 + 图像
draw.text(x, y, color, text, opts?)
opts:
font— 字体句柄,从draw.font(name)取(默认 = 系统字体)size— 强制字号 float;不传 =ImGui::GetFontSize()(当前活动字体的 size,不是传入font参数的默认 size)outline—true→ 主题深灰描边(项目统一风格)uint32 color→ 自定义颜色描边- 不传 /
false→ 不描边
描边实现 = 4 向 1px 偏移叠加,连续无锯齿;比脚本自己手动多次 draw.text 加偏移正确。
draw.image(tex_handle, x, y, w, h, opts?)
参数:tex_handle 来自 file.image 的 :load / :svg / :create
opts:{tint = uint32_white, uv0 = {0,0}, uv1 = {1,1}}
uv0 / uv1 必须是 array-style table {u, v},不接受 {u=..., v=...} 命名形式。
draw.image_rotated(tex_handle, cx, cy, w, h, angle_deg, opts?)
绕 (cx, cy) 旋转 angle_deg 度的图像。w/h 是旋转前的尺寸。 opts:同 draw.image(tint / uv0 / uv1)。
-- 罗盘指针随玩家朝向转
draw.image_rotated(arrow_tex, sw/2, sh/2, 32, 32, yaw_deg)裁剪栈
draw.push_clip(x1, y1, x2, y2, intersect?)
压栈一个矩形裁剪区,后续绘制只在此矩形内可见。
intersect默认true(跟当前 clip 求交,嵌套裁剪更安全)- 必须在
frame_update内成对调用pop_clip,跨帧不持久
draw.pop_clip()
弹出最近一次 push_clip 推入的矩形。
-- 进度条 mask(图像上盖一层 clip,实现剪裁式进度)
draw.push_clip(x, y, x + w * progress, y + h)
draw.image(icon, x, y, w, h)
draw.pop_clip()度量
draw.measure(text, opts?) → w, h
opts:{font, size} —— 不传 = 用当前活动 font + ImGui::GetFontSize 测量
draw.screen() → w, h
当前帧屏幕分辨率。
字体
字体由项目启动时加载(ImGui font atlas 一次性构建),运行时不支持新加字体——用户字体需放 res/fonts/ 启动时自动扫入。
draw.fonts() → table<string>
列出可用字体名清单。内置 7 个:"default" / "small" / "icon" / "logo" / "esp" / "loot" / "models";加上 res/fonts/ 目录下扫到的 .ttf/.otf 文件名(无扩展)。
draw.font(name) → Font | nil
取字体句柄,nil 表示该 name 不存在。
注意:当前
draw.font(name)仅暴露 7 个内置字体("default" / "small" / "icon" / "logo" / "esp" / "loot" / "models");draw.fonts()会列出res/fonts/下额外的 .ttf/.otf 文件名,但实际取句柄按内置名走(额外字体目前不挂句柄,未来扩展用)。
示例
event.on("frame_update", function(e)
local sw, sh = draw.screen()
local red = draw.rgba(1.0, 0.2, 0.2, 1.0)
local trans = draw.u8(255, 255, 255, 90)
-- 屏幕中央十字
draw.line(sw/2 - 8, sh/2, sw/2 + 8, sh/2, red, { thickness = 2 })
draw.line(sw/2, sh/2 - 8, sw/2, sh/2 + 8, red, { thickness = 2 })
-- 左上 watermark(渐变背景)
draw.rect_gradient(10, 10, 200, 40,
draw.rgba(0.1, 0.1, 0.15, 0.7), draw.rgba(0.2, 0.2, 0.3, 0.7),
draw.rgba(0.2, 0.2, 0.3, 0.7), draw.rgba(0.1, 0.1, 0.15, 0.7))
-- 描边文字(自动跟主题)
local big = draw.font("logo")
draw.text(15, 18, draw.rgba(1, 1, 1, 1), "HELLO",
{ font = big, size = 24, outline = true })
-- 方向箭头(朝向某玩家)
local cx, cy = sw/2, sh - 100
draw.triangle(cx, cy - 12, cx - 10, cy + 8, cx + 10, cy + 8,
draw.rgba(1, 0.8, 0.2, 1), { filled = true })
end)动画综合示例(CD ring + 渐变颜色 + clip 进度条 + 旋转图标)
local start_t = time.now()
event.on("frame_update", function(e)
local t = (time.now() - start_t) % 4.0
local progress = t / 4.0
local sw, sh = draw.screen()
-- CD 环(顺时针填充)
local ring_col = draw.color_lerp(draw.rgba(0,0.9,1,1), draw.rgba(0.2,1,0.4,1), progress)
draw.circle(120, 120, 36, ring_col, { fill = progress, thickness = 5 })
-- 进度条 mask: clip 限制图像左半截
local bar_x, bar_y, bar_w, bar_h = 80, 200, 240, 14
draw.rect(bar_x, bar_y, bar_x + bar_w, bar_y + bar_h,
draw.color_darken(ring_col, 0.7), { filled = true, rounding = 6 })
draw.push_clip(bar_x, bar_y, bar_x + bar_w * progress, bar_y + bar_h)
draw.rect(bar_x, bar_y, bar_x + bar_w, bar_y + bar_h,
ring_col, { filled = true, rounding = 6 })
draw.pop_clip()
-- 旋转图标(如果有 file.image:load 的句柄)
-- draw.image_rotated(spinner_tex, 300, 120, 32, 32, progress * 360)
end)