美高梅4688.com学《雷霆战机》飞行射击手游开发–新手引导

转载请注明: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()方法。由于碰撞体的骨干坐标是对立于Sprite锚点的坐标,所以要一旦为此来判断两独碰撞体是否发碰撞(是否发重合区域),必须要获得两单碰撞体在世界坐标下之位置与尺寸,这时就要调用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是自从配置文件中取的,配置文件的读写将于随后详述)。最后将骨骼动画长到Sprite上。

   
这里就有一个疑点了,为什么既要支持帧序列动画,又要支持骨骼动画也?我们明白骨骼动画的表现形式比帧序列动画更丰富,但是随之而来的题材便是骨骼动画更占用资源。如果单出一个简短的动画,或者诸如子弹那样速度比快以数量比较多的娱乐对象,应该尽可能用帧序列动画,甚至对于子弹来说,只用单张图片来展现便好了,根本用不着动画。而对于玩家飞机、boss来说,因为涉及到变形,那就算只能用骨骼动画了。

   
另外,这里吧发生一个得以优化的地方。我们可以管GameObject继承自Node,当戏对象是行帧动画时,就补加一个Sprite子节点,如果是骨骼动画,就补给加一个Armature子节点。

 下充斥参考代码

 

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

产同样篇开始,我们用各个介绍GameObject的子类

 

     
传统的初手引导方式一般是装一个大局的静态变量来保存时新手引导进度,然后以档次受到每个可能出现新手引导之职上加同句判断:若当前新手引导步骤等于我所企盼之步调就是实施引导部分的逻辑,新手引导常常逻辑混乱,而且跟界面的逻辑常常交叉在同步,弄的坏的话代码里处处都是if
else,保存各种临时状态变量。

      本文将因学雷霆战机游戏啊例,说说内部关于新手引导的宏图。

打闹效果

  下面先看打中比突出的片近乎引导

1、 菜单引导

美高梅4688.com 1

 

 

      
当用于初次启动游戏常常,通过两三只步骤引导被用户迅速的进去娱乐,体验游戏的快感,所以,这里运用了三个步骤:

a)       大xiong妹妹出没,吸引男玩家的眼球,引导玩家进入主菜单;

b)       引导玩家选择默认飞机,并上关卡选择界面;

c)        引导玩家选择第一拖累,并跻身战斗界面;

2、 游戏引导

美高梅4688.com 2 

  以玩耍经过被,当满足一定的规格时,就半途而废游戏,弹出游戏道具(上图备受经常护盾,可以管屏幕上的枪弹全部改为宝石)的以办法求证,并引导玩家体验道具的效用。

  新手引导之示力量啊:

a)       突出展示得用户点击的控件(例如:按钮),其他机构全方位骤降亮度

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

c)        显示文字说明,告知玩家相关的操作步骤或道具使用方法

若吃界面变暗生简单,覆盖一个半晶莹剔透底重合即好了。那么怎么才会吃有控件变亮呢?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; 
}

靡啥好说之,一个单例,两个map变量(m_condMap/m_createMap),通过引导项目来查找对应引导的标准化判断及创函数,然后创建Guide,并保留到m_objectMap中。

 

  好了,本游戏中的新手引导相关规划介绍了了,当然就并无是一个极致好之宏图,如果产生好之宏图及模式,希望能一起谈论。

 

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

生其他问题可沟通:thorqq@163.com

转载请注明:http://www.cnblogs.com/thorqq/p/6403666.html 

相关文章

发表评论

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