课程作业 飞机大战游戏

游戏的编写能用到C++学习过程中的很多知识,数组、函数和面向对象。这个练习是一个开放式的练习,你可以在基本要求的基础上进行任何扩充。
扩充下游戏1定义的飞机大战游戏的功能:

增加多个界面,初始化界面,说明游戏功能;结束界面,提示用户的得分情况,以及是否开始一个新的游戏;

随着积分的增加,可以考虑增加难度,加快敌机的下落速度,和出现的速度;

功能上做更多的性能处理:例如防止玩家操控飞机飞出边界,击中/碰撞检测的处理

增加按Esc键后游戏暂停的功能

增加图形界面(easyX,Qt, MFC)以及面向对象的程序设计

游戏规则

用户通过WASD进行方向移动,空格发射子弹。初始时,得分为0,操作者每击中一个敌机,得分加1,每被敌机击中一次,得分减1,被敌机撞上,得分减2.当得分小于0时游戏结束,当将设定的敌机数量的所有敌机全消灭,游戏胜利,最后显示总得分。
游戏中可以选择难度,随着游戏进行,敌人会变得更加厉害

设计思路

将游戏界面分成一个个小的单元,将每一种物品设置一个编号,使用一个二维数组记录每个位置当前对应的物品,从而实现记录每个物品的位置。
游戏中主要通过show函数和control函数完成。show函数来显示画面,control函数控制游戏中的一些操作。将游戏分为9个部分,对应9个不同的背景,分成9个函数来控制。
主函数中是一个循环,循环中是show函数和control函数。

设计这个游戏过程中注意的地方
随机敌机位置的时候需要考虑敌机的宽度,防止出框
飞机移动或者子弹移动过程中注意数组越界
飞机不能飞出框框
敌机子弹从上往下走,需要从下到上扫描
飞机有宽度,子弹击中和碰撞判断需要一个范围
重新开始,所有变量需要重置
敌机随机位置的时候,避免重叠
在游戏一开始和继续的时候,需要有停顿1s,给使用者反应时间

点击下载
(和下面贴出的代码是一样的,只是多了音乐,图片等

代码

#include<iostream>
#include<windows.h>
#include<graphics.h>
#include<conio.h>
#include<algorithm>
#include<stdlib.h>
#include<cstring>

#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;
				}
				else
					plspeed++;				
			}
			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;
				}
				else
					bulletTime[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;
		}
		else
			enemyTime[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();
}
  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值