2 画点(harib20b)

终于进入今天的正题——图形处理了。虽然我们已经可以描绘字符和方块了,但现在却还不能画点呢。其实仔细想想,只要能画点就可以画出任何图形,画点简直是基本中的基本。然而就是这最基本的东西到现在都还没有实现,这是怎么搞的嘛!好了,我们马上来编写。

编写画点的API太麻烦了,笔者想要不就用画方块的API画一个1像素见方的小方块来代替好了……不过这样一来各位读者肯定会发飙的,还是不耍小聪明了,认认真真来编写这个API吧(笑)。

在窗口中画点

EDX =11

EBX =窗口句柄

ESI =显示位置的x坐标

EDI =显示位置的y坐标

EAX =色号

嗯,看上去挺简单的,三两下就能写出来了。

本次的console.c节选

  1. int *hrb_api(int edi, int esi, int ebp, int esp, int ebx, int edx, int ecx, int eax)
  2. {
  3. (中略)
  4. } else if (edx == 11) {
  5. sht = (struct SHEET *) ebx;
  6. sht->buf[sht->bxsize * edi + esi] = eax;
  7. sheet_refresh(sht, esi, edi, esi + 1, edi + 1);
  8. }
  9. return 0;
  10. }

好,完工啦。

■■■■■

我们写一个什么样的应用程序好呢?可以画点的确意味着可以画出任何图形,不过这样一来就更不知道该干啥了。要不就在黑色的背景上画一个黄色的点吧,题曰“最亮的星”。

本次的a_nask.nas节选

  1. _api_point: ; void api_point(int win, int x, int y, int col);
  2. PUSH EDI
  3. PUSH ESI
  4. PUSH EBX
  5. MOV EDX,11
  6. MOV EBX,[ESP+16] ; win
  7. MOV ESI,[ESP+20] ; x
  8. MOV EDI,[ESP+24] ; y
  9. MOV EAX,[ESP+28] ; col
  10. INT 0x40
  11. POP EBX
  12. POP ESI
  13. POP EDI
  14. RET

本次的star1.c

  1. int api_openwin(char *buf, int xsiz, int ysiz, int col_inv, char *title);
  2. void api_boxfilwin(int win, int x0, int y0, int x1, int y1, int col);
  3. void api_initmalloc(void);
  4. char *api_malloc(int size);
  5. void api_point(int win, int x, int y, int col);
  6. void api_end(void);
  7. void HariMain(void)
  8. {
  9. char *buf;
  10. int win;
  11. api_initmalloc();
  12. buf = api_malloc(150 * 100);
  13. win = api_openwin(buf, 150, 100, -1, "star1");
  14. api_boxfilwin(win, 6, 26, 143, 93, 0 /*黑色*/);
  15. api_point(win, 75, 59, 3 /*黄色*/);
  16. api_end();
  17. }

和之前一样,这个程序也相当简单,不过貌似光看名字就让人感觉这个程序很有料啊(笑)。

我们来“make run”,运行成功,意料之中。不过说起来,要是这么简单的程序还出错的话也太对不起笔者的实力了。

2 画点(harib20b) - 图1

最亮的星星找到了!

■■■■■

做这种小程序当然会成功啦,所以没有以往的那种成就感啊,最好能再锦上添花一下。对了,我们就多画些星星吧,就画30个左右。

本次的stars.c

  1. int api_openwin(char *buf, int xsiz, int ysiz, int col_inv, char *title);
  2. void api_boxfilwin(int win, int x0, int y0, int x1, int y1, int col);
  3. void api_initmalloc(void);
  4. char *api_malloc(int size);
  5. void api_point(int win, int x, int y, int col);
  6. void api_end(void);
  7. int rand(void); /*产生0~32767之间的随机数*/
  8. void HariMain(void)
  9. {
  10. char *buf;
  11. int win, i, x, y;
  12. api_initmalloc();
  13. buf = api_malloc(150 * 100);
  14. win = api_openwin(buf, 150, 100, -1, "stars");
  15. api_boxfilwin(win, 6, 26, 143, 93, 0 /*黑色*/);
  16. for (i = 0; i < 50; i++) {
  17. x = (rand() % 137) + 6;
  18. y = (rand() % 67) + 26;
  19. api_point(win, x, y, 3 /*黄色*/);
  20. }
  21. api_end();
  22. }

我们来讲解一下这里出现的rand函数。这个函数和sprintf、strcmp一样,都是编译器自带的函数,它的功能是随机产生位于0~32767的一个数字,术语称为“随机数”,这个函数也可以称为“骰子函数”。

“%”这个运算符的功能是求除法运算的余数,在舍入取整的地方我们曾经讲到过,所以这里就一笔带过吧。将随机数的值除以123求余,结果一定落在0~122之间,也就是说,我们可以得到一个0~122的随机数。

其实所谓随机数也是通过计算得到的,电脑中不可能真有一个骰子,即便重新运行应用程序,得到的结果也总是一样的。因此大家“make run”之后所看到的星空,和笔者这里看到的应该是一样的。

于是我们来“make run”。出来了!

2 画点(harib20b) - 图2

呼,星空真美丽呀!

可能有人会问,这些星座我怎么都没见过?要从哪个角度看星空才能看到这样的排列啊?咳咳,其实呢,这是从笔者的朋友所居住的外星球上所看到的星空哦。下次他还会不会乘坐UFO来地球玩呢……呵呵。