画点
点是各种图形的基础,要实现图形处理就先从画点开始。创建窗口的程序之前写过了,忘记的话往前翻翻找一下。再给窗口来一个黑色背景,窗口名就叫“夜空中最亮的星”吧。
画点API式样:
画点API:
EDX=11
EBX=窗口句柄
ESI=显示位置的x的坐标
EDI=显示位置的y坐标
EAX=色号
a_nask.nas节选:
_api_point: ; void api_point(int win, int x, int y, int col);
PUSH EDI
PUSH ESI
PUSH EBX
MOV EDX,11
MOV EBX,[ESP+16] ; win
MOV ESI,[ESP+20] ; x
MOV EDI,[ESP+24] ; y
MOV EAX,[ESP+28] ; col
INT 0x40
POP EBX
POP ESI
POP EDI
RET
夜空中最亮的星,star.c:
int api_openwin(char *buf, int xsiz, int ysiz, int col_inv, char *title);
void api_boxfilwin(int win, int x0, int y0, int x1, int y1, int col);
void api_initmalloc(void);
char *api_malloc(int size);
void api_point(int win, int x, int y, int col);
void api_end(void);
void HariMain(void)
{
char *buf;
int win;
api_initmalloc();
buf = api_malloc(150 * 100);
win = api_openwin(buf, 450, 300, -1, "The brightest stars");
api_boxfilwin(win, 6, 26, 443, 293, 0 /* 黑色 */);
api_point(win, 225, 150, 3 /* 黄色 */);
api_end();
}
make run一下——

“夜空中最亮的星”好像并没有那么闪亮,屏幕上有点灰还真不容易看的见。
那么我们来让星星布满整个夜空吧(听起来有点中二),星星也可以不是黄色的,红色、蓝色的星星也可以有,我们来画一个彩色的星空好了。
彩色星空,stars.c
int api_openwin(char *buf, int xsiz, int ysiz, int col_inv, char *title);
void api_boxfilwin(int win, int x0, int y0, int x1, int y1, int col);
void api_initmalloc(void);
char *api_malloc(int size);
void api_point(int win, int x, int y, int col);
void api_end(void);
int rand(void); /* 0 ~32767随机数*/
void HariMain(void)
{
char *buf;
int win, i, x, y ,c;
api_initmalloc();
buf = api_malloc(150 * 100);
win = api_openwin(buf, 450, 300, -1, "stars");
api_boxfilwin(win, 6, 26, 443, 293, 0 /* 黑色 */);
for (i = 0; i < 500; i++) {
x = (rand() % 437) + 6;
y = (rand() % 267) + 26 ;
c = rand() % 15 ;
api_point(win, x, y, c /* 黄色 */);
}
api_end();
}
rand函数我们比较熟悉,用于产生0 ~ 32767的随机数,而对437取余就会得到0 ~ 436的随机数。
make run一下——

画的密密麻麻,这回看清楚了,不过彩色的星空好像没想象中好看呢。
画直线
接下来我们实现画直线的功能,画直线我们需要知道起始点的坐标,直线的颜色。
API式样:
在窗口上画直线
EDX=13
EBX=窗口句柄
EAX=x0
ECX=y0
ESI=x1
EDI=y1
EBP=色号
a_nask.nas节选:
_api_linewin: ; void api_linewin(int win, int x0, int y0, int x1, int y1, int col);
PUSH EDI
PUSH ESI
PUSH EBP
PUSH EBX
MOV EDX,13
MOV EBX,[ESP+20] ; win
MOV EAX,[ESP+24] ; x0
MOV ECX,[ESP+28] ; y0
MOV ESI,[ESP+32] ; x1
MOV EDI,[ESP+36] ; y1
MOV EBP,[ESP+40] ; col
INT 0x40
POP EBX
POP EBP
POP ESI
POP EDI
RET
画彩色直线,lines.c:
int api_openwin(char *buf, int xsiz, int ysiz, int col_inv, char *title);
void api_initmalloc(void);
char *api_malloc(int size);
void api_refreshwin(int win, int x0, int y0, int x1, int y1);
void api_linewin(int win, int x0, int y0, int x1, int y1, int col);
void api_end(void);
void HariMain(void)
{
char *buf;
int win, i;
api_initmalloc();
buf = api_malloc(160 * 100);
win = api_openwin(buf, 460, 300, -1, "lines");
for (i = 0; i < 8; i++) {
api_linewin(win + 1, 8, i * 30 + 26, 450, i * 30 + 26, i);
}
api_refreshwin(win, 6, 26, 454, 290);
api_end();
}
执行make run——

画出来的直线,看起来有点像小时候练习拼音用的那种拼音簿。
左右移动
接下来我们可以做个好玩点的,比如一个能动的小程序。
walk.c节选:
void HariMain(void)
{
char *buf;
int win, i, x, y;
api_initmalloc();
buf = api_malloc(160 * 100);
win = api_openwin(buf, 160, 100, -1, "walk");
api_boxfilwin(win, 4, 24, 155, 95, 0 /* 黑色 */);
x = 76;
y = 56;
api_putstrwin(win, x, y, 3 /* 黄色 */, 1, "@");
for (;;) {
i = api_getkey(1);
api_putstrwin(win, x, y, 0 /* 黑色 */, 1, "@"); /* 用黑色擦除 */
if (i == '4' && x > 4) { x -= 8; }
if (i == '6' && x < 148) { x += 8; }
if (i == '8' && y > 24) { y -= 8; }
if (i == '2' && y < 80) { y += 8; }
if (i == 0x0a) { break; } /* 按回车键结束 */
api_putstrwin(win, x, y, 3 /* 黄色 */, 1, "@");
}
api_closewin(win);
api_end();
}
这个程序可以让“@”在窗口中移动,按键 2 、 4、 6、 8分别对应上下左右,按键 5 回到窗口中心。
执行make run——

注:本文参照《30天自制操作系统》制作,感谢各位的持续关注,原著源码链接见第十九篇。
在30天自制操作系统的旅程中,我们从画点开始,创建了一个名为'夜空中最亮的星'的窗口,并实现了彩色星空的绘制,通过 rand 函数生成不同颜色的星星。接着,我们添加了画直线的功能,允许用户指定起点、颜色。最后,通过键盘控制,实现了一个可以移动的“@”字符,为操作系统增添动态效果。
477

被折叠的 条评论
为什么被折叠?



