[cocos2d-x 3.x]子ノードをタッチした時に親ノードも反応してしまう問題

今回は親ノードから子ノードを呼び出して、子ノードで画面をタッチした時に親ノードまで反応してしまうことへの対策を記述していきます。主に、ダイアログを作成した時に使うかなと思います。

    auto listener = EventListenerTouchOneByOne::create();
    listener->setSwallowTouches(true);
    listener->onTouchBegan = [](Touch *touch, Event *event) {return true;};
    this->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this);

肝心なのは2行目の

listener->setSwallowTouches(true);

です。
これが今回の目的を果たすための記述です。また、3行目にonTouchBeginを持ってくるのは、

CCASSERT(false, "Invalid EventListenerTouchOneByOne!");

とかで落ちてしまうからです。

[cocos2d-x 3.x]iPhoneで何か音楽をかけているときはゲームのBGMを流さないようにする方法[SimpleAudioEngine]

iPhoneで何か音楽をかけているときはゲームのBGMを流さないようにする方法を発見しました。
が、この方法はベストな方法ではないでしょう。何か他に方法があるだろうとは思います。
方法はとっても簡単です。

    SimpleAudioEngine::getInstance()->setBackgroundMusicVolume(1.0);
    SimpleAudioEngine::getInstance()->playBackgroundMusic("aaa.wav", true);

    // BGMが流れているなら停止
    SimpleAudioEngine::getInstance()->pauseBackgroundMusic();
    SimpleAudioEngine::getInstance()->resumeBackgroundMusic();

音楽をplayBackgroundMusicで流すそのすぐ下に上記の記述をしてください。
やってることは停止して再開しているだけです。でも、これでできちゃいます。なんでこれでうまくいくのかはさっぱりですが、ぜひやってみてください。

[cocos2d-x 3.x]plistなど外部から読み取った文章が「\n」で改行できない

よく
cocos2dx 改行
なんかで検索すると「\n」をやればうまくいくよ、というサイトを見かけますが、この方法では外部から読み取ったファイルのテキストは改行されません。

テキスト:あいう\nえお
出力:あいう\nえお
そのままですね。これは実際には、
あいう\\nえお
と認識されているからだそうです。
なので、
replaceなどを使って、「\\n」→「\n」に変更してあげましょう。

今回は、
plistの改行文字
こちらを参考にしました。

[cocos2d-x 3.x]csvファイルやテキストファイルを読み込む方法

この方法も検索すれば嫌というほどでてきます、がなかなかうまくいく方法が見つからず。
やっとできた方法がこちら

    auto split = [](const std::string& input, char delimiter) {
        std::istringstream stream(input);
        std::string field;
        std::vector<std::string> result;
        while (std::getline(stream, field, delimiter)) {
            result.push_back(field);
        }
        return result;
    };
    
    auto fileText = FileUtils::getInstance()->getStringFromFile("text.csv");
    auto lines = split(fileText, '\n');
    for (const auto& line : lines) {
        // ここに処理を記述
        log("%s", line.c_str());
    }

参考は
cocos2d-xでテキストファイルを1行ずつ処理する方法
こちら

[cocos2d-x 3.x]2点間の角度を求める

2点間の角度を求めようと検索をかけてみると、割とすぐにいくつかのサイトがヒットします。が、どれをやってもうまくいかない。
おそらく、自分のやり方が悪かったのでしょうが、それでもうまくいかない。
そして、最終的にやっとできました。
以下がそのコードです。

    float radian = atan2f(to.y-from.y, to.x-from.x);
    float degree = -radian * 360 / ( 2 * M_PI);

これでOKです。このdegreeをsetRotationにでもつっこんでやってください。

[cocos2d-x 3.x]DrawNodeで破線を描きたい

今回、自分はいま製作中のもののなかで破線を描く必要がありました。
しかし、検索してもcocos2dのときのものしか出てこなかったので、仕方なく自分で書き直しました。(偉そうに言ってますが、実際は元から大して変更せずに実装できました)
cocos2dxライブラリ内をいじっていきます。
CCDrawNode.cpp、CCDrawNode.hのふたつのファイルを今回は編集します。

CCDrawNode.h

void drawDashedLine(const cocos2d::Point &origin, const cocos2d::Point &destination,float radius, float dashLength,const cocos2d::Color4F &color);

CCDrawNode.cpp

void DrawNode::drawDashedLine(const cocos2d::Point &origin, const cocos2d::Point &destination,float radius, float dashLength, const cocos2d::Color4F &color)
{
    auto delta = Point(destination.x-origin.x,destination.y-origin.y);
    float dist = origin.getDistance(destination);
    float x = delta.x / dist * dashLength;
    float y = delta.y / dist * dashLength;
    float linePercentage = 0.3;
    
    auto p1 = origin;
    for(float i = 0; i <= dist / dashLength * linePercentage; i++)
    {
        auto p2 = Point(p1.x + x, p1.y + y);
        this->drawSegment(p1, p2,radius,color);
        p1 = Point(p1.x + x / linePercentage, p1.y + y / linePercentage);
    }
}

これらを記述すれば、あとはメインのほうでdrawDashedLineを呼び出せば破線が描けます。
引数は、
void DrawNode::drawDashedLine(スタート地点, ゴール地点, 太さ, ダッシュの長さ, 色)
となっています。

今回は、
DRAWING A DASHED LINE IN COCOS2D
こちらのサイトを参考させていただきました。

[cocos2d-x 3.x]ボタンなどに使うMenuでアンカーポイントが設定できない!?

タイトル通りです。Menuってアンカーポイントが設定できないんです。setPositonとか簡単にできてしまうので、てっきりアンカーポイントも設定できるかと思っていました。
アンカーポイントを設定するにはMenuItemImageを使う必要があるそうです。
具体的には、

    auto menuItem = MenuItemImage::create("back.png","back.png");
    menuItem->setAnchorPoint(Point::ANCHOR_TOP_RIGHT);
    menuItem->setTouchMenuCallback([this](Ref *sender){
    });
    auto menu = Menu::create(menuItem, NULL);
    menu->setPosition(Point(200,200));
    this->addChild(menu);

と、こんなかんじです。
menuItem->setTouchMenuCallbackについては、
[Cocos2d-x 3.x]Menuなどのボタンを押した(触れた)直後にアクションを起こす方法
を参照してください。

このページは、
CCMenuと不思議なAnchorPointとScale
を参考にしました。

[cocos2d-x 3.x]ProgressTimerでHPのように右から左へ減少させる方法

本来、cocos2d-xのProgressBarは左から右へと減少していくプログレスバーを提供しています。
しかし、ゲーム開発者にとっては左から右よりも右から左へと減少してくれないと困る場合があります。
そこで便利な機能を紹介します。

    auto timer=ProgressTimer::create(Sprite::create("timer.png"));
    timer->setPosition(Point(200,200));
    //この下、setReverseProgressで逆から減少するようになる
    timer->setReverseProgress(true);
    timer->setPercentage(40.0);
    this->addChild(_timer);

と、setReverseProgress()を使えば、簡単に右から左へと減少するプログレスバーの完成です。
お試しあれ。

[Cocos2d-x 3.x]Cocos2d-xでタイマーを実現したいとき、scheduleではうまくいかなかったのでその代わりとなる方法

Cocos2d-xで0.1秒で処理を繰り返したいとき、ほとんどの人がscheduleを使うと思います。自分もそうでした。
具体的にはしたのようなコードです。

void HelloWorld::countTime(float frame){
        _count+=0.1;
        printf("///count=%f///",_count);
}

しかし、これを実行してみると、実際の時間とは少しずれていました。

iPhoneタイマーとこの処理を同時スタート
iPhone 10秒→schedule 13秒
iPhone 20秒→schedule 25秒

と少しずつずれていました。
これが自分にとって、とても致命的でした。
そして、試行錯誤した結果、無事正確な時間を刻むタイマーを作ることができました。
下がそのコードです。

this->runAction(RepeatForever::create(Sequence::create(DelayTime::create(0.1),CallFunc::create([this](){
        _count+=0.1;
        printf("///count=%f///",_count);
}),NULL)));

以前の記事で紹介した応用です。
是非、皆さんも試してみてください。

[Cocos2d-x 3.x]scheduleOnce以外で処理を遅延させる方法

私はいつも処理を遅延させたい場合、scheduleを使っていました。
多くの方もそうではないかと思います。
このschedule、大変便利ではありますが、これをするのにいちいち関数を作らなければならないというデメリットがあります。
単純にインクリメントしたいだけとかの場合、いちいち関数を作るのはばからしくなります。そんなときのためにこの方法を記述します。

this->runAction(Sequence::create(DelayTime::create(3.0f),CallFunc::create([this](){
    //ここに処理
    }), NULL));

これだけです。
これで、scheduleと同じことができます。
この画期的な方法は以下のサイトを参照させていただきました。
http://qiita.com/keroxp/items/ba15b1ab485b1b11eceb
ありがとうございます。