6 캐릭터 생성, 저장, 조회 구현하기

지난번 연재 6-1, 6-2와 이어집니다.

6.1 캐릭터 생성 구현하기

6.1.5 홈, 랜덤 버튼 기능 구현하기

랜덤하게 이미지를 가져오는 메서드 까지 만들었으니 홈버튼과 RANDOM버튼에 기능을 구현하겠습니다.

----------CharacterScene.cpp----------

 

…생략…

 

void CharacterScene::onClickHome(Ref *object){

    log("onClickHome");

    Director::getInstance()->popScene();

}

 

void CharacterScene::onClickRandom(Ref *object){

    log("onClickRandom");

    setImage("TB_FACE", -1, -1);

    setImage("TB_HAIR1", -1, -1);

    setImage("TB_HAIR2", -1, -1);

    setImage("TB_EYE", -1, -1);

    setImage("TB_MOUTH", -1, -1);

    setImage("TB_ETC", -1, -1);

    setImage("TB_BG", -1, -1);

}

이미 생성해놓은 콜백 메서드에 기능을 하는 코드를 추가했습니다.

popScene()의 경우 Directer에서 현재 Scene을 꺼냅니다. 즉 현재 Scene을 없애고 이전으로 돌아가는 것입니다.

 

Figure 6‑30 pushScene과 replaceScene의 차이

 

1.     pushScene()

  - 현재의 Scene에 다른Scene을 추가한다.

2.     replaceScene()

  - 현재의 Scene을 다른Scene으로 교체한다.

3.     popScene()

  - 현재의 Scene을 꺼낸다.

 

 

랜덤버튼의 콜백 메서드에서 setImage()를 랜덤한 값을 이용해 생성하도록 호출해 주었습니다.

setImage()메서드 내부에서 이미 자신이 있으면 삭제하고 새로 추가하였으므로 기존이미지가 교체되는 것 처럼 보이는 것 입니다.

 

디버거를 실행해 기능이 동작하는지 확인해봅니다.

 

Figure 6‑31 홈버튼 기능 동작 확인

 

 

Figure 6‑32 랜덤버튼 기능 동작 확인

 

6.1.6 얼굴, 머리, 눈, 입, 악세서리, 배경 선택 Event 구현하기

얼굴, 머리, 눈, 입, 악세서리, 배경을 변경할 수 있는 기능을 구현하겠습니다.

[6.1.1장]에서 각 버튼에 따른 콜백 메서드를 등록해놨으니 버튼 선택에 따른 서브메뉴 구성부터 구현하겠습니다.

서브 메뉴는 말풍선 처럼 구현할 것이며 말풍선에 화살표를 이용해 어떤 메뉴가 선택중인지 확인할 수 있도록 하겠습니다.

먼저 기본은 face부분이 선택된 것으로 구현하겠습니다.

 

CharacterScene에 버튼 선택에 따른 말풍선의 화살표의 위치를 수정할 수 있는 메서드와 _balloon과 _arrow란 이름을 갖은 Sprite객체를 선언하도록 합니다.

----------CharacterScene.h----------

#include "cocos2d.h"

 

USING_NS_CC;

 

class CharacterScene : public cocos2d::Layer

{

public:

    //생성자

    CharacterScene();

    //소멸자

    ~CharacterScene();

 

    // there's no 'id' in cpp, so we recommend returning the class instance pointer

    static cocos2d::Scene* createScene();

 

    // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone

    virtual bool init();

 

    // implement the "static create()" method manually

    CREATE_FUNC(CharacterScene);

 

    Sprite *_characterBg;

 

    void onClickMenu(Ref *object);

    void onClickHome(Ref *object);

    void onClickRandom(Ref *object);

    void onClickSave(Ref *object);

    void onClickGallery(Ref *object);

 

    void setImage(std::string tableName, int rowNo, int colorNo);

 

    Sprite *_face;

    Sprite *_hair1;

    Sprite *_hair2;

    Sprite *_eye;

    Sprite *_mouth;

    Sprite *_etc;

    Sprite *_bgStyle;

 

    //포지션에 따라 말풍선의 화살표의 위치를 변경한다.

    void setBalloon(int position);

    Sprite *_arrow;

    Sprite *_balloon;

};

 

----------CharacterScene.cpp----------

 

…생략…

 

CharacterScene::CharacterScene(){

    //객체를 초기화

    _face = NULL;

    _hair1 = NULL;

    _hair2 = NULL;

    _eye = NULL;

    _mouth = NULL;

    _etc = NULL;

    _bgStyle = NULL;

    _balloon = NULL;

    _arrow = NULL;

}

 

CharacterScene::~CharacterScene(){

 

}

 

// on "init" you need to initialize your instance

bool CharacterScene::init()

{

    //////////////////////////////

    // 1. super init first

    if (!Layer::init())

    {

        return false;

    }

 

    //code here

 

    //UserDefault를 가져옵니다.

    auto UserDefault = UserDefault::getInstance();

    //UserDefault에서 isFirst의 값을 가져옵니다.

    bool isFirst = UserDefault->getBoolForKey("isFirst", true);

    if (isFirst || DB_INIT){

        DatabaseManager::getInstance()->createDB();

        DatabaseManager::getInstance()->insertDB();

 

        //isFirst의 값을 변경합니다.

        UserDefault->setBoolForKey("isFirst", false);

        //UserDefault의 값을 변경하였으면 flush()를 호출해야 적용됩니다.

        UserDefault->flush();

    }

 

    /*****Device의 크기를 가져옵니다.*****/

    //Director를 가져옵니다.

    auto director = Director::getInstance();

    //OpenGLView를 가져옵니다.

    auto glView = director->getOpenGLView();

    //OpenGLView에서 DesignResolutionSize를 가져옵니다.

    auto winSize = glView->getDesignResolutionSize();

    /*****Device의 크기를 가져옵니다.*****/

 

    //배경 추가

    auto back = Sprite::create("bg_main.png");

    back->setPosition(Point(winSize.width / 2, winSize.height / 2));

    this->addChild(back);

 

    //캐릭터 박스 추가

    _characterBg = Sprite::create("bg_1.png");

    //Node의 기준을 상단중앙으로 변경함. setAnchorPoint의 값은 0~1. 1이 100%입니다.

    _characterBg->setAnchorPoint(Point(0.5, 1));

    //AnchorPoint를 상단의 중앙으로 변경하여 상단에서 15px만큼 아래로 내렸다.

    _characterBg->setPosition(Point(winSize.width / 2, winSize.height - 15));

    //back에 자식노드로 추가함

    back->addChild(_characterBg);

 

    //캐릭터 UI 선택 버튼 추가

    auto menu1Face = MenuItemImage::create("btn_face.png", "btn_face_on.png", CC_CALLBACK_1(CharacterScene::onClickMenu, this));

    menu1Face->setPosition(Point(25, 125));

 

    auto menu1Hair1 = MenuItemImage::create("btn_hair1.png", "btn_hair1_on.png", CC_CALLBACK_1(CharacterScene::onClickMenu, this));

    menu1Hair1->setPosition(Point(70, 125));

 

    auto menu1Hair2 = MenuItemImage::create("btn_hair2.png", "btn_hair2_on.png", CC_CALLBACK_1(CharacterScene::onClickMenu, this));

    menu1Hair2->setPosition(Point(115, 125));

 

    auto menu1Eye = MenuItemImage::create("btn_eye.png", "btn_eye_on.png", CC_CALLBACK_1(CharacterScene::onClickMenu, this));

    menu1Eye->setPosition(Point(160, 125));

 

    auto menu1Mouth = MenuItemImage::create("btn_mouth.png", "btn_mouth_on.png", CC_CALLBACK_1(CharacterScene::onClickMenu, this));

    menu1Mouth->setPosition(Point(205, 125));

 

    auto menu1Etc = MenuItemImage::create("btn_etc.png", "btn_etc_on.png", CC_CALLBACK_1(CharacterScene::onClickMenu, this));

    menu1Etc->setPosition(Point(250, 125));

 

    auto menu1Bg = MenuItemImage::create("btn_bg.png", "btn_bg_on.png", CC_CALLBACK_1(CharacterScene::onClickMenu, this));

    menu1Bg->setPosition(Point(295, 125));

 

    auto menu1 = Menu::create(menu1Face, menu1Hair1, menu1Hair2, menu1Eye, menu1Mouth, menu1Etc, menu1Bg, NULL);

    menu1->setPosition(Point::ZERO);

    this->addChild(menu1);

 

    //각 MenuItemImage에 태그 지정

    menu1Face->setTag(1);

    menu1Hair1->setTag(2);

    menu1Hair2->setTag(3);

    menu1Eye->setTag(4);

    menu1Mouth->setTag(5);

    menu1Etc->setTag(6);

    menu1Bg->setTag(7);

 

    //하단 메뉴 버튼의 좌표와 가로 세로크기 변수들

    float x;

    float y;

    float width;

    float height;

 

    //하단 메뉴 버튼 추가

    auto menu2Home = MenuItemImage::create("menu_home.png", "menu_home_on.png", CC_CALLBACK_1(CharacterScene::onClickHome, this));

    width = menu2Home->getContentSize().width;

    height = menu2Home->getContentSize().height;

    x = width / 2;

    y = height / 2;

    menu2Home->setPosition(Point(x, y));

 

    auto menu2Random = MenuItemImage::create("menu_random.png", "menu_random_on.png", CC_CALLBACK_1(CharacterScene::onClickRandom, this));

    x = menu2Home->getPositionX() + width;

    menu2Random->setPosition(Point(x, y));

 

    auto menu2Save = MenuItemImage::create("menu_save.png", "menu_save_on.png", CC_CALLBACK_1(CharacterScene::onClickSave, this));

    x = menu2Random->getPositionX() + width;

    menu2Save->setPosition(Point(x, y));

 

    auto menu2Gallery = MenuItemImage::create("menu_gallary.png", "menu_gallary_on.png", CC_CALLBACK_1(CharacterScene::onClickGallery, this));

    x = menu2Save->getPositionX() + width;

    menu2Gallery->setPosition(Point(x, y));

 

    auto menu2 = Menu::create(menu2Home, menu2Random, menu2Save, menu2Gallery, NULL);

    menu2->setPosition(Point::ZERO);

    this->addChild(menu2);

 

    setImage("TB_FACE", -1, -1);

    setImage("TB_HAIR1", -1, -1);

    setImage("TB_HAIR2", -1, -1);

    setImage("TB_EYE", -1, -1);

    setImage("TB_MOUTH", -1, -1);

    setImage("TB_ETC", -1, -1);

    setImage("TB_BG", -1, -1);

 

    //1번이 기본으로 선택되도록

    setBalloon(1);

 

    return true;

}

 

void CharacterScene::onClickMenu(Ref *object){

    log("onClickMenu");

    //sender의 객체를 Node로 캐스팅하여 태그를 가져온다.

    setBalloon(((Node *)object)->getTag());

}

 

…생략…

 

void CharacterScene::setBalloon(int position){

    if (_arrow == NULL){

        //Device의 크기를 가져옵니다.

        auto winSize = Director::getInstance()->getOpenGLView()->getDesignResolutionSize();

 

        _balloon = Sprite::create("box_list.png");

        _balloon->setPosition(Point(winSize.width / 2, 75));

        this->addChild(_balloon, 1);

 

        _arrow = Sprite::create("box_list2.png");

        //말풍선의 상단에 딱 붙이기 위해 화살표의 하단 가운데를 기준으로 설정해주었다.

        _arrow->setAnchorPoint(Point(0.5, 0));

        _balloon->addChild(_arrow);

    }

 

    Point arrowPoint;

    switch (position)

    {

    case 1:

        arrowPoint = Point(22, _balloon->getContentSize().height);

        break;

    case 2:

        arrowPoint = Point(68, _balloon->getContentSize().height);

        break;

    case 3:

        arrowPoint = Point(113, _balloon->getContentSize().height);

        break;

    case 4:

        arrowPoint = Point(158, _balloon->getContentSize().height);

        break;

    case 5:

        arrowPoint = Point(203, _balloon->getContentSize().height);

        break;

    case 6:

        arrowPoint = Point(248, _balloon->getContentSize().height);

        break;

    case 7:

        arrowPoint = Point(293, _balloon->getContentSize().height);

        break;

    }

 

    _arrow->setPosition(arrowPoint);

}

 

setBalloon()메서드는 position이란 매개변수를 받아 _arrow의 위치를 제어했습니다.

이번에 새롭게 사용해본 테크닉은 MenuItem에 태그를 지정하여 콜백 메서드로 넘어온 자기자신의 노드의 태그를 가져와 position번호로 사용하였습니다.

콜백 메서드에는 자기 자신이 그대로 매개변수로 넘어가므로 해당 객체를 받아 제어가 가능합니다.

태그는 모든 Node에서 사용이 가능하므로 여러 부분에서 응용이 가능합니다.

 

Figure 6‑33 클래스의 구조

MenuItem의 클레스를 확인해보면 MenuItem의 상위클레스가 Node라는 것을 알 수 있습니다.

따라서 Node로 클래스 캐스팅하여 사용이 가능한 것입니다.   

 

디버거를 실행해 제대로 동작하는지 확인해보도록 합니다.

  

Figure 6‑34 화살표의 위치 확인

버튼 선택에 따른 말풍선의 화살표의 위치가 변하는 것을 확인할 수 있습니다.

 

6.1.7 버튼 선택에 따른 서브메뉴 구성(ScrollView)

이번엔 버튼 선택에 따른 서브메뉴를 스크롤뷰를 사용하여 구현하겠습니다.

----------CharacterScene.h----------

#include "cocos2d.h"

#include "cocos-ext.h"

 

USING_NS_CC;

USING_NS_CC_EXT;

 

class CharacterScene : public cocos2d::Layer

{

public:

 

    //생성자

    CharacterScene();

    //소멸자

    ~CharacterScene();

 

    // there's no 'id' in cpp, so we recommend returning the class instance pointer

    static cocos2d::Scene* createScene();

 

    // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone

    virtual bool init();

 

    // implement the "static create()" method manually

    CREATE_FUNC(CharacterScene);

 

    Sprite *_characterBg;

    void onClickMenu(Ref *object);

    void onClickHome(Ref *object);

    void onClickRandom(Ref *object);

    void onClickSave(Ref *object);

    void onClickGallery(Ref *object);

 

    void setImage(std::string tableName, int rowNo, int colorNo);

 

    Sprite *_face;

    Sprite *_hair1;

    Sprite *_hair2;

    Sprite *_eye;

    Sprite *_mouth;

    Sprite *_etc;

    Sprite *_bgStyle;

 

    //포지션에 따라 말풍선의 화살표의 위치를 변경한다.

    void setBalloon(int position);

    Sprite *_arrow;

    Sprite *_balloon;

 

    ScrollView *_scrollView;

};

 

----------CharacterScene.cpp----------

 

…생략…

 

CharacterScene::CharacterScene(){

    //객체를 초기화

    _face = NULL;

    _hair1 = NULL;

    _hair2 = NULL;

    _eye = NULL;

    _mouth = NULL;

    _etc = NULL;

    _bgStyle = NULL;

    _balloon = NULL;

    _arrow = NULL;

    _scrollView = NULL;

}

 

…생략…

 

void CharacterScene::setBalloon(int position){

    if (_arrow == NULL){

        //Device의 크기를 가져옵니다.

        auto winSize = Director::getInstance()->getOpenGLView()->getDesignResolutionSize();

 

        _balloon = Sprite::create("box_list.png");

        _balloon->setPosition(Point(winSize.width / 2, 75));

        this->addChild(_balloon, 1);

 

        _arrow = Sprite::create("box_list2.png");

        //말풍선의 상단에 딱 붙이기 위해 화살표의 하단 가운데를 기준으로 설정해주었다.

        _arrow->setAnchorPoint(Point(0.5, 0));

        _balloon->addChild(_arrow);

    }

 

    Point arrowPoint;

    switch (position)

    {

    case 1:

        arrowPoint = Point(22, _balloon->getContentSize().height);

        break;

    case 2:

        arrowPoint = Point(68, _balloon->getContentSize().height);

        break;

    case 3:

        arrowPoint = Point(113, _balloon->getContentSize().height);

        break;

    case 4:

        arrowPoint = Point(158, _balloon->getContentSize().height);

        break;

    case 5:

        arrowPoint = Point(203, _balloon->getContentSize().height);

        break;

    case 6:

        arrowPoint = Point(248, _balloon->getContentSize().height);

        break;

    case 7:

        arrowPoint = Point(293, _balloon->getContentSize().height);

        break;

    }

 

    _arrow->setPosition(arrowPoint);

 

    if (_scrollView != NULL)

        _scrollView->removeFromParentAndCleanup(true);

 

    //LayerColor는 Layer와 동일하나 색상을 지정할 수 있습니다.

    auto layer = LayerColor::create(Color4B(0, 0, 255, 255), 500, _balloon->getContentSize().height);

 

    //첫번째 매개변수는 보여질 크기, 두번째 매개변수는 container입니다.

    _scrollView = ScrollView::create(_balloon->getContentSize(), layer);

 

    //ScrollView::Direction::HORIZONTAL : 가로 스크롤, ScrollView::Direction::VERTICAL : 세로 스크롤, ScrollView::Direction::BOTH : 둘다 스크롤

    _scrollView->setDirection(ScrollView::Direction::HORIZONTAL);

 

    _balloon->addChild(_scrollView);

}

 

스크롤뷰는 Cocos2d-x에서 Extension에 추가되어있습니다. 따라서 #include "cocos-ext.h"를 추가하여야 사용이 가능합니다. 네임스페이스를 사용하기위해 USING_NS_CC_EXT도 추가해줍니다.

스크롤뷰는 좌우로 화면의 이동이 가능한 클레스입니다. 주로 화면을 넘어가는 크기를 갖는 UI를 구성할때 사용합니다. 스크롤하여 보이지않던 내용을 가져와 화면에 보여줄 수 있습니다.

 

비주얼 스튜디오에서 Extension을 사용하기위해 libExtensions을 추가하겠습니다.

Figure 6‑35 Extensions 추가1

minigame 프로젝트에서 오른쪽 버튼을 선택한뒤 속성을 선택합니다.

 

Figure 6‑36 Extensions 추가2

속성 페이지에서 구성 속성 – C/C++ - 일반을 선택합니다.

 

Figure 6‑37 Extensions 추가3

Figure 6‑38 Extensions 추가4

 

하단의 빈곳을 더블클릭하여 $(EngineRoot)와 $(EngineRoot)extensions\GUI를 추가하고 OK를 선택합니다.

이경로를 잡아주어야 Include 된 파일들의 위치를 참조하여 사용할 수 있습니다.

 

CharacterScene에 스크롤뷰를 추가했고 Extension도 추가하였으니 디버거를 실행해보도록 합니다.

 

   

Figure 6‑39 실행화면

정상적으로 스크롤뷰가 추가된 것을 볼 수 있습니다. 하단의 말풍선 부분을 보면 LayerColor 생성할때 스크롤뷰를 눈으로 확인하기 위해 파란색으로 생성한 것을 알 수 있습니다. 스크롤뷰는 좌우로 스크롤이 가능합니다.

 

이번엔 스크롤뷰에 sub메뉴를 추가해보도록 하겠습니다.

 

먼저 sub메뉴를 추가할 수 있는 메서드를 헤더파일에 선언합니다.

----------CharacterScene.h----------

#include "cocos2d.h"

#include "cocos-ext.h"

 

USING_NS_CC;

USING_NS_CC_EXT;

 

class CharacterScene : public cocos2d::Layer

{

public:

    //생성자

    CharacterScene();

    //소멸자

    ~CharacterScene();

 

    // there's no 'id' in cpp, so we recommend returning the class instance pointer

    static cocos2d::Scene* createScene();

 

    // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone

    virtual bool init();

 

    // implement the "static create()" method manually

    CREATE_FUNC(CharacterScene);

 

    Sprite *_characterBg;

 

    void onClickMenu(Ref *object);

    void onClickHome(Ref *object);

    void onClickRandom(Ref *object);

    void onClickSave(Ref *object);

    void onClickGallery(Ref *object);

 

    void setImage(std::string tableName, int rowNo, int colorNo);

 

    Sprite *_face;

    Sprite *_hair1;

    Sprite *_hair2;

    Sprite *_eye;

    Sprite *_mouth;

    Sprite *_etc;

    Sprite *_bgStyle;

 

    //포지션에 따라 말풍선의 화살표의 위치를 변경한다.

    void setBalloon(int position);

    Sprite *_arrow;

    Sprite *_balloon;

 

    ScrollView *_scrollView;

 

    void setSubMenuItem(int position);

};

 

----------CharacterScene.cpp----------

 

…생략…

 

 

void CharacterScene::setBalloon(int position){

 

…생략…

 

    if (_scrollView != NULL)

        _scrollView->removeFromParentAndCleanup(true);

 

    //LayerColor는 Layer와 동일하나 색상을 지정할 수 있습니다.

    auto layer = LayerColor::create(Color4B(0, 0, 255, 255), 500, _balloon->getContentSize().height);

 

    //첫번째 매개변수는 보여질 크기, 두번째 매개변수는 container입니다.

    _scrollView = ScrollView::create(_balloon->getContentSize(), layer);

 

    //ScrollView::Direction::HORIZONTAL : 가로 스크롤, ScrollView::Direction::VERTICAL : 세로 스크롤, ScrollView::Direction::BOTH : 둘다 스크롤

    _scrollView->setDirection(ScrollView::Direction::HORIZONTAL);

 

    _balloon->addChild(_scrollView);

 

    setSubMenuItem(position);

}

 

void CharacterScene::setSubMenuItem(int position){

    std::string table;

 

    switch (position)

    {

    case 1:

        table = "TB_FACE";

        break;

    case 2:

        table = "TB_HAIR1";

        break;

    case 3:

        table = "TB_HAIR2";

        break;

    case 4:

        table = "TB_EYE";

        break;

    case 5:

        table = "TB_MOUTH";

        break;

    case 6:

        table = "TB_ETC";

        break;

    case 7:

        table = "TB_BG";

        break;

    }

 

    //이전에 데이터 베이스 구축당시 No를 0으로 넣으면 해당 테이블 전체를 가져오도록 구현

    auto headList = DatabaseManager::getInstance()->selectDB(table, 0);

 

    //메뉴아이템을 동적으로 생성하기위해 Array를 사용하였다.

    Vector<MenuItem*> itemArray;

 

    //for구문에 headList.size()를 조건문에 넣으면 pop_front를 하면서 size()가 줄어들어 원하는 값보다 적게 반복문을 실행한다. 따라서 미리 크기를 가져와 변수로 사용하였다.

    int listCnt = headList.size();

 

    float iconWidth = 0;

    for (int i = 0; i < listCnt; i++){

        //첫번째 구조체 가져오기

        auto head = headList.front();

 

        char icon[50];

 

        //아이콘은 i_파일명으로 이름을 정해놓았습니다. 이런식으로 사용하면 따로 아이콘 파일명을 가질 필요없이 사용이 가능합니다.

        sprintf(icon, "i_%s", head->image);

 

        auto item_img = Sprite::create(icon);

 

        if (iconWidth <= 0){

            //icon width 크기

            iconWidth = item_img->getContentSize().width;

        }

 

        auto item = MenuItemSprite::create(item_img, NULL);

        item->setAnchorPoint(Point(0, 0.5));

        //아이템의 가로크기 x i 만큼 + 5(padding) x i 만큼에 위치시켰다.

        item->setPosition(Point(i * item_img->getContentSize().width + 5 * i, _scrollView->getContentSize().height / 2));

 

        itemArray.pushBack(item);

 

        headList.pop_front();

    }

 

    auto menu = Menu::createWithArray(itemArray);

    menu->setPosition(Point::ZERO);

    _scrollView->getContainer()->addChild(menu);

}

 

setSubMenuItem() 메서드를 정의하였습니다.

setSubMenuItem()은 setBalloon()메서드에서 position을 넘겨받아 어떤 버튼이 눌렸는지 체크하였습니다.

setSubMenuItem() 메서드에서 selectDB()메서드에 가져올 테이블명과 No값을 넘겨 headList를 받아왔습니다. No가 0이 넘어오게 되면 해당 테이블의 모든 값을 가져오도록 구현해놓았었습니다.

받아온 구조체에서 image를 가져와 image에 i_라는 prefix(접두사)를 사용해 아이콘의 파일명을 가져왔습니다.

가져온 icon의 Sprite를 MenuItemSprite에 담아 Array에 추가하여 이 Array를 Menu에 추가하였습니다.

 

디버거를 실행해보도록 합니다.

    

Figure 6‑40 실행화면

 

서브메뉴의 아이콘들이 추가된 것을 볼 수 있습니다.

 

메뉴가 추가되면서 아이콘있는 부분을 눌러 스크롤하려 하면 스크롤이 되지않는 문제를 확인할 수 있습니다.

이유는 터치 우선순위가 스크롤보다 메뉴가 높아 터치를 먼저 받아 스크롤뷰에 터치를 넘겨주지 않아서 입니다.

 

Menu가 터치를 스크롤뷰로 넘겨주도록 수정하겠습니다.

----------CharacterScene.cpp----------

 

…생략…

 

 

void CharacterScene::setSubMenuItem(int position){

 

…생략…

 

    auto menu = Menu::createWithArray(itemArray);

    menu->setPosition(Point::ZERO);

    _scrollView->getContainer()->setLocalZOrder(-1);

    _scrollView->getContainer()->addChild(menu);

}

 

_scrollView의 Container를 가져와서 LocalZOrder를 -1로 수정해주었습니다.

 

디버거를 실행하고 스크롤뷰를 확인해봅니다.

Figure 6‑41 실행화면

 

버튼을 누른상태로 스크롤하여도 스크롤이 되는 것을 확인 할 수 있습니다.

 

이번엔 스크롤뷰의 컨테이너의 크기를 동적으로 수정할 수 있도록 해보겠습니다.

 

CharacterScene.cpp 파일의 setSubMenuItem()을 아래와 같이 수정합니다.

----------CharacterScene.cpp----------

 

…생략…

 

void CharacterScene::setSubMenuItem(int position){

 

…생략…

 

    auto menu = Menu::createWithArray(itemArray);

    menu->setPosition(Point::ZERO);

    _scrollView->getContainer()->setLocalZOrder(-1);

    auto ContainerSize = Size(listCnt * iconWidth + 5 * (listCnt - 1), _scrollView->getContainer()->getContentSize().height);

    _scrollView->getContainer()->setContentSize(ContainerSize);

    _scrollView->getContainer()->addChild(menu);

}

 

컨테이너의 크기를 메뉴의 아이템 개수와 여백을 이용하여 동적으로 Size를 생성하였고 _scrollView의 컨테이너를 가져와 크기를 재정의 해주었습니다.

 

디버거를 실행하여 컨테이너의 크기를 확인해보도록 합니다.

 

Figure 6‑42 실행화면

 

아이템 개수에 따라 파란색의 컨테이너 크기가 변경되는 것을 확인할 수 있습니다.

 

컨테이너 크기확인을 완료 하였으니 컨테이너의 색상을 없애도록 하겠습니다.

----------CharacterScene.cpp----------

 

…생략…

 

void CharacterScene::setBalloon(int position){

 

…생략…

 

    //LayerColor는 Layer와 동일하나 색상을 지정할 수 있습니다.

    auto layer = LayerColor::create(Color4B(0, 0, 0, 0), 500, _balloon->getContentSize().height);

 

    //첫번째 매개변수는 보여질 크기, 두번째 매개변수는 container입니다.

    _scrollView = ScrollView::create(_balloon->getContentSize(), layer);

 

    //ScrollView::Direction::HORIZONTAL : 가로 스크롤, ScrollView::Direction::VERTICAL : 세로 스크롤, ScrollView::Direction::BOTH : 둘다 스크롤

    _scrollView->setDirection(ScrollView::Direction::HORIZONTAL);

 

    _balloon->addChild(_scrollView);

 

    setSubMenuItem(position);

}

 

LayerColor를 생성하는 부분에서 색상을 지정하는 Color4B를 Color4B(0, 0, 0, 0)으로 수정하여 투명도를 0으로 수정해 색상을 없애도록 합니다.

 

디버거를 실행해 파란색의 컨테이너의 색상이 없어졌는지 확인합니다.

Figure 6‑43 실행화면


Prev | Next