仿《雷霆战机美高梅4688.com》飞行射击掌游开发–GameObject

转载请注解:http://www.cnblogs.com/thorqq/p/5646509.html 

转发请注解:http://www.cnblogs.com/thorqq/p/6403666.html 

体系首页:https://www.oschina.net/p/raiden

 

 

Windows试玩版下载:

 
 在上一篇中,大家介绍了各类娱乐对象的功力及类的合并关系,现在咱们来探望GameObject的源代码

http://files.cnblogs.com/files/thorqq/Raiden-win.part1.rar

碰撞体

GameObject.h

 1 class GameObject : public Sprite
 2 {
 3 public:
 4     GameObject();
 5 
 6     virtual void setBodySize(const Size& s);
 7     virtual void setBodySize(float w, float h);
 8     virtual const Size& getBodySize();
 9     virtual const Size& getOrignBodySize() const;
10 
11     virtual void setBodyCenter(const Vec2& v);
12     virtual void setBodyCenter(float x, float y);
13     virtual const Vec2& getBodyCenter() const;
14 
15     //获取世界坐标下的body的位置和大小
16     virtual Rect getBodyBox() const;
17 
18 
19 protected:
20     //用于碰撞检测的刚体大小和位置
21     Vec2 m_bodyCenter; //刚体的中心点坐标(相对于精灵锚点的坐标)
22     Size m_bodySize;   //刚体的宽高
23 };

GameObject.cpp

 1 void GameObject::setBodySize(const Size& s)
 2 {
 3     m_bodySize = s;
 4 }
 5 
 6 void GameObject::setBodySize(float w, float h)
 7 {
 8     setBodySize(Size(w, h));
 9 }
10 
11 const Size& GameObject::getBodySize()
12 {
13     return m_bodySize;
14 }
15 
16 void GameObject::setBodyCenter(const Vec2& v)
17 {
18     m_bodyCenter = v;
19 }
20 
21 void GameObject::setBodyCenter(float x, float y)
22 {
23     m_bodyCenter = Vec2(x, y);
24 }
25 
26 const Vec2& GameObject::getBodyCenter() const
27 {
28     return m_bodyCenter;
29 }
30 
31 //获取世界坐标下的body的位置和大小
32 Rect GameObject::getBodyBox() const
33 {
34     Vec2 pos = getPosition();
35 
36     return Rect(pos.x + m_bodyCenter.x - m_bodySize.width * getAnchorPoint().x,
37         pos.y + m_bodyCenter.y - m_bodySize.height * getAnchorPoint().y,
38         m_bodySize.width,
39         m_bodySize.height);
40 }

碰撞体的概念很简短,中央坐标+宽高,然后加上周边的get/set方法。在那之中相比较有效的是getBodyBox()方法。由于碰撞体的主导坐标是相对于Pepsi-Cola锚点的坐标,所以只要要用来判定多个碰撞体是或不是产生撞击(是还是不是有重叠区域),必供给赢得四个碰撞体在世界坐标下的岗位和大小,那时就要调用getBodyBox()方法来收获Rect对象,然后再调用Rect的bool
intersectsRect(const Rect& rect)方法来判断七个碰撞体是或不是发生了碰撞。

http://files.cnblogs.com/files/thorqq/Raiden-win.part2.rar

 暂停/恢复

GameObject.h

1     virtual void pause() override;
2     virtual void resume() override;
3     void pause(Node *pNode);
4     void resume(Node *pNode);

GameObject.cpp

 1 void GameObject::pause()
 2 {
 3     this->pause(this);
 4 }
 5 
 6 void GameObject::resume()
 7 {
 8     this->resume(this);
 9 }
10 
11 void GameObject::pause(Node *pNode)
12 {
13     Node::pause();
14 
15     for (auto p : pNode->getChildren())
16     {
17         p->pause();
18     }
19 }
20 
21 void GameObject::resume(Node *pNode)
22 {
23     Node::resume();
24 
25     for (auto p : pNode->getChildren())
26     {
27         p->resume();
28     }
29 }

调用pause和resume的还要,会调用全部子节点的pause和resume。那样,当玩家飞机暂停时,僚机作为它的子节点,也会随着暂停。

 

初始化 

先看代码

 1 bool GameObject::initSpriteWithFileList(const std::vector<std::string>& fileList, float dura)
 2 {
 3     SpriteFrame *frame = SpriteFrameCache::getInstance()->getSpriteFrameByName(fileList.at(0));
 4     if (NULL == frame)
 5     {
 6         DEBUG_LOG("Error get frame of '%s'", fileList.at(0).c_str());
 7         CCASSERT(frame, "Error get frame");
 8     }
 9     Sprite::initWithSpriteFrame(frame);
10 
11     //动画
12     if (fileList.size() > 1)
13     {
14         Animation* animation = Animation::create();
15         animation->setDelayPerUnit(dura);
16         for (unsigned i = 0; i < fileList.size(); i++)
17         {
18             SpriteFrame* pFrame = CCSpriteFrameCache::getInstance()->getSpriteFrameByName(fileList[i]);
19             if (NULL == pFrame)
20             {
21                 continue;
22             }
23             animation->addSpriteFrame(pFrame);
24         }
25 
26         //设置重复
27         Animate* animate = Animate::create(animation);
28         Repeat* repeat = Repeat::create(animate, CC_REPEAT_FOREVER);
29         m_pAnimateSequence = Sequence::create(repeat, NULL);
30         m_pAnimateSequence->retain();
31         runAction(m_pAnimateSequence);
32     }
33 
34     return true;
35 }

以此函数是透过帧体系来初阶化。那里有多少个输入参数:fileList是图表列表,dura是每张图片之间个时刻间隔。怎么着是骨骼动画呢?看下边这几个代码:

 1 bool GameObject::initArmature(const std::string& armatureName, float scale)
 2 {
 3     if (armatureName.length() <= 0)
 4     {
 5         return true;
 6     }
 7 
 8     m_pArmature = cocostudio::Armature::create(armatureName);
 9     m_pArmature->setPosition(getContentSize() / 2);
10     m_pArmature->getAnimation()->play(GlobalData::getInstance()->getArmatureData(armatureName)->defaultAction);
11     m_pArmature->setScale(scale);
12 
13     addChild(m_pArmature);
14 
15     return true;
16 }

   
首先通过骨骼动画的名号armatureName创立骨骼动画,然后实施暗许动作defaultAction(defaultAction是从配置文件中赢得的,配置文件的读写将在后来详述)。最终把骨骼动画添加到Pepsi-Cola上。

   
那里就有3个问号了,为何既要援助帧类别动画,又要协助骨骼动画呢?大家清楚骨骼动画的表现方式比帧系列动画更增加,不过随之而来的标题正是骨骼动画更占财富。假使唯有多个简短的动画,只怕像子弹那样速度比较快并且数量相比较多的游艺对象,应该尽量使用帧类别动画,甚至对于子弹来说,只用单张图片来表现就可以了,根本用不着动画。而对此玩家飞机、boss来说,因为涉嫌到变形,那就只可以用骨骼动画了。

   
别的,那里也有四个足以优化的地方。大家得以把GameObject继承自Node,当游戏对象是类别帧动画时,就添加三个七喜子节点,假若是骨骼动画,就添加三个Armature子节点。

 下载参考代码

 

转载请申明:http://www.cnblogs.com/thorqq/p/5646509.html 

下一篇起头,我们将各种介绍GameObject的子类

 

     
传统的新手教导情势相似是安装几个大局的静态变量来保存当前新手辅导进程,然后在品种中种种或然出现新手指点的职务添加一句判断:若当前新手指导步骤等于小编所期望的步调就推行辅导部分的逻辑,新手指导平常逻辑混乱,而且跟界面包车型客车逻辑平常交叉在协同,弄的不佳的话代码里所在都是if
else,保存各类方今状态变量。

      本文将以仿雷霆战机游戏为例,说说内部有关新手教导的规划。

娱乐效果

  上面先看游戏中相比较独立的两类辅导

壹 、 菜单引导

美高梅4688.com 1

 

 

      
当用于初次运行游戏时,通过两八个步骤指点让用户神速的进去娱乐,体验游戏的快感,所以,那里运用了八个步骤:

a)       大xiong小姨子出没,吸引男性玩家的眼珠子,指点玩家进入主菜单;

b)       教导玩家选拔私下认可飞机,并进加入关贸总协定组织卡选取界面;

c)        指点玩家选用第3关,并跻身战斗界面;

贰 、 游戏指引

美高梅4688.com 2 

  在娱乐进程中,当满足一定的标准时,就搁浅游戏,弹出行戏道具(上海体育场所中时护盾,能够把显示器上的子弹全体变成宝石)的行使情势求证,并辅导玩家体验道具的机能。

  新手教导的来得效果为:

a)       出色体现要求用户点击的控件(例如:按钮),其余机构全部下挫亮度

b)       用动画箭头指向该控件,方便玩家识别

c)        展现文字表明,告知玩家相关的操作步骤或道具使用格局

要让界面变暗相当粗略,覆盖3个半晶莹剔透的层就足以了。那么怎么才能让有些控件变亮呢?easy,把这么些控件从父节点上摘下来,挂到半透明层上就足以了。

规律介绍实现,下边该讲讲代码设计了。

接口调用

  菜单引导一般位于界面包车型地铁onEnter函数中,那样,当玩家进入该界面时就会及时触发新手辅导逻辑。上面是出现美人欢迎界面包车型地铁函数,如何,唯有几行代码,一点也不细略吗。

void MenuMainUI::onEnter()
{
    Layer::onEnter();

    //美女新手引导
    Guide* pGuide = GuideMgr::getInstance()->show(GuideType::WelcomeGirl, this, nullptr, [this](){
        GuideMgr::getInstance()->show(GuideType::WelcomeClickButtonLevel, this, m_pBtnLevel);
    });
}

  在下面的代码中,我们采取了这一个函数:

Guide* GuideMgr::show(int guideType, Node* parent, Node* widget, const std::function<void()>& callback)

其中:

1)      guideType是教导项目,有如下的取值:

const int WelcomeGirl = 10; //第一次进入游戏后的欢迎说明
const int WelcomeClickButtonLevel = 20; //点击闯关模式
const int WelcomeClickMissionOne = 30;  //点击第一关

const int GameShield = 140; //护盾引导

2)     
parent是父节点,一般是日前的界面层。半透明层正是要挂在这一个节点下。

3)     
widget是索要高亮展现的控件节点。对于赏心悦目的女孩子引导的话,没有控件需求高亮展现,所以传入nullptr;对于第三个引导界面来说,是“闯关形式“按钮节点。

4)     
callback是lambda表明式。当用户点击辅导界面包车型客车任意处使得教导界面消失时,就会调用callback。在那几个事例中,大家利用那个参数来落到实处几个辅导界面三番五次现身。

GuideMgr::show()函数返回Guide对象指针,那是怎么着鬼?大家前面再说。

咱俩再看下护盾使用教导界面包车型地铁调用代码:

void HubLayer::displayGuideShield()
{
    Guide* pGuide = GuideMgr::getInstance()->show(GuideType::GameShield, this->getParent(), m_pBtnShield);
    if (pGuide)
    {
        m_pPlaneLayer->pause();
    }
}

void HubLayer::menuShieldCallback(Ref* pSender)
{
    if (GuideMgr::getInstance()->destory(GuideType::GameShield))
    {
        m_pPlaneLayer->resume();
    }
}

逻辑很不难,弹出携带界面,并暂停游戏。点击护盾按钮后,销毁指导层,苏醒游戏运维,这时,满屏的子弹哗啦啦的成为了宝石。

新手教导接口调用貌似瞅着挺不难的,仿佛也不太会破坏原有代码的雅观。那么其内部逻辑是否很复杂呢?

兑现原理

       新手指引实现代码设计如下多少个类:

1)       PopupLayer类:呈现半透明层,响应用户的各类触摸操作

2)       Guide类:显示新手指点的主逻辑

3)       GuideMgr类:管理全数的新手指引Guide类

4)       GuideWelcomeGirl/ GuideWelcomeClickButtonLevel/
GuideWelcomeClickMissionOne/
GuideGameShield类:继承自Guide类,用于落实各类指点。

上边大家一一解析这一个类。

半透明层

class PopupLayer : public LayerColor
{
public:
    PopupLayer();
    ~PopupLayer();

    virtual bool init();
    virtual bool doInit() = 0;

    //touch事件监听 屏蔽向下触摸
    virtual bool onTouchBegan(Touch *touch, Event *event) override;
    virtual void onTouchMoved(Touch *touch, Event *event) override;
    virtual void onTouchEnded(Touch* touch, Event* event) override;

    virtual std::function<bool(Touch*, Event*)> getTouchBeganFunc() { return CC_CALLBACK_2(PopupLayer::onTouchBegan, this); };
    virtual std::function<void(Touch*, Event*)> getTouchMovedFunc() { return CC_CALLBACK_2(PopupLayer::onTouchMoved, this); }
    virtual std::function<void(Touch*, Event*)> getTouchEndedFunc() { return CC_CALLBACK_2(PopupLayer::onTouchEnded, this); }

protected:
    EventListenerTouchOneByOne* m_pListener;
};

PopupLayer::PopupLayer()
    : m_pListener(nullptr)
{
}

PopupLayer::~PopupLayer()
{
    Director::getInstance()->getEventDispatcher()->removeEventListener(m_pListener);
}

bool PopupLayer::init()
{
    if (!LayerColor::init())
    {
        return false;
    }

    m_pListener = EventListenerTouchOneByOne::create();
    m_pListener->setSwallowTouches(true);
    m_pListener->onTouchBegan = getTouchBeganFunc();
    m_pListener->onTouchMoved = getTouchMovedFunc();
    m_pListener->onTouchEnded = getTouchEndedFunc();
    auto dispatcher = Director::getInstance()->getEventDispatcher();
    dispatcher->addEventListenerWithSceneGraphPriority(m_pListener, this);

    setColor(Color3B(0, 0, 0));
    setOpacity(160);

    return doInit();
}

bool PopupLayer::onTouchBegan(Touch *touch, Event *event)
{
    return true;
}

void PopupLayer::onTouchMoved(Touch *touch, Event *event)
{

}

void PopupLayer::onTouchEnded(Touch* touch, Event* event)
{

}

上面那段代码中,通过继承LayerColor,并应用setColor(Color3B(0, 0, 0));
setOpacity(160);来兑现三个半透明层的遮盖,而实际的界面初叶化和动手响应,则由子类来重写doInit/onTouchBegan/
onTouchMoved/ onTouchEnded来贯彻。

新手辅导基类

先上代码

 

#define DECLARE_GUIDE(name)\
private:\
    static bool mInit; \
    static int mType; \
public:\
    static Guide* create()\
    {\
        return new name(); \
    }\
    static bool checkCondition();

#define REGISTER_GUIDE(type, name) \
    bool name::mInit = GuideMgr::getInstance()->registerFunc(type, name::checkCondition, name::create); \
    int name::mType = type;

class Guide : public PopupLayer
{
public:
    Guide();

public:
    //显示
    Guide* show(int GuideType, Node* pRoot, Node* pTarget, const std::function<void()>& callback = nullptr);
    //还原target
    void restore();

    //设置文字描述
    void setPrompt(const std::string& prompt);

    //设置玩家触摸屏幕任意一点后的响应,例如:销毁当前的引导并弹出新的引导
    virtual void onTouchEnded(Touch *touch, Event *event) override;
    virtual std::function<void(Touch*, Event*)> getTouchEndedFunc() override
    {
        return CC_CALLBACK_2(Guide::onTouchEnded, this);
    }

    virtual void onEnter() override;
    virtual void onExit() override;

protected:
    //在最上层创建一个GuideBg,然后把target按钮从原节点上拿下来,添加到GuideBg上
    virtual bool doInit() override;

protected:
    int m_iGuideType;
    std::function<void()> m_callback;

    Node* m_pRoot;

    Node* m_pTarget;
    int m_targetLocalZOrder;
    Vec2 m_targetPos;
    Node* m_targetParent;

    ui::Text* m_pTextPrompt;
    std::string m_prompt;
    bool m_touchEnable;
};

本条类中,最重点的就是doInit函数,其功能包含了:把指标按钮从原本的父节点上摘下来,挂到半透明层上。

        m_targetPos = m_pTarget->getPosition();
        m_targetParent = m_pTarget->getParent();
        m_targetLocalZOrder = m_pTarget->getLocalZOrder();

        //Vec2 pos = m_pRoot->convertToWorldSpace(m_pTarget->getPosition());
        Vec2 pos = m_pTarget->convertToWorldSpace(Vec2::ZERO);
        pos += m_pTarget->getAnchorPointInPoints();

        //将target移到本layer上
        m_pRoot->addChild(this);
        m_pTarget->retain();
        this->addChild(m_pTarget);
        m_pTarget->release();
        m_pTarget->setPosition(pos);

添加提示箭头动画

        //m_pTarget的中心位置(根据锚点进行转换)
        float deltaX = (0.5 - m_pTarget->getAnchorPoint().x) * m_pTarget->getAnchorPointInPoints().x / m_pTarget->getAnchorPoint().x;
        float deltaY = (0.5 - m_pTarget->getAnchorPoint().y) * m_pTarget->getAnchorPointInPoints().y / m_pTarget->getAnchorPoint().y;

        //添加指示箭头
        Sprite* pArrow = Sprite::createWithSpriteFrameName("Guide_Arrow.png");
        const Size& targetSize = m_pTarget->getContentSize();
        const Size& arrowSize = pArrow->getContentSize();
        bool bArrowTop = true;

        Node* pDialogBox = nullptr;
        Sprite* pDialogBoxBg = nullptr;
        ui::Text* m_pTextPrompt = nullptr;
        if (m_prompt.length() > 0)
        {
            pDialogBox = Preload::getInstance()->getUI("GameUI_Dialogbox.csb");
            FIND_UI_CONTROL_RE(ui::Text*, "Text_Content", m_pTextPrompt, pDialogBox);
            FIND_UI_CONTROL_RE(Sprite*, "GameUI_Dialogbox_Bg", pDialogBoxBg, pDialogBox);
            m_pTextPrompt->setTextAreaSize(Size(360, 110));
            m_pTextPrompt->ignoreContentAdaptWithSize(false);
        }
        if (m_pTarget->getPositionY() < CONSTANT::DESIGN_RES_HEIGHT / 2 + 100)
        {
            //箭头在控件的上方
            bArrowTop = true;
            pArrow->setPosition(m_pTarget->getPosition().x + deltaX,
                m_pTarget->getPosition().y + targetSize.height / 2 + arrowSize.height / 2 + 20 + deltaY);

            if (pDialogBox)
            {
                pDialogBox->setPosition(CONSTANT::DESIGN_RES_WIDTH / 2, CONSTANT::DESIGN_RES_HEIGHT - pDialogBoxBg->getContentSize().height / 2);
                m_pTextPrompt->setString(m_prompt);
                this->addChild(pDialogBox);
            }
        }
        else
        {
            //箭头在控件的下方
            bArrowTop = false;
            pArrow->setFlippedY(true);
            pArrow->setPosition(m_pTarget->getPosition().x + deltaX,
                m_pTarget->getPosition().y - targetSize.height / 2 - arrowSize.height / 2 - 20 + deltaY);

            if (pDialogBox)
            {
                pDialogBox->setPosition(CONSTANT::DESIGN_RES_WIDTH / 2, pDialogBoxBg->getContentSize().height / 2);
                m_pTextPrompt->setString(m_prompt);
                this->addChild(pDialogBox);
            }
        }
        this->addChild(pArrow);

        //箭头动画
        DelayTime* pDelay = DelayTime::create(0.4f);
        MoveBy* pMove1 = MoveBy::create(0.15f, Vec2(0, -10.0f));
        MoveBy* pMove2 = MoveBy::create(0.15f, Vec2(0, 10.0f));
        Sequence* pSeq = nullptr;
        if (bArrowTop)
        {
            pSeq = Sequence::create(pDelay, pMove1, pMove2, nullptr);
        }
        else
        {
            pSeq = Sequence::create(pDelay, pMove2, pMove1, nullptr);
        }
        RepeatForever* pRepeat = RepeatForever::create(pSeq);
        pArrow->runAction(pRepeat);
        m_touchEnable = false;

销毁新手指点层,将对象按钮挂到原来的父节点上。 

//还原target
void Guide::restore()
{
    if (m_pTarget)
    {
        m_pTarget->retain();

        this->getChildren().eraseObject(m_pTarget);
        m_targetParent->addChild(m_pTarget);
        m_pTarget->setLocalZOrder(m_targetLocalZOrder);
        m_pTarget->setPosition(m_targetPos);

        m_pTarget->release();
    }

    this->removeFromParent();
}

新手引导子类

那边大家大致介绍第二个红颜欢迎和主菜单那四个新手辅导。

 

////////////////////////////////////////////////////////////////
//
//  首次进入游戏的介绍
//
////////////////////////////////////////////////////////////////
class GuideWelcomeGirl : public Guide
{
public:
    DECLARE_GUIDE(GuideWelcomeGirl);

public:
    virtual bool doInit() override;
};

////////////////////////////////////////////////////////////////
//
//  首次进入游戏,点击闯关模式
//
////////////////////////////////////////////////////////////////
class GuideWelcomeClickButtonLevel : public Guide
{
public:
    DECLARE_GUIDE(GuideWelcomeClickButtonLevel);

public:
    virtual bool doInit() override;
};

  

////////////////////////////////////////////////////////////////
//
//  首次进入游戏的介绍
//
////////////////////////////////////////////////////////////////
REGISTER_GUIDE(GuideType::WelcomeGirl, GuideWelcomeGirl);

bool GuideWelcomeGirl::checkCondition()
{
    switch (GuideConstant::GuideDisplay)
    {
    case GuideTestNoGuide:   return false;//用于测试
    case GuideTestNecessary: return true; //用于测试
    default:
        return !GameData::getInstance()->checkGuide(mType)
            && GameData::getInstance()->getLevelFinish(Difficulty::Easy) == 0;
    }
}

bool GuideWelcomeGirl::doInit()
{
    Guide::setPrompt(GlobalData::getInstance()->getParameter(GuideConstant::StringGuideWelcome));

    if (!Guide::doInit())
    {
        return false;
    }

    return true;
}

////////////////////////////////////////////////////////////////
//
//  首次进入游戏,点击闯关模式
//
////////////////////////////////////////////////////////////////
REGISTER_GUIDE(GuideType::WelcomeClickButtonLevel, GuideWelcomeClickButtonLevel);

bool GuideWelcomeClickButtonLevel::checkCondition()
{
    switch (GuideConstant::GuideDisplay)
    {
    case GuideTestNoGuide:   return false; //用于测试
    case GuideTestNecessary: return true; //用于测试
    default:
        return !GameData::getInstance()->checkGuide(mType)
            && GameData::getInstance()->getLevelFinish(Difficulty::Easy) == 0;
    }
}

bool GuideWelcomeClickButtonLevel::doInit()
{
    Guide::setPrompt(GlobalData::getInstance()->getParameter(GuideConstant::StringGuidePressLevelMode));

    if (!Guide::doInit())
    {
        return false;
    }

    return true;
}

精心比较这三个新手指导代码,最大的差异点就在checkCondition函数,约等于判定当前的标准化是不是供给展现指引。然后,设置下要求具体的文字表达,接着,没了。

指点管理类

class GuideMgr
{
public:
    static GuideMgr* getInstance();

    bool registerFunc(int type, const std::function<bool()>& checkFunc, const std::function<Guide*()>& createFunc);

    Guide* show(int GuideType, Node* parent, Node* widget, const std::function<void()>& callback = nullptr);
    bool destory(int GuideType);

    void incGuideCnt();
    void decGuideCnt();
    bool hasGuide();

protected:
    GuideMgr();

private:
    std::map<int, std::function<bool()>> m_condMap;
    std::map<int, std::function<Guide*()>> m_createMap;
    std::map<int, Guide*> m_objectMap;
    int m_iCnt;

    static GuideMgr* m_pInstance;
};

  

GuideMgr* GuideMgr::m_pInstance = nullptr;

GuideMgr* GuideMgr::getInstance()
{
    if (!m_pInstance)
    {
        m_pInstance = new GuideMgr();
    }

    return m_pInstance;
}

GuideMgr::GuideMgr()
 : m_iCnt(0)
{

}

bool GuideMgr::registerFunc(int type, const std::function<bool()>& checkFunc, const std::function<Guide*()>& createFunc)
{
    m_condMap.insert(std::map<int, std::function<bool()>>::value_type(type, checkFunc));
    m_createMap.insert(std::map<int, std::function<Guide*()>>::value_type(type, createFunc));

    return true;
}

Guide* GuideMgr::show(int guideType, Node* parent, Node* widget, const std::function<void()>& callback)
{
    if (hasGuide())
    {
        return nullptr;
    }

    auto itCond = m_condMap.find(guideType);
    auto itCreate = m_createMap.find(guideType);
    if (itCond != m_condMap.end() && itCreate != m_createMap.end())
    {
        if (itCond->second())
        {
            Guide* pGuide = itCreate->second();
            pGuide->autorelease();

            if (pGuide)
            {
                auto it = m_objectMap.find(guideType);
                if (it != m_objectMap.end())
                {
                    m_objectMap.erase(it);
                }
                m_objectMap.insert(std::map<int, Guide*>::value_type(guideType, pGuide));
                return pGuide->show(guideType, parent, widget, callback);
            }
        }
    }

    return nullptr;
}

bool GuideMgr::destory(int GuideType)
{
    auto it = m_objectMap.find(GuideType);
    if (it != m_objectMap.end())
    {
        it->second->restore();
        m_objectMap.erase(it);

        return true;
    }
    else
    {
        return false;
    }

}

void GuideMgr::incGuideCnt()
{ 
    ++m_iCnt; 
}

void GuideMgr::decGuideCnt()
{ 
    --m_iCnt; 
    if (m_iCnt < 0)
    {
        m_iCnt = 0;
    }
}

bool GuideMgr::hasGuide()
{ 
    return m_iCnt > 0; 
}

没啥好说的,2个单例,八个map变量(m_condMap/m_createMap),通过引导项目来搜寻对应教导的原则判断和开创函数,然后创设Guide,并保留到m_objectMap中。

 

  好了,本游戏中的新手指引相关安插介绍完了,当然那并不是3个最好的设计,借使有好的设计和情势,希望能一起谈谈。

 

正文涉及的连带代码下载:guide.rar

有其余难点可交换:thorqq@163.com

转发请表明:http://www.cnblogs.com/thorqq/p/6403666.html 

发表评论

电子邮件地址不会被公开。 必填项已用*标注