FunCode太空战机C++实现

仅供交流学习使用,因博主水平有限,有错误欢迎批评指正
作者(即博主本人): Akame Qixisi / Excel Bloonow
游戏截图
IDE:Code::Blocks 17.12
编译器需要支持C++14或以上标准(Code::Blocks如何设置见附录Ⅰ)
当然你也可以更改代码以兼容更低版本的编译器
源码下载链接: 下载地址为作者GithubGitHub的如何使用不在本篇讨论范围内
当然你也可以参考以下内容自行实现

博主自己编写的文件有:
  1. Main.cpp(FunCode已提供,但需要自己增加内容)
  2. LessonX.hLessonX.cpp(FunCode已提供,但需要自己增加内容)
  3. moveobject.hmoveobject.cpp
  4. bullet.hbullet.cpp
  5. basiccraft.hbasiccraft.cpp
  6. mycraft.hmycraft.cpp
  7. basicenemy.hbasicenemy.cpp
  8. horizenemy.hhorizenemy.cpp
  9. verticenemy.hverticenemy.cpp
  10. rotateenemy.hrotateenemy.cpp
  11. boosenemy.hboosenemy.cpp
  12. enemystool.henemystool.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
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值