libro
www.tuyano.com
初心者のためのCocos2d-xゲームプログラミング入門

タッチイベントを利用しよう! (5/6)

作成:2015-06-13 10:53
更新:2015-06-13 10:53

■ラムダ式を使おう!

実は、関数をプロパティに設定する方法は、他にもあります。それは「ラムダ式」を使うのです。

ラムダ式というのは、「匿名関数」と呼ばれるものの一つで、処理をその場で値として記述するのに利用されます。このラムダ式は、こんな具合に記述します。
[ キャプチャ ]( 引数 )-> 返値
{
    ……処理を記述……
};

●キャプチャとは?
最初にある「キャプチャ」というのは、ラムダ式の内部で利用できるローカル変数などを指定するためのものです。ラムダ式は一種の関数であり、その内部は外とは切り離されています。このため、外側で使っていた変数などをラムダ式の内部でも使いたいような場合には、このキャプチャを利用するのです。

キャプチャには、いくつかの書き方があります。ざっと整理しましょう。

[=] ――全てのオブジェクトのコピーがラムダ式に渡されます。
[&] ――全てのオブジェクトの参照がラムダ式に渡されます。
[変数] ――指定した変数のコピーがラムダ式に渡されます。
[&変数] ――指定した変数の参照がラムダ式に渡されます。

変数のコピーを渡すか参照を渡すか、は重要です。オブジェクトの場合、コピーを渡してしまうと元のオブジェクトを操作できなくなってしまいますからね。

が! イベントリスナーでラムダ式を使う場合は、そのへんは深く考えなくてもいいです。なぜなら、キャプチャは、[this]にする、と考えてしまえばいいからです。こうすることで、thisに用意されているプロパティなどにもアクセスできるようになりますから。

サンプルのラムダ式部分を見てみましょう。
listener->onTouchBegan = [this](cocos2d::Touch* touch, cocos2d::Event* event)->bool
{
    auto str = String::create("No, ");
    str->appendWithFormat("%i", count++);
    label->setString(str->getCString());
    return true;
};

キャプチャには、[this]を指定してしますね。そして引数には、onTouchBeganに割り当てる関数では必須のTouchEventが用意されています。

内部の処理を見ると、countlabelがそのままできているのがわかるでしょう。thisを渡すことで、こんな具合にthis内のプロパティやメソッドにそのままアクセスできるようになるのです。

ちなみに、[&this]じゃないの?と思った人。thisが既に参照ですから、そのままコピーして使えばいいんですよ。

※プログラムリストが表示されない場合

AddBlockなどの広告ブロックツールがONになっていると、プログラムリスト等が表示されない場合があります。これらのツールをOFFにしてみてください。

●プログラム・リスト●

#pragma execution_character_set("utf-8")

#include "HelloWorldScene.h"

USING_NS_CC;

Scene* HelloWorld::createScene()
{
    auto scene = Scene::create();
    auto layer = HelloWorld::create();
    scene->addChild(layer);
    return scene;
}

bool HelloWorld::init()
{
    if (!Layer::init())
    {
        return false;
    }
    Size visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();
    Director::getInstance()->setDisplayStats(false); // stats OFF
    count = 0;

    label = Label::createWithTTF("Hello World", "fonts/Marker Felt.ttf", 96);
    label->setPosition(Vec2(origin.x + 50, origin.y + 50));
    label->setAnchorPoint(Vec2(0, 0));
    label->setName("label");
    this->addChild(label, 1);

    auto listener = EventListenerTouchOneByOne::create();
    listener->onTouchBegan = [this](cocos2d::Touch* touch, cocos2d::Event* event)->bool
    {
        auto str = String::create("No, ");
        str->appendWithFormat("%i", count++);
        label->setString(str->getCString());
        return true;
    };
    this->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this);

    return true;
}
※関連コンテンツ

「初心者のためのCocos2d-xゲームプログラミング入門」に戻る