仅供交流学习使用,因博主水平有限,有错误欢迎批评指正
作者(即博主本人): 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); /// OKsetScore(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