课程作业 飞机大战游戏
游戏的编写能用到C++学习过程中的很多知识,数组、函数和面向对象。这个练习是一个开放式的练习,你可以在基本要求的基础上进行任何扩充。
扩充下游戏1定义的飞机大战游戏的功能:
增加多个界面,初始化界面,说明游戏功能;结束界面,提示用户的得分情况,以及是否开始一个新的游戏;
随着积分的增加,可以考虑增加难度,加快敌机的下落速度,和出现的速度;
功能上做更多的性能处理:例如防止玩家操控飞机飞出边界,击中/碰撞检测的处理
增加按Esc键后游戏暂停的功能
增加图形界面(easyX,Qt, MFC)以及面向对象的程序设计
游戏规则
用户通过WASD进行方向移动,空格发射子弹。初始时,得分为0,操作者每击中一个敌机,得分加1,每被敌机击中一次,得分减1,被敌机撞上,得分减2.当得分小于0时游戏结束,当将设定的敌机数量的所有敌机全消灭,游戏胜利,最后显示总得分。
游戏中可以选择难度,随着游戏进行,敌人会变得更加厉害
设计思路
将游戏界面分成一个个小的单元,将每一种物品设置一个编号,使用一个二维数组记录每个位置当前对应的物品,从而实现记录每个物品的位置。
游戏中主要通过show函数和control函数完成。show函数来显示画面,control函数控制游戏中的一些操作。将游戏分为9个部分,对应9个不同的背景,分成9个函数来控制。
主函数中是一个循环,循环中是show函数和control函数。
设计这个游戏过程中注意的地方
随机敌机位置的时候需要考虑敌机的宽度,防止出框
飞机移动或者子弹移动过程中注意数组越界
飞机不能飞出框框
敌机子弹从上往下走,需要从下到上扫描
飞机有宽度,子弹击中和碰撞判断需要一个范围
重新开始,所有变量需要重置
敌机随机位置的时候,避免重叠
在游戏一开始和继续的时候,需要有停顿1s,给使用者反应时间
点击下载
(和下面贴出的代码是一样的,只是多了音乐,图片等
代码
#include
#include
#include
#include
#include
#include
#include#pragma comment(lib,"Winmm.lib") // 引用 Windows Multimedia API#pragma warning(disable : 4996) //忽略4996警告/*Dev里面运行不了在VS里面新建项目,将代码复制进去还需将属性中的字符集从Unicode改成使用多字节字符集,要不报错右键点击右面的项目的名字->点击属性->点击->高级->找到字符集->改成使用多字节字符集*/using namespace std;#define height 598 //窗口大小是 55*35
#define width 396 //画面大小
#define enemySum 20 //敌人总数
#define enemyNum 3 //一次出现的敌人数量
#define enemySpeed 20 //敌人发射子弹的速度
#define EnemyBulletTime 2000 //一个敌人子弹发射的时间间隔
#define planeSpeed 2 //己方子弹速度
#define enemyDown 25 //敌机下落的速度
int EnemySum; //调整难度参数
int EnemySpeed;
int EnemyNum;
int EnemyDown;IMAGE img_background1; //欢迎背景
IMAGE img_background2; //功能选择背景
IMAGE img_background3; //游戏背景
IMAGE img_background4; //关于背景
IMAGE img_background5; //帮助背景
IMAGE img_background6; //胜利游戏结束背景
IMAGE img_background7; //失败游戏结束背景
IMAGE img_background8; //难度选择背景
IMAGE img_background9; //游戏暂停背景
IMAGE img_plane; //飞机
IMAGE img_zplane; //遮罩图飞机
IMAGE img_enemy; //敌机
IMAGE img_zenemy; //遮罩图敌机
IMAGE img_bullet; //子弹
IMAGE img_zbullet; //遮罩图子弹
IMAGE img_ebullet; //敌机子弹
IMAGE img_zebullet; //遮罩图敌机
IMAGE img_dieenemy; //敌机击毁
IMAGE img_zdieenemy; //遮罩图敌机击毁
IMAGE img_dieplane; //飞机击毁
IMAGE img_zdieplane; //遮罩图飞机击毁int bk_no; //背景切换编号
bool bk_change; //是否换背景
int plane_x, plane_y; //飞机坐标
int canvas[1000][1000]; //画布
int bulletTime[1000][1000]; //控制敌机子弹飞行速度
int enemy_x[20], enemy_y[20]; //敌机坐标
int enemyDownTime[20]; //飞机下落时间
int enemyTime[20]; //敌机子弹发射时间间隔
int score; //得分
int killSum; //击杀敌人的数量
bool stop; //控制画面是否停顿void initialization(); //数据初始化
void startup(); //载入图片
bool checkPos(int x, int y); //检查敌机位置是否重复
void bkShow(); //背景显示
void gameShow(); //游戏显示
void show(); //显示
void updateWithInput(); //有操作更新
void updateWithoutInput(); //无操作更新
void bk3Control(); //操作3
void bk45Control(); //操作4 5
void bk67Control(); //操作6 7
void bk8Control(); //操作8
void control(); //操作控制int main()
{startup();while (1){show();control();}
}void initialization()
{memset(canvas, 0, sizeof(canvas)); //画布清空memset(bulletTime, 0, sizeof(bulletTime));memset(enemyDownTime, 0, sizeof(enemyDownTime));plane_x = 396 / 2;plane_y = 518;score = 0;killSum = 0;stop = 1;canvas[plane_y][plane_x] = 1;for (int i = 1; i <= EnemyNum; i++){enemy_x[i] = rand() % (width - 35); //注意敌机长度 enemy_y[i] = 0;if (checkPos(enemy_x[i], enemy_y[i])) //防止重叠{i--;continue;}canvas[enemy_y[i]][enemy_x[i]] = 3;canvas[enemy_y[i] + 36][enemy_x[i] + 14] = 4;enemyTime[i] = rand() % EnemyBulletTime;}
}void startup() //数据初始化
{initgraph(396, 598); //定义画布大小loadimage(&img_background1, _T(".\\picture\\background1.png"));//载入图片loadimage(&img_background2, _T(".\\picture\\background2.png"));loadimage(&img_background3, _T(".\\picture\\background3.jpg"));loadimage(&img_background4, _T(".\\picture\\background4.png"));loadimage(&img_background5, _T(".\\picture\\background5.png"));loadimage(&img_background6, _T(".\\picture\\background6.png"));loadimage(&img_background7, _T(".\\picture\\background7.png"));loadimage(&img_background8, _T(".\\picture\\background8.png"));loadimage(&img_background9, _T(".\\picture\\background9.png"));loadimage(&img_plane, _T(".\\picture\\plane.png"));loadimage(&img_zplane, _T(".\\picture\\zplane.png"));loadimage(&img_enemy, _T(".\\picture\\enemy.png"));loadimage(&img_zenemy, _T(".\\picture\\zenemy.png"));loadimage(&img_bullet, _T(".\\picture\\bullet.png"));loadimage(&img_zbullet, _T(".\\picture\\zbullet.png"));loadimage(&img_ebullet, _T(".\\picture\\ebullet.png"));loadimage(&img_dieenemy, _T(".\\picture\\dieenemy.png"));loadimage(&img_zdieenemy, _T(".\\picture\\zdieenemy.png"));loadimage(&img_dieplane, _T(".\\picture\\dieplane.png"));loadimage(&img_zdieplane, _T(".\\picture\\zdieplane.png")); mciSendString("open .\\sound\\gamemusic.mp3 alias bkmusic", NULL, 0, NULL);//打开背景音乐 //需要改成使用多字节字符集mciSendString("play bkmusic repeat", NULL, 0, NULL); // 循环播放bk_no = 1;bk_change = 1;
}bool checkPos(int x,int y)
{for (int i = 0; i <= 35; i++)if (canvas[y][x + i]||canvas[y][x-i])return true;return false;
}void bkShow()
{if (bk_no == 1){putimage(0, 0, &img_background1);Sleep(3000);bk_no = 2;bk_change = 1;}else if (bk_no == 2)putimage(0, 0, &img_background2);else if (bk_no == 3)putimage(0, 0, &img_background3);else if (bk_no == 4)putimage(0, 0, &img_background4);else if (bk_no == 5)putimage(0, 0, &img_background5);else if(bk_no==6)putimage(0, 0, &img_background6);else if (bk_no == 7)putimage(0, 0, &img_background7);else if(bk_no==8)putimage(0, 0, &img_background8);else if (bk_no == 9)putimage(0, 0, &img_background9);
}void gameShow()
{BeginBatchDraw(); //开始绘制背景 防止加载图片闪烁putimage(0, 0, &img_background3); //背景重新载入,防止闪动putimage(plane_x, plane_y, &img_zplane,NOTSRCERASE);putimage(plane_x, plane_y, &img_plane, SRCINVERT);for (int i = 0; i <= height; i++){for (int j = 0; j <= width; j++){if (canvas[i][j] == 2){putimage(j, i, &img_zbullet, NOTSRCERASE);putimage(j, i, &img_bullet, SRCINVERT);}else if (canvas[i][j] == 3){putimage(j, i, &img_zenemy, NOTSRCERASE);putimage(j, i, &img_enemy, SRCINVERT);}else if (canvas[i][j] == 4){putimage(j, i, &img_ebullet, NOTSRCERASE);putimage(j, i, &img_zebullet, SRCINVERT);}}}settextstyle(18, 9, _T("黑体")); //设置字体格式TCHAR s[] = _T("得分:");outtextxy(5, 570, s); //显示得分TCHAR sc[5];_stprintf(sc, _T("%d"), score); //转换类型outtextxy(50, 570, sc);EndBatchDraw(); //结束绘制
}void show()
{if (bk_change){bk_change = 0;bkShow(); }if (bk_no == 3)gameShow();}void updateWithInput() //有操作更新
{char input;if (kbhit()) //判断是否有输入{input = getch();if (input == 'a') //控制不超过边界 {canvas[plane_y][plane_x] = 0;if(plane_x>0)plane_x-=2; //1移动太慢canvas[plane_y][plane_x] = 1;}if (input == 'd'){canvas[plane_y][plane_x] = 0;if(plane_x<346)plane_x+=2;canvas[plane_y][plane_x] = 1;}if (input == 'w'){canvas[plane_y][plane_x] = 0;if(plane_y>25)plane_y-=2;canvas[plane_y][plane_x] = 1;}if (input == 's'){canvas[plane_y][plane_x] = 0;if(plane_y<510)plane_y+=2;canvas[plane_y][plane_x] = 1;}if (input == ' ') //发射子弹{canvas[plane_y-28][plane_x+18] = 2; //子弹的初始位置在飞机的正上方mciSendString("close firing", NULL, 0, NULL); // 先把前面一次的音乐关闭mciSendString("open .\\sound\\firing.wav alias firing", NULL, 0, NULL); // 打开音乐mciSendString("play firing", NULL, 0, NULL); // 仅播放一次}if (input == 0x1b){bk_no = 9;bk_change = 1;}}
}void updateWithoutInput() //无操作更新
{for (int i = 0; i <= height; i++){for (int j = 0; j <= width; j++){if (canvas[i][j] == 2) //判断子弹击中敌机 {for (int k = 1; k <= EnemyNum; k++) //多个敌机 {if (((j >= enemy_x[k] - 5 && j <= enemy_x[k] + 35) &&(i >= enemy_y[k]&&i == enemy_y[k] + 35))){putimage(enemy_x[k], enemy_y[k], &img_zdieenemy, NOTSRCERASE); //敌机击毁图片putimage(enemy_x[k], enemy_y[k], &img_dieenemy, SRCINVERT);mciSendString("close enemyExplode", NULL, 0, NULL); // 先把前面一次的音乐关闭mciSendString("open .\\sound\\enemyExplode.wav alias enemyExplode", NULL, 0, NULL); // 打开音乐mciSendString("play enemyExplode", NULL, 0, NULL); // 仅播放一次score++;canvas[enemy_y[k]][enemy_x[k]] = 0;while (1) //敌机更新 {enemy_x[k] = rand() % (width - 35);enemy_y[k] = 0;if (checkPos(enemy_x[k],enemy_y[k]))continue;break;}canvas[enemy_y[k]][enemy_x[k]] = 3;canvas[enemy_y[k] + 36][enemy_x[k] + 14] = 4;//新的敌机子弹 canvas[i][j] = 0; //子弹消失 enemyTime[i] = rand() % EnemyBulletTime;killSum++;}}}static int plspeed = 1;if (canvas[i][j] == 2) //子弹上移 {if (plspeed == planeSpeed){canvas[i][j] = 0;if (i - 1 >= 0) //不飞出边界canvas[i - 1][j] = 2;plspeed = 1;}elseplspeed++; }if (canvas[i][j] == 4){ //飞机子弹击中 if (i>=plane_y&&i<=plane_y+50&&j>=plane_x&&j<=plane_x+50){score--;canvas[i][j] = 0;}}}}for (int i = height; i; i--) //敌机子弹从上往下走,需要从下到上扫描 {for (int j = 0; j <= width; j++){if (canvas[i][j] == 4){if (bulletTime[i][j] == EnemySpeed/10) //时间大一些便于控制难度选择{canvas[i][j] = 0;bulletTime[i][j]=0;if (i < height)canvas[i + 1][j] = 4;}elsebulletTime[i][j]++;}}}for (int i = 1; i <= EnemyNum; i++) //发射新的子弹 {if (enemyTime[i] == EnemyBulletTime){canvas[enemy_y[i] + 36][enemy_x[i] + 14] = 4;enemyTime[i] = 0;}elseenemyTime[i]++;if (enemyDownTime[i] == EnemyDown) //敌机下移{canvas[enemy_y[i]][enemy_x[i]] = 0;enemyDownTime[i] = 0;if (enemy_y[i] < height - 20){enemy_y[i]++;canvas[enemy_y[i]][enemy_x[i]] = 3;}else{ while (1) //敌机更新 {enemy_x[i] = rand() % (width - 35);enemy_y[i] = 0;if (checkPos(enemy_x[i], enemy_y[i]))continue;break;}canvas[enemy_y[i]][enemy_x[i]] = 3;canvas[enemy_y[i] + 36][enemy_x[i] + 14] = 4; //新的敌机子弹 }}else{enemyDownTime[i]++;}//敌机撞上if (enemy_y[i] <= plane_y + 35 && enemy_y[i] >= plane_y - 50 && enemy_x[i] <= plane_x + 50 && enemy_x[i] >= plane_x - 35){score =score- 2;putimage(enemy_x[i], enemy_y[i], &img_zdieenemy, NOTSRCERASE); putimage(enemy_x[i], enemy_y[i], &img_dieenemy, SRCINVERT);mciSendString("close enemyExplode", NULL, 0, NULL); mciSendString("open .\\sound\\enemyExplode.wav alias enemyExplode", NULL, 0, NULL); mciSendString("play enemyExplode", NULL, 0, NULL); canvas[enemy_y[i]][enemy_x[i]] = 0;while (1) {enemy_x[i] = rand() % (width - 35);enemy_y[i] = 0;if (checkPos(enemy_x[i], enemy_y[i]))continue;break;}canvas[enemy_y[i]][enemy_x[i]] = 3;canvas[enemy_y[i] + 36][enemy_x[i] + 14] = 4;enemyTime[i] = rand() % EnemyBulletTime;killSum++;}}canvas[plane_y][plane_x] = 1; //飞机恢复,防止被其他覆盖
}void bk2Control() //主菜单
{MOUSEMSG m; //鼠标信息if (MouseHit()) //鼠标动了{m = GetMouseMsg(); //获取鼠标信息if (m.uMsg == WM_LBUTTONDOWN) //按下左键{if (m.x >= 108 && m.x <= 298 && m.y <= 256 && m.y >= 215){ //点击指定位置memset(canvas, 0, sizeof(canvas)); //画布清零initialization(); //可能是后面游戏结束返回菜单,所以数据重置bk_no = 8; //开始bk_change = 1; //更新控制变量}else if (m.x >= 108 && m.x <= 298 && m.y <= 330 && m.y >= 283){bk_no = 5; //帮助bk_change = 1;}else if (m.x >= 108 && m.x <= 298 && m.y <= 400 && m.y >= 350){bk_no = 4; //关于bk_change = 1;}else if (m.x >= 108 && m.x <= 298 && m.y <= 471 && m.y >= 420)exit(1); //退出}}
}void bk3Control()
{if (stop){Sleep(1000); //给游戏者1s反应时间stop = 0;}updateWithInput();updateWithoutInput();if (score < 0) //游戏结束{bk_change = 1;bk_no = 7;putimage(plane_x, plane_y, &img_zdieplane, NOTSRCERASE); //飞机击毁图片putimage(plane_x, plane_y, &img_dieplane, SRCINVERT);mciSendString("close gameover", NULL, 0, NULL); //失败音效mciSendString("open .\\sound\\gameover.mp3 alias gameover", NULL, 0, NULL); mciSendString("play gameover", NULL, 0, NULL);Sleep(2000);}if (killSum == EnemySum) //击灭所有敌人{bk_change = 1;bk_no = 6;mciSendString("close victory", NULL, 0, NULL); //胜利音效mciSendString("open .\\sound\\victory.wav alias victory", NULL, 0, NULL);mciSendString("play victory", NULL, 0, NULL);}if (killSum > EnemySum / 4 * 3) //击杀一定数量敌人后,提高敌人子弹发射速度EnemySpeed / 5 * 4;else if (killSum > EnemySum / 4 * 2)EnemySpeed / 5 * 4;else if (killSum > EnemySum / 4 * 1)EnemySpeed / 5 * 4;
}void bk45Control()
{MOUSEMSG m;if (MouseHit()){m = GetMouseMsg();if (m.uMsg == WM_LBUTTONDOWN){if (m.x <= 396 && m.x >= 300 && m.y <= 598 && m.y >= 555){ //返回至功能选择bk_no = 2;bk_change= 1;}}}
}void bk67Control()
{if (bk_no == 6){TCHAR sc[5];settextstyle(40, 20, _T("黑体")); //设置字体格式_stprintf(sc, _T("%d"), score);outtextxy(302, 265, sc);}MOUSEMSG m;if (MouseHit()){m = GetMouseMsg();if (m.uMsg == WM_LBUTTONDOWN){if (m.x <= 267 && m.x >= 130 && m.y <= 430 && m.y >= 393) //再来一局{memset(canvas, 0, sizeof(canvas));initialization();bk_no = 8;bk_change = 1;}if (m.x <= 282 && m.x >= 114 && m.y <= 497 && m.y >= 461) //返回主菜单{bk_no = 2;bk_change = 1;}if (m.x <= 270 && m.x >= 130 && m.y <= 562 && m.y >= 528) //退出游戏{exit(1);}}}}void bk8Control()
{MOUSEMSG m;if (MouseHit()){m = GetMouseMsg();if (m.uMsg == WM_LBUTTONDOWN){if (m.x <= 235 && m.x >= 147 && m.y <= 292 && m.y >= 249)//简单{ EnemySum = enemySum;EnemySpeed = enemySpeed;EnemyNum = enemyNum;EnemyDown = enemyDown;bk_no = 3;bk_change = 1;initialization();}else if (m.x <= 235 && m.x >= 147 && m.y <= 364 && m.y >= 320)//普通{EnemySum = enemySum*2;EnemySpeed = enemySpeed/2;EnemyNum = enemyNum+1;EnemyDown = enemyDown/2;bk_no = 3;bk_change = 1;initialization();}else if (m.x <= 235 && m.x >= 147 && m.y <= 428 && m.y >= 389)//困难{EnemySum = enemySum*3;EnemySpeed = enemySpeed/3;EnemyNum = enemyNum+2;EnemyDown = enemyDown/3;bk_no = 3;bk_change = 1;initialization();}}}
}void bk9Control()
{MOUSEMSG m;settextstyle(40, 20, _T("黑体")); TCHAR sc[5];_stprintf(sc, _T("%d"), score); outtextxy(241, 212, sc);if (MouseHit()){m = GetMouseMsg();if (m.uMsg == WM_LBUTTONDOWN){if (m.x <= 288 && m.x >= 107 && m.y <= 326 && m.y >= 277) //继续游戏{ stop = 1;bk_no = 3;bk_change = 1;}if (m.x <= 288 && m.x >= 107 && m.y <= 393 && m.y >= 348) //重新开始{bk_no = 8;bk_change = 1;}if (m.x <= 315 && m.x >= 85 && m.y <= 470 && m.y >= 421) //返回主菜单{bk_no = 2;bk_change = 1;}if (m.x <= 288 && m.x >= 107 && m.y <= 546 && m.y >= 500) //退出游戏{exit(1);}}}
}void control()
{if (bk_no == 2)bk2Control();if (bk_no == 4 || bk_no == 5)bk45Control();if (bk_no == 3)bk3Control();if (bk_no == 6||bk_no==7)bk67Control();if (bk_no == 8)bk8Control();if (bk_no == 9)bk9Control();
}
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
