這裡以電腦VGA 13H視頻模式為例,系統介紹製作電腦遊戲的基本方法。VGA INT 13H模式是一種工作在圖形方式下的模式,它具有320X200的螢幕分辯率,同屏上可以顯示256種顏色(超級任天堂和世嘉5代遊戲機也只有256種顏色),早期的許多遊戲都是在這一圖形方式下開發的(如大家非常熟悉的仙劍奇俠傳、紅色警戒、DOOM等),在這種模式下開發遊戲具有編程簡單、運行速度快、顏色豐富等特點。雖然以今天的標準來說320X200的分辯率已經不算什麼,但是它仍然是一個學習電腦遊戲編程的很好的入門環境,我們可以通過開發VGA 13H模式下的遊戲,逐步地由簡單到複雜地學習遊戲設計的基本方法,只要掌握了遊戲設計的基本方法和理論,再利用其它軟體工具(象WATCOM C、DJGPP、VC、DIRECT X等32位的C編譯器等)來設計遊戲將變得非常容易。函數用TURBO C 2.0編譯,也可以稍作修改用其它的C編譯器來編譯運行。我們先來瞭解一下電腦顯示器的工作原理和顯示卡的結構。
一.顯示器的工作原理
目前在個人電腦上廣泛使用的是採用陰極射線管(CRT)的光柵掃描顯示器,我們在螢幕上所看到的顏色是由電子槍發出的電子束打在CRT螢幕背面的熒光層上的點形成的,通過控制點的亮度可以產生不同的顏色。電子束不斷地從左至右、從上到下掃描整個螢幕,使螢幕顯示出圖案,電子束以大約每秒70次的速率在螢幕上重畫這一圖案,這個過程稱為顯示重新整理或螢幕重新整理,具體的掃描頻率依賴於所用的顯示適配器(又稱為顯示卡)。電子束從螢幕的左上方開始向右掃描,到達螢幕的右邊緣後,電子束被關閉(水平斷開),接著它又迅速地返回到螢幕的左邊緣(水平回掃)開始進行下一行水平方向的掃描,在完成全部的水平方向的掃描後,電子束在螢幕的右下角結束,此時電子束被關閉(垂直斷開),接著又迅速地返回到螢幕的左上方(垂直回掃),開始下一屏掃描。電子束就是這樣周而復始地掃描整個螢幕。顯示器在兩種方式下工作:文本方式和圖形方式,電腦遊戲一般在圖形方式下進行。
二.顯示器的座標系統
電腦螢幕上的座標與我們通常使用的直角座標系不同,座標原點(0,0)在螢幕的左上方,向右是水平方向的座標,向下是垂直方向的座標,且座標沒有負值。
三.顯示卡的結構
顯示器上的顯示卡負責將圖形顯示在螢幕上。顯示儲存空間中存放著在螢幕上顯示的映像資料,顯示卡硬體不停地將顯存中的內容顯示在螢幕上。顯示儲存空間實際上是安裝在顯示卡上的一塊或幾塊大規模整合電路,其容量有1M、2M、4M、8M等,在DOS下我們可以訪問的記憶體只有1MB空間(這就是DOS的局限性所在),地址從00000H到FFFFFH,這段記憶體根據用途又分為不同的塊,系統分配給圖形緩衝區(顯示儲存空間)的地址在A0000H到BFFFFH之間,大小為128KB,其中,VGA佔用了A0000H到AFFFFH段,共64KB,這段地址是記憶體映射地址,供我們訪問顯示儲存空間用。在VGA 13H圖形模式下,顯示記憶體使用量A0000H到AF9FFH的一段線性記憶體空間,每個位元組表示一個點,對應螢幕上的一個像點,320*200的螢幕解析度共需要64000個位元組,剛好64KB,因為一個位元組可以表示的最大整數值為256,所以每個像點就可以表示256種顏色。
四.設定視頻模式
畫圖以前必須使螢幕工作在圖形方式,這就要設定螢幕的視頻模式。設定視頻模式有許多種方法,其中調用視頻BIOS功能是最簡單的一種,通過調用BIOS中斷0x10的服務程式,可以很方便地設定螢幕模式。調用方法是將值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是水平方向的座標,320是螢幕的寬度。有了像點的位移地址,然後加上顯示記憶體的首地址即可得到像點在顯示記憶體中的絕對位址。只要將表示點的顏色值放到這個地址處,就可以在螢幕上畫點了。首先建立一個指標VideoBufferPtr,使它指向顯示記憶體的首地址:
char far *VideoBufferPtr=( char far *)0xa0000000;
將這個指標加上像點的位移地址,像點的最終地址就確定了,它等於:
VideoBufferPtr+y*320+x;
把顏色值color寫到這個地址:
*(VideoBufferPtr+y*320+x)=color;
畫點的函數:
void DrawPoint(int x,int y,unsigned char color)
{
*(VideoBufferPtr+y*320+x)=color;
}
六.顯示字元
遊戲經常在螢幕上列印出顯示遊戲狀態的文本,使遊戲者瞭解當前遊戲的狀態,這是遊戲與遊戲者進行互動的必不可少的。然而在圖形模式下顯示文本與在文字模式下有很大區別,在圖形模式下文本必須使用基於畫位元影像的方法來顯示。這裡介紹一種簡便的方法:利用電腦唯讀記憶體中的ASCII字型資料。在電腦唯讀記憶體(ROM)中固化有ASCII字型資料,這可在基址F000:FA6E上找到。我們只需瞭解資料是如何儲存的,然後再得出存取該資料的演算法,就可以用任意顏色在螢幕上用畫位元影像的方法把字元畫出來。在ROM中,字元按照ASCII字元編碼的順序放置,由於每個字元為8*8的點陣,所以每個字元佔據8個位元組的儲存空間,要找出某個字元,我們只需將這個字元的ASCII碼與8相乘,然後將結果加到基址F000:FA6E上。由於字元用畫位元影像的方法來顯示,因此我們可以隨意給它們指定顏色(前景或背景顏色)。在圖形模式下,我們只需要兩個函數就能夠列印文本:一個用於顯示單個字元,另一個用來顯示字串。 定義一個遠指標指向ROM字元集的開始位置:
char far *RomCharPtr=(char far *)0xf000fa6e;
下面是在螢幕上列印字元和字串的函數:
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>1);
}
offset+=320;
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[index]!=0;index++)
PrintChar(x+(indexred);
outportb(0x3c9,color->green);
outportb(0x3c9,color->blue);
}
擷取顏色寄存器值的函數:
void GetPaletteRegister(int index,RGBColorPtr color)
{
outportb(0x3c6,0xff);
outportb(0x3c7,index);
color->red=inportb(0x3c9);
color->green=inportb(0x3c9);
color->blue=inportb(0x3c9);
}
八.在螢幕上畫位元影像
電腦繪製映像通常採用一種稱為位映射圖(BITMAP)的圖形處理方法進行,位映射圖是一個矩形的點陣結構(二維矩陣),顯示在螢幕上時,對應螢幕上一個矩形地區,組成位元影像的資料儲存在記憶體中一段連續的區間。我們比較常見的位元影像檔案有:BMP、PCX、GIF、JPG等。位元影像通常儲存在外部檔案中,使用以前必須將其從磁碟檔案調入記憶體。下面介紹將一個256色PCX圖形檔案讀入記憶體的方法:
1.定義PCX檔案頭結構:
typedef 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; /* 水平解析度 */
int vres; /* 垂直解析度 */
char palette[48]; /* 顏色調色盤 */
char unused; /* 未使用 */
char bit_plance; /* 位平面個數 */
int bytes; /* 單一水平線佔用的位元組數 */
int palette_type; /* 調色盤類型 */
char unused2[58]; /* 未使用 */
}PCXHeader,*PCXHeaderPtr;
2.定義用來存放PCX映像資料的結構:
typedef struct 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 *)farmalloc(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;
if((fp=fopen(filename,"rb"))==NULL)
return 0;
fread(&PcxHeader,sizeof(PCXHeader),1,fp);
count=0;
while(count=192&&data0)
{
*(image->buffer+count)=data;
++count;
}
}
else
{
*(image->buffer+count)=data;
++count;
}
}
fseek(fp,-768L,SEEK_END);
for(index=0;indexpalette[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;indexpalette[index]);
return 1;
}
其中參數flag用來指明調入檔案的同時是否設定顏色寄存器(flag=1設定)。
----------------------------------------------
有事點這裡
2005-02-17 23:26:57
瘋暈
等級:管理員
文章:65
積分:1067
註冊:2005-02-14
第 2 樓
5.畫位元影像的函數:
void DrawImage(int x,int y,int width,int height,char far *image)
{
int i,j;
for(i=0;i=0&&(x+j)=0&&(y+i)=0&&(x+j)=0&&(y+i)=0&&(x+j)=0&&(y+i)>8)&0x00ff)
int far *clk=(int far *)0x0000046c;
1.改變時間定時器值的函數:
void ChangTime(unsigned cnt)
{
outportb(0x43,0x3c);
outportb(0x40,LOW_BYTE(cnt));
outportb(0x40,HI_BYTE(cnt));
}
2.延時函數:
void Delay(int d)
{
int tm=*clk;
while(*clk-tm. */
#define KEY_COMMA 0x34 /*
上一篇:ASCII表
下一篇:XP系統中Net User命令的另類用法