繪事與畫布
其途有二:PIDS 之屏,以 Text / Texture / Rect 流式之 API 徑出之;像素之級(LCD、點陣屏),以 GraphicsTexture 與 Gfx2D 原生光柵之。
螢幕坐標系之內容(PIDS 文字之行、貼圖之塊),則歸 Text/Texture:一繪製記錄,宿主循與 JS 全同之程式碼路徑而回放。像素之級(車輛 LCD、動態點陣屏、圖表),則歸 GraphicsTexture:自繪其像素,經 Gfx2D 光柵諸基元,惟以髒矩形(dirty rectangle)上諸 GPU。
Text、Texture 與 Rect(PIDS)
<mtr/text.hpp> 者,JS TextWrapper / TextureWrapper / Rect 流式 API 一比一之移植也——其法之名,循 C++ 之習為 snake_case,鏈鏈相承而呼之:
mtr::Text::create()
.text("Tsim Sha Tsui")
.scale(1.725)
.size(100, 9)
.stretch_xy()
.font_mc()
.color(0xFC9700)
.pos(3, rowY)
.draw(ctx);
| Text 之法 | JS 所應 | 釋義 |
|---|---|---|
.text(str[, len]) | .text() | UTF-8 之文 |
.scale(s) | .scale() | 整體縮放 |
.left_align() / .center_align() / .right_align() | 同名 | 對齊(預設居中) |
.shadowed() / .bold() / .italic() | 同名 | 字之飾 |
.stretch_xy() / .scale_xy() / .wrap_text() / .marquee(duration) | 同名 | 溢出之式(跑馬燈可以 .with_marquee_progress(p) 固其進) |
.font(id) / .font_mc() | 同名 | 資源字體(如 .font("jsblock:shanghai"))/ MC 內建字體 |
.color(argb) | 同名 | 色(ARGB) |
.pos(x, y) / .size(w, h) | 同名 | 螢幕坐標與包圍之匣 |
.z_order(z) / .layer(l) | 同名 | 層級;z=-1 時上下文自配之 |
.render_type("LIGHT_1") | .renderType() | 以名舉渲染之層(同 QueuedRenderLayer.valueOf 之義;名之不識者,則擲異常) |
.natural_light() | .naturalLight() | 取世間之光照,不用至亮之渲染光 |
| Texture 之法 | 釋義 |
|---|---|
.texture(id) | 貼圖資源之 id(如 "mtr:textures/block/pids.png") |
.uv(u1, v1, u2, v2) | UV 子矩形 |
.color(argb) | 染色 |
.pos(x, y) / .size(w, h) | 位置與尺寸 |
.z_order(z) / .layer(l) | 層級 |
.render_type("LIGHT_1") / .natural_light() | 以名舉層 / 取世間光照(同 Text) |
Rect(純色矩形)
mtr::Rect 映上游 JS 之 Rect 類(舊名 Rectangle,易名自上游 v2.3.0-prerelease.2 始;Java 類名如故)——繪 mtr:white.png 全 UV 之四邊形而通體染色,凡底色之塊、分隔之條、狀態之帶,莫便於斯:
mtr::Rect::create()
.color(0xFF00539F) // 不透明之染(預設 ARGB_WHITE)
.pos(2, rowY + 18)
.size(pids.width() - 4, 1) // 預設 20×20
.draw(ctx);
| Rect 之法 | 釋義 |
|---|---|
.color(argb) | 染色(預設白 ARGB_WHITE) |
.pos(x, y) / .size(w, h) | 位置與尺寸(預設 20×20) |
.render_type("LIGHT_2") | 以名舉層(預設 LIGHT_2) |
.natural_light() / .z_order(z) | 世間光照 / 層級(z=-1 則上下文自配之) |
配套之上下文法(PidsContext):
ctx.set_auto_z_ordering(bool)—— 自動 z 序(預設啟)ctx.set_z_order_step(step)—— 自動 z 序之步長(預設 0.0002)
渲染之層(2D 層之枚舉 MtrRenderLayer,與 mtr::Matrices 無涉):MTR_LAYER_TEXT 者文字,MTR_LAYER_LIGHT 者發光之體,MTR_LAYER_EXTERIOR / MTR_LAYER_INTERIOR 者外觀與內飾,與 MTR 之 QueuedRenderLayer 一致。
Matrices 與模型之繪
<mtr/matrices.hpp> 者,JS 全域 Matrices 之映也:變換入棧,compile() 編當前之棧為一組矩陣,書於幀之矩陣之區:
mtr::Matrices m;
m.translate(0.5f, 1.0f, 0.0f);
m.rotate_y_degrees(90.0f);
m.scale(1.0f, 1.0f, 1.0f);
ctx.draw_car_model(model_handle, car_index, &m); // 車輛
ctx.draw_model(model_handle, &m); // 裝飾 / 電梯
| 成員 | 釋義 |
|---|---|
translate(x, y, z) / scale(x, y, z) | 平移 / 縮放 |
rotate_x / rotate_y / rotate_z(radians) | 旋轉(弧度) |
rotate_x_degrees / …_y… / …_z…(deg) | 旋轉(角度) |
compile() | 編當前之姿入幀(返矩陣組之索引,以傳乎 draw 之呼) |
車輛上下文別具三法:draw_bogie_model(model, car, bogie, matrices) 司轉向架,play_car_sound(sound, car, x, y, z, volume, pitch) 司聲,play_ann_sound(sound, volume, pitch) 司報站之廣播(惟乘者聞之)。
模型之柄,出自宿主之服務:ctx.host()->acquire_model(user, "namespace:path/model.json") 以取之,release_model(user, handle) 以縱之;acquire_quad_model(...) 則以模型空間之頂點四+UV,構宿主所持之貼圖面片(化 GraphicsTexture 為可貼車廂之屏)。其細務見 C ABI 與宿主服務。
GraphicsTexture(像素畫布)
<mtr/gfx.hpp> 之 GraphicsTexture,留像素緩衝於君之模塊;遊戲之側所受,惟髒矩形之上傳而已——像素之據,不逐幀搬越其界:
struct LcdState {
mtr::GraphicsTexture tex; // 宜置於 State:與實例同其始終
};
void create(mtr::VehicleContext& ctx, LcdState& s, const mtr::Vehicle&) {
s.tex.create(ctx.input(), 512, 128); // 並向宿主註 GPU 紋理
// 貼紋理於車廂:host->acquire_quad_model(...) → draw_car_model(...)
}
void render(mtr::VehicleContext& ctx, LcdState& s, const mtr::Vehicle& vehicle) {
// 一曰繪像素(Gfx2D 或直用 set_pixel)
// 二曰惟上傳所變之區:
s.tex.upload(ctx.frame());
}
| 成員 | 釋義 |
|---|---|
create(input, w, h) | 配像素之緩衝(BGRA8 行主序),且於宿主側建 GPU 紋理;既返,則全體視為髒 |
pixels() / pixels32() | 徑取像素之指針(uint8_t* / uint32_t*) |
set_pixel(x, y, argb) | 書單像素而自積髒區 |
upload(frame) | 書當前髒矩形於幀像素之區(一 JCM_DRAW_TEXTURE_UPLOAD 記錄),隨即髒區復位 |
last_upload_bytes() | 前次上傳位元組之數——察疾之利器也 |
close(input) / 析構 | 釋宿主之 GPU 紋理 |
handle() / width() / height() / texture_bytes() | 宿主紋理之柄與尺寸之訊 |
upload() 所搬者,惟自前次上傳以來所變之包圍匣。靜態之景,一繪足矣;每幀惟動其所當動——跑馬燈也,閃爍之段也,進度之條也。車輛 LCD 閃爍 / 輪播若惟改一小條,則上傳之量,亦惟彼一小條而已。
同頭文件別供 LcdCanvas——本乎內建 5×7 點陣字體之 LCD 畫筆也(明滅二色,皆可配置),宜於經典點陣之屏。
Gfx2D 軟體光柵器
<mtr/gfx2d.hpp> 者,取 java.awt.Graphics2D 常用之子集,行為確定之軟體光柵器也,徑繪於 GraphicsTexture 之上。JS 資源包之中,fillRect / fillOval / drawLine / GeneralPath / clip / drawString 之邏輯,皆得機械而移植:
mtr::Gfx2D g(s.tex, ctx.host(), "jsblock:shanghai"); // 畫布+宿主字體
g.set_color(mtr::clr(12, 28, 44)); // 深底之色
g.fill_rect(0, 0, W, H);
g.push_clip(8, 8, W - 16, 40); // 裁剪之棧
g.set_color(mtr::clra(255, 205, 66, 255));
g.draw_text_centered(W / 2, 30, 18.0, "下一站 Next");
g.pop_clip();
| 基元 | 釋義 |
|---|---|
fill_rect / fill_round_rect / draw_round_rect | 矩形(圓角弧半徑之參) |
fill_oval / draw_oval | 橢圓填充 / 描邊(線寬) |
draw_line(x1, y1, x2, y2, lw) | 線段 |
fill_polygon(xs, ys, n) | 多邊形填充(與 GeneralPath 等價) |
push_clip / pop_clip | 裁剪匣之棧;諸基元先裁而後光柵,髒區亦受裁剪之約 |
draw_text / draw_text_centered / draw_text_compressed / draw_mixed_text | 文字(字體見下節) |
draw_logo_badge(x, y, w, h, bg, fg) | 圓角徽章之底 |
full_aa() / no_aa() | 一像素覆蓋率抗鋸齒之開關(預設關,映上游 fullAA() / noAA()):橢圓、圓角矩形、描邊、多邊形填充之緣,行整數 src-over 之合成;文字恆為宿主 TTF 抗鋸齒,不與焉 |
顏色之輔:mtr::clr(r, g, b) 與 mtr::clra(r, g, b, a)(一不透明,一帶 alpha),應 JS config.js 同名之函。半透明之色,行 src-over 之合成;不透明之色,則有快捷之途焉。
字體之制
字體之制凡三層,視其所可用者而自降焉:
| 層級 | 所覆 | 釋義 |
|---|---|---|
| 資源字體(首選) | 全 UTF-8 | 以字體資源之 id,傳於 Text::font("jsblock:shanghai") 與 Gfx2D 構造之第三參:用宿主真實之 FontMetrics 與 drawString,字距也,基線也,壓縮也,alpha 與裝置裁剪也,皆存焉——與 JS 端同一字體之管線 |
| 宿主 TTF 回呼 | CJK 等 | 無資源字體時,CJK 字形經宿主服務 rasterize_text 光柵之(映 JCM FontManager 之 TTF 集) |
| 內建 5×7 點陣字體 | ASCII / 拉丁 | 按所求之尺寸而縮放;按字形之寬窄,予比例之步(i/l/. 者窄,m/W 者寬)——text_width() 與實繪所用,同一組之數;JS 自適應字號與 5% 壓縮布局之算,得原樣移植;CJK 無宿主時,退為占位之框 |
內建字體度量之約:ascent 者 0.78 em,descent 者 0.22 em(約當 Arial / HanSans);CJK 全角,1.0 em 之步。資源字體之度量(宿主服務 measure_font_text),按真實字體而算之。
繼之:mtr::Api 與 Java 互通 —— 快照而外,萬物皆備焉。