本篇文章总结一下我在网上看到的一个C++坦克大战小游戏,我在原有的基础上加入了技能功能,并对碰撞代码进行了改进,然后将代码进行了整理,感觉很有意思。游戏中用到了EasyX图形库,这个库非常小巧轻便,下载地址:https://www.easyx.cn/downloads/
现在正文开始,首先,创建一个简单的坐标类
#ifndef POINT_H
#define POINT_H
//坐标类
class Point
{
public:
Point(int x = 0, int y = 0) : m_x(x), m_y(y) {};
~Point() {};
Point& operator=(const Point &p)
{
m_x = p.m_x;
m_y = p.m_y;
return *this;
}
void Set(int x, int y){
m_x = x;
m_y = y;
}
void SetX(int x) { m_x = x; }
void SetY(int y) { m_y = y; }
int GetX() const{ return m_x; }
int GetY()const {return m_y;}
private:
int m_x;
int m_y;
};
#endif
然后为了便于画图,创建一个Rect类
#include "Point.h"
#ifndef RECT_H
#define RECT_H
//矩形类,便于画图
class Rect
{
public:
Rect(int x1 = 0, int y1 = 0, int x2 = 0, int y2 = 0) :
m_StartPoint(x1, y1), m_EndPoint(x2, y2)
{}
Rect(const Point p1, const Point p2) :
m_StartPoint(p1), m_EndPoint(p2)
{}
Rect(const Rect& r1):
m_StartPoint(r1.GetStartPoint()), m_EndPoint(r1.GetEndPoint())
{}
~Rect() {};
void SetRect(const Point pStart, const Point pEnd);
void SetRect(int x1, int y1, int x2, int y2);
void SetStartPoint(const Point p){ m_StartPoint = p; }
void SetEndPoint(const Point p){ m_EndPoint = p; }
Point GetStartPoint() const{ return m_StartPoint; }
Point GetEndPoint() const{ return m_EndPoint; }
Point GetRightPoint() const;
Point GetLeftPoint() const;
Rect& operator=(const Rect &rect)
{
m_StartPoint = rect.GetStartPoint();
m_EndPoint = rect.GetEndPoint();
return *this;
}
int GetWidth();
int GetHeight();
private:
Point m_StartPoint;//矩形左上角的坐标点
Point m_EndPoint;//矩形右下角的坐标点
};
#endif
#include "Rect.h"
void Rect::SetRect(Point pStart, Point pEnd)
{
m_StartPoint = pStart;
m_EndPoint = pEnd;
}
void Rect::SetRect(int x1, int y1, int x2, int y2)
{
m_StartPoint.Set(x1, y1);
m_EndPoint.Set(x2, y2);
}
Point Rect::GetRightPoint() const
{
Point p = m_StartPoint;
p.SetX(m_EndPoint.GetX());
return p;
}
Point Rect::GetLeftPoint() const
{
Point p = m_StartPoint;
p.SetY(m_EndPoint.GetY());
return p;
}
int Rect::GetWidth()
{
return m_EndPoint.GetX() - m_StartPoint.GetX();
}
int Rect::GetHeight()
{
return m_EndPoint.GetY() - m_StartPoint.GetY();
}
游戏对象之间会发生碰撞,需要写一个用于碰撞检测的类Shape
#include "Rect.h"
#ifndef SHAPE_H
#define SHAPE_H
//该类用于碰撞检测
class Shape
{
public:
static bool CheckPointInRect(Point& point, Rect& rect);//判断第一个参数点point是否在第二个参数代表的矩形内
static bool CheckIntersect(Rect& rectA, Rect& rectB);//判断两个矩形是否碰撞
};
#endif
#include "Shape.h"
bool Shape::CheckPointInRect(Point& point, Rect& rect)
{
if (point.GetX() < rect.GetStartPoint().GetX()-1 || point.GetX() >rect.GetEndPoint().GetX()+1 ||
point.GetY() <rect.GetStartPoint().GetY()-1 || point.GetY() >rect.GetEndPoint().GetY()+1)
return false;
else return true;
}
bool Shape::CheckIntersect(Rect& rectA, Rect& rectB)
{
if (CheckPointInRect(rectA.GetStartPoint(), rectB) ||
CheckPointInRect(rectA.GetEndPoint(), rectB) ||
CheckPointInRect(rectA.GetRightPoint(), rectB) ||
CheckPointInRect(rectA.GetLeftPoint(), rectB))
return true;
else return false;
}
好的,现在需要一个对游戏数据进行统计处理的类,因为游戏中的数据是伴随整个游戏过程的,区别与游戏中具体的对象,所以把数据成员都设置为静态
#include <list>
#ifndef SETTING_H
#define SETTING_H
using namespace std;
//数值设定类,用于计算分数和关卡等
class Setting
{
public:
static bool NewLev;
static int GetGameLevel() { return m_GameLevel; }
static int GetTankNum() { return m_TankNum; }
static int GetHp(){return m_Hp;}
static void SetHp(int hp) { m_Hp = hp; }
static int GetSumScore(){ return m_SumScore; }
static int GetKillNum() { return m_KillNum; }
static void NewGameLevel();
static void Damaged();
static int GetGameSpeed() { return m_GameSpeed; }
private:
static int m_GameSpeed; //游戏速度
static int m_Hp; // 生命值
static int m_GameLevel; // 关卡等级
static int m_TankNum; // 当前坦克数
static int m_SumScore; // 总分
static int m_KillScore; // 击毁坦克得分
static int m_KillNum; // 共击毁坦克数
};
#endif
#include "Setting.h"
int Setting::m_GameSpeed = 60;
bool Setting::NewLev = true;
int Setting::m_Hp = 20;
int Setting::m_GameLevel = 0;
int Setting::m_TankNum = 5;
int Setting::m_SumScore = 0;
int Setting::m_KillScore = 5;
int Setting::m_KillNum = 0;
void Setting::NewGameLevel()
{
m_GameLevel++;
m_TankNum = 10 + 5 * (m_GameLevel - 1);
m_KillScore += 5;
}
void Setting::Damaged()
{
m_TankNum--;
m_SumScore += m_KillScore;
m_KillNum++;
if (m_TankNum == 0) NewLev = true;
}
有了以上的基础后,还需要创建一个画图类,进行游戏基础界面的展示,注意这个类需要包含graphics.h,用到了一些画图接 口,需要查文档
#include <graphics.h>
#include "Rect.h"
#ifndef GRAPHIC_H
#define GRAPHIC_H
enum
{
SCREEN_WIDTH = 1024,
SCREEN_HEIGHT = 568
};
enum
{
BATTLE_GROUND_X1 = 5,
BATTLE_GROUND_Y1 = 5,
BATTLE_GROUND_X2 = 800,
BATTLE_GROUND_Y2 = (SCREEN_HEIGHT - BATTLE_GROUND_Y1)
};
class Graphic
{
public:
static void DrawBattleGround();
static void Create();
static void Destroy();
static void ShowScore();
static int GetScreenWidth(){ return SCREEN_WIDTH; }
static int GetScreenHeight(){ return SCREEN_HEIGHT; }
static Rect GetBattleGround(){ return m_RectBattleGround; }
private:
static Rect m_RectBattleGround;
static Rect m_RectScreen;
static char m_pArray[100];
};
#endif
#include "Graphic.h"
#include "Setting.h"
enum { SCORE_LEFT = 810, SCORE_TOP = 5 };
Rect Graphic::m_RectScreen;
Rect Graphic::m_RectBattleGround;
char Graphic::m_pArray[100];
void Graphic::ShowScore()
{
COLORREF fill_color_save = getfillcolor();
COLORREF color_save = getcolor();
rectangle(SCORE_LEFT, SCORE_TOP, SCORE_LEFT + 200, SCORE_TOP + 40);
RECT r = { SCORE_LEFT, SCORE_TOP, SCORE_LEFT + 200, SCORE_TOP + 40 };
wsprintf((LPSTR)m_pArray, _T("第 %d 关"), Setting::GetGameLevel());
drawtext((LPSTR)m_pAr