仅供交流学习使用,因博主水平有限,有错误欢迎批评指正
作者(即博主本人): Akame Qixisi / Excel Bloonow
IDE:Code::Blocks 17.12
编译器需要支持C++14或以上标准(Code::Blocks如何设置见附录Ⅰ)
当然你也可以更改代码以兼容更低版本的编译器
源码下载链接: 下载地址为作者Github (GitHub的如何使用不在本篇讨论范围内)
当然你也可以参考以下内容自行实现
博主自己编写的文件有:
- Main.cpp(FunCode已提供,但需要自己增加内容)
- LessonX.h 和 LessonX.cpp(FunCode已提供,但需要自己增加内容)
- moveobject.h 和 moveobject.cpp
- bullet.h 和 bullet.cpp
- basiccraft.h 和 basiccraft.cpp
- mycraft.h 和 mycraft.cpp
- basicenemy.h 和 basicenemy.cpp
- horizenemy.h 和 horizenemy.cpp
- verticenemy.h 和 verticenemy.cpp
- rotateenemy.h 和 rotateenemy.cpp
- boosenemy.h 和 boosenemy.cpp
- enemystool.h 和 enemystool.cpp
各文件内容如下:
Main.cpp
#include "CommonClass.h"
#include "LessonX.h"
// 主函数入口
int PASCAL WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// 初始化游戏引擎
if( !CSystem::InitGameEngine( hInstance, lpCmdLine ) )
return 0;
// To do : 在此使用API更改窗口标题
CSystem::SetWindowTitle("LessonX");
// 引擎主循环,处理屏幕图像刷新等工作
while( CSystem::EngineMainLoop() )
{
// 获取两次调用之间的时间差,传递给游戏逻辑处理
float fTimeDelta = CSystem::GetTimeDelta();
// 执行游戏主循环
g_GameMain.GameMainLoop( fTimeDelta );
};
// 关闭游戏引擎
CSystem::ShutdownGameEngine();
return 0;
}
// 引擎捕捉鼠标移动消息后,将调用到本函数
void CSystem::OnMouseMove( const float fMouseX, const float fMouseY )
{
// 可以在此添加游戏需要的响应函数
}
// 引擎捕捉鼠标点击消息后,将调用到本函数
void CSystem::OnMouseClick( const int iMouseType, const float fMouseX, const float fMouseY )
{
// 可以在此添加游戏需要的响应函数
}
// 引擎捕捉鼠标弹起消息后,将调用到本函数
void CSystem::OnMouseUp( const int iMouseType, const float fMouseX, const float fMouseY )
{
// 可以在此添加游戏需要的响应函数
}
// 引擎捕捉键盘按下消息后,将调用到本函数
// bAltPress bShiftPress bCtrlPress 分别为判断Shift,Alt,Ctrl当前是否也处于按下状态。比如可以判断Ctrl+E组合键
void CSystem::OnKeyDown( const int iKey, const bool bAltPress, const bool bShiftPress, const bool bCtrlPress )
{
// 可以在此添加游戏需要的响应函数
g_GameMain.OnKeyDown(iKey, bAltPress, bShiftPress, bCtrlPress);
}
// 引擎捕捉键盘弹起消息后,将调用到本函数
void CSystem::OnKeyUp( const int iKey )
{
// 可以在此添加游戏需要的响应函数
g_GameMain.OnKeyUp(iKey);
}
// 引擎捕捉到精灵与精灵碰撞之后,调用此函数
void CSystem::OnSpriteColSprite( const char *szSrcName, const char *szTarName )
{
}
// 引擎捕捉到精灵与世界边界碰撞之后,调用此函数.
// iColSide : 0 左边,1 右边,2 上边,3 下边
void CSystem::OnSpriteColWorldLimit( const char *szName, const int iColSide )
{
}
LessonX.h
#ifndef _LESSON_X_H_
#define _LESSON_X_H_
#include <Windows.h>
#include "mycraft.h"
#include "enemystool.h"
#include "bullet.h"
// 游戏总管类。负责处理游戏主循环、游戏初始化、结束等工作
class CGameMain
{
private:
int m_iGameState; // 游戏状态,0:结束或者等待开始;1:初始化;2:游戏进行中
std::shared_ptr<MyCraft> player;
EnemysTool enemysCtrl;
std::list<std::shared_ptr<Bullet>> myBullets;
std::list<std::shared_ptr<Bullet>> enemyBullets;
std::shared_ptr<CTextSprite> playerScore;
std::shared_ptr<CTextSprite> playerHp;
public:
CGameMain(); //构造函数
~CGameMain(); //析构函数
// Get方法
int GetGameState() { return m_iGameState; }
// Set方法
void SetGameState( const int iState ) { m_iGameState = iState; }
// 游戏主循环等
void GameMainLoop( float fDeltaTime );
void GameInit();
void GameRun( float fDeltaTime );
void GameEnd();
void OnKeyDown( const int iKey, const int iAltPress, const int iShiftPress, const int iCtrlPress );
void OnKeyUp( const int iKey );
void onLoop();
};
extern CGameMain g_GameMain;
#endif // _LESSON_X_H_
LessonX.cpp
#include <Stdio.h>
#include "CommonClass.h"
#include "LessonX.h"
#include <fstream>
CGameMain g_GameMain;
CSprite* beginWords = new CSprite("GameBegin"); //“空格开始”
//inline
bool checkBulletIsOverScreen(auto& bullets) {
for (auto b = std::begin(bullets); b != std::end(bullets); ++b) {
if ((*b)->isOverScreen()) {
(*b)->DeleteSprite();
bullets.erase(b);
return true;
}
}
return false;
}
//inline
bool checkMyBulletIsDoen(auto& myBullets, auto& target) {
for (auto mb = std::begin(myBullets); mb != std::end(myBullets); ++mb) {
for (auto t = std::begin(target); t != std::end(target); ++t) {
if ( (*t)->IsPointInSprite((*mb)->GetSpritePositionX(), (*mb)->GetSpritePositionY()) ) {
(*mb)->DeleteSprite();
myBullets.erase(mb);
(*t)->setHp((*t)->getHp() - 1);
if ((*t)->getHp() <= 0) {
(*t)->beenDown(); /// ok
(*t)->DeleteSprite();
target.erase(t);
return true;
}
return false;
}
}
}
return false;
}
//inline
bool checkPlayerIsDoen(auto& player, auto& target) {
for (auto t = std::begin(target); t != std::end(target); ++t) {
if (player->IsPointInSprite((*t)->GetSpritePositionX(), (*t)->GetSpritePositionY())) {
player->setHp(player->getHp() - 1);
(*t)->beenDown();
(*t)->DeleteSprite();
target.erase(t);
return true;
}
}
return false;
}
// 大体的程序流程为:GameMainLoop函数为主循环函数,在引擎每帧刷新屏幕图像之后,都会被调用一次。
// 构造函数
CGameMain::CGameMain()
{
m_iGameState = 0;
player = nullptr;
myBullets = std::list<std::shared_ptr<Bullet>>();
enemyBullets = std::list<std::shared_ptr<Bullet>>();
playerScore = std::shared_ptr<CTextSprite>();
playerHp = std::shared_ptr<CTextSprite>();
}
// 析构函数
CGameMain::~CGameMain() {}
// 游戏主循环,此函数将被不停的调用,引擎每刷新一次屏幕,此函数即被调用一次
// 用以处理游戏的开始、进行中、结束等各种状态.
// 函数参数fDeltaTime : 上次调用本函数到此次调用本函数的时间间隔,单位:秒
void CGameMain::GameMainLoop( float fDeltaTime )
{
switch( GetGameState() )
{
// 初始化游戏,清空上一局相关数据
case 1:
{
GameInit();
SetGameState(2); // 初始化之后,将游戏状态设置为进行中
}
break;
// 游戏进行中,处理各种游戏逻辑
case 2:
{
// TODO 修改此处游戏循环条件,完成正确游戏逻辑
if( player->getHp() > 0 )
{
GameRun( fDeltaTime );
}
else // 游戏结束。调用游戏结算函数,并把游戏状态修改为结束状态
{
SetGameState(0);
GameEnd();
}
}
break;
// 游戏结束/等待按空格键开始
case 0:
default:
break;
};
}
// 每局开始前进行初始化,清空上一局相关数据
void CGameMain::GameInit()
{
beginWords->SetSpriteVisible(false);
player = std::make_shared<MyCraft>("ControlSprite");
player->SetSpriteVisible(true);
playerScore = std::make_shared<CTextSprite>("playerScore");
playerHp = std::make_shared<CTextSprite>("playerHp");
}
// 每局游戏进行中
void CGameMain::GameRun( float fDeltaTime )
{
onLoop();
auto mB = player->onFire(fDeltaTime);
if (mB != nullptr) {
myBullets.push_back(mB);
}
enemysCtrl.creatEnemy(fDeltaTime);
enemysCtrl.onLooop(fDeltaTime);
for (auto enemy = std::begin(enemysCtrl.enemys); enemy != std::end(enemysCtrl.enemys); ++enemy) {
auto eB = (*enemy)->onFire(fDeltaTime);
if (eB != nullptr)
enemyBullets.push_back(eB);
}
}
// 本局游戏结束
void CGameMain::GameEnd()
{
player->beenDown();
player->SetSpriteVisible(false);
playerHp->SetTextValue(0);
beginWords->SetSpriteVisible(true);
std::ofstream fout("PlayerScore.txt", std::ios::out | std::ios::app);
fout << "Player's score is : " << player->getScore() << std::endl;
}
void CGameMain::OnKeyDown( const int iKey, const int iAltPress, const int iShiftPress, const int iCtrlPress )
{
if( KEY_SPACE == iKey && 0 == GetGameState() )
SetGameState( 1 );
//当游戏状态为2时
if( 2 == GetGameState() ) {
player->onMove(true, iKey);
if (iKey == KEY_SPACE)
player->setFire(true);
}
}
void CGameMain::OnKeyUp( const int iKey )
{
if( 2 == GetGameState() ) {
player->onMove(false, iKey);
if (iKey == KEY_SPACE)
player->setFire(false);
}
}
void CGameMain::onLoop() {
playerScore->SetTextValue(player->getScore());
playerHp->SetTextValue(player->getHp());
checkBulletIsOverScreen(myBullets);
checkBulletIsOverScreen(enemyBullets);
if (checkMyBulletIsDoen(myBullets, enemysCtrl.enemys)) player->setScore(player->getScore() + 10);
checkMyBulletIsDoen(myBullets, enemyBullets);
checkPlayerIsDoen(player, enemyBullets);
checkPlayerIsDoen(player, enemysCtrl.enemys);
}
moveobject.h
#ifndef MOVEOBJECT_H
#define MOVEOBJECT_H
#include "CommonClass.h"
#include <memory>
class MoveObject : public CSprite {
public:
MoveObject(const char* name_);
virtual ~MoveObject();
virtual void onMove(const float deltaTime_) = 0;
virtual void beenDown() = 0;
virtual void setHp(const int val) { hp = val; }
virtual int getHp() { return hp; }
private:
int hp;
};
#endif // MOVEOBJECT_H
moveobject.cpp
#include "moveobject.h"
MoveObject::MoveObject(const char* name_)
: CSprite(name_) {}
MoveObject::~MoveObject() {}
bullet.h
#ifndef BULLET_H
#define BULLET_H
#include "moveobject.h"
class Bullet : public MoveObject {
public:
Bullet(const char* name_);
virtual ~Bullet();
virtual void onMove(const float deltaTime_) {}
virtual bool isOverScreen();
virtual void beenDown();
private:
int beenDownId;
};
#endif // BULLET_H
bullet.cpp
#include "bullet.h"
#include <sstream>
Bullet::Bullet(const char* name_)
: MoveObject(name_) {
beenDownId = 0;
setHp(1);
}
Bullet::~Bullet() {}
bool Bullet::isOverScreen() {
return ((GetSpritePositionX() <= CSystem::GetScreenLeft() - 10) || (GetSpritePositionX() >= CSystem::GetScreenRight() + 10));
}
void Bullet::beenDown() {
std::stringstream ss;
ss << "enemyDown_" << beenDownId++;
std::string str;
ss >> str;
std::shared_ptr<CSprite> bd = std::make_shared<CSprite>(str.c_str());
bd->CloneSprite("bulletDown");
bd->SetSpriteLifeTime(0.2);
bd->SetSpritePosition(GetSpritePositionX(), GetSpritePositionY());
}
basiccraft.h
#ifndef BASICCRAFT_H
#define BASICCRAFT_H
#include "moveobject.h"
#include "bullet.h"
#include <list>
class BasicCraft : public MoveObject {
public:
BasicCraft(const char* name_);
virtual ~BasicCraft();
virtual void onMove(const float deltaTime_) = 0;
virtual std::shared_ptr<Bullet> onFire(const float deltaTime_) = 0;
virtual void setFire(const bool fire_) { isFire = fire_; }
virtual bool getFire() const { return isFire; }
virtual void beenDown() = 0;
protected:
virtual std::shared_ptr<Bullet> fire() = 0;
float deltaFireTime;
int bulletId;
bool isFire;
};
#endif // BASICCRAFT_H
basiccraft.cpp
#include "basiccraft.h"
BasicCraft::BasicCraft(const char* name_)
: MoveObject(name_), deltaFireTime(0), bulletId(0) {}
BasicCraft::~BasicCraft() {}
mycraft.h
#ifndef MYCRAFT_H
#define MYCRAFT_H
#include "basiccraft.h"
class MyCraft : public BasicCraft {
public:
MyCraft(const char* name_);
virtual ~MyCraft();
virtual void onMove(const float deltaTime_) {}
virtual void onMove(const bool isKeyDown_, const int key_);
virtual std::shared_ptr<Bullet> onFire(const float deltaTime_);
virtual void beenDown();
virtual void setScore(const int val) { score = val; }
virtual int getScore() {return score; }
private:
virtual std::shared_ptr<Bullet> fire();
float left;
float right;
float up;
float down;
int score;
};
#endif // MYCRAFT_H
mycraft.cpp
#include "mycraft.h"
#include "bullet.h"
#include <sstream>
MyCraft::MyCraft(const char* name_)
: BasicCraft(name_) {
left = 0;
right = 0;
up = 0;
down = 0;
setHp(5); /// OK
setScore(0);
}
MyCraft::~MyCraft() {}
void MyCraft::onMove(const bool isKeyDown_, const int key_) {
if (isKeyDown_) {
switch(key_) {
case KEY_A:
left = 30;
break;
case KEY_D:
right = 30;
break;
case KEY_W:
up = 15;
break;
case KEY_S:
down = 15;
break;
}
} else {
switch(key_) {
case KEY_A:
left = 0;
break;
case KEY_D:
right = 0;
break;
case KEY_W:
up = 0;
break;
case KEY_S:
down = 0;
break;
}
}
float x = right - left;
float y = down - up;
SetSpriteLinearVelocity(x, y);
}
std::shared_ptr<Bullet> MyCraft::fire() {
std::stringstream ss;
ss << "myBullet_" << bulletId++;
std::string str;
ss >> str;
std::shared_ptr<Bullet> pb = std::make_shared<Bullet>(str.c_str());
pb->CloneSprite("Bullet1_Template");
pb->SetSpritePosition(GetSpritePositionX(), GetSpritePositionY());
pb->SetSpriteFlipX(true);
pb->SetSpriteLinearVelocityX(60);
return pb;
}
std::shared_ptr<Bullet> MyCraft::onFire(const float deltaTime_) {
deltaFireTime -= deltaTime_;
if (deltaFireTime <= 0 && isFire) {
// 固定发射时间
deltaFireTime = 0.3;
return fire();
}
return nullptr;
}
void MyCraft::beenDown() {
std::string str = "playerIsDead";
std::shared_ptr<CSprite> bd = std::make_shared<CSprite>(str.c_str());
bd->CloneSprite("playerExplode");
bd->SetSpriteLifeTime(1);
bd->SetSpritePosition(GetSpritePositionX(), GetSpritePositionY());
std::shared_ptr<CSprite> bd2 = std::make_shared<CSprite>((str + "_").c_str());
bd2->CloneSprite("bulletDown");
bd2->SetSpriteLifeTime(1);
bd2->SetSpritePosition(GetSpritePositionX(), GetSpritePositionY());
}
basicenemy.h
#ifndef BASICENEMY_H
#define BASICENEMY_H
#include "basiccraft.h"
class BasicEnemy : public BasicCraft {
public:
BasicEnemy(const char* name_);
virtual ~BasicEnemy();
virtual void onMove(const float deltaTime_) = 0;
virtual std::shared_ptr<Bullet> onFire(const float deltaTime_);
// 判断是否飞出屏幕
virtual bool isOverScreen() = 0;
virtual void beenDown();
protected:
virtual std::shared_ptr<Bullet> fire();
float deltaMoveTime;
bool increMove;
int beenDownId;
};
#endif // BASICENEMY_H
basicenemy.cpp
#include "basicenemy.h"
#include "bullet.h"
#include <sstream>
BasicEnemy::BasicEnemy(const char* name_)
: BasicCraft(name_), increMove(true) {
isFire = true;
deltaMoveTime = 0;
increMove = true;
beenDownId = 0;
}
BasicEnemy::~BasicEnemy() {}
std::shared_ptr<Bullet> BasicEnemy::fire() {
std::stringstream ss;
ss << "enemyBullet_" << bulletId++;
std::string str;
ss >> str;
std::shared_ptr<Bullet> pb = std::make_shared<Bullet>(str.c_str());
pb->CloneSprite("Bullet1_Template");
pb->SetSpritePosition(GetSpritePositionX(), GetSpritePositionY());
pb->SetSpriteFlipX(false);
pb->SetSpriteLinearVelocityX(-30);
pb->SetSpriteWorldLimit(WORLD_LIMIT_NULL, CSystem::GetScreenLeft()-10, CSystem::GetScreenTop(), CSystem::GetScreenRight() + 200, CSystem::GetScreenBottom());
return pb;
}
std::shared_ptr<Bullet> BasicEnemy::onFire(const float deltaTime_) {
deltaFireTime -= deltaTime_;
if (deltaFireTime <= 0 && isFire) {
// 固定发射时间
deltaFireTime = 2;
return fire();
}
return nullptr;
}
void BasicEnemy::beenDown() {
std::stringstream ss;
ss << "enemyDown_" << beenDownId++;
std::string str;
ss >> str;
std::shared_ptr<CSprite> bd = std::make_shared<CSprite>(str.c_str());
bd->CloneSprite("enemyExplode");
bd->SetSpriteLifeTime(1);
bd->SetSpritePosition(GetSpritePositionX(), GetSpritePositionY());
std::shared_ptr<CSprite> bd2 = std::make_shared<CSprite>((str + "_").c_str());
bd2->CloneSprite("bulletDown");
bd2->SetSpriteLifeTime(0.3);
bd2->SetSpritePosition(GetSpritePositionX(), GetSpritePositionY());
}
horizenemy.h
#ifndef HORIZENEMY
#define HORIZENEMY
#include "basicenemy.h"
class HorizEnemy : public BasicEnemy {
public:
HorizEnemy(const char* name_);
virtual ~HorizEnemy();
// 创建敌机
static std::shared_ptr<BasicEnemy> creatEnemy(const int id_);
virtual void onMove(const float deltaTime_);
virtual bool isOverScreen();
};
#endif // HORIZENEMY
horizenemy.cpp
#include "horizenemy.h"
#include <sstream>
HorizEnemy::HorizEnemy(const char* name_)
: BasicEnemy(name_) {
deltaMoveTime = 0;
increMove = true;
setHp(1);
}
HorizEnemy::~HorizEnemy() {}
// 创建敌机
std::shared_ptr<BasicEnemy> HorizEnemy::creatEnemy(const int id_) {
std::stringstream ss;
ss << "horizEnemy_" << id_;
std::string str;
ss >> str;
std::shared_ptr<BasicEnemy> pe = std::make_shared<HorizEnemy>(str.c_str());
pe->CloneSprite("HorizontalSprite_Template"); //克隆模板
pe->SetSpritePosition(static_cast<float>(CSystem::GetScreenRight() + 20),
CSystem::RandomRange(static_cast<int>(CSystem::GetScreenTop()),
static_cast<int>(CSystem::GetScreenBottom() ) ) );
pe->SetSpriteLinearVelocityX(-10);
// 不用设置世界边缘,因为手动判断删除
return pe;
}
void HorizEnemy::onMove(const float deltaTime_) {
if (increMove) {
deltaMoveTime += deltaTime_;
if (deltaMoveTime >= 2) increMove = false;
} else {
deltaMoveTime -= deltaTime_;
if (deltaMoveTime <= -2) increMove = true;
}
SetSpriteLinearVelocityY(deltaMoveTime * 3);
}
bool HorizEnemy::isOverScreen() {
return GetSpritePositionX() <= CSystem::GetScreenLeft() - 10;
}
verticenemy.h
#ifndef VERTICENEMY_H
#define VERTICENEMY_H
#include "basicenemy.h"
class VerticEnemy : public BasicEnemy {
public:
VerticEnemy(const char* name_);
virtual ~VerticEnemy();
static std::shared_ptr<BasicEnemy> creatEnemy(const int id_);
virtual void onMove(const float deltaTime_);
virtual bool isOverScreen();
};
#endif // VERTICENEMY_H
verticenemy.cpp
#include "verticenemy.h"
#include <sstream>
VerticEnemy::VerticEnemy(const char* name_)
: BasicEnemy(name_) {
deltaMoveTime = 0;
increMove = true;
setHp(1);
}
VerticEnemy::~VerticEnemy() {}
// 创建敌机
std::shared_ptr<BasicEnemy> VerticEnemy::creatEnemy(const int id_) {
std::stringstream ss;
ss << "verticEnemy_" << id_;
std::string str;
ss >> str;
std::shared_ptr<BasicEnemy> pe = std::make_shared<VerticEnemy>(str.c_str());
pe->CloneSprite("VerticalSprite_Template"); //克隆模板
pe->SetSpritePosition(CSystem::RandomRange(static_cast<int>(CSystem::GetScreenLeft() + 50),
static_cast<int>(CSystem::GetScreenRight()) ),
static_cast<float>(CSystem::GetScreenBottom() + 10) );
pe->SetSpriteLinearVelocityY(-10);
// 不用设置世界边缘,因为手动判断删除
return pe;
}
void VerticEnemy::onMove(const float deltaTime_) {
if (increMove) {
deltaMoveTime += deltaTime_;
if (deltaMoveTime >= 1) increMove = false;
} else {
deltaMoveTime -= deltaTime_;
if (deltaMoveTime <= -1) increMove = true;
}
SetSpriteLinearVelocityX(deltaMoveTime * 4);
}
bool VerticEnemy::isOverScreen() {
return GetSpritePositionY() <= CSystem::GetScreenTop() - 10;
}
rotateenemy.h
#ifndef ROTATEENEMY_H
#define ROTATEENEMY_H
#include "basicenemy.h"
class RotateEnemy : public BasicEnemy {
public:
RotateEnemy(const char* name_);
virtual ~RotateEnemy();
static std::shared_ptr<BasicEnemy> creatEnemy(const int id_);
virtual void onMove(const float deltaTime_);
virtual bool isOverScreen();
};
#endif // ROTATEENEMY_H
rotateenemy.cpp
#include "rotateenemy.h"
#include <sstream>
RotateEnemy::RotateEnemy(const char* name_)
: BasicEnemy(name_) {
deltaMoveTime = 0;
increMove = true;
setHp(1);
}
RotateEnemy::~RotateEnemy() {}
// 创建敌机
std::shared_ptr<BasicEnemy> RotateEnemy::creatEnemy(const int id_) {
std::stringstream ss;
ss << "rotateEnemy_" << id_;
std::string str;
ss >> str;
std::shared_ptr<BasicEnemy> pe = std::make_shared<RotateEnemy>(str.c_str());
pe->CloneSprite("RotateSprite_Template"); //克隆模板
pe->SetSpritePosition(static_cast<float>(CSystem::GetScreenLeft() - 20),
CSystem::RandomRange(static_cast<int>(CSystem::GetScreenTop()),
static_cast<int>(CSystem::GetScreenBottom() ) ) );
pe->SetSpriteLinearVelocityX(10);
// 不用设置世界边缘,因为手动判断删除
return pe;
}
void RotateEnemy::onMove(const float deltaTime_) {
if (increMove) {
deltaMoveTime += deltaTime_;
if (deltaMoveTime >= 2) increMove = false;
} else {
deltaMoveTime -= deltaTime_;
if (deltaMoveTime <= -2) increMove = true;
}
SetSpriteLinearVelocityY(deltaMoveTime * 2);
}
bool RotateEnemy::isOverScreen() {
return GetSpritePositionX() >= CSystem::GetScreenRight() + 10;
}
boosenemy.h
#ifndef BOOSENEMY_H
#define BOOSENEMY_H
/// boos 纯属拼写错误 实为 boss
#include "basicenemy.h"
class BoosEnemy : public BasicEnemy {
public:
BoosEnemy(const char* name_);
virtual ~BoosEnemy();
static std::shared_ptr<BasicEnemy> creatEnemy(const int id_);
virtual void onMove(const float deltaTime_);
virtual bool isOverScreen();
};
#endif // BOOSENEMY_H
boosenemy.cpp
#include "boosenemy.h"
#include <sstream>
BoosEnemy::BoosEnemy(const char* name_)
: BasicEnemy(name_) {
deltaMoveTime = 0;
increMove = true;
setHp(3);
}
BoosEnemy::~BoosEnemy() {}
// 创建敌机
std::shared_ptr<BasicEnemy> BoosEnemy::creatEnemy(const int id_) {
std::stringstream ss;
ss << "boosEnemy_" << id_;
std::string str;
ss >> str;
std::shared_ptr<BasicEnemy> pe = std::make_shared<BoosEnemy>(str.c_str());
pe->CloneSprite("BigBoss_Template"); //克隆模板
pe->SetSpritePosition(static_cast<float>(CSystem::GetScreenRight() + 20),
CSystem::RandomRange(static_cast<int>(CSystem::GetScreenTop()),
static_cast<int>(CSystem::GetScreenBottom() ) ) );
pe->SetSpriteLinearVelocityX(-10);
// 不用设置世界边缘,因为手动判断删除
return pe;
}
void BoosEnemy::onMove(const float deltaTime_) {
if (increMove) {
deltaMoveTime += deltaTime_;
if (deltaMoveTime >= 2) increMove = false;
} else {
deltaMoveTime -= deltaTime_;
if (deltaMoveTime <= -2) increMove = true;
}
SetSpriteLinearVelocityY(deltaMoveTime * 3);
}
bool BoosEnemy::isOverScreen() {
return GetSpritePositionX() <= CSystem::GetScreenLeft() - 10;
}
enemystool.h
#ifndef ENEMYSTOOL_H
#define ENEMYSTOOL_H
#include "basicenemy.h"
#include <list>
class EnemysTool {
public:
EnemysTool();
virtual ~EnemysTool();
// 创建敌机
virtual void creatEnemy(const float deltaTime_);
virtual void onLooop(const float deltaTime_);
// 敌机列表,基类指针
std::list<std::shared_ptr<BasicEnemy>> enemys;
private:
int enemyId;
float deltaCreatTime;
};
#endif // ENEMYSTOOL_H
enemystool.cpp
#include "enemystool.h"
#include "horizenemy.h"
#include "rotateenemy.h"
#include "verticenemy.h"
#include "boosenemy.h"
EnemysTool::EnemysTool() : enemyId(0), deltaCreatTime(0){}
EnemysTool::~EnemysTool() {}
// 创建敌机
void EnemysTool::creatEnemy(const float deltaTime_) {
deltaCreatTime -= deltaTime_;
if (deltaCreatTime < 0) {
if (enemyId % 1 == 0) {
std::shared_ptr<BasicEnemy> phe(HorizEnemy::creatEnemy(enemyId++));
enemys.push_back(phe);
}
if (enemyId % 5 == 0) {
std::shared_ptr<BasicEnemy> pre(RotateEnemy::creatEnemy(enemyId++));
enemys.push_back(pre);
}
if (enemyId % 3 == 0) {
std::shared_ptr<BasicEnemy> pve(VerticEnemy::creatEnemy(enemyId++));
enemys.push_back(pve);
}
if (enemyId % 10 == 0) {
std::shared_ptr<BasicEnemy> pbe(BoosEnemy::creatEnemy(enemyId++));
enemys.push_back(pbe);
}
deltaCreatTime = 2;
}
}
void EnemysTool::onLooop(const float deltaTime_) {
// 遍历敌机
for (auto iter = std::begin(enemys); iter != std::end(enemys); ++iter) {
if ((*iter)->isOverScreen()) {
(*iter)->DeleteSprite();
enemys.erase(iter);
break;
}
if ((*iter) != nullptr) {
(*iter)->onMove(deltaTime_);
}
}
}
附录Ⅰ:Code::Blocks 设置编译器支持C++14
打开Code::Blocks 选择 Settings > Compiler…
在一列复选框里勾选 Have g++ follow the C++14 ISO C++ language standard [-std=C++14]
注:如果你的Code::Blocks 中没有改选项,说明版本太低,请自行下载最新版本的Code::Blocks