30天自制操作系统——第二十二天图形处理

在30天自制操作系统的旅程中,我们从画点开始,创建了一个名为'夜空中最亮的星'的窗口,并实现了彩色星空的绘制,通过 rand 函数生成不同颜色的星星。接着,我们添加了画直线的功能,允许用户指定起点、颜色。最后,通过键盘控制,实现了一个可以移动的“@”字符,为操作系统增添动态效果。

画点

点是各种图形的基础,要实现图形处理就先从画点开始。创建窗口的程序之前写过了,忘记的话往前翻翻找一下。再给窗口来一个黑色背景,窗口名就叫“夜空中最亮的星”吧。

画点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天自制操作系统》制作,感谢各位的持续关注,原著源码链接见第十九篇。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值