ImageVerifierCode 换一换
格式:DOC , 页数:17 ,大小:90.01KB ,
资源ID:7779441      下载积分:10 金币
快捷注册下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

开通VIP
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.zixin.com.cn/docdown/7779441.html】到电脑端继续下载(重复下载【60天内】不扣币)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

开通VIP折扣优惠下载文档

            查看会员权益                  [ 下载后找不到文档?]

填表反馈(24小时):  下载求助     关注领币    退款申请

开具发票请登录PC端进行申请

   平台协调中心        【在线客服】        免费申请共赢上传

权利声明

1、咨信平台为文档C2C交易模式,即用户上传的文档直接被用户下载,收益归上传人(含作者)所有;本站仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。所展示的作品文档包括内容和图片全部来源于网络用户和作者上传投稿,我们不确定上传用户享有完全著作权,根据《信息网络传播权保护条例》,如果侵犯了您的版权、权益或隐私,请联系我们,核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
2、文档的总页数、文档格式和文档大小以系统显示为准(内容中显示的页数不一定正确),网站客服只以系统显示的页数、文件格式、文档大小作为仲裁依据,个别因单元格分列造成显示页码不一将协商解决,平台无法对文档的真实性、完整性、权威性、准确性、专业性及其观点立场做任何保证或承诺,下载前须认真查看,确认无误后再购买,务必慎重购买;若有违法违纪将进行移交司法处理,若涉侵权平台将进行基本处罚并下架。
3、本站所有内容均由用户上传,付费前请自行鉴别,如您付费,意味着您已接受本站规则且自行承担风险,本站不进行额外附加服务,虚拟产品一经售出概不退款(未进行购买下载可退充值款),文档一经付费(服务费)、不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
4、如你看到网页展示的文档有www.zixin.com.cn水印,是因预览和防盗链等技术需要对页面进行转换压缩成图而已,我们并不对上传的文档进行任何编辑或修改,文档下载后都不会有水印标识(原文档上传前个别存留的除外),下载后原文更清晰;试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓;PPT和DOC文档可被视为“模板”,允许上传人保留章节、目录结构的情况下删减部份的内容;PDF文档不管是原文档转换或图片扫描而得,本站不作要求视为允许,下载前可先查看【教您几个在下载文档中可以更好的避免被坑】。
5、本文档所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用;网站提供的党政主题相关内容(国旗、国徽、党徽--等)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
6、文档遇到问题,请及时联系平台进行协调解决,联系【微信客服】、【QQ客服】,若有其他问题请点击或扫码反馈【服务填表】;文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“【版权申诉】”,意见反馈和侵权处理邮箱:1219186828@qq.com;也可以拔打客服电话:0574-28810668;投诉电话:18658249818。

注意事项

本文(电脑游戏编程入门%2B.doc)为本站上传会员【pc****0】主动上传,咨信网仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知咨信网(发送邮件至1219186828@qq.com、拔打电话4009-655-100或【 微信客服】、【 QQ客服】),核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载【60天内】不扣币。 服务填表

电脑游戏编程入门%2B.doc

1、这里以电脑VGA  13H视频模式为例,系统介绍制作电脑游戏的基本方法。VGA   INT 13H模式是一种工作在图形方式下的模式,它具有320X200的屏幕分辩率,同屏上可以显示256种颜色(超级任天堂和世嘉5代游戏机也只有256种颜色),早期的许多游戏都是在这一图形方式下开发的(如大家非常熟悉的仙剑奇侠传、红色警戒、DOOM等),在这种模式下开发游戏具有编程简单、运行速度快、颜色丰富等特点。虽然以今天的标准来说320X200的分辩率已经不算什么,但是它仍然是一个学习电脑游戏编程的很好的入门环境,我们可以通过开发VGA 13H模式下的游戏,逐步地由简单到复杂地学习游戏设计的基本方法,只要掌握

2、了游戏设计的基本方法和理论,再利用其它软件工具(象WATCOM    C、DJGPP、VC、DIRECT  X等32位的C编译器等)来设计游戏将变得非常容易。函数用TURBO C 2.0编译,也可以稍作修改用其它的C编译器来编译运行。我们先来了解一下电脑显示器的工作原理和显示卡的结构。 一.显示器的工作原理        目前在个人计算机上广泛使用的是采用阴极射线管(CRT)的光栅扫描显示器,我们在屏幕上所看到的颜色是由电子枪发出的电子束打在CRT屏幕背面的荧光层上的点形成的,通过控制点的亮度可以产生不同的颜色。电子束不断地从左到右、从上到下扫描整个屏幕,使屏幕显示出图案,电子束以大约每

3、秒70次的速率在屏幕上重画这一图案,这个过程称为显示刷新或屏幕刷新,具体的扫描频率依赖于所用的显示适配器(又称为显示卡)。电子束从屏幕的左上角开始向右扫描,到达屏幕的右边缘后,电子束被关闭(水平断开),接着它又迅速地返回到屏幕的左边缘(水平回扫)开始进行下一行水平方向的扫描,在完成全部的水平方向的扫描后,电子束在屏幕的右下角结束,此时电子束被关闭(垂直断开),接着又迅速地返回到屏幕的左上角(垂直回扫),开始下一屏扫描。电子束就是这样周而复始地扫描整个屏幕。显示器在两种方式下工作:文本方式和图形方式,电脑游戏一般在图形方式下进行。 二.显示器的坐标系统        计算机屏幕上的坐标与我们

4、通常使用的直角坐标系不同,坐标原点(0,0)在屏幕的左上角,向右是水平方向的坐标,向下是垂直方向的坐标,且坐标没有负值。 三.显示卡的结构        显示器上的显示卡负责将图形显示在屏幕上。显示存储器中存放着在屏幕上显示的图像数据,显示卡硬件不停地将显存中的内容显示在屏幕上。显示存储器实际上是安装在显示卡上的一块或几块大规模集成电路,其容量有1M、2M、4M、8M等,在DOS下我们可以访问的内存只有1MB空间(这就是DOS的局限性所在),地址从00000H到FFFFFH,这段内存根据用途又分为不同的块,系统分配给图形缓冲区(显示存储器)的地址在A0000H到BFFFFH之间,大小为12

5、8KB,其中,VGA占用了A0000H到AFFFFH段,共64KB,这段地址是内存映射地址,供我们访问显示存储器用。在VGA 13H图形模式下,显示内存使用A0000H到AF9FFH的一段线性内存空间,每个字节表示一个点,对应屏幕上的一个像点,320*200的屏幕分辨率共需要64000个字节,刚好64KB,因为一个字节可以表示的最大整数值为256,所以每个像点就可以表示256种颜色。 四.设置视频模式        画图以前必须使屏幕工作在图形方式,这就要设置屏幕的视频模式。设置视频模式有许多种方法,其中调用视频BIOS功能是最简单的一种,通过调用BIOS中断0x10的服务程序,可以很方便

6、地设置屏幕模式。调用方法是将值0放入ah寄存器,显示模式放入al寄存器中,然后调用int86()函数。 设置视频模式的函数: void SetVideoMode(int mode) { ??? union REGS r; ??? r.h.ah=0; ??? r.h.al=mode; ??? int86(0x10,&r,&r); } 其中mode是视频模式。 五.在屏幕上画点        由于显示存储器是线性排列的,每个像点用一个字节来表示,所以对像点寻址非常容易,像点在显示内存中的偏移地址可由这个公式确定:y*320+x,其中,y是像点在垂直方向的坐标,x是水平方向的坐

7、标,320是屏幕的宽度。有了像点的偏移地址,然后加上显示内存的首地址即可得到像点在显示内存中的绝对地址。只要将表示点的颜色值放到这个地址处,就可以在屏幕上画点了。首先建立一个指针VideoBufferPtr,使它指向显示内存的首地址: ? char far *VideoBufferPtr=( char far *)0xa0000000; 将这个指针加上像点的偏移地址,像点的最终地址就确定了,它等于: ??? VideoBufferPtr+y*320+x; 把颜色值color写到这个地址: *(VideoBufferPtr+y*320+x)=color; 画点的函数: void D

8、rawPoint(int x,int y,unsigned char color) { ??? *(VideoBufferPtr+y*320+x)=color; } 六.显示字符        游戏经常在屏幕上打印出显示游戏状态的文本,使游戏者了解当前游戏的状态,这是游戏与游戏者进行交互的必不可少的。然而在图形模式下显示文本与在文本模式下有很大区别,在图形模式下文本必须使用基于画位图的方法来显示。这里介绍一种简便的方法:利用计算机只读存储器中的ASCII字体数据。在计算机只读存储器(ROM)中固化有ASCII字体数据,这可在基址F000:FA6E上找到。我们只需了解数据是如何存储的,

9、然后再得出存取该数据的算法,就可以用任意颜色在屏幕上用画位图的方法把字符画出来。在ROM中,字符按照ASCII字符编码的顺序放置,由于每个字符为8*8的点阵,所以每个字符占据8个字节的存储空间,要找出某个字符,我们只需将这个字符的ASCII码与8相乘,然后将结果加到基址F000:FA6E上。由于字符用画位图的方法来显示,因此我们可以随意给它们指定颜色(前景或背景颜色)。在图形模式下,我们只需要两个函数就能够打印文本:一个用于显示单个字符,另一个用来显示字符串。 定义一个远指针指向ROM字符集的开始位置: ? char far *RomCharPtr=(char far *)0xf000fa

10、6e; 下面是在屏幕上打印字符和字符串的函数: 1.打印字符的函数。 void PrintChar(int cx,int cy,char c,unsigned char Fcolor,unsigned char Bcolor,int flag) { ??? int offset,x,y; ??? char far *TempPtr; ??? unsigned char bit_mask; ??? TempPtr=RomCharPtr+(c<<3); ??? offset=(cy<<8)+(cy<<6)+cx; ??? for(y=0;y<8;y++) ??? { ???

11、 bit_mask=0x80; ??????? for(x=0;x<8;x++) ??????? { ??????????? if((*TempPtr&bit_mask)) ??????????????? *(VideoBufferPtr+offset+x)=Fcolor; ??????????? else if(flag==1) ??????????????? *(VideoBufferPtr+offset+x)=Bcolor; ??????????? bit_mask=(bit_mask>>1); ??????? } ??????? offset+=320; ?

12、 TempPtr++; ??? } } 说明: cx,cy 是字符在屏幕上的坐标。 c 字符的ASCII码。 Fcolor,Bcolor 分别是字符的前景和背景颜色。           flag 打印标志,当flag=1时显示字符的背景色,否则打印的字符具有透明效果。 2.打印字符串的函数。 void PrintString(int x,int y,char *string,unsigned char Fcolor,unsigned char Bcolor,int flag) { ??? int index; ??? for(index=0;string[

13、index]!=0;index++) ??????? PrintChar(x+(index<<3),y,string[index],Fcolor,Bcolor,flag); } 说明: 1.x,y 是字符串在屏幕上的坐标。 2.*string 字符串指针。 3.Fcolor,Bcolor 分别是字符串的前景和背景颜色。 4.flag 打印标志,当flag=1时显示字符串的背景色,否则打印的字符串具有透明效果。 七.设置颜色寄存器         我们知道VGA显示卡具有显示256种颜色的能力,每种颜色能够用一个0-255之间的数值来表示,那么这些数值与我们在屏幕上实际见到的颜

14、色之间有什么关系呢?其实这些数值只是VGA显示卡上的颜色寄存器的索引值,颜色寄存器里才保存了屏幕上颜色的真实值。VGA显示卡上有一个包含256个单元的颜色寄存器(又称为调色板),每个单元由三部份组成,这三部份分别代表颜色中的红、绿、蓝三种成份(显示器就是用这三种成份来组成任何我们所看到的颜色),用三个字节表示,颜色寄存器一共有768个字节(3*256=768)。当我们要在屏幕上显示某种颜色时,显示卡硬件就根据颜色的索引值在颜色寄存器中查找,找到后再从相应单元中取出颜色值显示在屏幕上,这个过程与画家使用调色板相似,颜色寄存器相当于调色板,颜色寄存器中的单元相当于调色板上的色格,在色格中装有预先调

15、好的颜色,当画家需要用某种颜色作画时,就从装有那种颜色的色格中把颜色取出来。例如,我们要显示颜色索引值为30的颜色,显示卡硬件就去查找颜色寄存器的第30单元,30单元位于距颜色寄存器首址3*30=90处(因为每个单元有三个字节),然后取出90处记录有红、绿、蓝三种成份的三个字节作为在屏幕上显示的色彩信号。但是实际上每个字节只用了六位来表示颜色,其它两位没用,这六位表示的数的值域为0-63,所以每种颜色(红、绿、蓝)成份具有64种亮度的表现能力,三种颜色成份组合共可以产生64*64*64=262,144种颜色(VGA   13H模式从这262,144种颜色中取出256种在同一屏幕上显示)。我们可

16、以通过事先设置颜色寄存器的值来使用我们自己的颜色。   设置颜色寄存器有多种方法,如调用BIOS功能,但是这种方法速度比较慢,游戏设计中通常采用直接访问VGA显示卡的I/O端口的方法来快速设置颜色寄存器,我们只需访问四个I/O端口就可以完成设置颜色寄存器的工作。这四个端口分别是:  0x3c6、0x3c7、0x3c8和0x3c9。   端口0x3c6称为调色板屏蔽寄存器,用来屏蔽所要求的调色板寄存器的位,如果你在这个寄存器中放入0xff,你就可以通过调色板索引寄存器0x3c7和0x3c8(一个用于读,一个用于写)访问任何你希望访问的颜色寄存器,端口0x3c9称为调色板数据寄存器,红、绿、蓝

17、三种成份就是通过它进行读写(颜色值要读或写三次)。 我们定义一个结构来方便处理颜色寄存器: typedef struct RGB_COLOR { ??? unsigned char red; ??? unsigned char green; ??? unsigned char blue; }RGBColor,*RGBColorPtr; 结构中的red、green和blue变量用来保存颜色的红、绿、蓝三种成份。 设置颜色寄存器值的函数: void SetPaletteRegister(int index,RGBColorPtr color) { ??? outportb(

18、0x3c6,0xff); ??? outportb(0x3c8,index); ??? outportb(0x3c9,color->red); ??? outportb(0x3c9,color->green); ??? outportb(0x3c9,color->blue); } 获取颜色寄存器值的函数: void GetPaletteRegister(int index,RGBColorPtr color) { ??? outportb(0x3c6,0xff); ??? outportb(0x3c7,index); ??? color->red=inportb(0x3c

19、9); ??? color->green=inportb(0x3c9); ??? color->blue=inportb(0x3c9); } 八.在屏幕上画位图        计算机绘制图像通常采用一种称为位映射图(BITMAP)的图形处理方法进行,位映射图是一个矩形的点阵结构(二维矩阵),显示在屏幕上时,对应屏幕上一个矩形区域,组成位图的数据储存在内存中一段连续的区间。我们比较常见的位图文件有:BMP、PCX、GIF、JPG等。位图通常存储在外部文件中,使用以前必须将其从磁盘文件调入内存。下面介绍将一个256色PCX图形文件读入内存的方法: 1.定义PCX文件头结构: type

20、def struct PCX_HEADER { ??? char menufactrue; /* 厂家标识编号 0x0a */ ??? char version; /* 文件版本编号 */ ??? char packing_type; /* 压缩模式 */ ??? char bits_per_pixel; /* 每点占用的位数 */ ??? int minx; /* 最小X坐标值 */ ??? int miny; /* 最小Y坐标值 */ ??? int maxx; /* 最大X坐标值 */ ??? int maxy; /* 最大Y坐标值 */ ??? int hres;

21、/* 水平分辨率 */ ??? int vres; /* 垂直分辨率 */ ??? char palette[48]; /* 颜色调色板 */ ??? char unused; /* 未使用 */ ??? char bit_plance; /* 位平面个数 */ ??? int bytes; /* 单一水平线占用的字节数 */ ??? int palette_type; /* 调色板类型 */ ??? char unused2[58]; /* 未使用 */ }PCXHeader,*PCXHeaderPtr; 2.定义用来存放PCX图像数据的结构: typedef struc

22、t PCX_PICTURE { ??? int width; ??? int height; ??? char far *buffer; ??? RGBColor palette[256]; }PCXPicture,*PCXPicturePtr; 3.初始化图像数据的函数: int InitPCX(PCXPicturePtr image,int w,int h) { ??? unsigned size=w*h; ??? image->width=w; ??? image->height=h; ??? image->buffer=(char far *)farmallo

23、c(size); ??? if(image->buffer==NULL)? return 0; ??? return 1; } 4.从外部文件读入数据的函数: int LoadPCX(char *filename,PCXPicturePtr image,int flag) { ??? FILE *fp; ??? unsigned num_bytes,count,size; ??? int index; ??? unsigned char data; ??? PCXHeader PcxHeader; ??? size=image->width*image->height;

24、 ??? if((fp=fopen(filename,"rb"))==NULL) ??????? return 0; ??? fread(&PcxHeader,sizeof(PCXHeader),1,fp); ??? count=0; ??? while(count<=size) ??? { ??????? data=fgetc(fp); ??????? if(data>=192&&data<=255) ??????? { ??????????? num_bytes=data-192; ??????????? data=fgetc(fp); ??????????? wh

25、ile(num_bytes-->0) ??????????? { ??????????????? *(image->buffer+count)=data; ??????????????? ++count; ??????????? } ??????? } ??????? else ??????? { ??????????? *(image->buffer+count)=data; ??????????? ++count; ??????? } ??? } ??? fseek(fp,-768L,SEEK_END); ??? for(index=0;index<256;ind

26、ex++) ??? { ??????? image->palette[index].red=((fgetc(fp))>>2); ??????? image->palette[index].green=((fgetc(fp))>>2); ??????? image->palette[index].blue=((fgetc(fp))>>2); ??? } ??? fclose(fp); ??? if(flag==1) ??????? for(index=0;index<256;index++) ??????????? SetPaletteRegister(index,(RGBCo

27、lorPtr)&image->palette[index]); ??? return 1; } 其中参数flag用来指明调入文件的同时是否设置颜色寄存器(flag=1设置)。 5.画位图的函数: void DrawImage(int x,int y,int width,int height,char far *image) { ??? int i,j; ??? for(i=0;i=0&&(x+j)<320&

28、y+i)>=0&&(y+i)<200) ??????????????? DrawPoint(x+j,y+i,*image); ??????????? image++; ??????? } } x,y是图像在屏幕上的左上角坐标,width,height是图像的宽度和高度,image是指向内存中图像的指针。 我们对if(*image!=0&&(x+j)>=0&&(x+j)<320&&(y+i)>=0&&(y+i)<200)语句进行一下分析:   *image!=0用来检查所画的颜色值是否是透明色,如果是,则不画出来,这样我们就可以画出有透明效果的图象,即透过图象可以看到背景,透明

29、色通常取值0,也可以用其他的颜色值表示。   (x+j)>=0&&(x+j)<320&&(y+i)>=0&&(y+i)<200语句用来判断所画点的坐标是否超出屏幕显示的范围,这样可以画出具有裁剪效果的图象,如图象的一部份在屏幕外。        这个函数并不是最快的,因为它要执行width X height次判断,更快的函数请看VGA13H函数库中的绘图函数。 九.控制游戏的速度        初学游戏编程的人常常会遇到这样的问题,设计出来的游戏在一台机子上速度运行正常,为什么把游戏在另一台运算速度比较快的机子上运行时,游戏速度也变得很快呢?是为什么呢?        问题就在于游戏

30、中没有一个时间基准值在控制它。        那么如何控制游戏的速度呢?这就得用电脑时钟计数来控制游戏。首先我们来了解一下PC机的时钟是如何工作的,PC机采用一块8253定时器芯片计算系统时钟的脉冲,若干个系统时钟周期转换成一个脉冲,这些脉冲序列可以用以计时,也可以送入计算机的扬声器产生特定频率的声音。8253定时器芯片独立于CPU运行,它可以象实时时钟那样,CPU的工作状态对它没有任何影响。        8253芯片有三个独立的通道,每个通道的功能各不相同,三个通道的功能如下:通道0:为系统时钟所用,在启动时由BIOS置入初值,每秒钟约发出18.2个脉冲,脉冲的计数值存放在BIOS数据

31、区的0040:006c存储单元中(注意,这个单元的内容对我们非常有用!),通道0的输出脉冲作为申请定时器中断的请求信号,还用于磁盘的某些定时操作,如果改变了通道0的计数值,必须确保在CPU每次访问磁盘以前恢复原来的读数,否则将使磁盘读写产生错误。通道1:用于控制计算机的动态RAM刷新速率,一般情况下不要去改变它。通道2:连接计算机的扬声器,产生单一的方波信号控制扬声器发声。8253定时器芯片的每一个通道含有3个寄存器,CPU通过访问3个端口(通道0为40h,通道1为41h,通道2为42h)来访问各个端口的3个寄存器,8253每个端口有6种工作模式,当通道0用于定时或通道2用于定时或发声时,一般

32、用模式3。在模式3下,计数值被置入锁存器后立即复制到计数器,计数器在每次系统时钟到来时减1,减至0后一方面马上从锁存器中重新读取计数值,另一方面向CPU发出一个中断请求(INT 1CH中断,很有用),如此循环在输出线上高低电平的时间各占计数时间的一半,从而产生方波输出。        对8253定时器芯片编程是通过命令端口寄存器43h来实现,它决定选用的通道、工作模式、送入锁存器的计数值是一字节还是两字节、是二进制码还是BCD码等工作参数,端口43h各位的组合形式如下: 位0____若为1则采用二进制表示,否则用BCD码表示计数值。 位3-1____工作模式号,其值(0-5)对应6种模式

33、 位5-4____操作的类型:00:把计数值送入锁存器; 01:读写高字节; 10:读写低字节; 11:先读写高字节,再读写低字节; 位7-6____决定选用的通道号,其值为0-2。 对8253芯片编程的三个步骤:     1.设置命令端口43h,     2.向端口发送一个工作状态字节,     3.确定定时器的工作方式; 若是通道2,给端口61h的第0位和第1位置数,启动时钟信号,当第1位置1时,通道2驱动扬声器,置0时用于定时操作;将一个字的计数值,按先低字节后高字节的顺序送入通道的I/O端口寄存器(通道0为40h,通道1为41h,通道2为42h)。当第3个步骤完成

34、后被编程的通道马上在新的状态下开始工作。由于8253的三个通道都独立于CPU运行,所以在程序结束以前要恢复各通道的正常状态值。   在游戏中我们只使用通道0,怎样对其进行编程呢?首先得确定放入锁存器的16位的计数值:       16位的计数值=1.19318MB/希望的频率 其中1.19318MB是系统振荡器的频率。 由上式可知,计数器所能产生的值是18.2Hz-1.19318MHz,这已经足够了,可以满足我们游戏的要求。 以下是对8253定时器芯片通道0编程的函数: #define T60HZ 0x4dae #define T50HZ 0x5d37 #define T40H

35、Z 0x7468 #define T30HZ 0x965c #define T20HZ 0xe90b #define T18HZ 0xffff #define LOW_BYTE(n) (n&0x00ff) #define HI_BYTE(n) ((n>>8)&0x00ff) int far *clk=(int far *)0x0000046c; 1.改变时间定时器值的函数: void ChangTime(unsigned cnt) { ??? outportb(0x43,0x3c); ??? outportb(0x40,LOW_BYTE(cnt)); ??? outp

36、ortb(0x40,HI_BYTE(cnt)); } 2.延时函数: void Delay(int d) { ??? int tm=*clk; ??? while(*clk-tm

37、次的计数值,在读写磁盘操作时将引起读写错误甚至死机。 我们将时钟设置成每秒60HZ这样调用函数:ChangTime(T60HZ); 在游戏中延时一定时间这样调用函数:Delay(10); 十.在后台运行程序        所谓后台运行就是在游戏运行当中“同时“运行其它的程序,如在游戏中演奏背景音乐、游戏计时等,这些工作看起来好象与游戏过程“同时“在进行。这里的“同时“其实就是利用中断的方法来实现的,即在游戏中每隔一定时间产生一次中断去做其他工作,完成后再回到游戏中。        在BIOS中包含了一个特殊的伪中断----INT 1CH中断,这一中断在BIOS初始化时没有任何作用,它

38、的中断处理程序只有一条中断返回语句----IRET,因此该中断一经调用立即返回。INT 1CH中断是在BIOS中断INT 8H修正日历计数后由该中断调用,和INT 8H中断程序一起以定时器中断频率(正常情况下为每秒钟18.2次)不停地执行而与CPU无关,我们可以改变这一中断,使它指向我们的中断处理程序,当我们改变了时间定时器的值以后,INT   1CH程序将按改变后的频率被调用。        重置INT 1CH中断向量前必须先保存好原来的INT 1CH中断向量,以便在我们的程序运行结束时再恢复它,否则将引起系统崩溃。        另外,中断处理程序的处理时间不能超过定时器确定的时间,否

39、则将死机,所以在中断处理程序里不能运行太多的代码,也不能调用与相关的C函数,如sound,delay等。 编写新的INT 1CH中断程序的方法如下:     1.设置一个中断类型的函数指针用来保存原先的INT 1CH中断向量:         void interrupt far (*OldInt1chHandler)();     2.编写新的INT 1CH中断程序:         void far interrupt NewInt1ch(void) ??????? { ??????????? /*我们的中断程序*/ ??????? }     3.保存原来的INT 1C

40、H中断向量:         OldInt1chHandler=getvect(0x1c);     4.设置新的INT 1CH中断向量:         setvect(0x1c,NewInt1ch);     5.恢复旧的INT 1CH中断程序:         setvect(0x1c, OldInt1chHandler); 十一.如何处理按键        PC的键盘是一个智能化的键盘,它相当于一部完整的计算机,键盘内有一片Intel 8048(或8049)单片机(处理器)对整个键盘上的字符键、功能键、控制键和组合键进行管理,当在键盘上按下一个键时,键盘上的处理器首先向计

41、算机主机发出硬件中断请求,然后将该键的扫描码以串行的方式传送给计算机主机,计算机主机在硬件中断的作用下,调用INT 09H硬件中断把键盘送来的扫描码读入,并转换为ASCII码存入键盘缓冲区中。按下一个键,送出一个闭合码,键被释放时送出一个断开码,键盘处理中断程序从键盘I/O端口(端口地址为60H)读取一个字节的数据,如果读取的数据的第7位为1时表示按键已放开(送出断开码),如第7位为0表示键按下(送出闭合码),数据的第0-6位则为按键的扫描码。键盘上的每一个键都对应一个扫描码,根据扫描码就能唯一的确定一个键。键盘缓冲区位于0040:001EH-4000:003EH之间的BIOS数据区,长度为3

42、4个字节,是一个先进后出的循环队列。使用PC机原有的键盘处理程序可以很方便地处理键盘,但是因为它是调用BIOS,所以反应比较慢,另外当我们要同时处理几个按键时(例如同时按下Up箭头键和Left箭头键沿对角线运动),原有的键盘中断程序就不能满足要求,这时就需要编写一个适合我们要求的键盘中断程序。        编写新的键盘中断程序要做以下几项工作: 1.进入键盘中断程序。 2.从键盘I/O端口60H读取一个字节的按键码,并将它存入一个全局变量中供main程序处理,或者将按键码存入一个数据表中。 3.读取控制寄存器61H,并用82h完成一个OR操作。 4.将结果写回控制寄存器端口61H。

43、 5.在控制寄存器上用7fh完成一个AND操作,以便复位键盘触发器,告诉硬件一个按键已被处理,可以读下一个键了。 6.复位中断控制器8259,向端口20h写一个20h。 7.退出键盘中断程序。 我们先定义一组宏常量记录键值,它包括128个键盘扫描码: #define KEY_A 0x1E #define KEY_B 0x30 #define KEY_C 0x2e #define KEY_D 0x20 #define KEY_E 0x12 #define KEY_F 0x21 #define KEY_G 0x22 #define KEY_H 0x23 #define K

44、EY_I 0x17 #define KEY_J 0x24 #define KEY_K 0x25 #define KEY_L 0x26 #define KEY_M 0x32 #define KEY_N 0x31 #define KEY_O 0x18 #define KEY_P 0x19 #define KEY_Q 0x10 #define KEY_R 0x13 #define KEY_S 0x1f #define KEY_T 0x14 #define KEY_U 0x16 #define KEY_V 0x2f #define KEY_W 0x11 #define K

45、EY_X 0x2d #define KEY_Y 0x15 #define KEY_Z 0x2c #define KEY_1 0x02 #define KEY_2 0x03 #define KEY_3 0x04 #define KEY_4 0x05 #define KEY_5 0x06 #define KEY_6 0x07 #define KEY_7 0x08 #define KEY_8 0x09 #define KEY_9 0x0a #define KEY_0 0x0b #define KEY_DASH 0x0c /* _- */ #define KEY_EQUAL

46、 0x0d /* += */ #define KEY_LBRACKET 0x1a /* {[ */ #define KEY_RBRACKET 0x1b /* }] */ #define KEY_SEMICOLON 0x27 /* :; */ #define KEY_RQUOTE 0x28 /* "' */ #define KEY_LQUOTE 0x29 /* ~` */ #define KEY_PERIOD 0x33 /* >. */ #define KEY_COMMA 0x34 /* <, */ #define KEY_SLASH 0x35 /* ?/ */ #define

47、 KEY_BACKSLASH 0x2b /* |\ */ #define KEY_F1 0x3b #define KEY_F2 0x3c #define KEY_F3 0x3d #define KEY_F4 0x3e #define KEY_F5 0x3f #define KEY_F6 0x40 #define KEY_F7 0x41 #define KEY_F8 0x42 #define KEY_F9 0x43 #define KEY_F10 0x44 #define KEY_ESC 0x01 #define KEY_BACKSPACE 0x0e #define K

48、EY_TAB 0x0f #define KEY_ENTER 0x1c #define KEY_CONTROL 0x1d #define KEY_LSHIFT 0x2a #define KEY_RSHIFT 0x36 #define KEY_PRTSC 0x37 #define KEY_ALT 0x38 #define KEY_SPACE 0x39 #define KEY_CAPSLOCK 0x3a #define KEY_NUMLOCK 0x45 #define KEY_SCROLLLOCK 0x46 #define KEY_HOME 0x47 #define KEY_

49、UP 0x48 #define KEY_PGUP 0x49 #define KEY_MINUS 0x4a #define KEY_LEFT 0x4b #define KEY_CENTER 0x4c #define KEY_RIGHT 0x4d #define KEY_PLUS 0x4e #define KEY_END 0x4f #define KEY_DOWN 0x50 #define KEY_PGDOWN 0x51 #define KEY_INS 0x52 #define KEY_DEL 0x53 然后定义两个字符型数组来保存键盘状态: char key_state

50、[128],key_pressed[128]; 其中key_state[128]用来表示键的当前状态,key_pressed[128]里保存的值表示哪些键被按下,值1表示按下,0表示放开。 在挂上新的键盘中断以前,将原来的键盘中断程序地址保存好,以便在程序运行结束后恢复它,我们定义一个中断指针来存放原来的地址:     void interrupt far (*OldInt9Handler)(); 1.安装新的键盘中断程序的函数: void InstallKeyboard(void) { ??? int i; ??? for(i=0;i<128;i++) ??????? ke

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服