Cocos2d-x v3.4 ボタンを配置してタップ時と離した時のアクションを設定する。イメージとソースコードあり。
こんにちは、iPhoneアプリ開発者の中川です。
今回はCocos2d-x v3で使うボタンのアクションについて。
サンプル動画はボタンを押すとおじぎをするというものです。
Cocos2d-xでボタンといえばMenuクラスを使うことが多いと思いますが、これがイマイチ物足りない仕様で、タップした時の処理しか行ってくれない。僕はタップしたときとタップを離した時の両方にアクションを施したいのでいろいろとコードを追加しました。さっそくサンプルコードを。
【HelloWorld.h】
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 |
#ifndef __HELLOWORLD_SCENE_H__ #define __HELLOWORLD_SCENE_H__ #include "cocos2d.h" class HelloWorld : public cocos2d::Layer { public: // there's no 'id' in cpp, so we recommend returning the class instance pointer static cocos2d::Scene* createScene(); // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone virtual bool init(); // オリジナルメソッド。init()内の見通しをよくするためにプレイヤーとボタンの作成を別関数とする。 void addPlayer(); void addButton(); // implement the "static create()" method manually CREATE_FUNC(HelloWorld); // この部分を追加。 // プレイヤーのプロパティ宣言。 CC_SYNTHESIZE_RETAIN(cocos2d::Sprite*, _player1, Player1); CC_SYNTHESIZE_RETAIN(cocos2d::Sprite*, _player2, Player2); }; #endif // __HELLOWORLD_SCENE_H__ |
【HelloWorld.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 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
#include "HelloWorldScene.h" USING_NS_CC; Scene* HelloWorld::createScene() { // 'scene' is an autorelease object auto scene = Scene::create(); // 'layer' is an autorelease object auto layer = HelloWorld::create(); // add layer as a child to scene scene->addChild(layer); // return the scene return scene; } // on "init" you need to initialize your instance bool HelloWorld::init() { ////////////////////////////// // 1. super init first if ( !Layer::init() ) { return false; } // プレイヤーの設置。 this->addPlayer(); // ボタンの設置。 this->addButton(); return true; } // プレイヤーの設置。 void HelloWorld::addPlayer(){ // 画面サイズ取得。 Size visibleSize = Director::getInstance()->getVisibleSize(); Vec2 origin = Director::getInstance()->getVisibleOrigin(); // プレイヤー作成。 _player1 = Sprite::create("base_1.png"); _player2 = Sprite::create("base_2.png"); // プレイヤーの設置場所。 _player1->setPosition(Vec2(visibleSize.width/4, visibleSize.height/2)); _player2->setPosition(Vec2(visibleSize.width/4 * 3, visibleSize.height/2)); // プレイヤーのアンカーポイント(基準点)。ここでは真ん中中央下としている。 _player1->setAnchorPoint(Vec2::ANCHOR_MIDDLE_BOTTOM); _player2->setAnchorPoint(Vec2::ANCHOR_MIDDLE_BOTTOM); // プレイヤーの貼り付け。 this->addChild(_player1); this->addChild(_player2); } void HelloWorld::addButton(){ // 画面サイズ取得。 Size visibleSize = Director::getInstance()->getVisibleSize(); Vec2 origin = Director::getInstance()->getVisibleOrigin(); // ボタンを押した時、離した時の画像を設定。ラムダという概念で処理を記述。[](Ref* ref){ } auto PlayButton1 = MenuItemImage::create("button_red_tap.png", "button_red_push.png", [](Ref* ref){ // ボタンを押した時の処理。今回は押した時、離した時どちらもアクションを設定するのでここでは処理を書かない。 }); auto PlayButton2 = MenuItemImage::create("button_red_tap.png", "button_red_push.png", [](Ref* ref){ // ボタンを押した時の処理。今回は押した時、離した時どちらもアクションを設定するのでここでは処理を書かない。 }); // ボタンの設置場所。 PlayButton1->setPosition(Vec2(visibleSize.width/6.0, visibleSize.height/8.0)); PlayButton2->setPosition(Vec2(visibleSize.width/6.0 * 5.0, visibleSize.height/8.0)); // MenuItemImageで作られたボタンからメニューを作成。 auto menu1 = Menu::create(PlayButton1, NULL); auto menu2 = Menu::create(PlayButton2, NULL); // 基準点を0。 menu1->setPosition(Point::ZERO); menu2->setPosition(Point::ZERO); // ボタン貼り付け。(メニュー貼り付け) this->addChild(menu1); this->addChild(menu2); /* ここからが記事のメイン!!!! */ // タッチイベント // 左のボタン auto listener1 = EventListenerTouchOneByOne::create(); // ラムダを使用して関数内にonTouchBeganとonTouchEndedを実装する。 listener1->onTouchBegan = [this,visibleSize,PlayButton1](Touch* touch, Event* event){ // タッチされたボタンが左かどうか判別している。これがないと複数のイベントリスナーが実行されてしまう。 Vec2 point1 = touch->getLocation(); // タッチしたポイント。 Rect rectButton1 = PlayButton1->getBoundingBox(); // ボタン画像の範囲。 if (rectButton1.containsPoint(point1)) { // ボタン画像の範囲内をタッチした場合。 // タッチされた時の処理。 auto sprite_pose1_1 = Sprite::create("pose1_1.png"); auto sprite_pose1_1_size = sprite_pose1_1->getContentSize(); auto poseRect = Rect(0, 0, sprite_pose1_1_size.width, sprite_pose1_1_size.height); auto poseFrame = SpriteFrame::create("pose1_1.png", poseRect); _player1->setSpriteFrame(poseFrame); return true; }else{ return false; } }; listener1->onTouchEnded = [this](Touch* touch, Event* event){ // タッチ終了時の処理。(指を離した時) auto sprite_pose1_1 = Sprite::create("base_1.png"); auto sprite_pose1_1_size = sprite_pose1_1->getContentSize(); auto poseRect1 = Rect(0, 0, sprite_pose1_1_size.width, sprite_pose1_1_size.height); auto poseFrame1 = SpriteFrame::create("base_1.png", poseRect1); _player1->setSpriteFrame(poseFrame1); }; // listener1, PlayButton1をイベント登録する。 auto director = Director::getInstance(); director->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener1, PlayButton1); // 右のボタン auto listener2 = EventListenerTouchOneByOne::create(); // ラムダを使用して関数内にonTouchBeganとonTouchEndedを実装する。 listener2->onTouchBegan = [this,visibleSize,PlayButton2](Touch* touch, Event* event){ // タッチされたボタンが右かどうか判別している。これがないと複数のイベントリスナーが実行されてしまう。 Vec2 point2 = touch->getLocation(); // タッチしたポイント。 Rect rectButton2 = PlayButton2->getBoundingBox(); // ボタン画像の範囲。 if (rectButton2.containsPoint(point2)) { // ボタン画像の範囲内をタッチした場合。 // タッチされた時の処理。 auto sprite_pose1_2 = Sprite::create("pose1_2.png"); auto sprite_pose1_2_size = sprite_pose1_2->getContentSize(); auto poseRect = Rect(0, 0, sprite_pose1_2_size.width, sprite_pose1_2_size.height); auto poseFrame = SpriteFrame::create("pose1_2.png", poseRect); _player2->setSpriteFrame(poseFrame); return true; }else{ return false; } }; listener2->onTouchEnded = [this](Touch* touch, Event* event){ // タッチ終了時の処理。(指を離した時) auto sprite_pose1_2 = Sprite::create("base_2.png"); auto sprite_pose1_2_size = sprite_pose1_2->getContentSize(); auto poseRect2 = Rect(0, 0, sprite_pose1_2_size.width, sprite_pose1_2_size.height); auto poseFrame2 = SpriteFrame::create("base_2.png", poseRect2); _player2->setSpriteFrame(poseFrame2); }; // listener1, PlayButton1をイベント登録する。 director->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener2, PlayButton2); } |
ボタンアクションの実装は"void HelloWorld::addButton()"を参照してください。
ボタンアクションをonTouchBegan、onTouchEndedを使って設定しています。
Menuクラスはボタンを押した時と離した時の画像切り替えのみに使用しています。
タップした時がonTouchBegan、離した時がonTouchEnded。
それぞれのメソッドを外部に設けるのではなく、ラムダを使ってボタンを追加する"void HelloWorld::addButton()"内に記述しています。
こんなマニアックな実装が役に立つかはわかりませんが参考までに。ではでは。
ディスカッション
コメント一覧
まだ、コメントがありません