【Cocos游戏实战】功夫小子第四课之功夫小子之设置功能和图籍场景的实现

转载请注明出处:http://blog.csdn.net/suool/article/details/46553463

本节课的视频教程地址是:

第四课在此

如果本教程有帮助到您,希望您能点击进去观看一下,而且现在注册成为极客学院的会员,验证手机号码和邮箱号码会赠送三天的会员时间,手机端首次也可以领取五天的会员时间哦(即使是购买年会员目前也仅仅是年费260),成为极客学院学习会员可以无限制的下载和观看所有的学院网站的视频,谢谢您的支持!

第三课我们学习了过渡场景和主开始菜单的分析和实现。这节课我们讲学习下如何实现主开始菜单场景的附属场景设置功能场景和图籍场景。

设置功能场景

首先是设置功能场景的分析和实现。

整个设置功能场景要实现的就是设置游戏的音乐和音效的设置并将设置保存下来。

所以这里我们首先需要知道是如何保存用户的数据,在我们的Cocos2d-x引擎中提供了一个类似数据存储的功能API

Userdefault类

这个类的作用和一些重要的API我们可以通过其源码很容易看出来:

/**
 *首先说明的是这个类的作用类似于一个小型数据库,其实是以键值对的形式存储数据的
 * UserDefault acts as a tiny database. You can save and get base type values by it.
 * For example, setBoolForKey("played", true) will add a bool value true into the database.
 * Its key is "played". You can get the value of the key by getBoolForKey("played").
 *
 * It supports the following base types:支持以下几种特殊的数据类型的存储
 * bool, int, float, double, string
 */
class CC_DLL UserDefault
{
public:
    // 获取数据的方法,提供键取值
    // get value methods

    /**
    @brief Get bool value by key, if the key doesn‘t exist, a default value will return.
     You can set the default value, or it is false.
    * @js NA
    */
    bool    getBoolForKey(const char* pKey);
    /**
     * @js NA 如果取不到该键对应的值,则返回指定的默认值,一下的方法都是一样的
     */
    bool    getBoolForKey(const char* pKey, bool defaultValue)
    int     getIntegerForKey(const char* pKey);
    int     getIntegerForKey(const char* pKey, int defaultValue);
    float    getFloatForKey(const char* pKey);
    float    getFloatForKey(const char* pKey, float defaultValue);
    double  getDoubleForKey(const char* pKey);
    double  getDoubleForKey(const char* pKey, double defaultValue);
    std::string getStringForKey(const char* pKey);
    std::string getStringForKey(const char* pKey, const std::string & defaultValue);
    Data getDataForKey(const char* pKey);
    Data getDataForKey(const char* pKey, const Data& defaultValue);

    // 存储数据的方法,指定键和值存储数据,方法和上述取值一样
    // set value methods

    void    setBoolForKey(const char* pKey, bool value);
    void    setIntegerForKey(const char* pKey, int value);
    void    setFloatForKey(const char* pKey, float value);
    void    setDoubleForKey(const char* pKey, double value);
    void    setStringForKey(const char* pKey, const std::string & value);
    void    setDataForKey(const char* pKey, const Data& value);
    void    flush();
    /** returns the singleton 获取user default的一个实例(此处是单例模式)
     * @js NA
     * @lua NA
     */
    static UserDefault* getInstance();
    /**
     * @js NA
     */
    static void destroyInstance();
    // 已经弃用的方法
    /** deprecated. Use getInstace() instead
     * @js NA
     * @lua NA
     */
    CC_DEPRECATED_ATTRIBUTE static UserDefault* sharedUserDefault();
    /**
     * @js NA
     */
    CC_DEPRECATED_ATTRIBUTE static void purgeSharedUserDefault();
    /** 这个方法就说明userdefault存储的数据其实在xml文件中,这个是获取xml文件路径
     * @js NA
     */
    const static std::string& getXMLFilePath();
    /** 判断存储数据的xml文件是否存在,可以根据这个来判断是否是首次运行这个程序
     * @js NA
     */
    static bool isXMLFileExist();
    // 更多源码和实现请自行参考源码的cpp文件和文档
};

然后看下设置功能场景的ui效果图:

可以看出这个功能场景的控件就三种类型,一个是菜单按钮——关闭按钮和保存按钮以及音乐和音效的开关按钮。而是精灵图片——背景图片等,三是滑动条的控件。因此此处我们需要学习的两个全新的控件就是滑动条的控件和开关按钮的控件,他们对应的Cocos2d-x的控件是:滑动条:ControlSlider,开关按钮MenuItemToggle。

ControlSlider的用法

滑动条控件的组成分为三部分——互动的背景图,滑块,划过区域的图。看下他的关键源码:

ControlSlider.cpp
 /*
 继承自Control控件类,这个类有三个子类——ControlSlider(滑动条),ControlButton(按钮类,这个在后面会用到),ControlSwitch(开关类)。Control类为它的子类提供了一系列的触摸响应绑定的函数。具体参考Control的源码。
 */
class ControlSlider: public Control
{
public:
    /** 通过一个背景图片,划过区域,滑块图片名称创建一个滑动条。
     * Creates slider with a background filename, a progress filename and a
     * thumb image filename.
     */
    static ControlSlider* create(const char* bgFile, const char* progressFile, const char* thumbFile);

    /** 通过一个背景图片精灵,划过区域精灵,滑块图片精灵创建一个滑动条
     * Creates a slider with a given background sprite and a progress bar and a
     * thumb item.
     *
     * @see initWithSprites
     */
    static ControlSlider* create(Sprite * backgroundSprite, Sprite* pogressSprite, Sprite* thumbSprite);
    // 以上两个方法仅仅是参数不同,但是第一个其实在方法内部也是使用的精灵实现的

    /**
     * Creates slider with a background filename, a progress filename, a thumb
     * and a selected thumb image filename.
     */
    static ControlSlider* create(const char* bgFile, const char* progressFile, const char* thumbFile,
            const char* selectedThumbSpriteFile);

    /** 多了一个选中的滑块的图片,下面方法一样
     * Creates a slider with a given background sprite and a progress bar, a thumb
     * and a selected thumb .
     *
     * @see initWithSprites
     */
    static ControlSlider* create(Sprite * backgroundSprite, Sprite* pogressSprite, Sprite* thumbSprite,
            Sprite* selectedThumbSprite);
    /**
     * @js ctor
     */
    ControlSlider();
    /**
     * @js NA
     * @lua NA
     */
    virtual ~ControlSlider();

    /** 初始化一个Slider使用参数中的精灵,各个参数的意义见下面的注释
    * Initializes a slider with a background sprite, a progress bar and a thumb
    * item.
    *
    * @param backgroundSprite          Sprite, that is used as a background.
    * @param progressSprite            Sprite, that is used as a progress bar.
    * @param thumbSprite               Sprite, that is used as a thumb.
    */
    virtual bool initWithSprites(Sprite * backgroundSprite, Sprite* progressSprite, Sprite* thumbSprite);

    /**
    * Initializes a slider with a background sprite, a progress bar and a thumb
    * item.
    *
    * @param backgroundSprite          Sprite, that is used as a background.
    * @param progressSprite            Sprite, that is used as a progress bar.
    * @param thumbSprite               Sprite, that is used as a thumb.
    * @param selectedThumbSprite       Sprite, that is used as a selected thumb.
    */
    virtual bool initWithSprites(Sprite * backgroundSprite, Sprite* progressSprite, Sprite* thumbSprite,
            Sprite* selectedThumbSprite);

    virtual void needsLayout();
    // 常用的API
    virtual void setMaximumValue(float val); // 设置滑动的最大值
    virtual void setEnabled(bool enabled);   // 设置能否响应
    virtual bool isTouchInside(Touch * touch);
    Point locationFromTouch(Touch* touch);
    virtual void setValue(float val);     // 手动设置滑动条的值
    virtual void setMinimumValue(float val); // 设置最小值
    ``````
    // 更多方法请自查文档和源码
};

他的父类Control提供了一个绑定事件的函数如下:

/**
     * Adds a target and action for a particular event to an internal dispatch
     * table.
     * The action message may optionnaly include the sender and the event as
     * parameters, in that order.
     * When you call this method, target is not retained.
     *
     * @param target The target object?athat is, the object to which the action
     * message is sent. It cannot be nil. The target is not retained.
     * @param action A selector identifying an action message. It cannot be NULL.
     * @param controlEvent A control event for which the action message is sent.
     * See "CCControlEvent" for constants.
     */
    void addTargetWithActionForControlEvent(Ref* target, Handler action, EventType controlEvent);
// 其中Eventype是Control的强枚举类型:这里需要使用的是VALUE_CHANGE数据变化
/** Kinds of possible events for the control objects. */
    enum class EventType
    {
        TOUCH_DOWN           = 1 << 0,    // A touch-down event in the control.
        DRAG_INSIDE          = 1 << 1,    // An event where a finger is dragged inside the bounds of the control.
        DRAG_OUTSIDE         = 1 << 2,    // An event where a finger is dragged just outside the bounds of the control.
        DRAG_ENTER           = 1 << 3,    // An event where a finger is dragged into the bounds of the control.
        DRAG_EXIT            = 1 << 4,    // An event where a finger is dragged from within a control to outside its bounds.
        TOUCH_UP_INSIDE      = 1 << 5,    // A touch-up event in the control where the finger is inside the bounds of the control.
        TOUCH_UP_OUTSIDE     = 1 << 6,    // A touch-up event in the control where the finger is outside the bounds of the control.
        TOUCH_CANCEL         = 1 << 7,    // A system event canceling the current touches for the control.
        VALUE_CHANGED        = 1 << 8      // A touch dragging or otherwise manipulating a control, causing it to emit a series of different values.
    };

然后是MenuItemToggle的用法,这个控件的学习方法和上面一样,查看其源码就可以知道他的构造性方法和重要的API函数,我这里就不再带着大家走一遍了。

下面是该界面的主要实现代码:

// 头文件
/*!
 * \file SetLayer.h
 * \date 2015/05/23 8:21
 *
 * \author SuooL
 * Contact: [email protected]
 *
 * \brief 设置场景,用来设置音效,音乐,音量等
 *
 * TODO: long description
 *
 * \note
*/

#ifndef __SetLayer__H__
#define __SetLayer__H__
#include "cocos2d.h"
#include "extensions/cocos-ext.h"

USING_NS_CC;
using namespace cocos2d::extension;

class SetLayer : public Layer {
public:
    static Scene* createScene();
    virtual bool init();
    CREATE_FUNC(SetLayer);

    void changeMusicVol(Ref* pSender, Control::EventType type);
    void changeEffectVol(Ref* pSender, Control::EventType type);
    void saveSet(Ref* pSender);
    void closeBtn(Ref* pSender);
    void musicSet(Ref* pSender);
    void effectSet(Ref* pSender);
};
#endif

实现代码

Scene* SetLayer::createScene()
{
    Scene* setScene = Scene::create();
    SetLayer* layer = SetLayer::create();
    setScene->addChild(layer);
    return setScene;
}

bool SetLayer::init()
{
    if (!Layer::init())
    {
        return false;
    }

    float music = getFloatFromXML(MUSICVOL)*100.0f;
    float effect = getFloatFromXML(SOUNDVOL)*100.0f;
    // 背景精灵和关闭,保存按钮初始化
    auto BG = Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("image-0.png"));
    BG->setPosition(WINSIZE.width / 2, WINSIZE.height / 2);
    //BG->setColor(cocos2d::ccGRAY);

    auto bgInterface = Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("BGPicSet.png"));
    bgInterface->setPosition(WINSIZE.width / 2 + 50, WINSIZE.height / 2);

    auto closeBtn = MenuItemSprite::create(Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("closeSetNormal.png")),
        Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("closeSetSelected.png")), CC_CALLBACK_1(SetLayer::closeBtn, this));
    closeBtn->setPosition(WINSIZE.width - 150, WINSIZE.height - 100);

    auto saveBtn = MenuItemSprite::create(Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("SaveSettings.png")),
        Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("SaveSettings.png")), CC_CALLBACK_1(SetLayer::saveSet, this));
    saveBtn->setPosition(WINSIZE.width/2+40, WINSIZE.height / 2 - 190);
    // 音乐开关按钮
    auto musicOn = MenuItemSprite::create(Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("unchecked.png")),
        Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("unchecked.png")));
    auto musicOff = MenuItemSprite::create(Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("Hook.png")),
        Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("Hook.png")));
    // 音效开关按钮
    auto effectOn = MenuItemSprite::create(Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("unchecked.png")),
        Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("unchecked.png")));
    auto effectOff = MenuItemSprite::create(Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("Hook.png")),
        Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("Hook.png")));

    auto musicToggle = MenuItemToggle::createWithTarget(this, menu_selector(SetLayer::musicSet), musicOn, musicOff, NULL);
    musicToggle->setPosition(369.5, 457);
    auto effectToggle = MenuItemToggle::createWithTarget(this, menu_selector(SetLayer::effectSet), effectOn, effectOff, NULL);
    effectToggle->setPosition(369.5, 357);
    // 根据当前的音乐和音效状态设置开关按钮的初始化状态
    if (getBoolFromXML(MUSIC_KEY))
    {
        musicToggle->setSelectedIndex(1);
    }
    else
    {
        musicToggle->setSelectedIndex(0);
    }
    if (getBoolFromXML(SOUND_KEY))
    {
        effectToggle->setSelectedIndex(1);
    }
    else
    {
        effectToggle->setSelectedIndex(0);
    }
    // 封装MenuItem到Menu并添加到场景中来
    auto menu = Menu::create(closeBtn, saveBtn, musicToggle, effectToggle, NULL);
    menu->setPosition(Point::ZERO);
    // 初始化创建滑动条控件
    auto musicSlider = ControlSlider::create(Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("bgBar.png")),
        Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("progressBar.png")), Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("ThumbBtn.png")));
    // 绑定回调函数
    musicSlider->addTargetWithActionForControlEvents(this, cccontrol_selector(SetLayer::changeMusicVol), Control::EventType::VALUE_CHANGED);
    auto effectSlider = ControlSlider::create(Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("bgBar.png")),
        Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("progressBar.png")), Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("ThumbBtn.png")));
    // 绑定回调函数
    effectSlider->addTargetWithActionForControlEvents(this, cccontrol_selector(SetLayer::changeEffectVol), Control::EventType::VALUE_CHANGED);
    // 设置滑动条控件的基本属性
    musicSlider->setPosition(800, 457);
    musicSlider->setMinimumValue(0.0f);
    musicSlider->setMaximumValue(100.0f);
    musicSlider->setMinimumAllowedValue(0.0f);
    musicSlider->setMaximumAllowedValue(100.0f);

    musicSlider->setValue(music);
    effectSlider->setPosition(800, 357);
    effectSlider->setMinimumValue(0.0f);
    effectSlider->setMaximumValue(100.0f);
    effectSlider->setMinimumAllowedValue(0.0f);
    effectSlider->setMaximumAllowedValue(100.0f);
    effectSlider->setValue(effect);
    // 将控件添加到场景中
    this->addChild(BG);
    this->addChild(bgInterface);
    this->addChild(musicSlider);
    this->addChild(effectSlider);
    this->addChild(menu);

    return true;

}

// 滑动条控件的回调函数
void SetLayer::changeMusicVol(Ref* pSender, Control::EventType type)
{
    auto temp = (ControlSlider*)pSender;
    setFloatToXML(MUSICVOL, temp->getValue()/100.0f);
    UserDefault::getInstance()->flush();
    aduioEngine->setBackgroundMusicVolume(getFloatFromXML(MUSICVOL));
}

void SetLayer::changeEffectVol(Ref* pSender, Control::EventType type)
{
    auto temp = (ControlSlider*)pSender;
    setFloatToXML(SOUNDVOL, temp->getValue()/100.0f);
    UserDefault::getInstance()->flush();
    aduioEngine->setEffectsVolume(getFloatFromXML(SOUNDVOL));
}

// 菜单按钮的回调函数
void SetLayer::closeBtn(Ref* pSender)
{
    PLAYEFFECT;
    Director::getInstance()->replaceScene(StartLayer::createScene());
}

void SetLayer::saveSet(Ref* pSender)
{
    PLAYEFFECT;
    Director::getInstance()->replaceScene(StartLayer::createScene());
}
// 开关按钮的回调函数
void SetLayer::musicSet(Ref* pSender)
{
    auto musicTemp = (MenuItemToggle*)pSender;
    PLAYEFFECT;
    if (musicTemp->getSelectedIndex() == 0)
    {
        setBoolToXML(MUSIC_KEY, false);
        UserDefault::getInstance()->flush();
        SimpleAudioEngine::getInstance()->pauseBackgroundMusic();
    }
    else
    {
        setBoolToXML(MUSIC_KEY, true);
        UserDefault::getInstance()->flush();
        aduioEngine->setBackgroundMusicVolume(getFloatFromXML(MUSICVOL));
        SimpleAudioEngine::getInstance()->resumeBackgroundMusic();
    }
}

void SetLayer::effectSet(Ref* pSender)
{
    auto effectTemp = (MenuItemToggle*)pSender;
    if (effectTemp->getSelectedIndex() == 0)
    {
        setBoolToXML(SOUND_KEY, false);
        UserDefault::getInstance()->flush();
    }
    else
    {
        setBoolToXML(SOUND_KEY, true);
        UserDefault::getInstance()->flush();
    }
}

以上就是设置功能场景的基本实现,其所使用的新的内容首先是UserDefault类保存和读取用户的数据,然后是ControlSlider类和MenuItemToggle类。

图籍场景的实现

图籍场景的UI效果如所示:

从上面的UI效果图可以看出.这个场景中主要要实现的效果是左边的一个列表选择,中间的列表项展示区域以及一个标签提示。

关于能够实现列表显示的控件Cocos2d-x提供的相关的类有:ListView,TableView,以及一个相关的PageView。

这三个类都有些复杂,限于时间和篇幅,这里难以展开细说提供给大家几个学习的博文和demo:

TableVIew

http://blog.csdn.net/hitwhylz/article/details/22522841

ScrollView

http://shahdza.blog.51cto.com/2410787/1544983

ListVIew:

这个可以直接看我们项目中的对listview的使用。最好还是看一下源码,分析下他的实现方式,这样如果以后需要自己定制类似的控件也会方便许多。

这个场景的实现代码如下:

Scene* TujiLayer::createScene()
{
    Scene* scene = Scene::create();
    TujiLayer* tjLayer = TujiLayer::create();
    scene->addChild(tjLayer);

    return scene;
}

bool TujiLayer::init()
{
    if (!Layer::init())
    {
        return false;
    }

    m_iBeforeSel = 0;

    // 背景
    auto bgSprite = Sprite::create("PhotoGalleryBackground.png");
    bgSprite->setPosition(WINSIZE.width / 2, WINSIZE.height / 2);
    this->addChild(bgSprite);

    auto closeItem = MenuItemSprite::create(
        Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("GalleryOffNormal.png")),
        Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("GalleryOffSelected.png")),
        [&](Ref * ref){
        PLAYEFFECT;
        //弹出场景
        Director::getInstance()->replaceScene(StartLayer::createScene()); });
    // 关闭按钮
    closeItem->setPosition(WINSIZE.width/2+580, WINSIZE.height/2+320);
    auto menu = Menu::create(closeItem, NULL);
    menu->setPosition(Point::ZERO);
    bgSprite->addChild(menu);

    // 怪物图鉴
    m_pMZ_Pic = Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("ManWood.png"));
    m_pMZ_Txt = Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("Text.png"));
    m_pMZLabel = LabelTTF::create("木\n桩\n怪", "", 30);
    m_pMZLabel->setColor(ccc3(0, 255, 255));
    m_pLion_Pic = Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("ManLion.png"));
    m_pLionLabel = LabelTTF::create("狮\n子\n怪", "", 30);
    m_pLionLabel->setColor(ccc3(0, 255, 255));
    m_pStone_Pic = Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("ManStone.png"));
    m_pStoneLabel = LabelTTF::create("石\n头\n怪", "", 30);
    m_pStoneLabel->setColor(ccc3(0, 255, 255));

    m_pMZ_Pic->setPosition(WINSIZE.width / 2 + 50, WINSIZE.height / 2);
    m_pMZ_Pic->setVisible(true);
    m_pMZ_Txt->setPosition(WINSIZE.width / 2 + 460, WINSIZE.height / 2 );
    m_pMZ_Txt->setVisible(true);
    m_pMZLabel->setPosition(WINSIZE.width / 2 + 265, WINSIZE.height / 2 - 120);
    m_pMZLabel->setVisible(true);

    m_pLion_Pic->setPosition(WINSIZE.width / 2+50, WINSIZE.height / 2);
    m_pLion_Pic->setVisible(false);
    m_pLionLabel->setPosition(WINSIZE.width / 2 + 265, WINSIZE.height / 2 - 120);
    m_pLionLabel->setVisible(false);

    m_pStone_Pic->setPosition(WINSIZE.width / 2 , WINSIZE.height / 2 );
    m_pStone_Pic->setVisible(false);
    m_pStoneLabel->setPosition(WINSIZE.width / 2 + 265, WINSIZE.height / 2 - 120);
    m_pStoneLabel->setVisible(false);

    bgSprite->addChild(m_pMZ_Pic);
    bgSprite->addChild(m_pMZ_Txt);
    bgSprite->addChild(m_pMZLabel);
    bgSprite->addChild(m_pLion_Pic);
    bgSprite->addChild(m_pLionLabel);
    bgSprite->addChild(m_pStone_Pic);
    bgSprite->addChild(m_pStoneLabel);

    listView = ListView::create();
    listView->setDirection(SCROLLVIEW_DIR_VERTICAL);
    listView->setTouchEnabled(true);
    listView->setBounceEnabled(true);  // 反弹
    listView->setSize(Size(445, 500));
    listView->ignoreContentAdaptWithSize(false);
    listView->setAnchorPoint(Point(0.0, 0.0));
    listView->setPosition(Point(0, WINSIZE.height / 4));
    listView->addEventListenerListView(this, SEL_ListViewEvent(&TujiLayer::selectedItemEvent));

    bgSprite->addChild(listView);

    Button* default_button = Button::create("Cell_0.png", "CellSel_0.png", "", UI_TEX_TYPE_PLIST);

    default_button->setName("Title Button");

    Layout* default_item = Layout::create();
    default_item->setTouchEnabled(true);
    default_item->setSize(default_button->getSize());
    default_button->setPosition(Point(default_item->getSize().width / 2.0f,
    default_item->getSize().height / 2.0f));
    default_item->addChild(default_button);

    // set model 将创建的模板设置为项目模板
    listView->setItemModel(default_item);

    // 1
    Button* custom_buttonMZ = Button::create("CellSel_0.png", "Cell_0.png", "", UI_TEX_TYPE_PLIST);
    custom_buttonMZ->setName("one Button");
    custom_buttonMZ->setScale9Enabled(true);
    custom_buttonMZ->setSize(default_button->getSize());
    Layout *custom_itemMZ = Layout::create();
    custom_itemMZ->setSize(custom_buttonMZ->getSize());
    custom_buttonMZ->setPosition(Point(custom_itemMZ->getSize().width / 2.0f, custom_itemMZ->getSize().height / 2.0f));
    custom_itemMZ->addChild(custom_buttonMZ);

    // 2
    Button* custom_buttonLion = Button::create("CellSel_1.png", "Cell_1.png", "", UI_TEX_TYPE_PLIST);
    custom_buttonLion->setName("two Button");
    custom_buttonLion->setScale9Enabled(true);
    custom_buttonLion->setSize(default_button->getSize());
    Layout *custom_itemLion = Layout::create();
    custom_itemLion->setSize(custom_buttonLion->getSize());
    custom_buttonLion->setPosition(Point(custom_itemLion->getSize().width / 2.0f, custom_itemLion->getSize().height / 2.0f));
    custom_itemLion->addChild(custom_buttonLion);

    // 3
    Button* custom_buttonStone = Button::create("CellSel_2.png", "Cell_2.png", "", UI_TEX_TYPE_PLIST);
    custom_buttonStone->setName("three Button");
    custom_buttonStone->setScale9Enabled(true);
    custom_buttonStone->setSize(default_button->getSize());
    Layout *custom_itemStone = Layout::create();
    custom_itemStone->setSize(custom_buttonStone->getSize());
    custom_buttonStone->setPosition(Point(custom_itemStone->getSize().width / 2.0f, custom_itemStone->getSize().height / 2.0f));
    custom_itemStone->addChild(custom_buttonStone);

    // 4
    Button* custom_buttonWood = Button::create("CellSel_3.png", "Cell_3.png", "", UI_TEX_TYPE_PLIST);
    custom_buttonWood->setName("four Button");
    custom_buttonWood->setScale9Enabled(true);
    custom_buttonWood->setSize(default_button->getSize());
    Layout *custom_itemWood = Layout::create();
    custom_itemWood->setSize(custom_buttonWood->getSize());
    custom_buttonWood->setPosition(Point(custom_itemWood->getSize().width / 2.0f, custom_itemWood->getSize().height / 2.0f));
    custom_itemWood->addChild(custom_buttonWood);

    listView->pushBackCustomItem(custom_itemMZ);
    listView->pushBackCustomItem(custom_itemLion);
    listView->pushBackCustomItem(custom_itemStone);
    listView->pushBackCustomItem(custom_itemWood);

    return true;
}

// ListView触摸监听
void TujiLayer::selectedItemEvent(Ref* pSender, ListViewEventType  type)//ListView触摸事件
{
    ListView* listView = static_cast<ListView*>(pSender);
    CC_UNUSED_PARAM(listView);

//  if (m_iBeforeSel == listView->getCurSelectedIndex())
//  {
//      return;
//  }
//  String *normalBtn = String::createWithFormat("Cell_%d.png", m_iBeforeSel);
//  String *SelctBtn = String::createWithFormat("CellSel_%d.png", listView->getCurSelectedIndex());

    m_iBeforeSel = listView->getCurSelectedIndex();

    switch (m_iBeforeSel)
    {
    case 0:
        m_pMZ_Pic->setVisible(true);
        m_pMZ_Txt->setVisible(true);
        m_pMZLabel->setVisible(true);
        m_pLion_Pic->setVisible(false);
        m_pLionLabel->setVisible(false);
        m_pStone_Pic->setVisible(false);
        m_pStoneLabel->setVisible(false);
        break;
    case 1:
        m_pMZ_Pic->setVisible(false);
        m_pMZLabel->setVisible(false);
        m_pMZ_Txt->setVisible(false);
        m_pLionLabel->setVisible(true);
        m_pLion_Pic->setVisible(true);
        m_pStoneLabel->setVisible(false);
        m_pStone_Pic->setVisible(false);
        break;
    case 2:
        m_pMZ_Pic->setVisible(false);
        m_pMZ_Txt->setVisible(false);
        m_pMZLabel->setVisible(false);
        m_pLion_Pic->setVisible(false);
        m_pLionLabel->setVisible(false);
        m_pStone_Pic->setVisible(true);
        m_pStoneLabel->setVisible(true);
        break;
    case 3:
        m_pMZ_Pic->setVisible(false);
        m_pMZ_Txt->setVisible(false);
        m_pLion_Pic->setVisible(false);
        m_pStone_Pic->setVisible(false);
        m_pLionLabel->setVisible(false);
        m_pStoneLabel->setVisible(false);
        m_pMZLabel->setVisible(false);
        break;
    default:
        break;
    }
}

这就是我们的图籍场景的实现,所使用的是ListView,这个控件的使用方法是非常简单的,但是需要我们了解下其背后的实现原理。

这里有两个问题先提出来,一个是ListView 3.0版本的在Android平台下可能会出现白屏绿底的现象。二是我们的这个场景的标签在Windows平台下面是乱码。具体的解决办法我们会在后面的给出答案,当然您也可以提前找下解决的方法。

本节课的视频教程地址是:第四课在此

如果本教程有帮助到您,希望您能点击进去观看一下,而且现在注册成为极客学院的会员,验证手机号码和邮箱号码会赠送三天的会员时间,手机端首次也可以领取五天的会员时间哦(即使是购买年会员目前也仅仅是年费260),成为极客学院学习会员可以无限制的下载和观看所有的学院网站的视频,谢谢您的支持!

转载请注明出处:http://blog.csdn.net/suool/article/details/46553463

时间: 2024-10-23 03:55:16

【Cocos游戏实战】功夫小子第四课之功夫小子之设置功能和图籍场景的实现的相关文章

【Cocos游戏实战】功夫小子第八课之游戏打包和相关问题说明

至此,功夫小子系列的Cocos2d-x的实战文章就结束了. 再次贴个目录以便检索: 功夫小子专栏地址:http://blog.csdn.net/column/details/suoolcocoshit.html [Cocos游戏实战]功夫小子第一课需求分析和开发环境的基本配置 [Cocos游戏实战]功夫小子第二课之基础类分析和实现 [Cocos游戏实战]功夫小子第三课之过渡场景和开始菜单的实现 [Cocos游戏实战]功夫小子第四课之设置功能和图籍场景的实现 [Cocos游戏实战]功夫小子第五课之

【Cocos游戏实战】功夫小子第五课之帮助场景和选关功能的实现

功夫小子之帮助场景和选关功能的实现 转载请注明出处:http://blog.csdn.net/suool/article/details/46661231 本节课的视频教程地址是: 第五课在此 如果本教程有帮助到您,希望您能点击进去观看一下,而且现在注册成为极客学院的会员,即日起至7月1日,极客学院的 VIP 课程 30 天免费体验,想学编程的小伙伴速来,只针对新用户:http://e.jikexueyuan.com/invite/index.html?ZnJvbV9jb2RlPVkxblJUZ

【Cocos游戏实战】功夫小子第三课之过渡场景和開始菜单的实现

本节课的视频教程地址是:第三课在此 假设本教程有帮助到您,希望您能点击进去观看一下,并且如今注冊成为极客学院的会员,验证手机号码和邮箱号码会赠送三天的会员时间,手机端首次也能够领取五天的会员时间哦(即使是购买年会员眼下也不过年费260),成为极客学院学习会员能够无限制的下载和观看全部的学院站点的视频,谢谢您的支持! 经过前面两节课的学习.我们已经知道我们要做的是一个什么样的游戏项目.而且对游戏的基本特点和当中的重难点有了一个主要的认识,而且完毕了项目环境的基本搭建.以及项目基础类等工作. 从这节

【Cocos游戏实战】功夫小子第三课之过渡场景和开始菜单的实现

本节课的视频教程地址是:第三课在此 如果本教程有帮助到您,希望您能点击进去观看一下,而且现在注册成为极客学院的会员,验证手机号码和邮箱号码会赠送三天的会员时间,手机端首次也可以领取五天的会员时间哦(即使是购买年会员目前也仅仅是年费260),成为极客学院学习会员可以无限制的下载和观看所有的学院网站的视频,谢谢您的支持! 经过前面两节课的学习,我们已经知道我们要做的是一个什么样的游戏项目,并且对游戏的基本特点和其中的重难点有了一个基本的认识,并且完成了项目环境的基本搭建,以及项目基础类等工作. 从这

【Cocos游戏实战】功夫小子第二课之基础类分析和实现

本节课的视频教程地址是:第二课在此 如果本教程有帮助带您,希望您能点击进去观看一下,而且现在注册成为极客学院的会员,验证手机号码和邮箱号码会赠送三天的会员时间,会员可以无限制的下载和观看所有的视频,谢谢您的支持! 在开始第二节课之前,这里需要声明的是, 首先:本系列课程是为了结合Cocos2d-x 3.x 的基本组件和核心模块的学习而制作的,开发所使用的版本是3.0,但是代码稍加修改就可以运用在3.X的其他版本上. 其次:本游戏项目是一个非商业化项目,游戏资源和代码都会在后续的课程中释放出来,供

【Cocos游戏实战】功夫小子第六课之游戏主功能场景的分析和实现

本节课的视频教程地址是:第六课在此 如果本教程有帮助到您,希望您能点击进去观看一下,而且现在注册成为极客学院的会员,验证手机号码和邮箱号码会赠送三天的会员时间,手机端首次也可以领取五天的会员时间哦(即使是购买年会员目前也仅仅是年费260),成为极客学院学习会员可以无限制的下载和观看所有的学院网站的视频,谢谢您的支持! 转载请注明出处:http://blog.csdn.net/suool/article/details/46851335 前言 经过前面五节课的学习我们目前还剩的未完成的工作就是游戏

【Cocos游戏实战】功夫小子第七课之游戏主功能场景逻辑功能和暂停功能场景的分析和实现

CSDN的markdown编辑器是吃屎了么! !.什么玩意.!写了一半写不了东西还全没了,搞个毛线! 本节课的视频教程地址是:第七课在此 假设本教程有帮助到您,希望您能点击进去观看一下,并且如今注冊成为极客学院的会员,能够免费领取30天学习时间,免费拿极客学院VIP,1000+高清视频.学习Android.HTML5.iOS各种开发技术,限时领取.手快的戳:http://e.jikexueyuan.com/invite/index.html?ZnJvbV9jb2RlPVkxblJUZSZ1bmF

【Cocos游戏实战】功夫小子第一课需求分析概要和开发环境的基本配

第一课的视频教程在此处. 在开发一个手机游戏之前,我们要首先分析一个游戏的基本特点,包括游戏的基本角色和属性,以及游戏的基本功能,游戏的基本规则,将整个游戏的基本流程画出来. 然后在对我们游戏的核心场景进行分析,找出我们游戏中的难点和重点,对其分解. 游戏的部分效果图如下: 游戏的基本流程和分层如下: 核心场景分析: 详细的视频分析请参照此视频教程,视频教程在此处.谢谢点击啦! :)

swift语言实战晋级-第9章 游戏实战-跑酷熊猫-9-10 移除平台与视差滚动

原文:swift语言实战晋级-第9章 游戏实战-跑酷熊猫-9-10 移除平台与视差滚动 9.9 移除场景之外的平台 用为平台是源源不断的产生的,如果不注意销毁,平台就将越积越多,虽然在游戏场景中看不到.几十个还看不出问题,那几万个呢?几百万个呢? 所以我们来看看怎么移除平台,那什么样的平台需要移除呢?又如何移除呢?之前我们也说过,当平台完全移除游戏场景的时候就可以进行移除操作了.需要做两个操作,1从平台工厂类中移除,2从平台数组中移除. 而且,因为平台是一个接一个出现的,所以我们不需要每次都遍历