C++游戏开发——坦克大战

C++游戏开发——坦克大战_第1张图片

 C++游戏开发——坦克大战_第2张图片

引言:

就是练C++而已的。

 代码:

C++游戏开发——坦克大战_第3张图片

工具类

lag.h

#pragma once

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#pragma comment(lib,"winmm.lib")        // 播放音频

using namespace std;

/*
功能:窗口居中
参数:hWnd-窗口句柄
*/
void myCenterWindow(HWND hWnd);

/*
功能:得到某范围内的随机整数
参数:min - 最小值
     max - 最大值
返回:某范围内的随机整数
*/
int myRandom(int min, int max);

/*
功能:定时器
参数:interval - 延时间隔(毫秒)
     id - 编号 (0-max)
返回:true-已到时,false-未到时
*/
bool myTimer(int interval, int id);

/*
功能:播放音频
参数:fileName - 音频文件
     repeat - 是否循环播放(true-循环,false-不循环)
返回:无
*/
void myPlayAudio(const string& fileName, bool repeat = false);

/*
功能:判断某键是否被按下
参数:keyCode - 键值
返回:true-按下,false-未按下
*/
bool myKeyDown(int keyCode);

/*
功能:判断两个矩形是否相交
参数:x1 - 第一个矩形的左上角X坐标
     y1 - 第一个矩形的左上角Y坐标
     w1 - 第一个矩形的宽度
     h1 - 第一个矩形的高度
     x2 - 第二个矩形的左上角X坐标
     y2 - 第二个矩形的左上角Y坐标
     w2 - 第二个矩形的宽度
     h2 - 第二个矩形的高度
返回:true-相交,false-不相交
*/
bool myRectIntersectRect(int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2);

/*
功能:绘制透明图片
参数:dstX - 目的X坐标
     dstY - 目的Y坐标
     pSrcImg - 源图像指针
     winWidth - 窗口宽度(判断图片位置是否超出窗口范围,不录则默认为0,表示该参数不用)
     winHeight - 窗口高度(判断图片位置是否超出窗口范围,不录则默认为0,表示该参数不用)
返回:无
*/
void myDrawImage(int dstX, int dstY, IMAGE* pSrcImg, int winWidth = 0, int winHeight = 0);

/*
功能:绘制字符串
参数:text - 字符串内容
     x - X坐标
     y - Y坐标
返回:无
*/
void myDrawString(int x, int y, const string& text);

lag.cpp

#include "lag.h"

/*
功能:窗口居中
参数:hWnd-窗口句柄
*/
void myCenterWindow(HWND hWnd)
{
	int screenWidth;		// 屏幕宽度
	int screenHeight;		// 屏幕高度
	RECT rect;				// 矩形

	// 得到屏幕尺寸
	screenWidth = GetSystemMetrics(SM_CXSCREEN);
	screenHeight = GetSystemMetrics(SM_CYSCREEN);

	// 得到窗口尺寸
	GetWindowRect(hWnd, &rect);

	// 重新设置窗口尺寸
	rect.left = (screenWidth - (rect.right - rect.left)) / 2;
	rect.top = (screenHeight - (rect.bottom - rect.top)) / 3;

	// 移动窗口到屏幕中间
	SetWindowPos(hWnd, HWND_TOP, rect.left, rect.top, rect.right, rect.bottom, SWP_NOSIZE);
}

/*
功能:得到某范围内的随机整数
参数:min - 最小值
	 max - 最大值
返回:某范围内的随机整数
备注:公式:min + rand() % (max - min + 1)
	 原理:rand() % m => 返回[0-m)的随机数
*/
int myRandom(int min, int max)
{
	// 生成随机种子(必须在原有毫秒时间的基础上再加随机值,否则在类似for循环中会出现同一种子值的现象)
	srand((unsigned int)time(NULL) + (unsigned)rand());

	return (int)(min + rand() % (max - min + 1));
}

/*
功能:定时器
参数:interval - 延时间隔(毫秒)
	 id - 编号 (0-max)
返回:true-已到时,false-未到时
*/
bool myTimer(int interval, int id)
{
	// 静态vector数组(默认数组元素为5,值为0)
	static vector vectorLastTimeForMyTimer(5, 0);

	// 根据编号自动扩容
	if (id < 0) { id = 0; }
	if ((int)vectorLastTimeForMyTimer.size() <= id) { vectorLastTimeForMyTimer.resize(id + 1, 0); }

	// 得到当前毫秒并判断是否到时
	unsigned long long currentTime = GetTickCount64();
	if (vectorLastTimeForMyTimer[id] == 0)		// 未初始化呢
	{
		vectorLastTimeForMyTimer[id] = currentTime;
		return false;
	}
	else
	{
		int addTime = (int)(currentTime - vectorLastTimeForMyTimer[id]);
		if (addTime >= interval)
		{
			vectorLastTimeForMyTimer[id] = currentTime;
			return true;
		}
	}

	return false;
}

/*
功能:播放音频
参数:fileName - 音频文件
	 repeat - 是否循环播放(true-循环,false-不循环)
返回:无
*/
void myPlayAudio(const string& fileName, bool repeat)
{
	string command = "play " + fileName;
	if (repeat) { command += " repeat"; }
	mciSendString(command.c_str(), 0, 0, 0);
}

/*
功能:判断某键是否被按下
参数:keyCode - 键值
返回:true-按下,false-未按下
*/
bool myKeyDown(int keyCode)
{
	return (GetAsyncKeyState(keyCode) & 0x8000);
}

/*
功能:判断两个矩形是否相交
参数:x1 - 第一个矩形的左上角X坐标
	 y1 - 第一个矩形的左上角Y坐标
	 w1 - 第一个矩形的宽度
	 h1 - 第一个矩形的高度
	 x2 - 第二个矩形的左上角X坐标
	 y2 - 第二个矩形的左上角Y坐标
	 w2 - 第二个矩形的宽度
	 h2 - 第二个矩形的高度
返回:true-相交,false-不相交
*/
bool myRectIntersectRect(int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2)
{
	if (x1 > x2 + w2) { return false; }
	if (x2 > x1 + w1) { return false; }
	if (y1 > y2 + h2) { return false; }
	if (y2 > y1 + h1) { return false; }

	return true;
}

/*
功能:载入图片并过滤透明部分(做位运算)
参数:picture_x - 载入图片X坐标
	 picture_y - 载入图片Y坐标
	 picture - 载入图片
返回:无
*/
void myDrawImageAlpha(int  picture_x, int picture_y, IMAGE* picture)
{
	DWORD* dst = GetImageBuffer();						// GetImageBuffer()函数,用于获取绘图设备的显存指针,EASYX自带
	DWORD* draw = GetImageBuffer();
	DWORD* src = GetImageBuffer(picture);				// 获取picture的显存指针
	int picture_width = picture->getwidth();			// 获取picture的宽度,EASYX自带
	int picture_height = picture->getheight();			// 获取picture的高度,EASYX自带
	int graphWidth = getwidth();						// 获取绘图区的宽度,EASYX自带
	int graphHeight = getheight();						// 获取绘图区的高度,EASYX自带
	int dstX = 0;										// 在显存里像素的角标

	// 实现透明贴图 公式: Cp=αp*FP+(1-αp)*BP , 贝叶斯定理来进行点颜色的概率计算
	for (int iy = 0; iy < picture_height; iy++)
	{
		for (int ix = 0; ix < picture_width; ix++)
		{
			int srcX = ix + iy * picture_width;			// 在显存里像素的角标
			int sa = ((src[srcX] & 0xff000000) >> 24);	// 0xAArrggbb;AA是透明度
			int sr = ((src[srcX] & 0xff0000) >> 16);	// 获取RGB里的R
			int sg = ((src[srcX] & 0xff00) >> 8);		// G
			int sb = src[srcX] & 0xff;					// B
			if (ix >= 0 && ix <= graphWidth && iy >= 0 && iy <= graphHeight && dstX <= graphWidth * graphHeight)
			{
				dstX = (ix + picture_x) + (iy + picture_y) * graphWidth;		// 在显存里像素的角标
				int dr = ((dst[dstX] & 0xff0000) >> 16);
				int dg = ((dst[dstX] & 0xff00) >> 8);
				int db = dst[dstX] & 0xff;
				draw[dstX] = ((sr * sa / 255 + dr * (255 - sa) / 255) << 16)	// 公式: Cp=αp*FP+(1-αp)*BP  ; αp=sa/255 , FP=sr , BP=dr
					| ((sg * sa / 255 + dg * (255 - sa) / 255) << 8)			// αp=sa/255 , FP=sg , BP=dg
					| (sb * sa / 255 + db * (255 - sa) / 255);					// αp=sa/255 , FP=sb , BP=db
			}
		}
	}
}

/*
功能:绘制透明图片
参数:dstX - 目的X坐标
	 dstY - 目的Y坐标
	 pSrcImg - 源图像指针
	 winWidth - 窗口宽度(判断图片位置是否超出窗口范围,不录则默认为0,表示该参数不用)
	 winHeight - 窗口高度(判断图片位置是否超出窗口范围,不录则默认为0,表示该参数不用)
返回:无
*/
void myDrawImage(int dstX, int dstY, IMAGE* pSrcImg, int winWidth, int winHeight)
{
	IMAGE imgTmp;
	int newImgX = 0;
	int newImgY = 0;
	int newImgWidth = pSrcImg->getwidth();
	int newImgHeight = pSrcImg->getheight();
	int flag = 0;

	// 图片完全不在窗口中
	if (dstX <= -pSrcImg->getwidth()) { return; }
	if (winWidth > 0 && dstX >= winWidth) { return; }
	if (dstY <= -pSrcImg->getheight()) { return; }
	if (winHeight > 0 && dstY >= winHeight) { return; }

	// 处理X坐标
	if (dstX < 0)   // 左边界
	{
		newImgX = -dstX;
		newImgWidth = pSrcImg->getwidth() + dstX;
		dstX = 0;
		flag = 1;
	}
	else if (winWidth > 0 && dstX > winWidth - pSrcImg->getwidth())     // 右边界
	{
		newImgWidth = winWidth - dstX;
		flag = 1;
	}

	// 处理Y坐标
	if (dstY < 0)       // 上边界
	{
		newImgY = -dstY;
		newImgHeight = pSrcImg->getheight() + dstY;
		dstY = 0;
		flag = 1;
	}
	else if (winHeight > 0 && dstY > winHeight - pSrcImg->getheight())      // 下边界
	{
		newImgHeight = winHeight - dstY;
		flag = 1;
	}

	// 处理图片变动
	if (flag == 1)
	{
		SetWorkingImage(pSrcImg);   // 设定pSrcImg为当前的绘图设备
		getimage(&imgTmp, newImgX, newImgY, newImgWidth, newImgHeight);      // 从当前绘图设备获取图像(即截取pSrcImg的要显示部分内容放到imgTmp中)
		SetWorkingImage();          // 恢复默认绘图设备
		pSrcImg = &imgTmp;
	}

	// 开始输出透明位图
	myDrawImageAlpha(dstX, dstY, pSrcImg);
}

/*
功能:绘制字符串
参数:text - 字符串内容
	 x - X坐标
	 y - Y坐标
返回:无
*/
void myDrawString(int x, int y, const string& text)
{
	outtextxy(x, y, text.c_str());
}

/*
功能:绘制血条
参数:x - 血条X坐标
	 y - 血条Y坐标
	 width - 血条宽度
	 height - 血条高度
	 percent - 血条比例
返回:无
*/
void myDrawBloodBar(int x, int y, int width, int height, float percent);

/*
功能:绘制血条
参数:x - 血条X坐标
	 y - 血条Y坐标
	 width - 血条宽度
	 height - 血条高度
	 percent - 血条比例
返回:无
*/
void myDrawBloodBar(int x, int y, int width, int height, float percent)
{
	// 记录原来的状态,以便后面恢复
	COLORREF fillColor = getfillcolor();
	COLORREF getColor = getcolor();

	if (percent < 0) { percent = 0.0; }

	setfillcolor(YELLOW);
	solidrectangle(x, y, x + width, y + height);
	setfillcolor(RED);
	solidrectangle(x, y, (int)(x + width * percent), y + height);
	setcolor(WHITE);
	rectangle(x, y, x + width, y + height);

	// 恢复原来的状态
	setfillcolor(fillColor);
	setcolor(getColor);
}

方块类 

Block.h

#pragma once

#include "lag.h"

// 方块类
class Block
{
private:
	IMAGE imgWall;			// 墙块图片
	IMAGE imgIron;			// 铁块图片
	IMAGE imgHome;			// 老巢图片
	int(*map)[26];			// 当前地图
public:

	// 构造函数
	Block();

	// 绘制方块
	void draw();

};

Block.cpp

#include "Block.h"
#include "GameMap.h"
#include "define.h"

// 构造函数
Block::Block()
{
	// 加载图片
	loadimage(&imgWall, "./resources/image/wall.gif");
	loadimage(&imgIron, "./resources/image/iron.gif");
	loadimage(&imgHome, "./resources/image/home.jpg");
	
	// 得到当前地图
	map = GameMap::getMap();
}

// 绘制方块
void Block::draw()
{
	// 绘制墙块与铁块
	for (int i = 0; i < 26; i++)
	{
		for (int j = 0; j < 26; j++)
		{
			int value = map[i][j];
			if (value > 0)
			{
				if (value == WALL)			// 墙块
				{
					putimage(j * BLOCK_SIZE, i * BLOCK_SIZE, &imgWall);
				}
				else if (value == IRON)	// 铁块
				{
					putimage(j * BLOCK_SIZE, i * BLOCK_SIZE, &imgIron);
				}
			}
		}
	}

	// 绘制老巢
	myDrawImage(12 * BLOCK_SIZE, 24 * BLOCK_SIZE, &imgHome);
}

爆炸类

Bomb.h

#pragma once
#include "define.h"
#include "lag.h"

// 爆炸类
class Bomb
{
private:
	static IMAGE* imgBombs[5];				// 爆炸图片

public:
	int x = 0;								// 爆炸中心点X坐标
	int y = 0;								// 爆炸中心点Y坐标
	int frameIndex = -1;					// 爆炸图片帧数
	int maxFrame = 5;						// 最大图片帧数
	int size = BLOCK_SIZE * 2;				// 爆炸尺寸
	int status = BOMB_STATUS_FREE;			// 爆炸状态

public:

	// 构造函数
	Bomb();

	// 绘制爆炸
	void draw();
};

Bomb.cpp

#include "Bomb.h"

IMAGE* Bomb::imgBombs[5] = {NULL};				// 初始化爆炸图片

// 构造函数
Bomb::Bomb()
{
	// 加载图片
	if (imgBombs[0] == NULL)
	{
		IMAGE imgTmp;
		loadimage(&imgTmp, "./resources/image/bomb.png", size * 5, size);
		SetWorkingImage(&imgTmp);				// 设定当前绘图目标为imgTmp
		for (int i = 0; i < 5; i++)
		{
			imgBombs[i] = new IMAGE;
			getimage(imgBombs[i], i * size, 0, size, size);
		}
		SetWorkingImage();						// 设置绘图目标为绘图窗口
	}
}

// 绘制爆炸
void Bomb::draw()
{
	myDrawImage(x - size / 2 + 6, y - size / 2 + 6, imgBombs[frameIndex],GAME_WIDTH,GAME_HEIGHT);	// 得考虑子弹的尺寸
}

子弹类

Bullet.h

#pragma once

#include "lag.h"
#include "define.h"

// 子弹类
class Bullet
{
private:
	static IMAGE* imgBullets[4];			// 子弹图片

public:
	int x = 0;								// X坐标
	int y = 0;								// Y坐标
	int direction = 0;						// 方向
	int speed = 6;							// 速度
	int owner = 0;							// 拥有者
	int status = BULLET_STATUS_FREE;		// 状态

public:

	// 构造函数
	Bullet();

	// 子弹绘制
	void draw();

	// 子弹运行
	void run();

};

Bullet.cpp

#include "Bullet.h"

IMAGE* Bullet::imgBullets[4] = {NULL};			// 初始化子弹图片

// 构造函数
Bullet::Bullet()
{
	// 加载子弹图片
	if (imgBullets[0] == NULL)
	{
		IMAGE imgTmp;
		loadimage(&imgTmp, "./resources/image/bullet.png", BULLET_SIZE * 4, BULLET_SIZE);
		SetWorkingImage(&imgTmp);				// 设定当前绘图目标为imgTmp
		for (int i = 0; i < 4; i++)
		{
			imgBullets[i] = new IMAGE;
			getimage(imgBullets[i], i * BULLET_SIZE, 0, BULLET_SIZE, BULLET_SIZE);
		}
		SetWorkingImage();						// 设置绘图目标为绘图窗口
	}
}

// 子弹绘制
void Bullet::draw()
{
	myDrawImage(this->x, this->y, imgBullets[this->direction], GAME_WIDTH, GAME_HEIGHT);
}

// 子弹运行
void Bullet::run()
{
	switch (this->direction)
	{
		case TANK_DIRECTION_UP:
			if (this->y - this->speed >= 0)
			{
				this->y -= this->speed;
			}
			else
			{
				this->status = BULLET_STATUS_FREE;
			}
			break;
		case TANK_DIRECTION_DOWN:
			if (this->y + BULLET_SIZE + this->speed <= GAME_HEIGHT)
			{
				this->y += this->speed;
			}
			else
			{
				this->status = BULLET_STATUS_FREE;
			}
			break;
		case TANK_DIRECTION_LEFT:
			if (this->x >= this->speed)
			{
				this->x -= this->speed;
			}
			else
			{
				this->status = BULLET_STATUS_FREE;
			}
			break;
		case TANK_DIRECTION_RIGHT:
			if (this->x + BLOCK_SIZE + this->speed <= GAME_WIDTH)
			{
				this->x += this->speed;
			}
			else
			{
				this->status = BULLET_STATUS_FREE;
			}
			break;
	}
}

宏定义

define.h

#pragma once

// 主窗口宏定义
#define TITLE "坦克大战"						// 窗口标题
#define WIN_WIDTH 570						// 窗口宽度
#define WIN_HEIGHT 468						// 窗口高度
#define GAME_WIDTH 468						// 游戏宽度
#define GAME_HEIGHT 468						// 游戏高度
#define INTERVAL_REFRESH 10					// 界面刷新间隔
#define TIMERID_REFRESH 0					// 界面刷新ID
#define GAME_STATUS_RUN	0					// 游戏状态(运行)
#define GAME_STATUS_WIN 1					// 游戏状态(胜利)
#define GAME_STATUS_OVER 2					// 游戏状态(失败)
#define INTERVAL_SCORE 500					// 分数刷新间隔
#define TIMERID_SCORE 8						// 分数刷新ID

// 块宏定义
#define BLANK 0								// 空地
#define WALL 1								// 墙块
#define IRON 2								// 铁块
#define HOME 9								// 老巢
#define BLOCK_SIZE 18						// 方块尺寸

// 坦克宏定义
#define TANK_OWNER_HERO 8					// 我方坦克
#define TANK_OWNER_ENEMY 7					// 敌方坦克
#define TANK_DIRECTION_UP 0					// 坦克方向(向上)
#define TANK_DIRECTION_LEFT 1				// 坦克方向(向左)
#define TANK_DIRECTION_DOWN 2				// 坦克方向(向下)
#define TANK_DIRECTION_RIGHT 3				// 坦克方向(向右)
#define TANK_STATUS_FREE 0					// 坦克状态(空闲)
#define TANK_STATUS_RUN 1					// 坦克状态(运行)
#define INTERVAL_TANKMOVE 10				// 坦克移动进程刷新间隔
#define TIMERID_TANKMOVE 4					// 坦克移动进程刷新ID
#define INTERVAL_CREATEENEMY 5000			// 敌方坦克投放刷新间隔
#define TIMERID_CREATEENEMY 5				// 敌方坦克投放刷新ID
#define INTERVAL_MOVEENEMY 300				// 敌方坦克移动刷新间隔
#define TIMERID_MOVEENEMY 6					// 敌方坦克移动刷新ID

// 子弹宏定义
#define INTERVAL_BULLET_SHOOT 500			// 子弹射击间隔
#define TIMERID_BULLET_SHOOT 1				// 子弹射击ID
#define INTERVAL_BULLET_RUN 10				// 子弹运行间隔
#define TIMERID_BULLET_RUN 2				// 子弹运行ID
#define BULLET_STATUS_FREE 0				// 子弹状态(空闲)
#define BULLET_STATUS_RUN 1					// 子弹状态(运行)
#define BULLET_SIZE 9						// 子弹尺寸

// 爆炸宏定义
#define INTERVAL_BOMB 50					// 爆炸刷新间隔
#define TIMERID_BOMB 3						// 爆炸刷新ID
#define BOMB_STATUS_FREE 0					// 爆炸状态(空闲)
#define BOMB_STATUS_RUN 1					// 爆炸状态(运行)

// 星星宏定义
#define INTERVAL_STAR 100					// 星星刷新间隔
#define TIMERID_STAR 7						// 星星刷新ID
#define STAR_STATUS_FREE 0					// 星星状态(空闲)
#define STAR_STATUS_RUN 1					// 星星状态(运行)

游戏地图类

GameMap.h

#pragma once

#define LEVEL_TOTAL 2						// 总关卡数

// 游戏地图
class GameMap
{
private:
	static int maps[LEVEL_TOTAL][26][26];	// 各关地图
	static int level;						// 当前关数
	static int enemyTankNum[LEVEL_TOTAL];	// 当前关敌方坦克数

public:

	// 设置关数
	static void setLevel(int level);

	// 得到最大关数
	static int getMaxLevel();

	// 得到当前关敌方坦克数
	static int getEnemyTankNum(int level);

	// 得到当前关地图
	static int(*getMap())[26];

};

GameMap.cpp

#include "GameMap.h"

// 各关地图初始化
int GameMap::maps[LEVEL_TOTAL][26][26] =
{
    // 第1关地图
    {
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0},
        {0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0},
        {0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0},
        {0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0},
        {0,0,1,1,0,0,1,1,0,0,1,1,2,2,1,1,0,0,1,1,0,0,1,1,0,0},
        {0,0,1,1,0,0,1,1,0,0,1,1,2,2,1,1,0,0,1,1,0,0,1,1,0,0},
        {0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0},
        {0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0},
        {0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0},
        {0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0},
        {1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,1,1},
        {2,2,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,2,2},
        {0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0},
        {0,0,1,1,0,0,1,1,0,0,1,1,1,1,1,1,0,0,1,1,0,0,1,1,0,0},
        {0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0},
        {0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0},
        {0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0},
        {0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0},
        {0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0},
        {0,0,1,1,0,0,1,1,0,0,0,1,1,1,1,0,0,0,1,1,0,0,1,1,0,0},
        {0,0,0,0,0,0,0,0,0,0,0,1,9,9,1,0,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,0,1,9,9,1,0,0,0,0,0,0,0,0,0,0,0}
    },
    // 第2关地图
    {
        {0,0,0,0,0,0,2,2,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,2,2,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0},
        {0,0,1,1,0,0,2,2,0,0,0,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0},
        {0,0,1,1,0,0,2,2,0,0,0,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0},
        {0,0,1,1,0,0,0,0,0,0,0,0,1,1,1,1,0,0,1,1,2,2,1,1,0,0},
        {0,0,1,1,0,0,0,0,0,0,0,0,1,1,1,1,0,0,1,1,2,2,1,1,0,0},
        {0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0},
        {0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0},
        {0,0,0,0,0,0,1,1,0,0,0,0,2,2,0,0,0,0,1,1,0,0,1,1,2,2},
        {0,0,0,0,0,0,1,1,0,0,0,0,2,2,0,0,0,0,1,1,0,0,1,1,2,2},
        {0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,2,2,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,2,2,0,0,0,0,0,0,0,0},
        {0,0,1,1,1,1,1,1,0,0,0,0,0,0,2,2,0,0,0,0,0,0,1,1,0,0},
        {0,0,1,1,1,1,1,1,0,0,0,0,0,0,2,2,0,0,0,0,0,0,1,1,0,0},
        {0,0,0,0,0,0,2,2,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0},
        {0,0,0,0,0,0,2,2,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0},
        {2,2,1,1,0,0,2,2,0,0,1,1,0,0,1,1,0,0,0,0,0,0,1,1,0,0},
        {2,2,1,1,0,0,2,2,0,0,1,1,0,0,1,1,0,0,0,0,0,0,1,1,0,0},
        {0,0,1,1,0,0,1,1,0,0,1,1,1,1,1,1,0,0,1,1,2,2,1,1,0,0},
        {0,0,1,1,0,0,1,1,0,0,1,1,1,1,1,1,0,0,1,1,2,2,1,1,0,0},
        {0,0,1,1,0,0,1,1,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0},
        {0,0,1,1,0,0,1,1,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0},
        {0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0},
        {0,0,1,1,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,0,0,1,1,0,0},
        {0,0,1,1,0,0,1,1,0,0,0,1,9,9,1,0,0,0,1,1,1,1,1,1,0,0},
        {0,0,1,1,0,0,1,1,0,0,0,1,9,9,1,0,0,0,1,1,1,1,1,1,0,0}
    }
    // 其他关地图...
};

// 当前关卡初始化
int GameMap::level = 0;

// 当前关敌方坦克数初始化
int GameMap::enemyTankNum[LEVEL_TOTAL] = { 16,20 };

// 设置关数
void GameMap::setLevel(int level)
{
	GameMap::level = level;
}

// 得到最大关数
int GameMap::getMaxLevel()
{
    return LEVEL_TOTAL;
}

// 得到当前关敌方坦克数
int GameMap::getEnemyTankNum(int level)
{
    return GameMap::enemyTankNum[level];
}

// 得到当前关地图
int(*GameMap::getMap())[26]
{
    return GameMap::maps[GameMap::level];
}

星星类

Star.h

#pragma once

#include "define.h"
#include "lag.h"

// 星星类
class Star
{
private:
	static IMAGE* imgStars[4];				// 星星图片
	unsigned long long lastTime;			// 上次时间

public:
	int row = 0;							// 行坐标
	int column = 0;							// 列坐标
	int status = STAR_STATUS_FREE;			// 星星状态
	int frameIndex = -1;					// 星星图片帧数
	int maxFrame = 4;						// 星星图片帧数
	int size = BLOCK_SIZE * 2;				// 星星尺寸
	
public:

	// 构造函数
	Star();

	// 绘制星星
	void draw();

};

Star.cpp

#include "Star.h"

IMAGE* Star::imgStars[4] = {NULL};

// 构造函数
Star::Star()
{
	// 加载图片
	if (imgStars[0] == NULL)
	{
		IMAGE imgTmp;
		loadimage(&imgTmp, "./resources/image/star.png", size * 4, size);
		SetWorkingImage(&imgTmp);				// 设定当前绘图目标为imgTmp
		for (int i = 0; i < 4; i++)
		{
			imgStars[i] = new IMAGE;
			getimage(imgStars[i], i * size, 0, size, size);
		}
		SetWorkingImage();						// 设置绘图目标为绘图窗口
	}

	// 计时开始
	this->lastTime = GetTickCount64();
}

// 绘制星星
void Star::draw()
{
	myDrawImage(column * BLOCK_SIZE,row * BLOCK_SIZE, imgStars[frameIndex]);
}

坦克类

Tank.h

#pragma once

#include "lag.h"
#include "Bullet.h"

// 坦克类
class Tank
{
private:
	int owner;							// 坦克拥有者
	int(*map)[26];						// 关卡地图
	static IMAGE* imgHero[4][4][2];		// 我方坦克图片([装甲][方向][履带])
	static IMAGE* imgEnemy[4][4][2];	// 敌方坦克图片([装甲][方向][履带])
	vector bulletPool;			// 子弹池
	unsigned long long lastTime;		// 上次时间

public:
	int x;								// 坦克左上角X坐标
	int y;								// 坦克左上角Y坐标
	int row;							// 坦克所在行
	int column;							// 坦克所在列
	int oldRow;							// 坦克上次所在行
	int oldColumn;						// 坦克上次所在列
	int direction;						// 坦克方向
	int speed = 2;						// 坦克速度
	int originalArmor = 0;				// 原始装甲
	int armor = 0;						// 当前装甲(共4层)
	int status = TANK_STATUS_FREE;		// 坦克状态
	bool track = false;					// 履带切换

private:

	// 坦克是否可以移动
	bool moveValid(int direction);

public:

	// 有参构造函数
	Tank(int tankOwner, int tankRow, int tankColumn, int tankDirection);

	// 坦克绘制
	void draw();

	// 坦克移动
	bool move(int direction);

	// 坦克射击
	void shoot();

	// 坦克坐标映射到地图
	void toMap();

	// 坦克重置
	void reset();

	// 得到子弹池
	vector& getBulletPool();

};

Tank.cpp

#include "Tank.h"
#include "GameMap.h"
#include "define.h"

IMAGE* Tank::imgHero[4][4][2] = {NULL};				// 初始化我方坦克图片
IMAGE* Tank::imgEnemy[4][4][2] = {NULL};			// 初始化敌方坦克图片

// 有参构造函数
Tank::Tank(int owner, int row, int column, int direction)
{
	// 参数初始化
	this->owner = owner;
	this->row = row;
	this->column = column;
	this->oldRow = this->row;
	this->oldColumn = this->column;
	this->x = this->column * BLOCK_SIZE;
	this->y = this->row * BLOCK_SIZE;
	this->direction = direction;
	this->map = GameMap::getMap();

	// 加载敌我双方坦克图片(图片每一行装甲不同,这里没用装甲)
	if (imgHero[0][0][0] == NULL)
	{
		// 加载敌我坦克图片
		IMAGE imgTmp;
		loadimage(&imgTmp, "./resources/image/tank.png", BLOCK_SIZE * 16, BLOCK_SIZE * 16);			// 加载时扩大到合适尺寸,剪裁时就正好大小了
		SetWorkingImage(&imgTmp);			// 切换到绘图工作区
		for (int ar = 0; ar < 4; ar++)
		{
			for (int dir = 0; dir < 4; dir++)
			{
				for (int tr = 0; tr < 2; tr++)
				{
					// 我方坦克
					imgHero[ar][dir][tr] = new IMAGE;
					getimage(imgHero[ar][dir][tr], dir * BLOCK_SIZE * 4 + tr * BLOCK_SIZE * 2 - 1, ar * BLOCK_SIZE * 2, BLOCK_SIZE * 2, BLOCK_SIZE * 2);
					// 敌方坦克
					imgEnemy[ar][dir][tr] = new IMAGE;
					getimage(imgEnemy[ar][dir][tr], dir * BLOCK_SIZE * 4 + tr * BLOCK_SIZE * 2 - 1, BLOCK_SIZE * 8 + ar * BLOCK_SIZE * 2, BLOCK_SIZE * 2, BLOCK_SIZE * 2);
				}
			}
		}
		SetWorkingImage();					// 切换回窗口工作区
	}

	// 计时开始
	this->lastTime = GetTickCount64();
}

// 坦克绘制
void Tank::draw()
{
	// 绘制我方坦克
	if (this->owner == TANK_OWNER_HERO && this->status == TANK_STATUS_RUN)
	{
		myDrawImage(this->x, this->y, imgHero[this->armor][this->direction][this->track]);
	}
	// 绘制敌方坦克
	if (this->owner == TANK_OWNER_ENEMY && this->status == TANK_STATUS_RUN)
	{
		myDrawImage(this->x, this->y, imgEnemy[this->armor][this->direction][this->track]);
	}
}

// 坦克是否可以移动
bool Tank::moveValid(int direction)
{
	switch (direction)
	{
		case TANK_DIRECTION_UP:
			if (row == 0) { return false; }
			if (map[row - 1][column] > 0) { return false; }
			if (map[row - 1][column + 1] > 0) { return false; }
			break;
		case TANK_DIRECTION_DOWN:
			if (row == 24) { return false; }
			if (map[row + 2][column] > 0) { return false; }
			if (map[row + 2][column + 1] > 0) { return false; }
			break;
		case TANK_DIRECTION_LEFT:
			if (column == 0) { return false; }
			if (map[row][column - 1] > 0) { return false; }
			if (map[row + 1][column - 1] > 0) { return false; }
			break;
		case TANK_DIRECTION_RIGHT:
			if (column == 24) { return false; }
			if (map[row][column + 2] > 0) { return false; }
			if (map[row + 1][column + 2] > 0) { return false; }
			break;
	}
	return true;
}

// 坦克移动
bool Tank::move(int direction)
{
	// 如果坦克移动进程未完成则禁止再次移动
	if (this->oldRow != this->row) { return false; }
	if (this->oldColumn != this->column) { return false; }

	if (this->direction == direction)			// 方向相同则前进
	{
		//  判断是否可以移动
		if (!moveValid(direction)) { return false; }

		// 开始移动
		switch (direction)
		{
			case TANK_DIRECTION_UP:
				map[row + 1][column] = 0;
				map[row + 1][column + 1] = 0;
				map[row - 1][column] = owner;
				map[row - 1][column + 1] = owner;
				oldRow = row;
				row--;
				break;
			case TANK_DIRECTION_DOWN:
				map[row][column] = 0;
				map[row][column + 1] = 0;
				map[row + 2][column] = owner;
				map[row + 2][column + 1] = owner;
				oldRow = row;
				row++;
				break;
			case TANK_DIRECTION_LEFT:
				map[row][column + 1] = 0;
				map[row + 1][column + 1] = 0;
				map[row][column - 1] = owner;
				map[row + 1][column - 1] = owner;
				oldColumn = column;
				column--;
				break;
			case TANK_DIRECTION_RIGHT:
				map[row][column] = 0;
				map[row + 1][column] = 0;
				map[row][column + 2] = owner;
				map[row + 1][column + 2] = owner;
				oldColumn = column;
				column++;
				break;
		}
	}
	else    // 方向不同,仅调整方向不前进
	{
		this->direction = direction;
	}

	return true;
}

// 坦克射击
void Tank::shoot()
{
	// 射击冷却未到时间禁止发射
	unsigned long long currentTime = GetTickCount64();
	int addTime = (int)(currentTime - this->lastTime);
	if (addTime >= INTERVAL_BULLET_SHOOT)
	{
		this->lastTime = currentTime;
	}
	else
	{
		return;
	}
	
	// 在子弹池中寻找空闲的子弹
	Bullet *bullet = nullptr;
	int len = this->bulletPool.size();
	for (int i = 0; i < len; i++)
	{
		if (this->bulletPool[i].status == BULLET_STATUS_FREE)
		{
			bullet = &this->bulletPool[i];
			break;
		}
	}
  	if (bullet == nullptr)			// 没有就增加一个
	{
		Bullet newBullet;
		newBullet.owner = this->owner;
		this->bulletPool.push_back(newBullet);	// 浅拷贝
		bullet = &bulletPool[len];
	}

	// 设置子弹位置
	bullet->direction = this->direction;
	switch (this->direction)
	{
		case TANK_DIRECTION_UP:
			bullet->x = this->column * BLOCK_SIZE + BLOCK_SIZE - BULLET_SIZE / 2;
			bullet->y = this->row * BLOCK_SIZE - BULLET_SIZE - 4;
			break;
		case TANK_DIRECTION_DOWN:
			bullet->x = this->column * BLOCK_SIZE + BLOCK_SIZE - BULLET_SIZE / 2;
			bullet->y = this->row * BLOCK_SIZE + 2 * BLOCK_SIZE + 4;
			break;
		case TANK_DIRECTION_LEFT:
			bullet->x = this->column * BLOCK_SIZE - BULLET_SIZE - 4;
			bullet->y = this->row * BLOCK_SIZE + BLOCK_SIZE - BULLET_SIZE / 2;
			break;
		case TANK_DIRECTION_RIGHT:
			bullet->x = this->column * BLOCK_SIZE + 2 * BLOCK_SIZE + 4;
			bullet->y = this->row * BLOCK_SIZE + BLOCK_SIZE - BULLET_SIZE / 2;
			break;
	}

	// 设置子弹状态
	bullet->status = BULLET_STATUS_RUN;

	// 我方坦克发出射击声音
	if (owner == TANK_OWNER_HERO){myPlayAudio("./resources/audio/shoot.mp3");}
	
}

// 坦克坐标映射到地图
void Tank::toMap()
{
	map[row][column] = owner;
	map[row][column + 1] = owner;
	map[row + 1][column] = owner;
	map[row + 1][column + 1] = owner;
}

// 坦克重置
void Tank::reset()
{
	map[row][column] = 0;
	map[row][column + 1] = 0;
	map[row + 1][column] = 0;
	map[row + 1][column + 1] = 0;
	if (owner == TANK_OWNER_HERO)
	{
		this->row = 24;
		this->column = 8;
		this->oldRow = this->row;
		this->oldColumn = this->column;
		this->x = this->column * BLOCK_SIZE;
		this->y = this->row * BLOCK_SIZE;
		this->direction = TANK_DIRECTION_UP;
		this->armor = 3;
	}
	else
	{
		this->row = 0;
		this->oldRow = 0;
		this->column = 0;
		this->oldColumn = 0;
		this->x = 0;
		this->y = 0;
	}
	this->status = TANK_STATUS_FREE;
}

// 得到子弹池
vector& Tank::getBulletPool()
{
	return this->bulletPool;
}

我方坦克类

Hero.h

#pragma once

#include "Tank.h"

// 我方坦克类
class Hero : public Tank
{

public:

	// 构造函数
	Hero(int tankRow, int tankColumn, int tankDirection);

};

Hero.cpp

#include "Hero.h"
#include "define.h"

// 构造函数
Hero::Hero(int tankRow, int tankColumn, int tankDirection) : Tank(TANK_OWNER_HERO, tankRow, tankColumn, tankDirection) {}

敌方坦克类

Enemy.h

#pragma once
#include "Tank.h"

// 敌方坦克类
class Enemy : public Tank
{
public:
	int target = HOME;		// 坦克射击的目标(我方坦克,老巢)

public:

	// 构造函数
	Enemy(int tankRow, int tankColumn, int tankDirection);

};

Enemy.cpp

#include "Enemy.h"

// 构造函数
Enemy::Enemy(int tankRow, int tankColumn, int tankDirection) : Tank::Tank(TANK_OWNER_ENEMY, tankRow, tankColumn, tankDirection){}

main.cpp

#include "lag.h"
#include "define.h"
#include "GameMap.h"
#include "Block.h"
#include "Hero.h"
#include "Enemy.h"
#include "Bullet.h"
#include "Bomb.h"
#include "Star.h"

// 项目结构
struct _stu_project
{
	int gameStatus = GAME_STATUS_RUN;					// 游戏状态
	bool refreshFlag = false;							// 刷新标识
	int level = 0;										// 游戏关卡
	int enemyMaxNum = 0;								// 敌方坦克最大数量
	int enemyCreateNum = 0;								// 敌方坦克投放数量
	int enemyDeadNum = 0;								// 敌方坦克死亡数量
	int enemyArmorDeadNum[4] = {0,0,0,0};				// 敌方不同装甲坦克死亡数量
	IMAGE imgLogo;										// Logo图片
	IMAGE imgLevel;										// 关卡图片
	IMAGE imgScore;										// 分数图片
	IMAGE imgSuccess;									// 游戏成功图片
	IMAGE imgFailure;									// 游戏失败图片
	int(*map)[26] = nullptr;							// 关卡地图

} stu_project;

// 子弹所在行列结构
struct _stu_bullet_pos
{
	int row1;
	int col1;
	int row2;
	int col2;
};

// 方块类
Block block;

// 我方坦克类
Hero hero(24, 8, TANK_DIRECTION_UP);

// 我方子弹池
vector& heroBulletPool = hero.getBulletPool();

// 敌方坦克类
vector enemyPool;

// 爆炸池
vector bombPool;

// 星星池
vector starPool;

// 函数声明
void createWindow();
void welcome();
void loadResources();
void initGame();
void paint();
void run();
void keyEvent();
void mouseEvent();
void starCreate();
void starAdd(int row, int column);
void enemyTankCreate(int row, int column);
void enemyTankMove();
void enemyTankShoot();
int enemyTankAI(Enemy& enemy);
void bombAdd(int x, int y);
void collide();
void doGame();
void newGame();
void showScore();
void getBulletPos(struct _stu_bullet_pos* pos, int x, int y, int direction);

// 坦克大战
int main()
{
	// 创建窗口
	createWindow();

	// 显示封面
	welcome();

	// 开始游戏
	newGame();

	// 暂停一下
	system("pause");

	// 关闭窗口
	closegraph();

	return 0;
}

// 创建窗口
void createWindow()
{
	// 创建并得到窗口句柄
	HWND hWnd = initgraph(WIN_WIDTH, WIN_HEIGHT);

	// 修改标题
	SetWindowText(hWnd, TITLE);

	// 居中显示
	myCenterWindow(hWnd);
}

// 加载资源
void loadResources()
{
	// 加载游戏成功图片
	loadimage(&stu_project.imgSuccess, "./resources/image/success.png");

	// 加载游戏失败图片
	loadimage(&stu_project.imgFailure, "./resources/image/failure.png");

	// 加载关卡图片
	loadimage(&stu_project.imgLevel, "./resources/image/level.png");

	// 加载Logo图片
	loadimage(&stu_project.imgLogo, "./resources/image/logo.png");

	// 加载分数图片
	loadimage(&stu_project.imgScore, "./resources/image/score.jpg");
}

// 显示封面
void welcome()
{
	// 显示封面
	IMAGE imgWelcome;
	loadimage(&imgWelcome, "./resources/image/welcome.gif");
	putimage(0, 0, &imgWelcome);

	// 加载资源
	loadResources();

	// 暂停一下
	system("pause");
}

// 初始化游戏
void initGame()
{
	// 项目参数初始化
	stu_project.gameStatus = GAME_STATUS_RUN;
	stu_project.refreshFlag = false;
	stu_project.enemyMaxNum = GameMap::getEnemyTankNum(stu_project.level);
	stu_project.enemyCreateNum = 0;
	stu_project.enemyDeadNum = 0;
	stu_project.map = GameMap::getMap();
	for (int i = 0; i < 4; i++){stu_project.enemyArmorDeadNum[i] = 0;}

	// 设置游戏关卡
	GameMap::setLevel(stu_project.level);

	// 我方坦克初始化
	hero.reset();
	hero.status = TANK_STATUS_RUN;
	hero.toMap();

	// 敌方坦克池初始化10辆坦克
	int lenEnemyPool = enemyPool.size();
	if (lenEnemyPool == 0)
	{
		for (int i = 0; i < 10; i++)
		{
			Enemy enemy(0,0,TANK_DIRECTION_DOWN);
			enemyPool.push_back(enemy);
		}
	}
	else
	{
		for (int i = 0; i < lenEnemyPool; i++)
		{
			enemyPool[i].reset();
			vector& enemyBulletPool = enemyPool[i].getBulletPool();
			int lenEnemyBulletPool = enemyBulletPool.size();
			for (int j = 0; j < lenEnemyBulletPool; j++) { enemyBulletPool[j].status = BULLET_STATUS_FREE; }
		}
	}

	// 星星初始化
	int lenStarPool = starPool.size();
	if (lenStarPool == 0)
	{
		for (int i = 0; i < 3; i++)
		{
			Star star;
			starPool.push_back(star);
		}
	}
	else
	{
		for (int i = 0; i < lenStarPool; i++) { starPool[i].status = STAR_STATUS_FREE; }
	}

	// 爆炸初始化
	int lenBombPool = bombPool.size();
	for (int i = 0; i < lenBombPool; i++) {	bombPool[i].status = BOMB_STATUS_FREE;}

}

// 绘制窗口
void paint()
{
	// 开启双缓冲机制,防止闪烁
	BeginBatchDraw();

	// 绘制游戏区域
	setcolor(BLACK);
	cleardevice();
	setfillcolor(LIGHTGRAY);
	fillrectangle(GAME_WIDTH, -2, WIN_WIDTH, WIN_HEIGHT + 2);

	// 绘制分数
	settextstyle(20, 0, "微软雅黑");
	settextcolor(YELLOW);
	setbkmode(TRANSPARENT);
	myDrawString(GAME_WIDTH + 20, 6, "总数:" + to_string(stu_project.enemyMaxNum));
	myDrawString(GAME_WIDTH + 20, 26, "死亡:" + to_string(stu_project.enemyDeadNum));
	myDrawString(GAME_WIDTH + 20, 46, "剩余:" + to_string(stu_project.enemyMaxNum - stu_project.enemyDeadNum));
	int notCreateNum = stu_project.enemyMaxNum - stu_project.enemyCreateNum;
	if (notCreateNum > 0)
	{
		int logoRow = notCreateNum / 2;
		if (notCreateNum % 2 != 0) { logoRow++; }
		int logoCount = 0;
		for (int i = 0; i < logoRow; i++)
		{
			for (int j = 0; j < 2; j++)
			{
				if (logoCount >= notCreateNum) { break; }
				myDrawImage(GAME_WIDTH + 22 + j * (20 + 14), 80 + i * (16 + 4), &stu_project.imgLogo,WIN_WIDTH,WIN_HEIGHT);
				logoCount++;
			}
		}
	}
	myDrawImage(GAME_WIDTH + 20, 330, &stu_project.imgLevel);
	settextcolor(RED);
	myDrawString(GAME_WIDTH + 20, 380, "关数:" + to_string(stu_project.level + 1));
	settextcolor(WHITE);
	myDrawString(GAME_WIDTH + 20, 420, "作者:Lag");

	// 绘制地图
	block.draw();

	// 绘制我方坦克
	hero.draw();

	// 绘制我方子弹
	int lenHeroBulletPool = heroBulletPool.size();
	for (int i = 0; i < lenHeroBulletPool; i++)
	{
		if (heroBulletPool[i].status == BULLET_STATUS_RUN)
		{
			heroBulletPool[i].draw();
		}
	}

	// 绘制敌方坦克、子弹
	int lenEnemyPool = enemyPool.size();
	for (int i = 0; i < lenEnemyPool; i++)
	{
		if (enemyPool[i].status == TANK_STATUS_RUN) { enemyPool[i].draw(); }
		vector& enemyBulletPool = enemyPool[i].getBulletPool();
		int lenEnemyBulletPool = enemyBulletPool.size();
		for (int j = 0; j < lenEnemyBulletPool; j++)
		{
			if (enemyBulletPool[j].status == BULLET_STATUS_RUN){enemyBulletPool[j].draw();}
		}
	}
	
	// 绘制爆炸
	int lenBombPool = bombPool.size();
	for (int i = 0; i < lenBombPool; i++)
	{
		if (bombPool[i].status == BOMB_STATUS_RUN)
		{
			bombPool[i].draw();
		}
	}

	// 绘制星星
	int lenStarPool = starPool.size();
	for (int i = 0; i < lenStarPool; i++)
	{
		if (starPool[i].status == STAR_STATUS_RUN)
		{
			starPool[i].draw();
		}
	}

	// 结束双缓冲机制
	EndBatchDraw();
}

// 向星星池增加
void starAdd(int row, int column)
{
	// 流星雨
	myPlayAudio("./resources/audio/star.mp3");

	// 查找空闲的星星
	int len = starPool.size();
	for (int i = 0; i < len; i++)
	{
		if (starPool[i].status == STAR_STATUS_FREE)
		{
			starPool[i].row = row;
			starPool[i].column = column;
			starPool[i].frameIndex = 0;
			starPool[i].status = STAR_STATUS_RUN;
			break;
		}
	}
}

// 星星创建(在坦克创建前先创建星星)
void starCreate()
{
	// 创建坦克标识
	bool createFlag = false;

	if (stu_project.enemyCreateNum == 0 || myTimer(INTERVAL_CREATEENEMY, TIMERID_CREATEENEMY)) { createFlag = true; }

	if (createFlag)
	{
		// 判断投放地点是否为空
		int createPos[3] = { -1,-1,-1 };
		int createPosNum = 0;
		if (stu_project.map[0][0] == BLANK && stu_project.map[0][1] == BLANK && stu_project.map[1][0] == BLANK && stu_project.map[1][1] == BLANK)			// 判断左上角位置是否可以投放
		{
			createPos[createPosNum] = 0;
			createPosNum++;
		}
		if (stu_project.map[0][12] == BLANK && stu_project.map[0][13] == BLANK && stu_project.map[1][12] == BLANK && stu_project.map[1][13] == BLANK)		// 判断中间位置是否可以投放
		{
			createPos[createPosNum] = 12;
			createPosNum++;
		}
		if (stu_project.map[0][24] == BLANK && stu_project.map[0][25] == BLANK && stu_project.map[1][24] == BLANK && stu_project.map[1][25] == BLANK)		// 判断右上角位置是否可以投放
		{
			createPos[createPosNum] = 24;
			createPosNum++;
		}
		if (createPosNum < 1) { return; }		// 无投放位置,退出

		// 首次一次性投放3辆坦克
		if (stu_project.enemyCreateNum == 0)
		{
			for (int i = 0; i < createPosNum; i++)
			{
				// 先把茅坑占上
				stu_project.map[0][createPos[i]] = 999;
				stu_project.map[0][createPos[i] + 1] = 999;
				stu_project.map[1][createPos[i]] = 999;
				stu_project.map[1][createPos[i] + 1] = 999;
				// 增加星星
				starAdd(0, createPos[i]);
			}
		}
		else     // 每隔一段时间投放一辆坦克
		{
			// 判断是否达到最大投放数量
			if (stu_project.enemyCreateNum >= stu_project.enemyMaxNum) { return; }
			// 得到随机投放位置
			int pos = createPos[myRandom(0, createPosNum - 1)];
			// 先把茅坑占上
			stu_project.map[0][pos] = 999;
			stu_project.map[0][pos + 1] = 999;
			stu_project.map[1][pos] = 999;
			stu_project.map[1][pos + 1] = 999;
			// 增加星星
			starAdd(0, pos);
		}
	}
}

// 敌方坦克创建(在星星创建的位置)
void enemyTankCreate(int row,int column)
{
	// 在坦克池中寻找空闲的坦克
	Enemy* enemy = nullptr;
	int lenEnemyPool = enemyPool.size();
	for (int i = 0; i < lenEnemyPool; i++)
	{
		if (enemyPool[i].status == TANK_STATUS_FREE)
		{
			enemy = &enemyPool[i];
			break;
		}
	}
	if (enemy == nullptr)			// 没有就增加一个
	{
		Enemy newEnemy(0, 0, TANK_DIRECTION_DOWN);
		enemyPool.push_back(newEnemy);
		enemy = &enemyPool[lenEnemyPool];
	}

	// 开始投放
	enemy->row = row;
	enemy->oldRow = enemy->row;
	enemy->column = column;
	enemy->oldColumn = enemy->column;
	enemy->x = enemy->column * BLOCK_SIZE;
	enemy->y = 0;
	enemy->direction = TANK_DIRECTION_DOWN;
	if (stu_project.enemyCreateNum >= 3)
	{
		enemy->armor = myRandom(0, 3);
	}
	else
	{
		enemy->armor = 0;
	}
	enemy->originalArmor = enemy->armor;
	enemy->target = myRandom(TANK_OWNER_HERO, HOME);
	enemy->status = TANK_STATUS_RUN;
	enemy->toMap();
	stu_project.enemyCreateNum++;

}

// 敌方坦克AI(返回方向)
// 原理:判断目标与敌方坦克的相应位置,找出哪个方向最可能靠近目标。
int enemyTankAI(Enemy &enemy)
{
	// 先剔除墙与铁块那个方向(铁块暂时打不动)
	int validDirectory[4][2] = { -1,-1,-1,-1,-1,-1,-1,-1 };		// 可用方向数组[方向][空地/墙]
	int validDirectoryNum = 0;
	for (int i = 0; i < 4; i++)
	{
		bool blankFlag = false;		// 空地标识(true-是空地,false-非空地)
		if (i == TANK_DIRECTION_UP)
		{
			if (enemy.row == 0){continue;}
			if (stu_project.map[enemy.row - 1][enemy.column] == IRON || stu_project.map[enemy.row - 1][enemy.column + 1] == IRON) { continue; }
			if (stu_project.map[enemy.row - 1][enemy.column] == BLANK && stu_project.map[enemy.row - 1][enemy.column + 1] == BLANK) { blankFlag = true; }
		}
		else if (i == TANK_DIRECTION_DOWN)
		{
			if (enemy.row == 24) { continue; }
			if (stu_project.map[enemy.row + 2][enemy.column] == IRON || stu_project.map[enemy.row + 2][enemy.column + 1] == IRON) { continue; }
			if (stu_project.map[enemy.row + 2][enemy.column] == BLANK && stu_project.map[enemy.row + 2][enemy.column + 1] == BLANK) { blankFlag = true; }
		}
		else if (i == TANK_DIRECTION_LEFT)
		{
			if (enemy.column == 0) { continue; }
			if (stu_project.map[enemy.row][enemy.column - 1] == IRON || stu_project.map[enemy.row + 1][enemy.column - 1] == IRON) { continue; }
			if (stu_project.map[enemy.row][enemy.column - 1] == BLANK && stu_project.map[enemy.row + 1][enemy.column - 1] == BLANK) { blankFlag = true; }
		}
		else if (i == TANK_DIRECTION_RIGHT)
		{
			if (enemy.column == 24) { continue; }
			if (stu_project.map[enemy.row][enemy.column + 2] == IRON || stu_project.map[enemy.row + 1][enemy.column + 2] == IRON) { continue; }
			if (stu_project.map[enemy.row][enemy.column + 2] == BLANK && stu_project.map[enemy.row + 1][enemy.column + 2] == BLANK) { blankFlag = true; }
		}
		validDirectory[validDirectoryNum][0] = i;
		if (blankFlag)
		{
			validDirectory[validDirectoryNum][1] = BLANK;
		}
		else
		{
			validDirectory[validDirectoryNum][1] = WALL;
		}
		validDirectoryNum++;
	}

	// 判断目标与敌方坦克位置关系
	int directory[4] = { -1,-1,-1,-1 };
	int targetRow;
	int targetColumn;
	if (enemy.target == TANK_OWNER_HERO)	// 目标是我方坦克
	{
		targetRow = hero.row;
		targetColumn = hero.column;
	}
	else   // 目标是老巢
	{
		targetRow = 24;
		targetColumn = 12;
	}
	if (targetColumn > enemy.column)		// 目标在敌方坦克右边
	{
		if (targetRow < enemy.row)			// 右上角(上或右)
		{
			for (int i = 0; i < validDirectoryNum; i++)
			{
				if (validDirectory[i][0] == TANK_DIRECTION_UP || validDirectory[i][0] == TANK_DIRECTION_RIGHT)
				{
					// 空地优先级别高
					if (validDirectory[i][1] == BLANK)
					{
						if (directory[0] != -1){directory[1] = directory[0];}
						directory[0] = validDirectory[i][0];
						continue;
					}
					// 从左向右填充
					for (int j = 0; j < 4; j++)
					{
						if (directory[j] == -1)
						{
							directory[j] = validDirectory[i][0];
							break;
						}
					}
				}
				else
				{
					// 从右向左填充
					for (int j = 3; j >= 0; j--)
					{
						if (directory[j] == -1)
						{
							directory[j] = validDirectory[i][0];
							break;
						}
					}
				}
			}
		}
		else     // 右下角(下或右)
		{
			for (int i = 0; i < validDirectoryNum; i++)
			{
				if (validDirectory[i][0] == TANK_DIRECTION_DOWN || validDirectory[i][0] == TANK_DIRECTION_RIGHT)
				{
					// 空地优先级别高
					if (validDirectory[i][1] == BLANK)
					{
						if (directory[0] != -1) { directory[1] = directory[0]; }
						directory[0] = validDirectory[i][0];
						continue;
					}
					// 从左向右填充
					for (int j = 0; j < 4; j++)
					{
						if (directory[j] == -1)
						{
							directory[j] = validDirectory[i][0];
							break;
						}
					}
				}
				else
				{
					// 从右向左填充
					for (int j = 3; j >= 0; j--)
					{
						if (directory[j] == -1)
						{
							directory[j] = validDirectory[i][0];
							break;
						}
					}
				}
			}
		}
		// 特殊情况(同一条线上)
		if (targetRow == enemy.row)
		{
			for (int i = 0; i < validDirectoryNum; i++)
			{
				if (validDirectory[i][0] == TANK_DIRECTION_RIGHT)
				{
					if (validDirectory[i][1] == BLANK){return validDirectory[i][0];}		// 是空地就必须勇敢的冲过去
				}
			}
		}
	}
	else									// 目标在敌方坦克左边
	{
		if (targetRow < enemy.row)			// 左上角(上或左)
		{
			for (int i = 0; i < validDirectoryNum; i++)
			{
				if (validDirectory[i][0] == TANK_DIRECTION_UP || validDirectory[i][0] == TANK_DIRECTION_LEFT)
				{
					// 空地优先级别高
					if (validDirectory[i][1] == BLANK)
					{
						if (directory[0] != -1) { directory[1] = directory[0]; }
						directory[0] = validDirectory[i][0];
						continue;
					}
					// 从左向右填充
					for (int j = 0; j < 4; j++)
					{
						if (directory[j] == -1)
						{
							directory[j] = validDirectory[i][0];
							break;
						}
					}
				}
				else
				{
					// 从右向左填充
					for (int j = 3; j >= 0; j--)
					{
						if (directory[j] == -1)
						{
							directory[j] = validDirectory[i][0];
							break;
						}
					}
				}
			}
		}
		else     // 左下角(下或左)
		{
			for (int i = 0; i < validDirectoryNum; i++)
			{
				if (validDirectory[i][0] == TANK_DIRECTION_DOWN || validDirectory[i][0] == TANK_DIRECTION_LEFT)
				{
					// 空地优先级别高
					if (validDirectory[i][1] == BLANK)
					{
						if (directory[0] != -1) { directory[1] = directory[0]; }
						directory[0] = validDirectory[i][0];
						continue;
					}
					// 从左向右填充
					for (int j = 0; j < 4; j++)
					{
						if (directory[j] == -1)
						{
							directory[j] = validDirectory[i][0];
							break;
						}
					}
				}
				else
				{
					// 从右向左填充
					for (int j = 3; j >= 0; j--)
					{
						if (directory[j] == -1)
						{
							directory[j] = validDirectory[i][0];
							break;
						}
					}
				}
			}
		}
		// 特殊情况(同一条线上)
		if (targetRow == enemy.row)
		{
			for (int i = 0; i < validDirectoryNum; i++)
			{
				if (validDirectory[i][0] == TANK_DIRECTION_LEFT)
				{
					if (validDirectory[i][1] == BLANK) { return validDirectory[i][0]; }		// 是空地就必须勇敢的冲过去
				}
			}
		}
	}
	
	if (targetColumn == enemy.column)	// 目标在敌方坦克正上或下方
	{
		// 特殊情况(同一条线上)
		if (targetRow < enemy.row)		// 正上方
		{
			for (int i = 0; i < validDirectoryNum; i++)
			{
				if (validDirectory[i][0] == TANK_DIRECTION_UP)
				{
					if (validDirectory[i][1] == BLANK) { return validDirectory[i][0]; }		// 是空地就必须勇敢的冲过去
				}
			}
		}
		else
		{
			for (int i = 0; i < validDirectoryNum; i++)
			{
				if (validDirectory[i][0] == TANK_DIRECTION_DOWN)
				{
					if (validDirectory[i][1] == BLANK) {return validDirectory[i][0]; }		// 是空地就必须勇敢的冲过去
				}
			}
		}
	}

	// 方向补全
	for (int i = 0; i < 4; i++)
	{
		if (directory[i] == -1) { directory[i] = enemy.direction; }
	}

	// 随机抽取4:3:2:1
	int random = myRandom(1,10);
	if (random <= 4)
	{
		return directory[0];
	}
	else if (random <= 7)
	{
		return directory[1];
	}
	else if (random <= 9)
	{
		return directory[2];
	}
	else
	{
		return directory[3];
	}

}

// 敌方坦克移动
void enemyTankMove()
{
	if (myTimer(INTERVAL_MOVEENEMY, TIMERID_MOVEENEMY))
	{
		int lenEnemyPool = enemyPool.size();
		for (int i = 0; i < lenEnemyPool; i++)
		{
			if (enemyPool[i].status == TANK_STATUS_RUN)
			{
				// 得到移动方向
				enemyPool[i].direction = enemyTankAI(enemyPool[i]);
				enemyPool[i].move(enemyPool[i].direction);
				stu_project.refreshFlag = true;
			}
		}
	}
}

// 敌方坦克射击
void enemyTankShoot()
{
	if (myTimer(INTERVAL_BULLET_SHOOT, TIMERID_BULLET_SHOOT))
	{
		int lenEnemyPool = enemyPool.size();
		for (int i = 0; i < lenEnemyPool; i++)
		{
			if (enemyPool[i].status == TANK_STATUS_RUN)
			{
				// 敌方坦克比较傻,不爱射击
				if (myRandom(1, 10) < 4){enemyPool[i].shoot();}			// 30%几率开枪
				stu_project.refreshFlag = true;
			}
		}
	}
}

// 向爆炸池增加
void bombAdd(int x, int y)
{
	// 查找空闲的爆炸
	Bomb* bomb = nullptr;
	int len = bombPool.size();
	for (int i = 0; i < len; i++)
	{
		if (bombPool[i].status == BOMB_STATUS_FREE)
		{
			bomb = &bombPool[i];
			break;
		}
	}
	if (bomb == nullptr)				// 没有就增加一个
	{
		Bomb newBomb;
		bombPool.push_back(newBomb);
		bomb = &bombPool[len];
	}
	bomb->x = x;
	bomb->y = y;
	bomb->frameIndex = 0;
	bomb->status = BOMB_STATUS_RUN;
}

// 得到子弹所在行列位置(子弹位于坦克中间位置,所以正对着2个格子的中间位置,所以计算时2个格子都在其射击范围内)
void getBulletPos(struct _stu_bullet_pos* pBulletPos, int x, int y, int direction)
{
	int x1, y1, x2, y2;

	// 重算子弹图片中心点坐标(因为此时的x与y是子弹图片左上角的坐标)
	x = x + BULLET_SIZE / 2;
	y = y + BULLET_SIZE / 2;

	// 根据方向判断2个格子位置
	if (direction == TANK_DIRECTION_UP || direction == TANK_DIRECTION_DOWN)
	{
		x1 = x - BLOCK_SIZE / 2;
		y1 = y;
		x2 = x + BLOCK_SIZE / 2;
		y2 = y;
	}
	else
	{
		x1 = x;
		y1 = y - BLOCK_SIZE / 2;
		x2 = x;
		y2 = y + BLOCK_SIZE / 2;
	}
	pBulletPos->row1 = y1 / BLOCK_SIZE;
	pBulletPos->col1 = x1 / BLOCK_SIZE;
	pBulletPos->row2 = y2 / BLOCK_SIZE;
	pBulletPos->col2 = x2 / BLOCK_SIZE;
}

// 碰撞处理
void collide()
{
	// 子弹所在位置结构体
	struct _stu_bullet_pos stu_bullet_pos;

	// 判断我方子弹是否与敌方坦克或块或老巢碰撞
	int lenHeroBulletPool = heroBulletPool.size();
	for (int i = 0; i < lenHeroBulletPool; i++)
	{
		if (heroBulletPool[i].status == BULLET_STATUS_RUN)
		{
			// 得到子弹所在行与列
			getBulletPos(&stu_bullet_pos, heroBulletPool[i].x, heroBulletPool[i].y, heroBulletPool[i].direction);
			// 得到子弹2个点的值
			int v1 = stu_project.map[stu_bullet_pos.row1][stu_bullet_pos.col1];
			int v2 = stu_project.map[stu_bullet_pos.row2][stu_bullet_pos.col2];
			if (v1 == 0 && v2 == 0) { continue; }
			if (v1 == TANK_OWNER_HERO && v2 == TANK_OWNER_HERO) { continue; }
			// 判断是否与墙块碰撞
			if (v1 == WALL) { stu_project.map[stu_bullet_pos.row1][stu_bullet_pos.col1] = 0; }
			if (v2 == WALL) { stu_project.map[stu_bullet_pos.row2][stu_bullet_pos.col2] = 0; }
			// 判断是否与老巢碰撞
			if (v1 == HOME || v2 == HOME) { stu_project.gameStatus = GAME_STATUS_OVER; }
			// 判断是否与敌方坦克碰撞
			int lenEnemyPool = enemyPool.size();
			for (int i = 0; i < lenEnemyPool; i++)
			{
				if (enemyPool[i].status == TANK_STATUS_RUN) 
				{
					if (
							(enemyPool[i].row == stu_bullet_pos.row1 && enemyPool[i].column == stu_bullet_pos.col1) || 
							(enemyPool[i].row == stu_bullet_pos.row1 && enemyPool[i].column + 1 == stu_bullet_pos.col1) || 
							(enemyPool[i].row + 1 == stu_bullet_pos.row1 && enemyPool[i].column == stu_bullet_pos.col1) ||
							(enemyPool[i].row + 1 == stu_bullet_pos.row1 && enemyPool[i].column + 1 == stu_bullet_pos.col1) ||
							(enemyPool[i].row == stu_bullet_pos.row2 && enemyPool[i].column == stu_bullet_pos.col2) ||
							(enemyPool[i].row == stu_bullet_pos.row2 && enemyPool[i].column + 1 == stu_bullet_pos.col2) ||
							(enemyPool[i].row + 1 == stu_bullet_pos.row2 && enemyPool[i].column == stu_bullet_pos.col2) ||
							(enemyPool[i].row + 1 == stu_bullet_pos.row2 && enemyPool[i].column + 1 == stu_bullet_pos.col2)
						)
					{
						myPlayAudio("./resources/audio/boom.wav");
						if (enemyPool[i].armor == 0)
						{
							enemyPool[i].reset();
							stu_project.enemyDeadNum++;
							stu_project.enemyArmorDeadNum[enemyPool[i].originalArmor]++;
							if (stu_project.enemyDeadNum >= stu_project.enemyMaxNum){stu_project.gameStatus = GAME_STATUS_WIN;}
							break;
						}
						else
						{
							enemyPool[i].armor--;
						}
					}
				}
			}
			// 子弹销毁
			heroBulletPool[i].status = BULLET_STATUS_FREE;
			// 子弹爆炸
			bombAdd(heroBulletPool[i].x, heroBulletPool[i].y);
		}
	}

	// 判断敌方子弹是否与我方坦克或块或老巢碰撞(不需要判断敌方坦克状态,因为即使坦克销毁子弹可能仍然在飞)
	int lenEnemyPool = enemyPool.size();
	for (int m = 0; m < lenEnemyPool; m++)
	{
		vector& enemyBulletPool = enemyPool[m].getBulletPool();
		int lenEnemyBulletPool = enemyBulletPool.size();
		for (int i = 0; i < lenEnemyBulletPool; i++)
		{
			if (enemyBulletPool[i].status == BULLET_STATUS_RUN)
			{
				// 得到子弹所在行与列
				getBulletPos(&stu_bullet_pos, enemyBulletPool[i].x, enemyBulletPool[i].y, enemyBulletPool[i].direction);
				// 得到子弹2个点的值
				int v1 = stu_project.map[stu_bullet_pos.row1][stu_bullet_pos.col1];
				int v2 = stu_project.map[stu_bullet_pos.row2][stu_bullet_pos.col2];
				if (v1 == 0 && v2 == 0) { continue; }
				if (v1 == TANK_OWNER_ENEMY && v2 == TANK_OWNER_ENEMY) { continue; }
				// 判断是否与墙块碰撞
				if (v1 == WALL) { stu_project.map[stu_bullet_pos.row1][stu_bullet_pos.col1] = 0; }
				if (v2 == WALL) { stu_project.map[stu_bullet_pos.row2][stu_bullet_pos.col2] = 0; }
				// 判断是否与老巢碰撞
				if (v1 == HOME || v2 == HOME) { stu_project.gameStatus = GAME_STATUS_OVER; }
				// 判断是否与我方坦克碰撞
				if (hero.status == TANK_STATUS_RUN)
				{
					if (
							(hero.row == stu_bullet_pos.row1 && hero.column == stu_bullet_pos.col1) ||
							(hero.row == stu_bullet_pos.row1 && hero.column + 1 == stu_bullet_pos.col1) ||
							(hero.row + 1 == stu_bullet_pos.row1 && hero.column == stu_bullet_pos.col1) ||
							(hero.row + 1 == stu_bullet_pos.row1 && hero.column + 1 == stu_bullet_pos.col1) ||
							(hero.row == stu_bullet_pos.row2 && hero.column == stu_bullet_pos.col2) ||
							(hero.row == stu_bullet_pos.row2 && hero.column + 1 == stu_bullet_pos.col2) ||
							(hero.row + 1 == stu_bullet_pos.row2 && hero.column == stu_bullet_pos.col2) ||
							(hero.row + 1 == stu_bullet_pos.row2 && hero.column + 1 == stu_bullet_pos.col2)
						)
					{
						if (hero.armor == 0)
						{
							hero.reset();
							stu_project.gameStatus = GAME_STATUS_OVER;
						}
						else
						{
							hero.armor--;
						}
					}
				}
				// 子弹销毁
				enemyBulletPool[i].status = BULLET_STATUS_FREE;
				// 子弹爆炸
				bombAdd(enemyBulletPool[i].x, enemyBulletPool[i].y);
			}
		}
	}

}

// 游戏进程
void run()
{
	// 重置刷新标识
	stu_project.refreshFlag = false;

	// 星星创建
	starCreate();

	// 星星进程
	if (myTimer(INTERVAL_STAR, TIMERID_STAR))
	{
		int len = starPool.size();
		for (int i = 0; i < len; i++)
		{
			if (starPool[i].status == STAR_STATUS_RUN)
			{
				int index = starPool[i].frameIndex;
				if (index >= starPool[i].maxFrame - 1)
				{
					starPool[i].status = STAR_STATUS_FREE;
					enemyTankCreate(starPool[i].row, starPool[i].column);		// 创建敌方坦克
					continue;
				}
				starPool[i].frameIndex = ++index;
			}
		}
	}

	// 敌方坦克移动
	enemyTankMove();

	// 敌方坦克射击
	enemyTankShoot();

	// 坦克移动进程
	if (myTimer(INTERVAL_TANKMOVE, TIMERID_TANKMOVE))
	{
		// 我方坦克移动
		if (hero.oldRow != hero.row)
		{
			int destY = hero.row * BLOCK_SIZE;
			if (hero.direction == TANK_DIRECTION_UP)
			{
				if (hero.y > destY)
				{
					hero.y = hero.y - hero.speed;
					hero.track = !hero.track;		// 切换履带
				}
				else
				{
					hero.oldRow = hero.row;
					hero.y = destY;					// 坐标微调
				}
			}
			else if (hero.direction == TANK_DIRECTION_DOWN)
			{
				if (hero.y < destY)
				{
					hero.y = hero.y + hero.speed;
					hero.track = !hero.track;
				}
				else
				{
					hero.oldRow = hero.row;
					hero.y = destY;
				}
			}
			stu_project.refreshFlag = true;
		}
		else if (hero.column != hero.oldColumn)
		{
			int destX = hero.column * BLOCK_SIZE;
			if (hero.direction == TANK_DIRECTION_LEFT)
			{
				if (hero.x > destX)
				{
					hero.x = hero.x - hero.speed;
					hero.track = !hero.track;
				}
				else
				{
					hero.oldColumn = hero.column;
					hero.x = destX;
				}
			}
			else if (hero.direction == TANK_DIRECTION_RIGHT)
			{
				if (hero.x < destX)
				{
					hero.x = hero.x + hero.speed;
					hero.track = !hero.track;
				}
				else
				{
					hero.oldColumn = hero.column;
					hero.x = destX;
				}
			}
			stu_project.refreshFlag = true;
		}
		// 敌方坦克移动
		int lenEnemyPool = enemyPool.size();
		for (int i = 0; i < lenEnemyPool; i++)
		{
			if (enemyPool[i].status == TANK_STATUS_RUN)
			{
				if (enemyPool[i].oldRow != enemyPool[i].row)
				{
					int destY = enemyPool[i].row * BLOCK_SIZE;
					if (enemyPool[i].direction == TANK_DIRECTION_UP)
					{
						if (enemyPool[i].y > destY)
						{
							enemyPool[i].y = enemyPool[i].y - enemyPool[i].speed;
							enemyPool[i].track = !enemyPool[i].track;		// 切换履带
						}
						else
						{
							enemyPool[i].oldRow = enemyPool[i].row;
							enemyPool[i].y = destY;					// 坐标微调
						}
					}
					else if (enemyPool[i].direction == TANK_DIRECTION_DOWN)
					{
						if (enemyPool[i].y < destY)
						{
							enemyPool[i].y = enemyPool[i].y + enemyPool[i].speed;
							enemyPool[i].track = !enemyPool[i].track;
						}
						else
						{
							enemyPool[i].oldRow = enemyPool[i].row;
							enemyPool[i].y = destY;
						}
					}
					stu_project.refreshFlag = true;
				}
				else if (enemyPool[i].column != enemyPool[i].oldColumn)
				{
					int destX = enemyPool[i].column * BLOCK_SIZE;
					if (enemyPool[i].direction == TANK_DIRECTION_LEFT)
					{
						if (enemyPool[i].x > destX)
						{
							enemyPool[i].x = enemyPool[i].x - enemyPool[i].speed;
							enemyPool[i].track = !enemyPool[i].track;
						}
						else
						{
							enemyPool[i].oldColumn = enemyPool[i].column;
							enemyPool[i].x = destX;
						}
					}
					else if (enemyPool[i].direction == TANK_DIRECTION_RIGHT)
					{
						if (enemyPool[i].x < destX)
						{
							enemyPool[i].x = enemyPool[i].x + enemyPool[i].speed;
							enemyPool[i].track = !enemyPool[i].track;
						}
						else
						{
							enemyPool[i].oldColumn = enemyPool[i].column;
							enemyPool[i].x = destX;
						}
					}
					stu_project.refreshFlag = true;
				}
			}
		}
	}

	// 子弹进程
	if (myTimer(INTERVAL_BULLET_RUN, TIMERID_BULLET_RUN))
	{
		// 我方子弹运行
		int lenHeroBulletPool = heroBulletPool.size();
		for (int i = 0; i < lenHeroBulletPool; i++)
		{
			if (heroBulletPool[i].status == BULLET_STATUS_RUN)
			{
				heroBulletPool[i].run();
			}
		}
		// 敌方子弹运行
		int lenEnemyPool = enemyPool.size();
		for (int i = 0; i < lenEnemyPool; i++)
		{
			vector& enemyBulletPool = enemyPool[i].getBulletPool();
			int lenEnemyBulletPool = enemyBulletPool.size();
			for (int j = 0; j < lenEnemyBulletPool; j++)
			{
				if (enemyBulletPool[j].status == BULLET_STATUS_RUN)
				{
					enemyBulletPool[j].run();
				}
			}
		}
	}

	// 碰撞处理
	collide();

	// 爆炸进程
	if (myTimer(INTERVAL_BOMB, TIMERID_BOMB))
	{
		int len = bombPool.size();
		for (int i = 0; i < len; i++)
		{
			if (bombPool[i].status == BOMB_STATUS_RUN)
			{
				int index = bombPool[i].frameIndex;
				if (index >= bombPool[i].maxFrame - 1)
				{
					bombPool[i].status = BOMB_STATUS_FREE;
					break;
				}
				bombPool[i].frameIndex = ++index;
			}
		}
	}

	// 刷新界面
	if (stu_project.refreshFlag) { paint(); }

}

// 键盘监控
void keyEvent()
{
	// 重置刷新标识
	stu_project.refreshFlag = false;

	// 方向键只运行同时按一个,用else if判断
	if (myKeyDown(VK_UP))				// 上键
	{
		if (hero.move(TANK_DIRECTION_UP)) { stu_project.refreshFlag = true; }
	}
	else if (myKeyDown(VK_DOWN))		// 下键
	{
		if (hero.move(TANK_DIRECTION_DOWN)) { stu_project.refreshFlag = true; }
	}
	else if (myKeyDown(VK_LEFT))		// 左键
	{
		if (hero.move(TANK_DIRECTION_LEFT)) { stu_project.refreshFlag = true; }
	}
	else if (myKeyDown(VK_RIGHT))		// 右键
	{
		if (hero.move(TANK_DIRECTION_RIGHT)) { stu_project.refreshFlag = true; }
	}

	// 其他键不受限制
	if (myKeyDown(VK_SPACE))			// 空格
	{
		hero.shoot();
		stu_project.refreshFlag = true;
	}

	// 刷新界面
	if (stu_project.refreshFlag) { paint(); }
}

// 鼠标监控
void mouseEvent()
{
	ExMessage msg;							// 鼠标消息结构体
	if (peekmessage(&msg, EM_MOUSE))		// 只监听鼠标消息
	{
		switch (msg.message)
		{
		case WM_LBUTTONUP:				// 鼠标左键释放(用msg.x与msg.y来判断点击位置)
			break;
		case WM_MOUSEMOVE:				// 鼠标移动
			break;
		case WM_RBUTTONUP:				// 鼠标右键释放
			break;
		}
	}
}

// 显示本关分数
void showScore()
{
	putimage(0, 0, &stu_project.imgScore);
	settextstyle(24, 0, "微软雅黑");
	settextcolor(YELLOW);
	setbkmode(TRANSPARENT);
	myDrawString(330, 58, to_string(stu_project.level + 1));
	settextcolor(WHITE);
	int score = 0;
	for (int i = 0; i < 4; i++)
	{
		score = score + stu_project.enemyArmorDeadNum[i] * 100 * (i + 1);
		myDrawString(176, 183 + i * 42 , to_string(stu_project.enemyArmorDeadNum[i]));
		myDrawString(220, 183 + i * 42, "×");
		myDrawString(260, 183 + i * 42, to_string(100 * (i + 1)));
		myDrawString(320, 183 + i * 42, "=");
		myDrawString(350, 183 + i * 42, to_string(stu_project.enemyArmorDeadNum[i] * 100 * (i + 1)));
		Sleep(500);
	}
	settextcolor(RED);
	myDrawString(350, 350, to_string(score));
	Sleep(500);
	system("pause");
}

// 处理游戏状态(下一关或失败)
void doGame()
{
	// 游戏结束
	if (stu_project.gameStatus == GAME_STATUS_OVER)
	{
		myPlayAudio("./resources/audio/over.mp3");
		myDrawImage((GAME_WIDTH - stu_project.imgFailure.getwidth()) / 2, (GAME_HEIGHT - stu_project.imgFailure.getheight()) / 2, &stu_project.imgFailure);
		Sleep(1000);
		showScore();
	}
	else if (stu_project.gameStatus == GAME_STATUS_WIN)
	{
		myDrawImage((GAME_WIDTH - stu_project.imgSuccess.getwidth()) / 2, (GAME_HEIGHT - stu_project.imgSuccess.getheight()) / 2, &stu_project.imgSuccess);
		Sleep(1000);
		showScore();
		stu_project.level++;
		if (stu_project.level < GameMap::getMaxLevel())
		{
			newGame();
		}
	}

}

// 开始游戏
void newGame()
{
	myPlayAudio("./resources/audio/begin.mp3");

	// 初始化游戏
	initGame();

	// 开始游戏
	while (stu_project.gameStatus == GAME_STATUS_RUN)
	{
		// 开始刷新
		if (myTimer(INTERVAL_REFRESH, TIMERID_REFRESH))
		{
			// 绘制窗口
			paint();

			// 游戏进程
			run();
		}

		// 键盘监控
		keyEvent();

		// 鼠标监控(必须随时监控,否则不湿滑)
		//mouseEvent();
	}

	// 处理游戏状态(下一关或失败)
	doGame();
}

下载:

链接:https://pan.baidu.com/s/1Mk-yTrfrXnb-FmYO82YA4A?pwd=g67n 
提取码:g67n

你可能感兴趣的:(C小游戏合集,游戏开发,c++)