cpp/bgi/demo_bgi.cpp · 10876 字节 · 下载原文
// demo_bgi.cpp —— **第 3 层:传统图形接口**(BGI / Borland Graphics Interface)
// demo_bgi.cpp — **Layer 3: the classic graphics interface** (BGI / Borland Graphics Interface)
//
// 与 `Examples/c/demo_bgi.c` 是**同一个画面、同一套接口**,用 C++ 前端再编一遍。
// It is **the same picture with the same interface** as `Examples/c/demo_bgi.c`, just compiled again with the C++ frontend.
// C 与 C++ 是两个独立前端,同一份源码两边行为不保证一致,所以两份都要有
// C and C++ are two independent frontends, and the same source is not guaranteed to behave the same on both, so both copies are needed
// (`test_bgi.c` / `test_bgi.cpp` 一直是**逐字节相同**的两份,就是这个理由)。
// (that is also why `test_bgi.c` / `test_bgi.cpp` have always been two **byte-identical** copies).
//
// ## 这一层的两个特点
// ## Two traits of this layer
//
// · **固定分辨率**:开一次 `VGAHI` 就是 640×480,程序里到处写死坐标。
// · **Fixed resolution**: opening `VGAHI` once means 640×480, and coordinates are hardcoded all over the program.
// 宿主负责把这块固定画布摆到真实屏幕上(本平台走 `ui_win_open_pc`,不随旋转重排)。
// The host is responsible for placing this fixed canvas onto the real screen (on this platform it goes through `ui_win_open_pc` and is not re-laid-out on rotation).
// · **索引色**:`setcolor(4)` 说的是「红」,不是 RGB `0x000004`。全套 16 个色号。
// · **Indexed colors**: `setcolor(4)` means "red", not the RGB value `0x000004`. A full set of 16 color numbers.
//
// `Lib/c/graphics.h` 把 BGI 的**函数名与语义**原样接过来,落笔换成平台的 `ui_*`。
// `Lib/c/graphics.h` takes BGI's **function names and semantics** over as-is, and swaps the actual drawing for the platform's `ui_*`.
// C++ 的 include 路径包含 `Lib/c`,所以 `#include <graphics.h>` 两边是**同一份**
// The C++ include path contains `Lib/c`, so `#include <graphics.h>` is **the same file** on both sides
// (C++ 没有自己的 BGI 头,也不需要 —— 这一层就是 C 的接口)。
// (C++ has no BGI header of its own, and needs none — this layer is simply the C interface).
//
// ## ⚠ 不调 `getch()` 收尾
// ## ⚠ Do not call `getch()` at the end
//
// 老程序常见的结尾是 `getch(); closegraph();`。`conio` 的 `getch()` 在本平台是"按行"的,
// The common ending in old programs is `getch(); closegraph();`. On this platform `conio`'s `getch()` is line-based,
// 图形窗口里按不了键 —— 调它会把程序挂在 `--timeout` 上(实测 30 秒)才结束。
// and you cannot press keys inside a graphics window — calling it hangs the program until `--timeout` (measured: 30 seconds) before it ends.
// 所以画完直接 `closegraph()`,正常返回。
// So after drawing, just call `closegraph()` and return normally.
//
// 跑法:命令行页输入 vml run examples/cpp/demo_bgi.cpp
// How to run: type vml run examples/cpp/demo_bgi.cpp on the command-line page
// 出图:vmlcli Examples/cpp/demo_bgi.cpp --frames /tmp/fr
// Frames: vmlcli Examples/cpp/demo_bgi.cpp --frames /tmp/fr
#include <vml_ui.h>
#include <graphics.h>
#define VBAR_X 40
#define VBAR_Y 92
int main()
{
int gd = DETECT;
int gm = 0;
int i;
int x, y;
int tri[8];
// 界面语言:开局查一次(`ui_scr_get_language` 是 syscall,别每帧调)—— 文案按它取
// UI language: queried once at startup (`ui_scr_get_language` is a syscall, do not call it every frame) — the text is picked by it
int Lang = ui_scr_get_language();
// ── 1. 开场三行(DETECT ⇒ 库自己挑,本平台挑出 VGA + VGAHI 640×480)──
// ── 1. Three opening lines (DETECT ⇒ the library picks for itself; here it picks VGA + VGAHI 640×480) ──
initgraph(&gd, &gm, "");
// ── 2. 铺底:`cleardevice` 整屏刷成当前背景色 ──
// ── 2. Background: `cleardevice` floods the whole screen with the current background color ──
setbkcolor(BLACK);
cleardevice();
// ── 3. 标题(索引 14 = 黄;字号 3 = 3×16 像素)──
// ── 3. Title (index 14 = yellow; font size 3 = 3×16 pixels) ──
setcolor(YELLOW);
settextstyle(DEFAULT_FONT, HORIZ_DIR, 3);
// ⚠ 竖档必须写 `TOP_TEXT`(**盒顶**落在 y),**不能写 0** —— 0 是 `BOTTOM_TEXT`
// ⚠ The vertical setting must be `TOP_TEXT` (**box top** at y), and **must not be 0** — 0 is `BOTTOM_TEXT`
// (盒**底**落在 y)。字号 3 的盒高是 48px,写 0 的话整块标题被顶到屏幕外、
// (box **bottom** at y). The box height at font size 3 is 48px, so writing 0 pushes the whole title off the screen,
// 只剩底部十来行可见(`outtextxy` 的 y 是**盒顶**,这是 BGI 的缺省对齐)。
// leaving only the bottom dozen or so lines visible (`outtextxy`'s y is the **box top**, which is BGI's default alignment).
settextjustify(CENTER_TEXT, TOP_TEXT);
outtextxy(getmaxx() / 2, 12, Lang == 0 ? "BGI 传统图形接口 / demo_bgi.cpp" : "BGI legacy graphics API / demo_bgi.cpp");
settextstyle(DEFAULT_FONT, HORIZ_DIR, 1);
// `0` = `BOTTOM_TEXT`:正文行按"盒底贴着 y"排。
// `0` = `BOTTOM_TEXT`: body lines are laid out with the box bottom against y.
// ⚠ **别改成 `TOP_TEXT`** —— 那会把下面每一行整体再下移约 13px,底部会被顶出画布。
// ⚠ **Do not change it to `TOP_TEXT`** — that shifts every line below down by about another 13px and pushes the bottom off the canvas.
settextjustify(LEFT_TEXT, 0);
// y 取 74(不是 62):上面那行标题按 TOP 排时盒子占到 y=60,得给它让出位置
// y is 74 (not 62): laid out with TOP, the title line above occupies the box up to y=60, so we have to leave room for it
setcolor(LIGHTGRAY);
outtextxy(20, 74, "fixed resolution 640x480, 16-color indexed palette (setcolor 0..15)");
// ── 4. 16 色色带(这一层「索引色」最直观的一张图)──
// ── 4. The 16-color band (the most direct picture of "indexed colors" in this layer) ──
for (i = 0; i < 16; i++) {
setfillstyle(SOLID_FILL, i);
bar(VBAR_X + i * 34, VBAR_Y, VBAR_X + i * 34 + 30, VBAR_Y + 34);
}
setcolor(WHITE);
rectangle(VBAR_X - 1, VBAR_Y - 1, VBAR_X + 16 * 34 + 1, VBAR_Y + 35);
setcolor(LIGHTGRAY);
outtextxy(VBAR_X, VBAR_Y + 50, "0 black 1 blue 2 green 3 cyan 4 red 5 magenta 6 brown 7 lightgray");
outtextxy(VBAR_X, VBAR_Y + 66, "8 darkgray 9 lightblue 10 lightgreen 11 lightcyan 12 lightred 13 lightmagenta 14 yellow 15 white");
// ── 5. 直线 / 折线(moveto + lineto / linerel 是老程序的常规姿势)──
// ── 5. Lines / polylines (moveto + lineto / linerel is the usual posture of old programs) ──
setcolor(LIGHTGREEN);
line(40, 210, 200, 210);
moveto(40, 230);
lineto(120, 230);
linerel(80, 0);
setcolor(LIGHTCYAN);
moveto(40, 250);
linerel(40, -20);
linerel(40, 20);
linerel(40, -20);
linerel(40, 20);
setcolor(LIGHTGRAY);
outtextxy(40, 262, "line / moveto / lineto / linerel (polyline is open)");
// ── 6. 矩形与两种"条" ──
// ── 6. Rectangles and the two kinds of "bar" ──
setcolor(YELLOW);
rectangle(250, 205, 370, 265);
setfillstyle(SOLID_FILL, LIGHTBLUE);
bar(380, 205, 450, 265);
setfillstyle(SOLID_FILL, GREEN);
setcolor(WHITE);
bar3d(465, 215, 545, 265, 14, 1);
setcolor(LIGHTGRAY);
outtextxy(250, 272, "rectangle / bar / bar3d");
// ── 7. 圆与椭圆 ──
// ── 7. Circles and ellipses ──
setcolor(LIGHTMAGENTA);
circle(80, 330, 40);
circle(80, 330, 24);
setfillstyle(SOLID_FILL, BROWN);
fillellipse(200, 330, 56, 34);
setcolor(LIGHTGRAY);
ellipse(200, 330, 0, 360, 70, 44);
outtextxy(40, 388, "circle / fillellipse / ellipse");
// ── 8. 弧与扇形(只有"刷子接口"画得了这两样,见 graphics.h 的说明)──
// ── 8. Arcs and pies (only the "brush interface" can draw these two; see the notes in graphics.h) ──
setcolor(LIGHTRED);
arc(330, 330, 30, 150, 40);
setcolor(WHITE);
setfillstyle(SOLID_FILL, YELLOW);
pieslice(420, 330, 200, 340, 40);
setcolor(LIGHTGRAY);
outtextxy(290, 388, "arc (stroke) / pieslice (filled)");
// ── 9. 多边形(⚠ BGI 的顶点表**首点要重复一次**才闭合,老规矩)──
// ── 9. Polygons (⚠ in BGI the vertex list **must repeat the first point** to close, an old rule) ──
tri[0] = 520; tri[1] = 370;
tri[2] = 560; tri[3] = 300;
tri[4] = 600; tri[5] = 370;
tri[6] = tri[0]; tri[7] = tri[1];
setcolor(LIGHTGREEN);
drawpoly(4, tri);
setfillstyle(SOLID_FILL, LIGHTMAGENTA);
setcolor(WHITE);
fillpoly(4, tri);
setcolor(LIGHTGRAY);
outtextxy(520, 388, "drawpoly / fillpoly");
// ── 10. 像素与读回 ──
// ── 10. Pixels and read-back ──
for (y = 0; y < 6; y++) {
for (x = 0; x < 16; x++) {
// 棋盘格:两种索引色交替,一眼看出 putpixel 生效了
// Checkerboard: two indexed colors alternating, so you can see at a glance that putpixel took effect
if ((x + y) % 2 == 0) {
setcolor(WHITE);
} else {
setcolor(BLUE);
}
putpixel(60 + x * 8, 410 + y * 8, getcolor());
}
}
setcolor(LIGHTGRAY);
outtextxy(40, 466, "putpixel / getcolor");
// ── 11. 三档对齐(老程序居中排版靠 settextjustify)──
// ── 11. The three alignment settings (old programs center their layout with settextjustify) ──
setcolor(WHITE);
settextstyle(DEFAULT_FONT, HORIZ_DIR, 2);
settextjustify(LEFT_TEXT, 0);
outtextxy(300, 405, "LEFT");
settextjustify(CENTER_TEXT, 0);
outtextxy(430, 405, "CENTER");
settextjustify(RIGHT_TEXT, 0);
outtextxy(620, 405, "RIGHT");
settextstyle(DEFAULT_FONT, HORIZ_DIR, 1);
settextjustify(LEFT_TEXT, 0);
outtextxy(300, 430, "settextstyle(size) + settextjustify(LEFT/CENTER/RIGHT)");
// ── 12. 收尾(不调 getch(),理由见文件头)──
// ── 12. Wrap-up (no getch() call; see the file header for why) ──
ui_2d_present();
closegraph();
return 0;
}