読者です 読者をやめる 読者になる 読者になる

きょこみのーと

元六本木でGo書いてました。今はVRでGo書いてます。

Cocos2d-xでGoogleスプレッドシートの表データをjsonで取得する

f:id:kyokomi:20140525181220p:plain

ぶっちゃけ今回は、あんまりCocos2d-xは関係ないかもです。

他の言語とかでも全然使えるかと。

CocoStudioDataEditorを使ってみたのですが、思った以上に使い辛い。。。

そして、そもそも何がしたいのか理解できず。

Excelデータを読み込んでJson出力するだけ!!

以外の用途が汲み取れなかった。。。

そんなの他のツールとか一杯あるでしょ?ということで、Googleスプレッドシート使って色々やってました。

今回の流れは以下になります。

参考

Googleスプレッドシートを作成

まず、表データ適当につくります。

f:id:kyokomi:20140525181232p:plain

公開します

「ファイル」 ー> 「共有」

f:id:kyokomi:20140525181240p:plain

変更を押す

f:id:kyokomi:20140525181247p:plain

自分の場合は、別に誰に見られても困らないのでとりあえずリンクを知っている全員のやつにします。

f:id:kyokomi:20140525181256p:plain

※公開範囲は各自内容を確認してください適切に選んでください

GASを編集

GASを開く

スプレッドシートの「ツール」ー>「スクリプト エディタ...」を選択する。

f:id:kyokomi:20140525181305p:plain

「空のプロジェクト」を選ぶ

f:id:kyokomi:20140525181314p:plain

myFunctionを消して、以下のgistのscriptをまるごと貼り付けます。

{book_id}のところは自分のスプレッドシートのIDを入れてください。

IDは、スプレッドシートのURLに表示されてるやつです。

f:id:kyokomi:20140525181322p:plain

保存するとプロジェクト名を入れろと言われます。適当でいいです。

f:id:kyokomi:20140525181332p:plain

Googleスプレッドシートにデータを定義して公開

「公開」 ー> 「ウェブアプリケーションとして導入...」を選択

f:id:kyokomi:20140525181339p:plain

バージョンの説明を適当に入力して、「保存」を押す。

ユーザーは自分にする。これを変えるとURL叩く人はGoogleアカウント認証にリダイレクトされます。 (自分がかわりに実行してあげるイメージです)

アプリ実行は、誰でもOKにして「導入」を押す。

f:id:kyokomi:20140525181347p:plain

このURLをメモっておく(Cocos2d-xから呼び出します)

f:id:kyokomi:20140525181354p:plain

スクリプト認証

関数に「doGet」を指定して、スクリプトを実行する。

f:id:kyokomi:20140525181403p:plain

承認されてない警告が出てくる。続行する。

f:id:kyokomi:20140525181412p:plain

いつものGoolgeの認証でるので、承認する。

f:id:kyokomi:20140525181423p:plain

これでさっきのURLをブラウザとかで叩くとjsonがもらえるあとはこれをCocos2d-xから呼び出すだけ。

Cocos2d-xでHttpRequestでjsonを取得する

ちなみにバージョンは、Cocos2d-x 3.1です。

dropbox/json11の組み込みと使い方は、以前の記事「C++11でjson扱うならdropbox/json11がよさそう」を参考にしてください。

まあhppcppgithubから持ってきてClassesディレクトリ下に入れるだけです。

// 〜省略〜

#include "network/HttpClient.h"
#include "json11.hpp"

using namespace cocos2d::network;

// 〜省略〜

// on "init" you need to initialize your instance
bool HelloWorld::init()
{
    //////////////////////////////
    // 1. super init first
    if ( !Layer::init() )
    {
        return false;
    }

    Size visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();

    /////////////////////////////
    // 2. add a menu item with "X" image, which is clicked to quit the program
    //    you may modify it.

    // add a "close" icon to exit the progress. it's an autorelease object
    auto closeItem = MenuItemImage::create(
                                           "CloseNormal.png",
                                           "CloseSelected.png",
                                           CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));

      closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/2 ,
                                origin.y + closeItem->getContentSize().height/2));

    // ★★★ ここから追加したMenuと押したときのHttpRequestの処理。コールバックでjsonをdump

    auto winSize = Director::getInstance()->getWinSize();

    // Get
    auto labelGet = Label::createWithSystemFont("Test Get", "Arial", 22);
    auto itemGet = MenuItemLabel::create(labelGet, [this](Ref *sender) {

        HttpRequest* request = new HttpRequest();
        // Google SpreadSheetの公開URL
        request->setUrl("https://script.google.com/macros/s/AKfycbyrMJ_T_N_D_25PniSQ60SbcJpz0Rmfb8XVaoIYW8CcTHjwj-U/exec");
        request->setRequestType(HttpRequest::Type::GET);
        request->setResponseCallback([this](HttpClient* client, HttpResponse* response) {
            if (!response) {
                return;
            }

            if (0 != std::strlen(response->getHttpRequest()->getTag())) {
                CCLOG("%s completed", response->getHttpRequest()->getTag());
            }

            long statusCode = response->getResponseCode();
            auto statusString = StringUtils::format("HTTP Status Code: %ld, tag = %s", statusCode, response->getHttpRequest()->getTag());
            CCLOG("response code: %ld", statusCode);

            if (!response->isSucceed()) {
                CCLOG("response failed");
                CCLOG("error buffer: %s", response->getErrorBuffer());
                return;
            }

            // dropbox/json11 dump data
            std::string responseString(response->getResponseData()->begin(), response->getResponseData()->end());
            auto jsonData = json11::Json(responseString);

            CCLOG("response = %s", jsonData.dump().c_str());
        });
        request->setTag("GET test1");
        HttpClient::getInstance()->send(request);
        request->release();
    });
    itemGet->setPosition(Vec2(Vec2(origin.x + visibleSize.width/2,
                                   origin.y + visibleSize.height/2)));

    // create menu, it's an autorelease object
    auto menu = Menu::create(closeItem, itemGet, NULL);
    menu->setPosition(Vec2::ZERO);
    this->addChild(menu, 1);

    return true;
}

実行してボタンをクリックするとjsonを取得します。

ログに履かれたのが以下になります。

f:id:kyokomi:20140525181445p:plain

上記のjsonを取得するURLはこちら

おわり

他にもいい方法あると思いますが、 Mac使ってるんでまずExcelはないなーということでスプレッドシートはちょくちょく使ってました。

DBをしっかり設計して紐付けるのも楽しいですが、 ゲーム作るという本来の目的を見失うことが多々あるのでこんな感じにサクッと導入するのが良いかなと思います。