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

时间:2021-11-06 20:04:16

转载请注明出处: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效果图:
【Cocos游戏实战】功夫小子第四课之设置功能和图籍场景的实现
可以看出这个功能场景的控件就三种类型,一个是菜单按钮——关闭按钮和保存按钮以及音乐和音效的开关按钮。而是精灵图片——背景图片等,三是滑动条的控件。因此此处我们需要学习的两个全新的控件就是滑动条的控件和开关按钮的控件,他们对应的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¡ªthat 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: hu1020935219@gmail.com * * \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效果如所示:
【Cocos游戏实战】功夫小子第四课之设置功能和图籍场景的实现
从上面的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