飞机游戏
#define MAXOBJ 物体最大数量
#define MAXX 屏幕宽度
#define MAXY 屏幕高
struct TOBJ{
int mode;
int x, y;
int index;
int type;
}Objs[MAXOBJ];
int AllocObj()
{
int i=0;
while(i<MAXOBJ&&Objs[i].mode) i++;
if(i>=MAXOBJ) return MAXOBJ - 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;
}
void drivers()
{
if(!random(20)){
int i=AllocObj();
Objs[i].x=random(MAXX);
Objs[i].y=-random(60);
Objs[i].mode=1;
Objs[i].type=Objs[i].index=0;
if(!random(120)) Objs[i].type=2;
//直接出现的敌机的速度就很快
}
}
int fly_x=MAXX/2, fly_y=MAXY*4/5, fire_flag=0,
fly_flag=1;
int GameOver=1;
char GameOver()
{
while(GameOver){
clear();
control();
dirvers();
show();
if(key[ESC]) GameOver = 0;
}
return 1;
}
void control()
{
int i, j;
int x, y;
for(i=0; i<MAXOBJ; i++){
x=Objs[i].x; y=Objs[i].y;
switch(Objs[i].mode){
case 1:
if(!Objs[i].index){
switch(Objs[i].type){
case 0:
if(!random(3)) Objs[i].type = 1;
break;
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;
}//end switch(Objs[i].type);
if(Check(x, y, fly_x, fly_y, 15) fly_flag=0;// 画出敌机;
if(!random(10)){
j=AllocObj();
if(!random(3)) Objs[j].mode=3;
else{
Objs[j].mode = 4;
Objs[j].k = (fly_y - y)* 1.0 / (fly_x-x);
}
Objs[j].x=x; Objs[j].y=y;
}
}//end if(!Objs[i].index)
else{
if((Objs[i].index&3)==0) 画出敌机;
if(++Objs[i].index>50) Objs[i].mode=0;
}end if(!Objs[i].index))
y++;
if(y>MAXY) Objs[i].mode=0;
break;
case 2:
y-=3;
画出我方子弹;
for(j=0; j<MAXOBJ; j++)
if((Objs[j].mode==1)&&(!Objs[j].index)&&CheckHit(x, y,Objs[j].x, Objs[j].y, 15)){
Objs[j].index = 1;
Objs[i].mode = 0;
}
break;
case 3:
y+=3;
x+=random(20)-10;
if(y>MAXY) Objs[i].mode=0;
画出子弹;
if(Check(x, y, fly_x, fly_y, 15)) fly_flag=0;
break;
case 4:
x += -Objs[i].k;
abs(Objs[i].k)<=1?(y += 4):(y+=2) ;
画出子弹;
if(CheckHit(x,y,fly_x,fly_y,8)) fly_flag=0;
break;
}//end switch(Objs[i].mode);
}//end for
if(key[UP]) if(fly_y--<0) fly_y=0;
if(key[DOWN]) if(fly_y++>MAXY) fly_y=MAXY;
if(key[LEFT]) if(fly_x--<0) fly_x=0;
if(key[RIGHT]) if(fly_x++>MAXX) fly_x=MAXX;
if(key[CTRL]){
i=AllocObj();
Objs[i].x=fly_x,
Objs[i].y=fly_y-10;
Objs[i].mode=2;
}
if(!fly_flag) GameOver=0;
}
对飞机游戏编码的理解
int GameStart()
{
while(GameOver){
clear();
control();
dirver();
show();
if(key[ESC]) GameOver = 0;
}
return 1;
}
这个函数在此用while语句,是用来控制游戏退出的。clear()这个语句是清屏。control()这个函数是游戏的核心,控制整个游戏的,比如说控制飞机,子弹如何飞。dirver()这个函数是控制着敌人的出现。show()函数是显示图形
所以整个游戏的思路很简单,清屏——游戏控制——敌机出现——显示:
1.clear();
清屏函数直接把MemBuf全部赋值成0。
2.control();
首先定义物体结构。
struct TOBJ{
int mode; //类型,0:空闲,1:敌机;2,自己发射的子弹,3,敌人子弹类型1;
int x, y;
int type;
int index;
} Objs[MAXOBJ];
要控制整个游戏的进程,必须每个飞机,子弹都在动,所以用
for(i=0; i<MAXOBJ; i++) 这个循环对每个物体进行控制。
对单个物体来说,首先要确定每个物体的类型,类型不一样,执行的操作也就不一样
switch(Obj[i].mode){
case 1: //如果是敌机,执行敌机的操作;
......;
break;
case 2: //如果是自己发射的子弹,执行自己的子弹的操作;
......;
break;
case 3: //如果是敌人子弹类型1,执行子弹类型1的操作;
......;
break;
case 4: //执行敌人子弹类型2的操作
......;
break;
...... //执行子弹类型N的操作;
}
1.1敌机操作:
首先判断敌机是不是已经死亡,如果死亡,则显示死亡的效果,比如说爆炸,这是最常见的飞机游戏中,敌机死亡的效果,还比如说敌机出现闪烁的效果,这种方式倒是也有,不过效果自然没有爆炸的效果华丽,在此我用闪烁的效果。如果敌机没有死亡,则要往我机上撞,以期消灭我机——显然不能任何时候都跟着咱们跑,所以要有一定的几率性,这样,不会时时刻刻跟着咱们。
switch (Objs[i].type) {
case 0:
if(!random(20)) Objs[i].type=1;
break;
case 1:
if(Objs[i].x<fly_x) Objs[i].x++;
if(Objs[i].x>fly_x) Objs[i].x--;
if(!random(40)) Objs[i].type=2;
break;
case 2:
default:
if(!random(3)) y+=3;
break;
}
这段程序是执行敌机的飞行擦作的。Objs[i].type==0是,1/20的几率让敌机跟着自己飞,此时执行case
1。然后1/40的几率使敌机加速,此时执行case 2:default:;
敌机的飞行任务完成,还必须能发射子弹,一样,用随机函数,比方说:
if (!random(30){ // 1/30的几率发射子弹
j=AllocObj();// 从Objs中选择一个,也就是空闲的
if(!random(5)) Objs[j].mode=2; // 1/5的几率,是子弹类型2;
else Objs[j].mode=3;
Objs[j].x=Objs[i].x;
Objs[j].y=Objs[i].y;
}
最后这两句很容易理解,子弹发射的坐标,自然要从发射它的敌机那里发射,所以坐标一样。然后是判断敌机和我机相撞没有if(CheckHit(x,y,fly_x,fly_y,15)) fly_flag=0;CheckHit是碰撞函数,和上面的AllocObj()函数一起在后面给出实现过程。这只是敌机未死亡所执行的操作如果敌机死亡,则要出现死亡效果
if(Objs[i].index){
if ((Objs[i].index&3)==0) 画敌机图片
if(++Objs[i].index>50) Objs[i].mode=0;
}
这段程序很容易理解也就是过段时间,显示次敌机的图片。如果是不显示的话,在前面的主循环中,已经被clear()函数给清屏了。敌机的操作还有最后一步if(Objs[i].y>MAXY) Objs[i].mode=0;如果敌机飞到屏幕下方,则释放函数AllocObj()的实现
int AllocObj()
{
int i = 0;
while(i<MAXOBJ&&Objs[i].mode) i++;
if(i>=MAXOBJ) i = MAXOBJ - 1;
return i;
} 函数CheckHit()的实现这个函数通过矩形判断
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;
}
1.2我方子弹
先让子弹往上飞Objs[i].y-=3;然后判断是否射中敌人。
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){
Objs[j].index=1;
Objs[i].mode=0;
}
显然,要判断是否射中敌人,要首先扫描所有的敌人,看看是否射中,
Objs[i].mode = 0 回收此子弹
Objs[j].index = 0; 代表敌机存活
Objs[j].index!=0;代表敌机死亡,之所以不用Objs[j].mode=0代表敌人死亡,是因为还要出现死亡后的效果,也可以用Objs[j].mode=0代表敌机死亡,不过这样子就没有死亡后效果了,射中敌人,敌人就消失。)
1.3敌方:子弹
Objs[i].y+=3;
Objs[i].x+=random(10)-5;
if(CheckHit(x,y,fly_x,fly_y,10))
//敌机子弹射中我机
fly_flag=0;
这段程序x+=random(10)-5;这个语句,它在原横坐标的位置,往左右5幅度的概率相等,随机,因此造成这个子弹很阴险
1.4 我机的操作
if(key[KEY_UP]) if (--fly_y<0) fly_y=0;
if(key[KEY_DOWN]) if (++fly_y>MAXM-16) fly_y=MAXM-16;
if(key[KEY_LEFT]) if (--fly_x<0) fly_x=0;
if(key[KEY_RIGHT]) if (++fly_x>MAXX-16) fly_x=MAXX-16;
if(key[KEY_CONTROL]){
i=AllocObj();
Objs[i].x=fly_x,
Objs[i].y=fly_y-10;
Objs[i].mode=2;
}
画出我机的图片if(!fly_flag) GameOver = 1;在此,整个程序的思路很清晰了
2.0下面设计dirver()函数
void drivers()
{
if(!random(20)){
int i=AllocObj();
Objs[i].x=random(MAXX);
Objs[i].y=-random(60);
Objs[i].mode=1;
Objs[i].type=Objs[i].index=0;
if(!random(120)) Objs[i].type=2;
//直接出现的敌机的速度就很快
}
}