?? 空戰摸擬源程序.c
字號:
#include <stdio.h>
#include <dos.h>
#include <stdlib.h>
#include <conio.h>
#include <mem.h>
#include <time.h>
#include <math.h>
#include <alloc.h>
#define MAX_STAR 80 /* 最多星星數目 */
#define MAX_OBJ 30 /* 最多物體(子彈和敵人) */
#define MAXY 169 /* y坐標的最大值 */
typedef unsigned long ulong;
char far *VideoBuf=(char far*)0xa0000000L, *MemBuf; /* MemBuf 圖形二級緩存 */
char keys[128]; /* keys[0..100] 鍵盤上各鍵的狀態 */
const KEY_UP=72,KEY_DOWN=80,KEY_LEFT=75,KEY_RIGHT=77,KEY_ESC=1,KEY_CTRL=29;
/* 鍵盤掃描碼 */
void interrupt far (*OldInt9)(void); /* 老的鍵盤中斷程序地址 */
void interrupt NewInt9(void); /* 新的鍵盤中斷服務程序 */
char GameStart(void);
struct TStars { int x,y,v; } Stars[MAX_STAR]; /* 星星的描述 */
struct TObj { int mode,type,index,next,x,y; } Objs[MAX_OBJ]; /* 子彈和敵人的描述 */
long GameScore=0; /* 游戲分數 */
unsigned char fly_pic[260]={ /* 飛機的圖形,我是用程序將PCX圖形轉換過來的 */
16,0,16,0,0,0,0,29,25,0,0,0,0,25,29,196,0,0,0,0,0,0,0,25,25,0,0,0,0,25,0,196,0,
0,0,0,112,112,0,25,196,40,40,29,112,112,40,112,0,112,112,112,40,40,112,112,40,40,
25,25,112,40,40,112,112,112,112,112,112,40,112,25,40,40,112,112,112,40,40,25,
40,112,112,0,0,112,112,25,40,40,40,112,40,40,40,25,40,112,0,0,0,0,112,25,40,
112,40,112,112,112,40,25,112,0,0,0,0,0,0,29,112,0,40,0,112,0,112,29,0,0,0,0,
0,0,0,29,112,0,40,54,112,0,112,29,0,0,0,0,0,0,0,29,0,0,40,54,112,0,0,29,0,0,
0,0,0,0,0,0,0,40,112,25,112,112,0,0,0,0,0,0,0,0,0,0,0,40,112,25,112,112,0,0,
0,0,0,0,0,0,0,0,0,40,112,112,112,112,0,0,0,0,0,0,0,0,0,0,0,0,40,112,112,0,0,
0,0,0,0,0,0,0,0,0,0,0,40,25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,112,0,0,0,0,0,0,0,
0}; /* 數據頭四個字節分別由兩個16位數據表示圖片的長和寬,后面是圖片8bit的顏色數據 */
void copyright(void)
{ printf("Game Over. your score %ld\n",GameScore);
printf("Thank you for play it, if you have any question please call me\n");
printf("(0871)7167710 or lwwind@yeah.net, Lin Wei\n");
}
int game_init(void);
int game_restore(void);
void main(void)
{
if (!game_init()) return; /* 游戲初始化 */
printf(" - STAR WAR -\r"); /* 打印標題 */
GameStart(); /* 游戲主循環 */
game_restore(); /* 還原初始化 */
copyright(); /* 顯示說明文 */
}
int game_init(void)
{
long i;
union REGS regs;
MemBuf=(char far*)farmalloc(320L*(MAXY+1));
if (!MemBuf) {
printf("not enough memory\n"); return 0;
}
memset(MemBuf,0,320L*(MAXY+1));
randomize(); /* 初始化隨機函數 */
for (i=0;i<128;i++) keys[i]=0; /* 鍵盤碼初始化 */
for (i=0;i<MAX_STAR;i++) { /* 星空初始化 */
Stars[i].x=random(320);
Stars[i].y=-20+random(250);
Stars[i].v=1;
if (i<MAX_STAR/3) Stars[i].v++;
}
for (i=0;i<MAX_OBJ;i++) Objs[i].mode=0; /* 物體初始化 */
/* 鍵盤中斷初始化:設置新的中斷 */
OldInt9=getvect(9);
disable();
setvect(9,NewInt9);
enable();
/* 設置 320x200x256c圖形模式 */
regs.x.ax=0x13;
int86(0x10,®s,®s);
return 1;
}
int game_restore(void)
{
union REGS regs;
/* 還原設置:還原老的中斷 */
disable();
setvect(9,OldInt9);
enable();
regs.x.ax=3;
int86(0x10,®s,®s);
farfree(MemBuf);
return 0;
}
/* 鍵盤服務程序 */
void interrupt NewInt9(void)
{
unsigned char key;
key=inportb(0x60); /* 讀鍵盤掃描碼 */
if (key<0x80) keys[key]=1; /* 如果最高位是0,則為按下 */
else keys[key&0x7f]=0; /* 如果最高位是1,則為放開 */
key=inportb(0x61); key|=0x80; outportb(0x61,key); /* 告訴鍵盤已接收 */
outportb(0x61,key&0x7f);
outportb(0x20,0x20); /* 發送中斷結束信號 */
}
/*---------------------------- 游戲圖形引擎 ---------------------------------*/
void pixel(unsigned x,unsigned y,char c) /* 畫點 */
{
if (x>=320||y>MAXY) return; /* 判斷范圍 */
MemBuf[(y<<8)+(y<<6)+x]=c; /* MemBuf[y*320+x]=c */
}
/* 將二級緩存的內容顯示出來 */
void show(void)
{
int offset=(199-MAXY)*160;
memcpy(VideoBuf+offset,MemBuf,320L*(MAXY+1));
}
/* 清屏 */
void clear(void)
{
memset(MemBuf,0,320L*(MAXY+1));
}
/* 就是繪制圖塊,(x,y)是坐標b是內存地址mode表示是否上下顛倒
* 敵人和主人是同樣的圖片做顛倒
*/
void putimage(int x,int y,char *b,int mode)
{
int len, wid, i, j;
len = b[0] + (int)b[1] * 256;
wid = b[2] + (int)b[3] * 256;
x-=len/2; y-=wid/2; /* 中心對稱 */
for (j=0,b=b+4;j<wid;j++) for (i=0;i<len;i++,b++)
{ if (*b&&!mode) pixel(x+i,y+j,*b); /* 是否鏡面翻轉 */
if (*b&&mode) pixel(x+i,y+wid-j-1,*b);
}
}
void drawfire(int x,int y) /* 畫出激光 */
{ int i,j;
for (i=-6;i<6;i++) { pixel(x-5,y+i,9); pixel(x+3,y+i,9); }
}
/*---------------------------- 游戲控制引擎 ---------------------------------*/
unsigned long timepass; /* 游戲進行的時間 */
int GameOver, Sound=0;
int fly_x=160,fly_y=MAXY*2/3,fly_flag=1,fire_flag=1;
void drivers(void); /* 控制產生敵人的函數 */
void control(void); /* 對象控制(事件處理) */
int AllocObj(void) /* 分配空余對象 */
{ int i=0;
while (i<MAX_OBJ&&Objs[i].mode) i++;
if (i>=MAX_OBJ) i=MAX_OBJ-1;
return i;
}
int CheckHit(int x1,int y1,int x2,int y2,int r) /* 檢查碰撞 */
{
if (abs(x1-x2)<=r&&abs(y1-y2)<=r) return 1;
return 0;
}
ulong fclock(void) /* 讀取 1.19MHz的32位系統時鐘 */
{
ulong t;
disable(); outportb(0x43,0); t=inportb(0x40);
t+=(inportb(0x40)<<8); t=0xffff^t; enable(); /* (not t) + (clock()<<16) */
return (clock()<<16)+t;
}
char GameStart(void)
{
ulong start=0;
timepass=0;
while (!GameOver)
{
while (fclock()-start<=45000L); start=fclock(); /* 時間控制 */
clear(); /* 1.清屏. 以下5點為游戲的主循環 */
timepass++; /* 2.時間基數++ */
control(); /* 3.事件處理 */
drivers(); /* 4.事件引擎 */
show(); /* 5.顯示 */
if (--Sound<=0) nosound(); /* 聲音處理 */
if ((timepass&3)==0) printf("%d\r",GameScore); /* 到一定的時間更新顯示分數 */
if (keys[KEY_ESC]) GameOver=1;
}
sound(105); delay(700); nosound(); /* Game Over發音 */
return 1;
}
/* 游戲的事件處理主程序分別處理星空和物體還有主角控制
* 通過掃描對象數組:Objs[MAX_OBJ]來完成,根據掃描到的對象屬性Objs[i].mode來判斷
* 到底是什么對象:敵機或者子彈。并進入相應的處理程序:分析對象的狀態,然后作出
* 調整,并重新更改狀態,這就是游戲編程同時處理眾多物體的核心思想。
*/
void control(void)
{
int i,j,x,y, ok;
/* 星星處理 */
for (i=0;i<MAX_STAR;i++) {
Stars[i].y+=Stars[i].v; /* 向下移動 */
if (Stars[i].y>MAXY) { /* 如果移出屏幕就讓它重新出現在屏幕上方某位置 */
Stars[i].x=random(320);
Stars[i].y=-random(60);
}
if (Stars[i].v==1) pixel(Stars[i].x,Stars[i].y,23); /* 速度不一樣顏色也不一樣 */
else pixel(Stars[i].x,Stars[i].y,28);
}
/* 對象處理 */
for (i=0;i<MAX_OBJ;i++) /* 掃描對象數組 */
{ x=Objs[i].x; y=Objs[i].y; ok=1;
switch (Objs[i].mode) /* mode表示敵人,子彈等 */
{
/* 敵人處理 */
case 1: if (Objs[i].index==0) {
switch (Objs[i].type) /* 檢測敵人的三種狀態 */
{ case 0: if (!random(30)) Objs[i].type=1; break; /* 3種動作狀態 */
case 1: if (x<fly_x) x++; if (x>fly_x) x--;
if (!random(40)) Objs[i].type=2; break;
case 2:
default:if (!random(3)) y+=3;
break;
}
if (CheckHit(x,y,fly_x,fly_y,15)) fly_flag=0; /* 與主角相撞 */
putimage(x,y,fly_pic,0);
} else { /* 如果被擊中就閃爍地繪制飛機,然后消失 */
if ((Objs[i].index&3)==0) putimage(x,y,fly_pic,0);
if (++Objs[i].index>50) Objs[i].mode=0;
}
y++; if (y>MAXY) Objs[i].mode=0; /* 移出屏幕就清除 */
break;
/* 激光處理 */
case 2: y-=4; if (y<-20) Objs[i].mode=0; drawfire(x,y);
for (j=0;j<MAX_OBJ;j++) /* 檢查與敵機相碰 */
if (Objs[j].mode==1&&CheckHit(x,y,Objs[j].x,Objs[j].y,15)&&
!Objs[j].index&&ok) /* 擊中敵機 */
{
Objs[j].index=1; ok=0; Objs[i].mode=0;
sound(220); Sound=10; GameScore+=10;
}
break;
}
Objs[i].x=x; Objs[i].y=y; /* 更新坐標 */
}
/* 主角控制 */
if (keys[KEY_UP]) if (--fly_y<0) fly_y=0; /* 如果上鍵被按下 */
if (keys[KEY_DOWN]) if (++fly_y>MAXY) fly_y=MAXY; /* 如果下鍵被按下 */
if (keys[KEY_LEFT]) if (--fly_x<0) fly_x=0; /* 如果左鍵被按下 */
if (keys[KEY_RIGHT]) if (++fly_x>319) fly_x=319; /* 如果右鍵被按下 */
if (keys[KEY_CTRL]&&fire_flag) { /* 如果按下CTRL */
i=AllocObj(); Objs[i].x=fly_x,
Objs[i].y=fly_y-10, Objs[i].mode=2; fire_flag=0;
}
if (!keys[KEY_CTRL]) fire_flag=1; /* 如果放開CTRL */
putimage(fly_x,fly_y,fly_pic,1); /* 畫出主角 */
if (!fly_flag) GameOver=1; /* 判斷主角狀態 */
}
/* 控制產生敵人的部分 */
void drivers(void)
{
if (random(30)==0)
{ int i=AllocObj(); Objs[i].x=random(320); Objs[i].y=-random(20);
Objs[i].mode=1; Objs[i].type=Objs[i].index=0;
if (!random(20)) Objs[i].type=2;
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -