Cocos2d-x 勉強第10回「ファイルを保存する」+「HttpRequest」

木内智史之介(シャッチョー)
ミンカさんけっこんしてくださいおねがいします(ズザー
SEGAさん、DIVAの筐体ください(ズザー

今回の目標

ファイルを保存する必要性のあるアプリもあると思います。
僕なんかはゲーム系の開発に携わることが多いので、例えば画像データなどを端末側にダウンロードさせてしまって内部参照させるようなケースがまず思い浮かびます。
丁度いいので、そんな感じの想定で今回のお勉強、いってみたいと思うでござるよ!

下準備、下調べ

ググってみたところ

む?ファイル保存に関してはcocos2d::FileUtils::writeToFileを使用するイメージでいいのかな?
これは、前回の「変数の保存/永続化」 で使用したメソッドですね。

virtual bool writeToFile (
Dictionary * dict,
const std::string & fullPath
)

引数はDictionaryのみなのかなー。 単純にplainなテキスト(バイナリ含む)を保存するようなものはないのかしら?
そうすると、どうしたらいいものか…。

cocos2d::Image::saveToFileというメソッドがあるらしい

ほほう!そんなのもあるのか。

そもそもhttp通信ってどうやるんだろう?

  • HttpClient
  • HttpRequest
  • HttpResponse

あたりのクラスを駆使すればいけるのかな?

やってみる

HelloWorldScene.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include "network/HttpClient.h"
USING_NS_CC;

// snip...

bool HelloWorld::init()
{
    // snip...

    auto request = new extension::HttpRequest();
    request->setUrl("http://befool.co.jp/images/logo_befool.jpg");
    request->setRequestType(extension::HttpRequest::Type::GET);
    request->setResponseCallback(this, httpresponse_selector(HelloWorld::onHttpRequestCompleted));
    extension::HttpClient::getInstance()->send(request);

    return true;
}

/**
 * ファイルDL終了コールバック
 */
void HelloWorld::onHttpRequestCompleted(extension::HttpClient* sender, extension::HttpResponse* response)
{
    Size visibleSize = Director::getInstance()->getVisibleSize();
    Point origin = Director::getInstance()->getVisibleOrigin();

    auto fileUtils = FileUtils::sharedFileUtils();
    std::string filename = fileUtils->getWritablePath() + "hoge.jpg";

    if (fileUtils->isFileExist(filename)) {
        log("file exist. use hoge.jpg.");

        auto sprite = Sprite::create(filename.c_str());
        sprite->setPosition(Point(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
        this->addChild(sprite, 0);
    } else {
        log("no file exist. use default image, and save the file.");

        if (response->isSucceed()) {
            std::vector<char>* buffer = response->getResponseData();
            auto* img = new Image();
            img->initWithImageData(reinterpret_cast<unsigned char*>(&(buffer->front())), buffer->size());
            img->saveToFile(filename.c_str());

            auto* texture = new Texture2D();
            texture->initWithImage(img);

            auto sprite = Sprite::createWithTexture(texture);
            sprite->setPosition(Point(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
            this->addChild(sprite, 0);
        }
    }
}

動かしてみる

プレイ よし!

はまりポイント

setRequestTypeが必須

デフォルトはGETっしょ?という甘い考えでは痛い目を見る。拙者のようにね!

request->setRequestType(extension::HttpRequest::Type::GET);

の指定は忘れないようにしよう。

cocos2d::Image::initWithImageDataの仕様変更が入った

最初は

img->initWithImageData(&(buffer->front()), buffer->size());

のように書いていたんだけど、どうにも型が一致しないようでコンパイルが失敗する。

http://www.cocos2d-x.org/forums/18/topics/35462

こちらのやりとりを参考にして、

img->initWithImageData(reinterpret_cast<unsigned char*>(&(buffer->front())), buffer->size());

という内容にしたら通りました。
このあたりのキャストの方法とか&(buffer->front())のような書き方にどのような意味があるのか、まだイマイチ分かっていないでござるよ…。
const絡みであることは雰囲気から若干わかるような分からないような。。

次回に向けて

今回は「ファイルの保存」と言いつつもそれが画像に限定されてしまった(しかもHttpRequestに関するところでガッツリ詰まった…)。
今度にでもplainなテキストを保存したい場合などどうすればいいのか調べなくちゃな。。

次回は「Web View」に関して試してみたいと思います!

ソースコード

https://github.com/8823-scholar/cocos2d-x-study/commit/184adf641cf68d908b2dee5c5150eefb44988eb8

参考文献

感謝です!