2015年

2月

20日

Cocos2d-x Ver 3.x TableView 画面遷移と画像表示 Plist対応


Plistを利用してTableViewに表示さし該当の画像をクリックしたら画面遷移して画像を表示する方法を示しています。
Plistの設置場所は、Resourcesの中に置いています。置き場所については限定されるわけではありません。他の場所に置き動作検証済みです。

画像ファイルについても、このように同じ場所に設置しています。


Plistについては、キーなし配列型Plistを使用しています。
キー型を使用したかったのですが、iOSでは動作しましたがAndroidでの検証で動作せず落ちましたのでやむなくキーなし配列型Plistを使用して今回は、活用しています。

キーなし配列型Plistを使用しているため、あたかもキー付き配列型のような動作をするように工夫をしています。ソースはきたなくこれが正しいかはわかりませんが問題なく動作しております。


キー付き配列型Plistの問題


キー付き配列型Plistのソース記述の場合は下記の通りですが、iOSでは問題なく動作していましたがAndroid実機で検証してみたら2行目の「ValueMap vec_map_0 = vec.at(idx).asValueMap();」で落ちてしまうことが判明しました。色々と記述を変えてみましたがiOS側で落ちたりしましたのでキー付き配列型Plist読み込みを諦めキーなし配列型Plistを採用し読み込み記述を工夫しました。


Android実機で落ちたキー付き配列型Plistのソース記述例

// Plist ValueVector & ValueMap
ValueVector vec = FileUtils::getInstance()->getValueVectorFromFile("Data.plist");
ValueMap vec_map_0 = vec.at(idx).asValueMap();

std::string vec_0 = vec_map_0.at("number").asString();           // 連番
std::string vec_1 = vec_map_0.at("ItemName").asString();      // 花火の種類
std::string vec_2 = vec_map_0.at("images").asString();           // 花火の写真
std::string vec_3 = vec_map_0.at("ImageName").asString();   // 花火の小写真

    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/

// 花火小画像
Sprite* imge_1 = Sprite::create(vec_3);
imge_1->setAnchorPoint(Point(0, 0));
imge_1->setPosition(Point(10, 0));
imge_1->setScaleX(1.5); // 1.5倍拡大
imge_1->setScaleY(1.5); // 1.5倍拡大
cell->addChild(imge_1);

 // テキスト部分
auto *label_2 = LabelTTF::create(vec_1.c_str(), "Arial", 52);
label_2->setAnchorPoint(Point(0, 0));
label_2->setPosition(Point(140, 70)); // セル幅のセンター
label_2->setColor(Color3B::GREEN);
cell->addChild(label_2);



Cocos2dx 3.x C++言語
AppDelegate.hを次のように変更してみてください。
解像度の設定はAppDelegate.h内にてこの一行にて記述しています。

Android実機2台での動作確認
docomo SAMSUNG GALAXY SⅢ SC-06D  Android Ver 4.1.2
Nexus7 Android Ver 4.4.4

// デザイン解像度の設定(縦) iPhone 5s SHOW_ALL
glview->setDesignResolutionSize(640, 1136, ResolutionPolicy::SHOW_ALL);


#ifndef  _APP_DELEGATE_H_

#define  _APP_DELEGATE_H_


#include "cocos2d.h"


/**

@brief    The cocos2d Application.


The reason for implement as private inheritance is to hide some interface call by Director.

*/

class  AppDelegate : private cocos2d::Application

{

public:

    AppDelegate();

    virtual ~AppDelegate();


    virtual void initGLContextAttrs();


    /**

    @brief    Implement Director and Scene init code here.

    @return true    Initialize success, app continue.

    @return false   Initialize failed, app terminate.

    */

    virtual bool applicationDidFinishLaunching();


    /**

    @brief  The function be called when the application enter background

    @param  the pointer of the application

    */

    virtual void applicationDidEnterBackground();


    /**

    @brief  The function be called when the application enter foreground

    @param  the pointer of the application

    */

    virtual void applicationWillEnterForeground();

};


#endif // _APP_DELEGATE_H_


AppDelegate.cppを次のように変更してみてください。

#include "AppDelegate.h"

#include "TopTableView.h"


USING_NS_CC;


AppDelegate::AppDelegate() {


}


AppDelegate::~AppDelegate() 

{

}


//if you want a different context,just modify the value of glContextAttrs

//it will takes effect on all platforms

void AppDelegate::initGLContextAttrs()

{

    //set OpenGL context attributions,now can only set six attributions:

    //red,green,blue,alpha,depth,stencil

    GLContextAttrs glContextAttrs = {8, 8, 8, 8, 24, 8};


    GLView::setGLContextAttrs(glContextAttrs);

}


bool AppDelegate::applicationDidFinishLaunching() {

    // initialize director

    auto director = Director::getInstance();

    auto glview = director->getOpenGLView();

    if(!glview) {

        glview = GLViewImpl::create("My Game");

        director->setOpenGLView(glview);

    }

    

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

    

    // デザイン解像度の設定(縦) iPhone 5s SHOW_ALL

    glview->setDesignResolutionSize(640, 1136, ResolutionPolicy::SHOW_ALL);

    

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


    // turn on display FPS

    //director->setDisplayStats(true);


    // set FPS. the default value is 1.0/60 if you don't call this

    director->setAnimationInterval(1.0 / 60);


    // create a scene. it's an autorelease object

    auto scene = TopTableView::createScene();


    // run

    director->runWithScene(scene);


    return true;

}


// This function will be called when the app is inactive. When comes a phone call,it's be invoked too

void AppDelegate::applicationDidEnterBackground() {

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


    // if you use SimpleAudioEngine, it must be pause

    // SimpleAudioEngine::getInstance()->pauseBackgroundMusic();

}


// this function will be called when the app is active again

void AppDelegate::applicationWillEnterForeground() {

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


    // if you use SimpleAudioEngine, it must resume here

    // SimpleAudioEngine::getInstance()->resumeBackgroundMusic();

}





TableViewを作成していきます。

TopTableView.hを次のように変更してみてください。

TopTableView.hを次のように変更してみてください。

 

#ifndef __TableView02__TopTableView__

#define __TableView02__TopTableView__


#include <iostream>

#include "cocos2d.h"

#include <extensions/cocos-ext.h>


USING_NS_CC;

using namespace extension;


class TopTableView : public Layer,

public TableViewDataSource,

public TableViewDelegate

{

    Size window_size;

public:

    static cocos2d::Scene* createScene();

    virtual bool init();

    

    //TableViewDataSourceの抽象メソッド

    virtual Size cellSizeForTable(TableView* table);

    virtual TableViewCell* tableCellAtIndex(TableView* table,ssize_t idx);

    virtual ssize_t numberOfCellsInTableView(TableView* table);

    

    //TableViewDelegateの抽象メソッド

    virtual void tableCellTouched(TableView* table,TableViewCell* cell);

    

    //TableViewDelegateが継承しているScrollViewの抽象メソッド

    virtual void scrollViewDidScroll(ScrollView* view){};

    virtual void scrollViewDidZoom(ScrollView* view){};

    

    CREATE_FUNC(TopTableView);


    // バッククリックキー

    void onKeyReleased(cocos2d::EventKeyboard::KeyCode keyCode, cocos2d::Event *event);

    

};


#endif /* defined(__TableView02__TopTableView__) */


TopTableView.cppを次のように変更してみてください。

#include "TopTableView.h"

#include "SecondScene.h"

//音をならすためにinclude

#include "SimpleAudioEngine.h"


/// 行数格納用のキー

const char* ROW_KEY = "row";


Scene* TopTableView::createScene()

{

    auto scene = Scene::create();

    auto layer = TopTableView::create();

    // scenelayerを読み込み表示する

    scene->addChild(layer);

    

    return scene;

}


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

bool TopTableView::init()

{

    // 初期化

    if ( !Layer::init() ) return false;

    

    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/

    // バックキー処理 イベントリスナーを追加

    auto keyboardListener = cocos2d::EventListenerKeyboard::create();

    keyboardListener->onKeyReleased = CC_CALLBACK_2(TopTableView::onKeyReleased, this);

    _eventDispatcher->addEventListenerWithSceneGraphPriority(keyboardListener, this);

    

    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/

    

    // 画面サイズサイズを取得

    window_size = Director::getInstance()->getWinSize();

    

    // バックグランドカラー

    auto background = LayerColor::create(Color4B::BLACK,

                                         window_size.width,

                                         window_size.height);

    

    // バックグランドカラー 第2引数は表示順

    this->addChild(background, 0);

    

    // テーブル一覧ラベルを生成

    auto label1 = Label::createWithSystemFont("花火一覧", "Arial", 60);

    

    label1->setColor(Color3B::GREEN);

    

    // ラベルの設置

    label1->setPosition(Vec2(window_size.width / 2 ,window_size.height - 70));

    

    // ラベルタイトルを呼び込み追加

    this->addChild(label1,1);

    

    

    // テーブルのヘッダー空間

    TableView* tableView = TableView::create(this,Size(window_size.width,window_size.height*9/10));

    // テーブル全体表示

    //TableView* tableView = TableView::create(this, window_size);

    

    // 展開方向

    tableView->setDirection(TableView::Direction::VERTICAL);

    // 表示順序上からしたへ

    tableView->setVerticalFillOrder(TableView::VerticalFillOrder::TOP_DOWN);

    

    // 追加

    tableView->setDelegate(this);

    addChild(tableView);

    // tableViewに呼び込む

    tableView->reloadData();

    

    return true;

}


// セルの大きさを設定する

Size TopTableView::cellSizeForTable(TableView *table){

    

    return Size(window_size.width, 215);

}


// 1セルに表示させるValueをセット

TableViewCell* TopTableView::tableCellAtIndex(TableView *table, ssize_t idx){

    

    // 行番号

    std::string id = StringUtils::format("%zd", idx);

    

    // セル

    TableViewCell *cell = table->dequeueCell();

    

    cell = new TableViewCell();

    // autoreleaseを呼び出す

    cell->autorelease();

    

    // セルの背景色

    auto background_color = Color3B::GRAY;

    

    // Background

    Sprite* bg = Sprite::create();

    bg->setAnchorPoint(Point(0, 0));

    bg->setTextureRect(Rect(0, 0, window_size.width, 215));

    bg->setColor(background_color);

    bg->setTag(100);

    // Backgroundを呼び出し表示

    cell->addChild(bg);

    

    // ボーダーライン

    Sprite* line = Sprite::create();

    line->setAnchorPoint(Point(0, 0));

    line->setTextureRect(Rect(0, 0, window_size.width, 1));

    line->setColor(Color3B::WHITE);

    cell->addChild(line);

    

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

    

    // Plist ValueVector

    ValueVector vec = FileUtils::getInstance()->getValueVectorFromFile("data.plist");

    

    // セル行数変数

    long idx0 = 0;

    

    // Cellidxidx01に保存

    log("idx:%ld", idx);

    

    // 最初のCell0行目

    if (idx == 0) {

        idx0 = idx;     // 最初のCell1行目

    } else {

        idx0 = idx * 4; // 次のCell2行目 Plist行数 x 4

    }

    

    // Plist 1行目は、idx0

    long idx1 = idx0 + 1; // Plist 2行目

    long idx2 = idx1 + 1; // Plist 3行目 花火小画像

    long idx3 = idx2 + 1; // Plist 4行目 花火大画像

    

    // 花火の種類ラベル表示

    std::string vec_1 = vec.at(idx1).asString();

    auto *label_2 = LabelTTF::create(vec_1.c_str(), "Arial", 52);

    label_2->setAnchorPoint(Point(0, 0));

    label_2->setPosition(Point(140, 70)); // セル幅のセンター

    label_2->setColor(Color3B::GREEN);

    cell->addChild(label_2);

    

    // 花火小画像

    std::string vec_3 = vec.at(idx3).asString();

    Sprite* imge_1 = Sprite::create(vec_3);

    imge_1->setAnchorPoint(Point(0, 0));

    imge_1->setPosition(Point(10, 0));

    imge_1->setScaleX(1.5); // 1.5倍拡大

    imge_1->setScaleY(1.5); // 1.5倍拡大

    cell->addChild(imge_1);

    

    return cell;

}


// セル数

ssize_t TopTableView::numberOfCellsInTableView(TableView *table){

    return 19;

}


// セルがタッチされた時のcallback

void TopTableView::tableCellTouched(TableView* table, TableViewCell* cell){

    

    log("%ziのセルがタッチされました", cell->getIdx());

    // cell 行番号

    float row = cell->getIdx();

    

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

    // UserDefault 保存

    // 行番号保存

    UserDefault::getInstance()->setIntegerForKey(ROW_KEY, row);

    

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

    

    // 効果音を鳴らす

    CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("onepoint26.mp3");

    

    

    // 遷移先の画面のインスタンス

    Scene *pScene = SecondScene::createScene();

    

    // 0.5秒かけてフェードアウトしながら次の画面に遷移します

    //    引数1:フィードの時間

    //    引数2:移動先のシーン

    //    引数3:フィードの色(オプション)

    TransitionFade* transition = TransitionFade::create(0.5f, pScene);

    

    // 遷移実行  遷移時のアニメーション http://study-cocos2d-x.info/scenelayer/55/

    // 直前のsceneはもう使わないから捨ててしまう方法。基本はこれになります。

    Director::getInstance()->replaceScene(transition);

}


// バックキー処理 onKeyReleased()でバックキーのイベントを取得

void TopTableView::onKeyReleased(cocos2d::EventKeyboard::KeyCode keyCode, cocos2d::Event * event)

{

    if (keyCode == EventKeyboard::KeyCode::KEY_ESCAPE)

    {

        Director::getInstance()->end(); // アプリを終了させる

    }

}





画像表示作成していきます。

SecondScene.hを次のように変更してみてください。


SecondScene.hを次のように変更してみてください。

#ifndef __TableView02__SecondScene__

#define __TableView02__SecondScene__


#include "cocos2d.h"


class SecondScene : public cocos2d::Layer

{

public:

    

    //初期化のメソッド

    virtual bool init();

    

    static cocos2d::Scene* createScene();

    

    // スタートボタン押下時の処理宣言 戻る Object → Ref に変更

    void pushBack(cocos2d::Ref *pSender);

    

    // create()を使えるようにしている。

    CREATE_FUNC(SecondScene);


    // バッククリックキー

    void onKeyReleased(cocos2d::EventKeyboard::KeyCode keyCode, cocos2d::Event *event);

    

};


#endif /* defined(__TableView02__SecondScene__) */


SecondScene.cppを次のように変更してみてください。

#include "SecondScene.h"

#include "TopTableView.h"

//音をならすためにinclude

#include "SimpleAudioEngine.h"


// 名前空間 #define USING_NS_CC using namespace cocos2d

USING_NS_CC;


using namespace std; // String*


Scene* SecondScene::createScene()

{

    // 「シーン」は自動解放オブジェクトです

    auto scene = Scene::create();

    

    // 「レイアウト」は自動解放オブジェクトです

    auto layer = SecondScene::create();

    

    // シーンに子としてレイヤーを追加

    scene->addChild(layer);

    

    // シーンを返す

    return scene;

}


// INIT」初期化

bool SecondScene::init()

{

    if ( !Layer::init() )

    {

        return false;

    }

    

    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/

    // バックキー処理 イベントリスナーを追加

    auto keyboardListener = cocos2d::EventListenerKeyboard::create();

    keyboardListener->onKeyReleased = CC_CALLBACK_2(SecondScene::onKeyReleased, this);

    _eventDispatcher->addEventListenerWithSceneGraphPriority(keyboardListener, this);

    

    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/


    

    //画面の座標関係の詳しい説明はここ http://www.cocos2d-x.org/wiki/Coordinate_System

    //画面サイズを取得

    Size winSize = Director::getInstance()->getVisibleSize();

    Point origin = Director::getInstance()->getVisibleOrigin();

    

    // バックグランドカラー

    auto background = LayerColor::create(Color4B::BLUE,

                                         winSize.width,

                                         winSize.height);

    //バックグランドカラー追加 第2引数は表示順

    this->addChild(background, 0);

    

    

    // UserDefault 読込 LOG表示

    auto userRead = cocos2d::UserDefault::getInstance();

    log("row 行番号: %d", userRead->getIntegerForKey("row"));

    

    // int UserDefaultrowを呼び込む

    auto row = userRead->getIntegerForKey("row");

    

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

    

    // Plist ValueVector

    ValueVector vec = FileUtils::getInstance()->getValueVectorFromFile("data.plist");

    

    // row行数変数

    long idx0 = 0;

    

    // 最初の0行目を選択した時

    if (row == 0) {

        idx0 = row;     // 最初のCell1行目

    } else {

        idx0 = row * 4; // 次のCell2行目 Plist行数 x 4

    }


    // Plist 1行目は、idx0 = row 連番

    long idx1 = idx0 + 1; // Plist 2行目 花火の種類

    long idx2 = idx1 + 1; // Plist 3行目 花火の写真

    long idx3 = idx2 + 1; // Plist 4行目 花火の小写真

    

    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/

    

    // Plist 花火の写真画像CCSpriteクラスを初期化しています。

    std::string vec_3 = vec.at(idx2).asString();

    auto sprite1 = Sprite::create(vec_3);

    //位置を設定

    sprite1->setPosition(Vec2(winSize.width/2, winSize.height/2));

    //画面に追加をしています。

    this->addChild(sprite1);

    

    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/

    

    // Plist 花火の種類タイトルを設置

    std::string vec_1 = vec.at(idx1).asString();

    auto lbl_title = Label::createWithSystemFont(vec_1, "Arial", 40);

    lbl_title->setPosition(Point(origin.x + winSize.width/2,

                                 origin.y + winSize.height - 8

                                 -lbl_title->getContentSize().height));

    lbl_title->setColor(Color3B::GREEN);

    this->addChild(lbl_title,1);

    

    //戻るボタンを設置

    auto backButton = MenuItemImage::create(

                                            "Back.png"//表示

                                            "BackSelected.png"//タップ時の画像

                                            CC_CALLBACK_1(SecondScene::pushBack, this));

    

    backButton->setPosition(Point(winSize.width /2 - 260 ,winSize.height/2 + 520));

    

    //create menu, it's an autorelease object

    auto menu = Menu::create(backButton, NULL);

    

    menu->setPosition(Point::ZERO);

    

    this->addChild(menu, 1);

    

    return true;

}


// pushBackボタン

void SecondScene::pushBack(Ref *pSender)

{

    // 効果音を鳴らす

    CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("onepoint26.mp3");

    

    // 遷移先の画面のインスタンス

    Scene *pScene = TopTableView::createScene();

    

    // 0.5秒かけてフェードアウトしながら次の画面に遷移します

    //    引数1:フィードの時間

    //    引数2:移動先のシーン

    //    引数3:フィードの色(オプション)

    TransitionFade* transition = TransitionFade::create(0.5f, pScene);

    

    //遷移実行  遷移時のアニメーション http://study-cocos2d-x.info/scenelayer/55/

    Director::getInstance()->replaceScene(transition);

}


// バックキー処理 onKeyReleased()でバックキーのイベントを取得

void SecondScene::onKeyReleased(cocos2d::EventKeyboard::KeyCode keyCode, cocos2d::Event * event)

{

    if (keyCode == EventKeyboard::KeyCode::KEY_ESCAPE)

    {

        //Director::getInstance()->end(); // アプリを終了させる

        

        // 遷移先の画面のインスタンス

        Scene *pScene = TopTableView::createScene();

        

        // 0.5秒かけてフェードアウトしながら次の画面に遷移します

        //    引数1:フィードの時間

        //    引数2:移動先のシーン

        //    引数3:フィードの色(オプション)

        TransitionFade* transition = TransitionFade::create(0.5f, pScene);

        

        //遷移実行  遷移時のアニメーション http://study-cocos2d-x.info/scenelayer/55/

        // (replaceScene)直前のsceneはもう使わないから捨ててしまう方法

        Director::getInstance()->replaceScene(transition);

        

    }

}

 

GitHub TableView02

 

Androidのビルドに必要なAndroid.mkの編集
クラスを追加した場合には、Android.mkファイルの修正が必要です。

HelloWorld.cppの書き換えと追加クラス名を追加します。

これをしておかないと表示が変わらず真黒な画面が表示されますので注意してください。

 

Android.mkディレクトリーの場所

TableView02/proj.android/jni/Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

$(call import-add-path,$(LOCAL_PATH)/../../cocos2d)
$(call import-add-path,$(LOCAL_PATH)/../../cocos2d/external)
$(call import-add-path,$(LOCAL_PATH)/../../cocos2d/cocos)

LOCAL_MODULE := cocos2dcpp_shared

LOCAL_MODULE_FILENAME := libcocos2dcpp

LOCAL_SRC_FILES := hellocpp/main.cpp \
                   ../../Classes/AppDelegate.cpp \
                   ../../Classes/TopTableView.cpp \  <- ※HelloWorld.cppを書き換え 
                   ../../Classes/SecondScene.cpp   <- ※追加

LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes

LOCAL_STATIC_LIBRARIES := cocos2dx_static

include $(BUILD_SHARED_LIBRARY)

$(call import-module,.)

Android実機での動作確認

docomo SAMSUNG GALAXY SⅢ SC-06D  Android Ver 4.1.2

Nexus7 Android Ver 4.4.4

 

目 次