跳转至

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_boxlast_messagehp_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+ 已移除。