KubeJS UI 绘制(Painter API:在屏幕上画东西)¶
原文:原创教程(ぴよまる),API 依据官方 Wiki「Painter API」篇
KubeJS 的 Painter API 可以在玩家屏幕上画图形:矩形、渐变、文字、物品图标,还能做动画。服务端和客户端都能用——服务端给某个玩家画(比如 HUD 提示),客户端给自己画(比如屏幕特效)。
⚠️ 版本警告:Painter API 在 1.21+ 版本已被移除!本教程针对 KubeJS 6.x / Minecraft 1.20.1,1.21 以上用不了。
1. 基本原理:paint() 像"贴便签"¶
event.player.paint({...}) 是唯一的入口。传一个对象,里面每个键是一个"绘制对象"的名字(自己起),值是它的属性:
// 监听"玩家登录"事件
PlayerEvents.loggedIn(event => {
// 登录时给玩家屏幕上画一个绿色矩形
// paint() 传的对象:名字叫 my_box,类型是 rectangle(矩形)
event.player.paint({
my_box: { // 绘制对象的名字(自己起,之后更新/删除都用它)
type: 'rectangle', // 类型:rectangle 矩形
x: 10, // 左上角 X 坐标(离屏幕左边 10 像素)
y: 10, // 左上角 Y 坐标(离屏幕上边 10 像素)
w: 50, // 宽度 50 像素
h: 20, // 高度 20 像素
color: '#00FF00' // 颜色:绿色(#RRGGBB 格式)
}
})
})
upsert 原则(重要):paint() 是"没有就创建,有就更新"——同一个名字第一次画是创建,再画同一个名字就是改属性:
// 第一次:创建矩形(因为 my_box 还不存在,而且带了 type)
event.player.paint({ my_box: { type: 'rectangle', x: 10, y: 10, w: 50, h: 20, color: '#00FF00' } })
// 第二次:my_box 已存在,只更新 x 位置(其他属性不动)
event.player.paint({ my_box: { x: 100 } })
// 可以同时更新/创建多个对象(批量)
event.player.paint({
a: { x: 10 }, // 更新 a 的 x
b: { x: 30 }, // 更新 b 的 x
c: { type: 'rectangle', x: 10, y: 10 } // 创建新的 c(带 type 才会创建)
})
💡 名字可以随便起(
my_box、last_message、hp_bar……),用中英文都行,只要自己记住就行。
2. 删除对象¶
// 删除单个对象:加 remove: true
event.player.paint({ my_box: { remove: true } })
// 批量删除多个
event.player.paint({ a: { remove: true }, b: { remove: true } })
// 删除全部:名字用 '*' 通配
event.player.paint({ '*': { remove: true } })
⚠️ 玩家退出世界/服务器时,Painter 对象会被自动清空。如果想让"每次进服都有",就在
PlayerEvents.loggedIn(登录事件)里重新画一遍。
3. 四种可画的对象¶
3.1 rectangle 矩形(最常用)¶
// 纯色矩形 + 可选贴图(texture)
event.player.paint({
box: {
type: 'rectangle', // 矩形
x: 0, y: 0, // 位置(左上角)
w: 100, h: 30, // 尺寸
color: '0xFF0000' // 颜色(也可以写 '#FF0000' 或 'red')
}
})
3.2 gradient 渐变(颜色过渡)¶
// 从上到下从红渐变到蓝的矩形
event.player.paint({
grad: {
type: 'gradient', // 渐变
x: 10, y: 10, w: 100, h: 100, // 位置和大小
colorT: '#FF0000', // 顶部颜色:红
colorB: '#0000FF' // 底部颜色:蓝(从上到下渐变)
// 还有 colorL 左 / colorR 右 / colorTL 左上 / colorTR 右上 / colorBL 左下 / colorBR 右下
}
})
3.3 text 文字¶
// 屏幕右下角显示一行文字
event.player.paint({
tip: {
type: 'text', // 文字
text: '欢迎来到服务器!', // 内容(字符串)
x: -4, y: -4, // 位置:负值 + 对齐,见下面说明
alignX: 'right', // 水平对齐:right 右对齐(所以 x 用负数往屏幕内收)
alignY: 'bottom', // 垂直对齐:bottom 底部对齐
scale: 1.5, // 字号缩放(1.5 倍)
color: 'white', // 颜色(支持 'red'、'dark_aqua' 等聊天颜色)
shadow: true, // 文字阴影(更清晰)
draw: 'always' // 画在"游戏界面"和"菜单界面"都显示(见下方 draw)
}
})
3.4 item 物品图标¶
// 在屏幕上画一个物品图标(比如武器 HUD)
event.player.paint({
icon: {
type: 'item', // 物品图标
item: 'minecraft:diamond', // 物品 ID(也可以写完整 NBT 格式 {id:'minecraft:diamond', Count:1})
x: 100, y: 100, // 位置
scale: 2 // 放大 2 倍
}
})
4. 通用属性(所有类型都能用)¶
| 属性 | 作用 | 示例 |
|---|---|---|
x / y |
位置坐标(像素) | x: 10, y: 20 |
w / h |
宽 / 高 | w: 100, h: 30 |
visible |
是否可见(false 先藏起来,之后更新再显示) | visible: false |
alignX |
水平对齐:'left' / 'center' / 'right' |
alignX: 'center' |
alignY |
垂直对齐:'top' / 'center' / 'bottom' |
alignY: 'bottom' |
draw |
显示时机:'ingame' 仅游戏内 / 'gui' 仅界面 / 'always' 都显示 |
draw: 'always' |
moveX / moveY |
移动偏移(配合动画) | moveX: 5 |
expandW / expandH |
额外扩展宽高 | expandW: 2 |
💡 推荐套路:经常出现的对象(血条、提示框),在登录时先把所有固定属性画好并设
visible: false(隐藏),之后需要显示时只更新visible: true——省性能又方便。
5. 高级:用公式做动画¶
Painter 的位置/大小/颜色支持数学公式(Rhino Unit),还能引用屏幕尺寸、鼠标位置等变量:
可用变量:
| 变量 | 含义 |
|---|---|
$screenW |
屏幕宽度(像素) |
$screenH |
屏幕高度(像素) |
$delta |
渲染增量(帧间隔) |
$mouseX |
鼠标 X 坐标 |
$mouseY |
鼠标 Y 坐标 |
可用常量: PI(π)、HALF_PI(π/2)、TWO_PI(2π)、E(自然常数)、true/false(当作 1/0)。
// 一个在屏幕中央左右来回摆动的方块(用 sin 正弦函数)
PlayerEvents.loggedIn(event => {
event.player.paint({
anim_box: {
type: 'rectangle',
// x 用公式:正弦函数让位置在 (屏幕宽-32)/2 的范围内来回摆动
// time() 是当前时间(秒),越走越大,sin 让它来回摆
x: '(sin(time() * 1.1) * (($screenW - 32) / 2))',
y: 100, // 固定高度
w: 32, h: 32, // 32×32 像素
alignX: 'center', // 以屏幕中心为基准对齐
color: '#FF8800', // 橙色
texture: 'minecraft:block/iron_block' // 用方块贴图填充
}
})
})
💡 公式要写成字符串(带引号):
'(sin(time() * 1.1) * ...)'。纯数字直接写数字就行。
6. 完整案例:屏幕角落显示"最近一条聊天消息"¶
// server_scripts/ui_demo.js
// 效果:登录时在右下角画一个提示框和一行字;每次有人聊天,右下角文字更新成最新消息
// 1. 登录时创建两个绘制对象(提示框 + 文字),先都藏起来
PlayerEvents.loggedIn(event => { // 监听"玩家登录"事件
event.player.paint({
msg_box: { // 提示框(矩形背景)
type: 'rectangle', // 矩形
x: -4, y: -4, // 位置:负值往屏幕里收
w: 300, h: 40, // 宽 300 高 40
alignX: 'right', // 靠右
alignY: 'bottom', // 靠底
color: '#00000088', // 半透明黑(#AARRGGBB 格式,AA 是透明度)
draw: 'always' // 游戏内和菜单都显示
},
msg_text: { // 消息文字
type: 'text', // 文字
text: '暂无消息', // 初始内容
x: -10, y: -10, // 位置(比框稍微往里一点)
alignX: 'right', // 靠右
alignY: 'bottom', // 靠底
color: 'white', // 白色
shadow: true, // 阴影
draw: 'always' // 都显示
}
})
})
// 2. 有人聊天时,更新文字内容(矩形框不动)
PlayerEvents.chat(event => { // 监听"玩家聊天"事件
event.player.paint({
msg_text: { // 更新 msg_text 这个对象
text: `最新消息:${event.message}` // 改成最新聊天内容
}
})
})
7. 命令方式(测试用)¶
不用写脚本也能画,游戏里执行命令即可(常用于调试):
// 给最近的玩家画一个红色矩形
/kubejs painter @p {example: {type: 'rectangle', x: 10, y: 10, w: 20, h: 20, color: '#FF0000'}}
8. 速查表¶
| 想做什么 | 写法 |
|---|---|
| 创建/更新对象 | event.player.paint({名字: {属性...}}) |
| 创建矩形 | {type: 'rectangle', x, y, w, h, color} |
| 创建渐变 | {type: 'gradient', colorT, colorB, ...} |
| 创建文字 | {type: 'text', text: '内容', color, scale} |
| 创建物品图标 | {type: 'item', item: 'minecraft:diamond'} |
| 删除一个对象 | {名字: {remove: true}} |
| 删除全部 | {'*': {remove: true}} |
| 屏幕宽 / 高 | $screenW / $screenH |
| 鼠标位置 | $mouseX / $mouseY |
| 动画公式 | x: '(sin(time() * 1.1) * ...)' |
| 半透明色 | '#AARRGGBB'(如 '#00000088') |
| 命令画 | /kubejs painter @p {...} |
💡 记忆口诀:
paint是画笔、名字是贴纸标签、type决定画什么(rectangle/gradient/text/item)、改属性就重画同一个名字、remove: true撕掉、'*'清场;坐标用alignX/alignY对齐到屏幕角,动画用$screenW+sin()公式。
本文为 KubeJS 1.20.1 中文文档原创篇目。Painter API 仅 KubeJS 6.x(1.20.1 及以下)可用,1.21+ 已移除。