cocos2d-xはv2.0とv3.0でタッチイベントなどのイベント取得方法が変更になっています。これを踏まえて、サンプルを作成しながら解説します。
詳細は本家の記事を参照して下さい。
元のテンプレートのソースから出発して、コメントを追加しました。
- HelloWorldクラスを MoleSceneクラスに変更します。(必ずしも必要ではありません。)
- HelloWorldScene.hを MoleScene.hに、HelloWorldScene.cppを MoleScene.cppに変更します。(必ずしも必要ではありません。)
- ソースの可読性を上げるため、using句を追加します。(必ずしも必要ではありません。)
using namespace cocos2d;
- cocos2d-xのサンプルにあるアイコン( Icon.png)をResourcesに追加します。
- スプラッシュスクリーンの代わりに、アイコンを読み込むようにします。
- スプライトと画面サイズがクラス全体で必要になりますので、メンバー変数にします。
MoleScene.h
#ifndef __MOLE_SCENE_H__
#define __MOLE_SCENE_H__
#include <CCGeometry.h>
#include "cocos2d.h"
using namespace cocos2d;
class MoleScene : public cocos2d::Layer
{
private:
// 画面サイズ
Size visibleSize;
// スプライト
cocos2d::Sprite* sprite;
public:
// C++にはIDがないので、クラスのインスタンスポインタを返すことを推奨する。
static Scene* createScene();
// initメソッドは、cocos2d-iphoneではIDを返すが、cocos2d-xではboolを返すという違いがある。
virtual bool init();
// a selector callback
// セレクタのコースバック
void menuCloseCallback(cocos2d::Ref* pSender);
// static create()関数のマニュアル実装
CREATE_FUNC(MoleScene);
// 次の位置を取得する。
Point* getNextPosition();
};
#endif
// __MOLE_SCENE_H__
MoleScene.cpp
/*
* Sample2: 簡単なもぐらたたき風サンプル。
*
* Copyright (C) Takao WADA.
*/
#include "MoleScene.h"
USING_NS_CC;
/**
* シーンを作成する。
*
* @return シーン
*/
Scene* MoleScene::createScene()
{
// 'scene' は autorelease オブジェクト
auto scene = Scene::create();
// 'layer' は autorelease オブジェクト
auto layer = MoleScene::create();
// レイヤーをシーンの子として追加する。
scene->addChild(layer);
// シーンを返す。
return scene;
}
/**
* インスタンスを初期化する。
*
* @return 成功したらtrue
*/
bool MoleScene::init()
{
//////////////////////////////
// 1. 親クラスを初期化する。
if ( !Layer::init() )
{
return false;
}
// 画面サイズを取得する。
visibleSize = Director::getInstance()->getVisibleSize();
// 画面の原点を取得する。
Point origin = Director::getInstance()->getVisibleOrigin();
/////////////////////////////
// 2. クリックすると終了する”X”画像付きのメニュー項目を追加する。これは変更してもよい。
// プログラムを終了する"close"アイコンを追加する。これは autorelease オブジェクト。
auto closeItem = MenuItemImage::create(
"CloseNormal.png",
"CloseSelected.png",
CC_CALLBACK_1(MoleScene::menuCloseCallback, this));
closeItem->setPosition(Point(origin.x + visibleSize.width - closeItem->getContentSize().width/2 ,
origin.y + closeItem->getContentSize().height/2));
// メニューを作成する。これは autorelease オブジェクト。
auto menu = Menu::create(closeItem, NULL);
// メニューの位置を設定する。
menu->setPosition(Point::ZERO);
// メニューを子レイヤーとして追加する。
this->addChild(menu, 1);
/////////////////////////////
// 3. 独自のコードを追加する。
this->setTouchMode(Touch::DispatchMode::ONE_BY_ONE);
// ラベルを作成し、初期化する。
auto label = LabelTTF::create("whack a mole sample", "Arial", 24);
// 画面の中央にラベルを位置づける。
label->setPosition(Point(origin.x + visibleSize.width/2,
origin.y + visibleSize.height - label->getContentSize().height));
// ラベルをレイヤーの子として追加する。
this->addChild(label, 1);
// cocosアイコンを追加する。
sprite = Sprite::create("Icon.png");
// スプライトを画面の中央に位置づける。
sprite->setPosition(Point(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
// スプライトをレイヤーの子として追加する。
this->addChild(sprite, 0);
// シングルタッチイベントリスナーを作成する。
auto listener1 = EventListenerTouchOneByOne::create();
// スワロータッチモードにするとonTouchBeganメソッドはタッチイベントは他では使われない。
listener1->setSwallowTouches(true);
// onTouchBeganイベントコールバック関数実装のラムダ式の例
listener1->onTouchBegan = [](Touch* touch, Event* event) {
// event->getCurrentTarget() は、リスナーのsceneGraphPriorityの優先順に対象オブジェクトを返す。
auto target = static_cast<Sprite*>(event->getCurrentTarget());
// ボタンに対する相対的な位置を取得する。
Point locationInNode = target->convertToNodeSpace(touch->getLocation());
// コンテンツのサイズを取得する。
Size s = target->getContentSize();
// コンテンツ矩形を作成する。
Rect rect = Rect(0, 0, s.width, s.height);
// クリックエリアをチェックする。
if (rect.containsPoint(locationInNode))
{
log("sprite began... x = %f, y = %f", locationInNode.x, locationInNode.y);
// 不透明度を変更する。
target->setOpacity(180);
return true;
}
return false;
};
// タッチが移動した場合
listener1->onTouchMoved = [](Touch* touch, Event* event) {
// ターゲットを取得する。
// auto target = static_cast<Sprite*>(event->getCurrentTarget());
// ここに移動した場合の処理を書く。touch->getDelta()で移動量が取得できる。
};
// タッチイベントが終了した場合
listener1->onTouchEnded = [=](Touch* touch, Event* event) {
// ターゲットを取得する。
auto target = static_cast<Sprite*>(event->getCurrentTarget());
// ここに終了した場合の処理を書く。
log("sprite onTouchesEnded.. ");
// スプライトを画面の中央に位置づける。
sprite->setPosition(*getNextPosition());
// 不透明度を元に戻す。
target->setOpacity(255);
};
// イベントリスナーをスプライトに追加する。
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, sprite);
return true;
}
/**
* メニューの"Close"が選択された場合のコールバック関数。
*
* @param pSender 送信元
*/
void MoleScene::menuCloseCallback(Ref* pSender)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
return;
#endif
// ディレクタを終了する。
Director::getInstance()->end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit(0);
#endif
}
/**
*
* 画面上のランダムな位置を取得する。
*
* @return 画面上のランダムな位置
*/
Point* MoleScene::getNextPosition()
{
// スプライトを新しい位置に変更する。
Point* point = new Point(random() % (int)visibleSize.width, random() % (int)visibleSize.height);
return point;
}