最近在学C++,本想用面向对象的思想做一个小游戏热热手 ,但先后用了vc和dev c++,发现竟然没有找到我在win-tc下熟悉的graphics.h头文件,顿时不知所措,询问高人,回答“为什么不用DX或OPENGL”,晕~~~~,我要会的话还用DOS图形界面吗!!心有不甘,于是又拿起win-tc,写了这个想用C++写的小游戏——坦克打飞机!!呵呵,晕~~~~BUG多多啊,玩了会儿发现坦克不用移动照样打,不好玩!!而且飞机好像离地面好远好远,最后玩了会儿想起不应该叫坦克打飞机,而应该叫坦克打蚊子,哈哈~~~~
#include "Conio.h"#include "graphics.h"#include "math.h"#include "stdlib.h"#define GAMESPEED 2000#define closegr closegraph#define LEFT 0x4b00 #define RIGHT 0x4d00 #define DOWN 0x5000 #define UP 0x4800 #define ESC 0x011b static int x,y;static int bullets=10,hitted=0,count=0; //对子弹数量,击落敌机数量和飞过敌机数量初始化struct TANK //坦克结构体{ int x; //坦克横坐标 int y; //坦克纵坐标}tank;
struct PLANE //敌机结构体{ int x; //敌机横坐标 int y; //敌机纵坐标 int show; //敌机显隐,0为隐,1为显 int dirction; //敌机的飞行方向,0为从左向右,1为从右向左}plane;
struct BULLET //子弹结构体{ int x; //子弹横坐标 int y; //子弹纵坐标 int show; //子弹的显隐}bullet;
int key; //KEY为按键
drawfloor() //绘制外围{ setfillstyle(EMPTY_FILL,BLACK); //设置填充模式 setcolor(BLUE); bar(0,0,x,y); //实际目的为清屏 rectangle(0,y*0.1,x,y*0.9); //画边界 setcolor(BLUE); settextstyle(TRIPLEX_FONT,HORIZ_DIR,3); //设置文字风格 outtextxy(0,y*0.07,"HITTED:"); //用于显示击落数和剩余子弹数 outtextxy(x*0.15,y*0.07,"BULLETS:");}
drawtank(struct TANK tank) //绘制坦克{ rectangle(tank.x-3,tank.y,tank.x+3,tank.y+15); arc(tank.x,tank.y+25,0,180,10); rectangle(tank.x-20,tank.y+25,tank.x+20,tank.y+35); circle(tank.x-15,tank.y+40,5); circle(tank.x-5,tank.y+40,5); circle(tank.x+5,tank.y+40,5); circle(tank.x+15,tank.y+40,5);}
drawplanel(int x,int y) //绘制敌机(从左向右飞){ line(x-10,y-4,x-8,y); line(x-8,y,x+8,y); line(x,y-5,x+5,y); line(x,y+5,x+5,y);}
drawplaner(int x,int y) //绘制敌机(从右向左飞){ line(x-8,y,x+8,y); line(x+10,y-4,x+8,y); line(x,y-5,x-5,y); line(x,y+5,x-5,y);}
showdetail() //在顶端显示详细数据(击落敌机数和剩余子弹数){ char str1[2],str2[2]; setfillstyle(EMPTY_FILL,BLACK); setcolor(RED); bar(x*0.1,y*0.07,x*0.15,y*0.09); //用于抹去旧的数据 sprintf(str1,"%d",hitted); outtextxy(x*0.1,y*0.07,str1); bar(x*0.25,y*0.07,x*0.3,y*0.09); sprintf(str2,"%d",bullets); outtextxy(x*0.25,y*0.07,str2);}
playgame() /*游戏过程*/{ int quit=0; //控制是否退出 bullet.show=0; //子弹开始不显示 plane.x=10; //敌机出现位置 plane.y=y*0.15; plane.show=1; //敌机开始时就要显示 plane.dirction=0; //第一个敌机的飞行方向为从左向右飞 tank.x=x*0.5; //开始时坦克的出现位置 tank.y=y*0.9-47; drawtank(tank); //开始就要画出坦克 showdetail(); //显示初始的详细数据 while (1) { while(!kbhit()) //在没有按键的时候执行如下命令 {
setcolor(BLACK); circle(bullet.x,bullet.y+2,3); //用黑笔将子弹抹去 if(bullet.show) //如果子弹是显示的,就让它向上移动 { setcolor(BLUE); circle(bullet.x,bullet.y,3); bullet.y-=2; if(bullet.y<y*0.15) //判断子弹是否已经到达最高处 { if(abs(bullet.x-plane.x)<=20) //如果子弹到达最高处就还要判断是否击中敌机 { plane.show=0; //如果击中了就要让敌机消失 hitted++; //并且还要让击落数加1 setcolor(BLACK); circle(plane.x,plane.y,5); //要用黑笔将子弹抹去 showdetail(); //刷新详细数据 }/*end of if(abs(bullet.x-plane.x)<=30)*/ bullet.show=0; //子弹也要消失 }/*end of if(bullet.y<y*0.15)*/ }/*end of if(bullet.show)*/
setcolor(BLACK); if(plane.dirction) drawplaner(plane.x,plane.y); else drawplanel(plane.x,plane.y); //判断飞行方向并用黑笔将敌机抹去,? if(plane.show) //如果敌机是显示的,则要让它在飞行方向上往前飞 { if(plane.dirction) //根据飞行方向决定需要什么样的绘制方法 { plane.x-=1; if(plane.x<10) plane.show=0; //如果敌机机到达最左端,则让它消失,否则向左移动 else { setcolor(BLUE); drawplaner(plane.x,plane.y); }/*end of else(plane.x>x-10)*/ }/*end of if(plane.dirction)*/ else { plane.x+=1; if(plane.x>x-10) plane.show=0; //如果敌机机到达最右端,则让它消失,否则向右移动 else { setcolor(BLUE); drawplanel(plane.x,plane.y); }/*end of else(plane.x<10)*/ }/*end of else(plane.dirction))*/ }/*end of if(plane.show)*/ else //如果敌机没有显示,则让它随机从最左端或是从最右端出现 { int random=0; randomize(); //配置随机数发生器 random=rand()%2; //将随机数除以2的余数赋给random switch(random) { case 0:plane.x=10;plane.show=1;plane.dirction=0;count++;break; //设置敌机的出生位置并让飞过敌机数加1 case 1:plane.x=x-10;plane.show=1;plane.dirction=1;count++;break; }/*end of switch(random)*/ }/*end of else*/ if(count==10) return 0; //如果飞过敌机数为10则终止游戏 delay(GAMESPEED); //暂停一段时间 }/*end of while(!kbhit())*/ key=bioskey(0); //如果按键了,则让key来接收 switch(key) //判断按了什么键 { case UP:if(bullet.show==0&&bullets!=0) {bullet.x=tank.x;bullet.y=tank.y-5;bullet.show=1;bullets--;showdetail();}break; //如果按了up键,屏幕上还没有子弹并且还有剩余子弹数,则把子弹的位置设在坦克的炮口,并让剩余子弹数减1,还要刷新详细数据 case LEFT:if(tank.x-20<5) break; else {setcolor(BLACK);drawtank(tank);tank.x-=8;break;} //如果按了left键,并且坦克没有到最左边,则用黑笔抹去坦克,并让坦克的横坐标减8,等待重绘 case RIGHT:if(tank.x+20>x-10)break; else {setcolor(BLACK);drawtank(tank);tank.x+=8;break;} //如果按了right键,并且坦克没有到最右边,则用黑笔抹去坦克,并让坦克的横坐标加8,等待重绘 case ESC:quit=1;break; //如果按了ese键,则让退出控制变量quit为1 }/*end of switch(key)*/ if(quit) break; //判断quit的值,如为1,则跳出循环 setcolor(BLUE); drawtank(tank); //绘制坦克 }/*end of while(1)*/}/*end of playgame()*/
showrecord() //显示成绩{ char str[20],str1[20]; settextstyle(DEFAULT_FONT,HORIZ_DIR,3); setfillstyle(EMPTY_FILL,BLACK); setcolor(BLUE); bar(0,0,x,y); //实际作用为清屏 sprintf(str,"you shot down %d planes",hitted); outtextxy(50,200,str); if(0<=hitted<=5) //根据hitted数量作出评价, { sprintf(str1,"You Are Bad Soldier"); outtextxy(60,300,str1); } else if(6<=hitted<=9) { sprintf(str1,"You Are Good Soldier"); outtextxy(60,300,str1); } else if(hitted==10) { sprintf(str1,"You Are Hero"); outtextxy(80,300,str1); }}
showbegin() //显示开始界面{ char str[50]; settextstyle(DEFAULT_FONT,HORIZ_DIR,4); setcolor(RED); sprintf(str,"DANGEROUS!!!!!"); outtextxy(110,100,str); settextstyle(DEFAULT_FONT,HORIZ_DIR,2); sprintf(str,"The enemy plane is coming,Harry up!!"); outtextxy(30,180,str); sprintf(str,"UP:fire LEFT AND RIGHT:move"); //控制说明 outtextxy(80,400,str);}
void initgr(void) /* BGI初始化 */{ int gd = DETECT, gm = 0; /* 和gd = VGA,gm = VGAHI是同样效果 */ registerbgidriver(EGAVGA_driver);/* 注册BGI驱动后可以不需要.BGI文件的支持运行 */ initgraph(&gd, &gm, "");}
int main(void){ initgr(); /* BGI初始化 */ x=getmaxx();/*最大横坐标*/ y=getmaxy();/*最大纵坐标*/ showbegin(); sleep(5); drawfloor();/*绘制游戏围墙*/ playgame(); showrecord(); sleep(2); closegr(); /* 恢复TEXT屏幕模式 */ return 0;}