2 画点(harib20b)
终于进入今天的正题——图形处理了。虽然我们已经可以描绘字符和方块了,但现在却还不能画点呢。其实仔细想想,只要能画点就可以画出任何图形,画点简直是基本中的基本。然而就是这最基本的东西到现在都还没有实现,这是怎么搞的嘛!好了,我们马上来编写。
编写画点的API太麻烦了,笔者想要不就用画方块的API画一个1像素见方的小方块来代替好了……不过这样一来各位读者肯定会发飙的,还是不耍小聪明了,认认真真来编写这个API吧(笑)。
在窗口中画点
EDX =11
EBX =窗口句柄
ESI =显示位置的x坐标
EDI =显示位置的y坐标
EAX =色号
嗯,看上去挺简单的,三两下就能写出来了。
本次的console.c节选
int *hrb_api(int edi, int esi, int ebp, int esp, int ebx, int edx, int ecx, int eax)
{
(中略)
} else if (edx == 11) {
sht = (struct SHEET *) ebx;
sht->buf[sht->bxsize * edi + esi] = eax;
sheet_refresh(sht, esi, edi, esi + 1, edi + 1);
}
return 0;
}
好,完工啦。
■■■■■
我们写一个什么样的应用程序好呢?可以画点的确意味着可以画出任何图形,不过这样一来就更不知道该干啥了。要不就在黑色的背景上画一个黄色的点吧,题曰“最亮的星”。
本次的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
本次的star1.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, 150, 100, -1, "star1");
api_boxfilwin(win, 6, 26, 143, 93, 0 /*黑色*/);
api_point(win, 75, 59, 3 /*黄色*/);
api_end();
}
和之前一样,这个程序也相当简单,不过貌似光看名字就让人感觉这个程序很有料啊(笑)。
我们来“make run”,运行成功,意料之中。不过说起来,要是这么简单的程序还出错的话也太对不起笔者的实力了。
最亮的星星找到了!
■■■■■
做这种小程序当然会成功啦,所以没有以往的那种成就感啊,最好能再锦上添花一下。对了,我们就多画些星星吧,就画30个左右。
本次的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;
api_initmalloc();
buf = api_malloc(150 * 100);
win = api_openwin(buf, 150, 100, -1, "stars");
api_boxfilwin(win, 6, 26, 143, 93, 0 /*黑色*/);
for (i = 0; i < 50; i++) {
x = (rand() % 137) + 6;
y = (rand() % 67) + 26;
api_point(win, x, y, 3 /*黄色*/);
}
api_end();
}
我们来讲解一下这里出现的rand函数。这个函数和sprintf、strcmp一样,都是编译器自带的函数,它的功能是随机产生位于0~32767的一个数字,术语称为“随机数”,这个函数也可以称为“骰子函数”。
“%”这个运算符的功能是求除法运算的余数,在舍入取整的地方我们曾经讲到过,所以这里就一笔带过吧。将随机数的值除以123求余,结果一定落在0~122之间,也就是说,我们可以得到一个0~122的随机数。
其实所谓随机数也是通过计算得到的,电脑中不可能真有一个骰子,即便重新运行应用程序,得到的结果也总是一样的。因此大家“make run”之后所看到的星空,和笔者这里看到的应该是一样的。
于是我们来“make run”。出来了!
呼,星空真美丽呀!
可能有人会问,这些星座我怎么都没见过?要从哪个角度看星空才能看到这样的排列啊?咳咳,其实呢,这是从笔者的朋友所居住的外星球上所看到的星空哦。下次他还会不会乘坐UFO来地球玩呢……呵呵。