当前,我们的系统已经发展到了一定较为完善的程度,当然最为一个练习系统,它不可能跟专业的windows或linux相比,但麻雀虽小五腑俱全,我们的系统还是能支持用户在其上面开发出不少复杂但又有趣的应用程序的,它所展现的功能完全可以称得上是一个鲁棒的操作系统。

我们看看第一个有趣的应用程序:不规则窗口。
很多独居特色的应用程序,一大特点之一就是不规则窗口,奇形怪状的窗体形态确实容易给人耳目一新的感觉,不规则窗口主要是把窗体的某部分用透明色来显现,现在我们就来尝试一下,在app.c中完成以下代码:

void main() {int win;char buf[150*70];win = api_openwin(buf, 150, 70, 255, "noterec");api_boxfilwin(win, 0, 50, 34, 69, 255);api_boxfilwin(win, 115, 50, 149, 69, 255);api_boxfilwin(win, 50, 30, 99, 49, 255);for (;;) {if (api_getkey(1) == 0x1c) {break;}}api_closewin(win);return;
}

上面代码先创建一个窗体,然后把窗体的若干个部分填充成透明色,于是窗体形态变成一个有趣的非矩形,上面代码完成后,运行起来情况如下:

接下来我们再看看一个更有意思的用户程序,线团火球!在app.c中添加代码如下:

struct POINT {int x;int y;
};void main() {int win;char buf[216*237];struct POINT table[18] = {{204,129},{195,90},{172,58},{137,38},{98,34},{61,46},{31,73},{15,110},{15,148},{31,185},{61,212},{98,224},{137,220},{172,200},{195,168},{204,129}};win = api_openwin(buf, 216, 237, -1, "bball");api_boxfilwin(win, 8, 29, 207, 228, 255);int i = 0, j = 0, dis = 0;for (i = 0; i <= 14; i++) {for(j = i+1; j <= 15; j++) {dis = j - i;if (dis >= 8) {dis = 15 - dis;}if (dis != 0) {api_linewin(win, table[i].x, table[i].y,table[j].x, table[j].y, 8-dis);}}}api_refreshwin(win, 8, 29, 207, 228);for (;;) {if (api_getkey(1) == 0x1c) {break;}}api_closewin(win);return;
}

上面代码运行后效果如下:

绘制出来的图案是不是非常惊艳,非常绚丽夺目,我们的系统平台还是蛮给力的。

接下来我们要放大招,开发一个有趣的星球大战游戏。星球大战是一款像素级游戏,它的形态让我想起早年,大概是98年,所谓电脑刚传入中国,系统还是DOS时,当时上电脑课最喜欢的莫过于有游戏可玩。代码比较长,我们分段实现,首先在app.c中输入以下代码:


#define win_width 240void putstr(int win, char *winbuf,char * charset,int x, int y, int col, unsigned char *s) {int c, x0, i = 0, j;char *p, *q, t[2];x = x*8+8;y = y*16+29;x0 = x;while (s[i] != 0) {i++;}api_boxfilwin(win, 8, y, win_width - 8 , y+15, 0);q = winbuf + y * win_width; t[1] = 0;for (;;) {c = *s;if (c == 0) {break;}if (c != ' ') {if ('a' <= c && c <= 'h') {p = charset + 16 * (c-'a');q += x;for (i = 0; i < 16; i++) {if ((p[i] & 0x80) != 0) {q[0] = col;}if ((p[i] & 0x40) != 0) {q[1] = col;}if ((p[i] & 0x20) != 0) {q[2] = col;}if ((p[i] & 0x10) != 0) {q[3] = col;}if ((p[i] & 0x08) != 0) {q[4] = col;}if ((p[i] & 0x04) != 0) {q[5] = col;}if ((p[i] & 0x02) != 0) {q[6] = col;}if ((p[i] & 0x01) != 0) {q[7] = col;}q += win_width; }q -= win_width * 16 + x;} else if((c>='i' && c <= 'z') || (c>='A' && c <= 'Z')){t[0] = *s;api_putstrwin(win, x, y, col,1,t);}}s++;x += 8;}api_refreshwin(win,  8, y, win_width - 8, y+15);
}void main() {int win, i, j, ix, iy, fx;char winbuf[win_width * 237], invstr[32*6], s[12];char* p = winbuf;char invstr0[36] = {' ' , 'a','b','c','d',' ' ,'a','b','c','d', ' ','a','b','c','d',' ',  'a','b','c','d',' ','a','b','c','d', ' ',0};char charset[18 * 8] = {0x00, 0x00, 0x00, 0x43, 0x5f, 0x5f, 0x5f, 0x7f,0x1f, 0x1f, 0x1f, 0x1f, 0x00, 0x20, 0x3f, 0x00,0x00, 0x0f, 0x7f, 0xff, 0xcf, 0xcf, 0xcf, 0xff,0xff, 0xe0, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x00,0x00, 0xf0, 0xfe, 0xff, 0xf3, 0xf3, 0xf3, 0xff,0xff, 0x07, 0xff, 0xff, 0x03, 0x03, 0x03, 0x00,0x00, 0x00, 0x00, 0xc2, 0xfa, 0xfa, 0xfa, 0xfe,0xf8, 0xf8, 0xf8, 0xf8, 0x00, 0x04, 0xfc, 0x00,0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,0x01, 0x43, 0x47, 0x4f, 0x5f, 0x7f, 0x7f, 0x00,0x18, 0x7e, 0xff, 0xc3, 0xc3, 0xc3, 0xc3, 0xff,0xff, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0x00,0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,0x80, 0xc2, 0xe2, 0xf2, 0xfa, 0xfe, 0xfe, 0x00,0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00};win = api_openwin(winbuf, win_width, 237, -1, "invader");api_boxfilwin(win, 8, 29, win_width - 6, 228, 0);//putstr(win, winbuf, 22, 0, 7, "HIGH:00000000");restart:fx = 18;char fly[8] = {'e', 'f', 'g', 0};putstr(win, winbuf, charset, 18, 11, 6, fly);nextgroup:ix =  7;iy = 1;int invline = 6;for (i = 0; i < 3; i++) {for (j = 0; j < 20; j++) {invstr[i * 32 + j] = invstr0[j];}putstr(win, winbuf,charset, ix, iy + i, 2, invstr + i * 32);}api_refreshwin(win, 8, 29, 207, 228);for(;;) {if (api_getkey(1) == 0x1c) {break;}}api_closewin(win);return;
}

putstr函数有两个功能,当输入字符在’a’到’h’之间时,它根据点阵表charset,通过设置某个像素点的颜色来绘制图像。其中参数x,y是图像起始坐标,最后一个参数s用来控制图像绘制的方式,例如当最后的s内容为”abcd”时,该函数从charset表中取出前四行数据,其中每一个数值都在告诉代码在绘制哪一个像素点,它的绘制原理与早前我们讲解的如何绘制字符是一样的。我们先看看上面代码运行起来后的情况:

代码绘制了三排外星人和一架战斗机,在main函数中,代码:

restart:fx = 18;char fly[8] = {'e', 'f', 'g', 0};putstr(win, winbuf, charset, 18, 11, 6, fly);

绘制的就是图案底部的战斗机,而代码片段:

nextgroup:ix =  7;iy = 1;int invline = 6;for (i = 0; i < 3; i++) {for (j = 0; j < 20; j++) {invstr[i * 32 + j] = invstr0[j];}putstr(win, winbuf,charset, ix, iy + i, 2, invstr + i * 32);}

则是绘制了图案上方的三排外星人。

接着我们要想办法让图像动起来,这就需要使用到我们前面做过的定时器。首先,我们先添加代码,让飞机根据我们按键输入以便实现左右移动,因此我们添加日下代码:

void putstr(int win, char *winbuf,char * charset,int x, int y, int col, unsigned char *s) {....}void waitting(int i, int timer, char* keyflag) {int j;if (i > 0) {api_settimer(timer, i);i = 128;} else {i = 0x1c;}for(;;) {j = api_getkey(1);if (i == j) {break;}if (j == 0x24) {//key jkeyflag[0] = 1;}if (j == 0x25) {//key kkeyflag[1] = 1;}if (j == 0x39) {//key spacekeyflag[2] = 1;}}return;
}void main() {char keyflag[6];....nextgroup:....keyflag[0] = 0;keyflag[1] = 0;keyflag[2] = 0;for(;;) {waitting(4, timer, keyflag);if (keyflag[0] != 0 && fx > 1) {//fighter fly to leftfx--;fly[0] = 'e', fly[1] = 'f', fly[2] = 'g', fly[3] = ' ';fly[4] = 0;putstr(win, winbuf, charset, fx, 11, 6, fly); keyflag[0] = 0;}if (keyflag[1] != 0 && fx < 24) {fx++;fly[0] = ' ', fly[1] = 'e', fly[2] = 'f', fly[3] = 'g';fly[4] = 0;putstr(win, winbuf, charset, fx, 11, 6, fly);keyflag[1] = 0;}}
}

waitting 函数的作用是等待定时器放回结果,同时监控键盘按键,如果用户在键盘上点击按键’j’,那么它通过调用api_getkey就能获得对应扫描码,也就是0x24, 如果用户点击按键’k’,那么对应的扫描码为0x25,在main函数里,我们添加一个for循环,在里面我们调用waitting函数获取用户按键信息,当用户按下’j’后,我们把飞机向左移动一个单位,然后刷新窗口,如果用户点击的是k,那么我们把飞机向右移动一个单位,然后刷新窗口,上面代码完成后,编译加载到虚拟机,启动程序后,尝试按下按键’j’,我们可以发现飞机一直向左移动,知道抵达窗口左边界为止,效果如下:

飞机能移动后,我们需要外星人也飘动起来,因此我们添加如下代码:

void main () {
....for(;;) {waitting(4, timer, keyflag);....//move aliensif (movewait != 0) {movewait--;} else {movewait = movewait0;if (ix + idir > 12 || ix + idir < 1) {if (iy + invline == 13) {//game overbreak;}idir = -idir;putstr(win, winbuf, charset,ix + 1, iy, 0, "  ");iy++;} else {ix += idir;}for (i = 0; i < invline; i++) {putstr(win, winbuf,charset, ix, iy + i, 2, invstr + i * 32);}} }
}

上面代码先把外星人向右移动,直到边缘时,iy++,这就使得外星人向下移动,与此同时idir = -idir; 使得外星人开始反向移动,一直到左边边缘,这种移动一直在进行,直到外星人的y坐标做够大时,游戏结束。

从上面我们可以看到,飞机挪到左边时,外星人移动到右边。接着我们要实现用户按下空格键时,飞机能发射炮弹,并且判断一旦炮弹击中外星人后,外星人会被消灭掉,这个功能的实现主要依赖下面代码:

for(;;) {if (laserwait != 0) {laserwait--;keyflag[2] = 0;}....//draw laser bulletif (ly > 0) {if (ly < 8) {if (ix < lx && lx < ix + 25 && iy <= ly && ly < iy + invline) {putstr(win, winbuf, charset, ix, ly, 2, invstr + (ly - iy) * 32);}//if (ix < lx ...)else {putstr(win, winbuf, charset, lx, ly, 0, "  ");}}//if(ly < 13)ly--;if (ly > 0) {char c[2] = {'h', 0};putstr(win, winbuf,charset, lx, ly, 3, c);} // if(ly > 0)if (ix < lx && lx < ix + 25 && iy <= ly && ly < iy + invline) {p = invstr + (ly - iy) * 32 + (lx - ix);if (*p != ' ' ) {//hitfor(p--; *p != ' '; p--) {}for (i = 1; i < 5; i++) {p[i] = ' ';}putstr(win, winbuf, charset, ix, ly, 2, invstr+(ly-iy)*32);for(; invline > 0; invline--) {for(p = invstr + (invline-1)*32; *p != 0; p++) {if (*p != ' ') {goto alive;}}} gameover://hit all movewait0 -= movewait0 / 3;char gameover[12] = {'G','A','M','E',' ','O','V','E','R'};putstr(win, winbuf, charset, 15, 6, 1, gameover);waitting(10, timer, keyflag);goto nextgroup;alive:ly = 0;}} //if(ix < lx...)}//if (ly > 0)}
}

上面代码使得,当用户点击空格键时,程序就准备从飞机处发射出导弹。代码片段:

 if (ly > 0) {char c[2] = {'h', 0};putstr(win, winbuf,charset, lx, ly, 3, c);} // if(ly > 0)

它的作用是,如果用户点击了空格,同时外星人还没有入侵到飞机所在的势力范围,那么我们就绘制一个从底部向上发射的炮弹,接下来的系列代码是,当炮弹发射后,判断炮弹是否击中外星人,如果打到了,被击中的外星人要从屏幕上消失掉,这部分逻辑实现的情况如下:

从上图可以看到,黄色的竖线块就是飞机发射出的导弹,中间这排外星人被击毙了,所以在屏幕上没有显示出来。如果外星人下降到飞机所在高度,那么有游戏结束,如果外星人全部被击毙,那么战机成功保卫地球,游戏也结束:

游戏结束后,”GAME OVER”会打印到界面上,然后整个游戏重来一遍。

这个星球大战游戏是系统内核开发到此,我们做过的最为复杂的客户程序,它调用了几乎所有api,例如窗口绘制,字符串输出,时钟,键盘监听等等,这个复杂程序的成功运行,在一定程度上表明,我们的系统内核具备一定程度的复杂性和鲁棒性,虽然它不可与专业操作系统同日而语,但就算它再简单,再复杂,它也对得起一个“操作系统”的称号。

更详细的讲解和代码调试演示过程,请参看视频
Linux kernel Hacker, 从零构建自己的内核

更多技术信息,包括操作系统,编译器,面试算法,机器学习,人工智能,请关照我的公众号:

java开发系统内核:放大招!为系统开发星球大战游戏程序相关推荐

  1. WEB应用项目开发-网店购物系统开发

    ** WEB应用项目开发-网店购物系统开发 ** 文章目录 WEB应用项目开发-网店购物系统开发 **1.要求**: **2.功能模块:** **3.功能模块说明** **4.流程图说明:** **5 ...

  2. Python自动化开发基础 分布式监控系统开发实战 day8-李杰-专题视频课程

    Python自动化开发基础 分布式监控系统开发实战 day8-10994人已学习 课程介绍         从0基础开始讲解Python语法.流程控制.函数式编程.面向对象开发等重要的Python开发 ...

  3. 浅谈快速开发平台:突破系统开发边界,赋能企业数字化!

    快速开发平台,简单地说就是指那些不用编码或通过少量代码,就可以快速开发应用程序的平台.既可以降低开发人力成本,又可以缩短开发时间,从而实现企业降本增效的价值. 今天为大家介绍4款成熟业务的快速开发平台 ...

  4. 一对一直播源码开发,一对一直播系统开发

    如今,直播市场越发的火热,一对一直播源码也渐渐浮出水面,在直播大火的现在,您是不是也想要一款属于自己的直播平台呢?小编今天为您讲解一款一对一直播源码开发系统语言和媒体处理模块. 首先是系统开发语言 一 ...

  5. 引迈JNPF敏捷开发框架的开发运用之OA系统开发

    JNPF敏捷开发框架的第三个重量级运用是OA系统的开发.OA系统即,企业办公自动化系统,使公文在流转.审批.发布等方面提高效率,实现办公管理标准化和信息规范化,降低企业运行成本.那如何打造一个符合企业 ...

  6. 敏捷开发框架的开发运用之ERP系统开发

    JNPF敏捷开发框架的第七个重量级运用是ERP系统的开发.ERP系统是大家都很熟悉的一款企业资源管理软件,几乎是每家企事业单位都必备的一款软件系统.但从当前的市场使用情况来看,就会发现当下的erp系统 ...

  7. Android开发简单人脸签到系统开发

    需求分析 第一步我对该实验做了一个完整性的需求分析: 我们需要做到以下几点: (1)学生信息的管理,对学生的信息的添加,删除,编译修改: (2)基于每个学生的人脸上传,并识别该图片是否是一个人脸图片: ...

  8. 多商户商城系统开发方案 B2B2C商城系统开发方案

    随着电商模式的多样化带来的电商商城类型的饱满丰富,企业也从单用户商城的需求转向多商户商城,多商户商城能满足更多商家的创业需求.那么,多商户商城系统具体有哪些开发方案? 1 企业自主开发 多商户商城系统 ...

  9. JAVA分布式医疗云平台系统开发实战第一节 open-his系统技术架构与环境准备

    项目简介                                                                       Open-His 是以完整的基层医疗机构-信息化解 ...

最新文章

  1. nginx配置location总结及rewrite规则写法
  2. LoadRunner变量到参数的互换
  3. 案例一:网站模拟登录
  4. 要高薪地进入IT,你得这样做
  5. 芯片人才平均薪资近万元 2020年芯片人才缺口超30万
  6. android studio自定义类,为AndroidStudio设置自定义类注释
  7. 在Ubuntu上为Android系统内置C可执行程序测试Linux内核驱动程序
  8. vba 生成euc文件的方法
  9. Spring源码下载以及构建技巧
  10. 光纤带光缆的特点及应用场景
  11. Axure 基础教程
  12. 目标网站https://music.163.com/discover/toplist
  13. DFS算法原理及其具体流程,包你看一遍就能理解
  14. 自建kafka和公有云kafka对比
  15. Excel-计算数列元素间的和差
  16. 南京广义软件:Android lunch分析以及产品分支构建
  17. matlab实现图形几何变换如平移,matlab实现平面图形的几何变换
  18. 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
  19. FPGA芯片的GTX/GTH/GTY/GTP/GTZ/GTM高速信号有什么区别?
  20. Power BI Echart Tree开发自定义可视化对象

热门文章

  1. everything changes so quietly
  2. 基于JAVA在线点餐外卖系统设计与实现 开题报告
  3. 学习笔记,神经网络和反向传播
  4. mac系统python读取文件路径_mac下python目录
  5. 华为4G无线路由器测试锁频软件,华为4g无线路由器 新款E5375路由器测试
  6. 黑苹果big sur版本安装安卓USB共享网络(100%成功)
  7. InnoDB存储引擎中有页(Page)的概念
  8. JavaScript 整分或者指定时间执行操作
  9. object-c的存取权限(public/protected/private)
  10. 央视版笑傲江湖的价值观 (转)