レイヤーのタッチイベントの優先順位について(cocos2dx)

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ponkikki
記事: 7
登録日時: 10年前

レイヤーのタッチイベントの優先順位について(cocos2dx)

#1

投稿記事 by ponkikki » 9年前

お世話になっております。
レイヤーのタッチイベントについて質問があります。
ゲーム画面上にはプレイヤーがいて、プレイヤーを動かすアナログキーがあります。
アナログキーを押すと、プレイヤーが動き、アナログキー以外の場所を押すと、メニュー画面を呼び出すなどの別のタッチイベントを
実装したいと思っています。
アナログキーの実装はweb上にあったsneakyButtonというクラスで実装しています。タッチイベント全体を管理するクラスInputLayer(CCLayerを継承)を用意し、InputLayerにsneakyButtonを貼付けています。(addchild)
以下にInputLayerとsneakyButtonの簡単な構造を示します。


--------------------sneakyButton.cpp-------------------------

コード:

void SneakyButton::onEnterTransitionDidFinish()
{
        //十字キーの方がInputLayerよりタッチイベントの優先度を高くしています
	CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, -100, true);
}

void SneakyButton::onExit()
{
	CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);
}

//省略

bool SneakyButton::ccTouchBegan(CCTouch *touch, CCEvent *event)
{
    CCLOG("十字キーが押されました");
    //ボタンが押されている状態ならタッチ始めの処理はしません
	if (active) return false;
	
	CCPoint location = CCDirector::sharedDirector()->convertToGL(touch->getLocationInView());
	location = this->convertToNodeSpace(location);

    
	//Do a fast rect check before doing a circle hit check:
	if(location.x < -radius || location.x > radius || location.y < -radius || location.y > radius){

        //①十字キー以外の場所がタッチされました。本レイヤーよりタッチイベントの優先度が低いレイヤー(InputLayer)にタッチイベントが移行します。
		return false;
	}else{
		float dSq = location.x*location.x + location.y*location.y;
		if(radiusSq > dSq){

                        //②十字キーをアクティブ化します

			active = true;
			if (!isHoldable && !isToggleable){
				value = 1;
				this->schedule(schedule_selector(SneakyButton::limiter), rateLimit);
			}
			if (isHoldable) value = 1;
			if (isToggleable) value = !value;
			return true;
		}
	}
return false;
}






--------------------------InputLayer.cpp--------------------------------

コード:




void InputLayer::onEnter()
{
    //sneakyButtonより1つ優先度が低いです。十字キー以外の場所が押されたら、本レイヤーのタッチイベントが実行される。
    CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, -99, true);
}


void InputLayer::onExit()
{
    CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);   
}



bool InputLayer::init()
{
    
    if (!CCLayer::init()) {
        return false;
    }

    //タイマーセット
    this->scheduleUpdate();
    
    //======================================================================
    //                      十字キーの部分です
    //======================================================================
    
    //==========================各種ボタンをインスタンス化します============================
    UpButton = new SneakyButton();
    UpButton->initWithRect(CCRectZero);
    UpButton->setIsToggleable(false);
    UpButton->setIsHoldable(true);
    UpButton->setRadius(40.0);
    UpButton->setTag(0);
    UpButton->autorelease();
    
    //=======================================================
    SneakyButtonSkinnedBase *ButtonBase1 = SneakyButtonSkinnedBase::create();
    UpButton->init();
    ButtonBase1->setButton(UpButton);
    ButtonBase1->setDefaultSprite(CCSprite::create("UpArrow.png")); //通常時の画像
    //ButtonBase->setDisabledSprite(CCSprite::create("UpArrow.png"));
    ButtonBase1->setActivatedSprite(CCSprite::create("UpArrowSelected.png")); //押しっぱの時の画像
    ButtonBase1->setPressSprite(CCSprite::create("UpArrowSelected.png")); //押し始めの画像
    ButtonBase1->setPosition(ccp(200, 200));
    
    this->addChild(ButtonBase1);

  
   //以下同様、十字キーのボタンの分、sneakyButtonをインスタンス化します


   return true;
}


//このタイマーは十字キーが押されたかどうか常に監視しています
void InputLayer::update(float delta)
{

  //省略

        if (UpButton->getIsActive()) {
            CCLOG("上に行きます");
            
            //プレイヤーを押された方向に動かす処理
            
       
        }else if (DownButton->getIsActive()){
            CCLOG("下に行きます");
              
    //プレイヤーを押された方向に動かす処理
    
        }else if (RightButton->getIsActive()){
            CCLOG("右に行きます");
             
    //プレイヤーを押された方向に動かす処理

        }else if (LeftButton->getIsActive()){
            CCLOG("左に行きます");
            
    //プレイヤーを押された方向に動かす処理

        }

   
}





bool InputLayer::ccTouchBegan(cocos2d::CCTouch *touch, cocos2d::CCEvent *event)
{
    
    
    CCLOG("十字キー以外の場所がタッチされたので、メニュー画面を呼び出すなどの処理をします");
    return true;
}




以上になります。
実現しようとしているプログラムの流れを説明します。
InputLayerで十字キーが押されたかどうかをupdate関数で監視しています。押されたかどうかの判断は、sneakyButtonクラスのメンバ変数activeがtrueになったかどうかで判断しています、十字キーが押された場合、activeはtrueになりますので、update関数で十字キーが押されたと判断できるようになります。
次に、十字キー以外の場所をタッチされたとき、別のタッチイベントを発生させたいのです。(例えば、別のキャラクターの前でタッチしたら、会話が始まったり、またはメニュー画面を呼び出したりなど)。
そこで、まずsneakyButtonクラスのccTouchBegan関数内で、十字キー以外の場所が押されたと判断したら、falseを返します。そうしましたら、レイヤーのタッチイベントの優先度が次に高いInputLayerにタッチイベントが移行して、InputLayer内のccTouchBegan関数内で、別のタッチイベントを発生するという流れです。
これを実現しようとしたのですが、コンソールを見ると、まず十字キー以外の場所をタッチしたらsneakyButtonクラスでfalseを返し、InputLayerのccTouchBegan関数内に入ったところまでは確認できました。
ですが、十字キーを押したら、sneakyButtonクラスの②の部分まで入り、変数activeもtrueになっているのは確認できたのですが、InputLayer内のupdate関数でどうやらactiveがtrueになっていない様なのです。なので、キャラクターが動かず困っています。
試しに、InputLayerのタッチイベントを消して、sneakyButtonのみのタッチイベントで実行したら、キャラクターは動きました。

いったいどこに原因があるのでしょうか?

“C言語何でも質問掲示板” へ戻る