首页 / JS 脚本手册 / 动态贴图与 LCD

动态贴图与 LCD

车内屏幕的实现方式:用 Java2D 画到 BufferedImage,再上传成贴图。

整体流程

  1. 创建 GraphicsTexture
  2. 用 Java 的 BufferedImageGraphics2D 画内容
  3. upload() 传给 GPU
  4. 把贴图用到模型上
  5. 不用时 close()

GraphicsTexture

方法说明
upload()上传当前内容
upload(image)上传指定的 BufferedImage
close()立即释放
close(delay)延迟释放
isClosed()是否已释放
createArgbBufferedImage(src)转成 ARGB 格式,上传前通常需要
liveCount()当前存活的贴图数,排查泄漏用
贴图必须 close() 每张都占显存,忘了释放就是泄漏。 在 dispose 里关掉,或用 liveCount() 盯着数量。

一个 LCD 的骨架

function create(ctx, state, train) {
  state.tex  = null;
  state.shown = null;
}

function render(ctx, state, train) {
  if (!train.shouldRender()) return;

  var text = train.nextStationName();
  if (text === state.shown) return;   // 没变就不重画
  state.shown = text;

  var img = new java.awt.image.BufferedImage(
      512, 128, java.awt.image.BufferedImage.TYPE_INT_ARGB);
  var g = img.createGraphics();
  g.setColor(java.awt.Color.BLACK);
  g.fillRect(0, 0, 512, 128);
  g.setColor(java.awt.Color.WHITE);
  g.setFont(Resources.readFont(Resources.id("mypack:font/lcd.ttf")).deriveFont(48));
  g.drawString("下一站 " + text, 20, 80);
  g.dispose();

  if (state.tex === null) state.tex = new GraphicsTexture();
  state.tex.upload(img);
}

function dispose(ctx, state, train) {
  if (state.tex !== null) state.tex.close();
}
java.awt白名单内,可直接使用 BufferedImageGraphics2DColorFont 等。

只在必要时重画

这是 LCD 脚本最容易出问题的地方。每帧重画一张 512×128 的图并上传, 一辆 8 编组的车就是每秒几百次 —— 帧率会掉得很明显。

正确做法是比对内容:站名没变、时间没跨秒、滚动位置没动,就直接返回。 上面例子里的 state.shown 就是干这个的。

贴图上限

客户端配置 scriptTextureLimit 限制脚本动态贴图的缓存数量,默认 512。 超过后旧贴图会被淘汰。