天天看點

cocos2d-x中繼承CCMenu定義自己的MyMenu,這個是解決優先級的問題

為了用menu來進行對touch事件的阻斷,防止其傳到下一層,又不能影響上面的CCControlButton等優先級為0的sprite的點選響應,于是就定義了一個MyMenu。

下面為相關代碼,下一篇(cocos2d-x裡面touch事件傳遞機制 .)我再詳細說下cocos2d-x裡面的touch事件響應機制

這裡面代碼(1)(2)是MyMenu的例子,(7)(8)裡面控制touch傳遞的例子

(1)MyMenu.h

#pragma once

// MyMenu

#include "cocos2d.h"

using namespace cocos2d;

class MyMenu : public CCMenu
{
public:
	MyMenu(void);
	~MyMenu(void);

	/** creates a CCMenu with it's items */
	static MyMenu* create(CCMenuItem* item, ...);

	// 重寫registerWithTouchDispatcher
	virtual void registerWithTouchDispatcher();
};

           

(2)MyMenu.cpp

#include "MyMenu.h"

MyMenu::MyMenu(void)
{
}

MyMenu::~MyMenu(void)
{
}

MyMenu * MyMenu::create(CCMenuItem* item, ...)
{
	va_list args;
	va_start(args,item);
	MyMenu *pRet = new MyMenu();
	if (pRet && pRet->initWithItems(item, args))
	{
		pRet->autorelease();
		va_end(args);
		return pRet;
	}
	va_end(args);
	CC_SAFE_DELETE(pRet);
	return NULL;
}


// 重寫registerWithTouchDispatcher
void MyMenu::registerWithTouchDispatcher()
{
	//這裡優先級設為1,隻要比CCScrollView、tableView、CCControlButton等(這些優先級都為0)低就可以
	CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, 1, true);
}
           

(3)BattleBGLayer.h

#pragma once

// 戰役界面(包含左側的選項欄layer(BattleZuoLayer)、承載戰役場景的layer(BattleShowLayer)等)layer

#include "cocos2d.h"
#include "cocos-ext.h"

using namespace cocos2d;
using namespace cocos2d::extension;

class BattleBGLayer : public CCLayer
{
public:
	BattleBGLayer(void);
	~BattleBGLayer(void);

public:
	// init
	virtual bool init();

	CREATE_FUNC(BattleBGLayer);
};
           

(4)BattleBGLayer.cpp

#include "BattleBGLayer.h"
#include "BattleShowLayer.h"
#include "BattleZuoLayer.h"


//****************************************變量begin**********************************
// 定義全局變量
int bl_showNumber = 1;		// 選擇的是哪個戰役
//****************************************變量end*************************************


BattleBGLayer::BattleBGLayer(void)
{
}

BattleBGLayer::~BattleBGLayer(void)
{
}


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


	// 承載戰役場景的layer(BattleShowLayer)
	BattleShowLayer* battleShowLayer = BattleShowLayer::create();
	this->addChild(battleShowLayer,0,1000);

	// 左側的選項欄layer(BattleZuoLayer)
	BattleZuoLayer* battleZuoLayer = BattleZuoLayer::create();
	this->addChild(battleZuoLayer,10,1001);


	return true;
}
           

(5)BattleShowLayer.h

#pragma once

// 戰役場景界面layer

#include "cocos2d.h"
#include "cocos-ext.h"
#include "BattleBGLayer.h"			// 為了引人全局變量

using namespace cocos2d;
using namespace cocos2d::extension;


//****************************************變量begin**********************************
// 聲明全局變量
extern int bl_showNumber;		// 選擇的是哪個戰役
//****************************************變量end*************************************


class BattleShowLayer : public CCLayer
{
public:
	BattleShowLayer(void);
	~BattleShowLayer(void);

public:
	// init
	virtual bool init();

	CREATE_FUNC(BattleShowLayer);

public:
	// 兵臨華沙戰役中各個軍隊按鈕點選回調函數
	void jundui1UpInside(CCObject* pSender, CCControlEvent controlEvent);

	// 馬其諾防線戰役中各個軍隊按鈕點選回調函數
	void jundui2UpInside(CCObject* pSender, CCControlEvent controlEvent);

	// 敦刻爾克戰役中各個軍隊按鈕點選回調函數
	void jundui3UpInside(CCObject* pSender, CCControlEvent controlEvent);

	// 基輔會戰戰役中各個軍隊按鈕點選回調函數
	void jundui4UpInside(CCObject* pSender, CCControlEvent controlEvent);
};
           

(6)BattleShowLayer.cpp

#include "BattleShowLayer.h"

BattleShowLayer::BattleShowLayer(void)
{
}

BattleShowLayer::~BattleShowLayer(void)
{
}

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

	// winSize
	CCSize winSize = CCDirector::sharedDirector()->getWinSize();

	// Add the BG
	CCSprite* theBG = CCSprite::create(CCString::createWithFormat("battle/%d/bg%d.jpg", bl_showNumber, bl_showNumber)->getCString());
	theBG->setPosition(ccp(winSize.width/2-44, winSize.height/2));
	this->addChild(theBG,0,1000);

	// 兵臨華沙戰役
	if (bl_showNumber == 1)
	{
		// 坐标
		int position2_1[12][2] = {{90,598}, {190,550}, {150,434}, {162,318}, {212,214}, {298,304}, {314,426}, {424,538}, {488,468}, {570,432}, {670,500}, {826,462}};

		// 各個軍隊的點選圖檔
		for (int i=1; i<=12; i++)
		{
			CCControlButton* jundui1ControlBtn = CCControlButton::create(CCScale9Sprite::create(CCString::createWithFormat("battle/1/%d.png", i)->getCString()));
			jundui1ControlBtn->setPosition(ccp(position2_1[i-1][0],position2_1[i-1][1]));
			jundui1ControlBtn->addTargetWithActionForControlEvents(this,cccontrol_selector(BattleShowLayer::jundui1UpInside),CCControlEventTouchUpInside);
			jundui1ControlBtn->setPreferredSize(CCSizeMake(120,80));	// 點選區域
			if (i == 12)
			{
				jundui1ControlBtn->setPreferredSize(CCSizeMake(150,100));
			}
			this->addChild(jundui1ControlBtn,0,i);
		}
	}
	// 馬其諾防線
	else if (bl_showNumber == 2)
	{
		// 坐标
		int position2_2[11][2] = {{184,660}, {290,584}, {236,458}, {196,300}, {316,324}, {286,250}, {756,190}, {672,344}, {606,448}, {730,490}, {850,570}};

		// 各個軍隊的點選圖檔
		for (int i=1; i<=11; i++)
		{
			CCControlButton* jundui2ControlBtn = CCControlButton::create(CCScale9Sprite::create(CCString::createWithFormat("battle/2/%d.png", i)->getCString()));
			jundui2ControlBtn->setPosition(ccp(position2_2[i-1][0],position2_2[i-1][1]));
			jundui2ControlBtn->addTargetWithActionForControlEvents(this,cccontrol_selector(BattleShowLayer::jundui2UpInside),CCControlEventTouchUpInside);
			jundui2ControlBtn->setPreferredSize(CCSizeMake(120,80));	// 點選區域
			if (i == 11)
			{
				jundui2ControlBtn->setPreferredSize(CCSizeMake(150,100));
			}
			this->addChild(jundui2ControlBtn,0,i);
		}
	}
	// 敦刻爾克
	else if (bl_showNumber == 3)
	{
		// 坐标
		int position2_3[9][2] = {{156,590}, {258,548}, {86,390}, {336,228}, {440,360}, {500,542}, {654,482}, {830,538},{738,258}};

		// 各個軍隊的點選圖檔
		for (int i=1; i<=9; i++)
		{
			CCControlButton* jundui3ControlBtn = CCControlButton::create(CCScale9Sprite::create(CCString::createWithFormat("battle/3/%d.png", i)->getCString()));
			jundui3ControlBtn->setPosition(ccp(position2_3[i-1][0],position2_3[i-1][1]));
			jundui3ControlBtn->addTargetWithActionForControlEvents(this,cccontrol_selector(BattleShowLayer::jundui3UpInside),CCControlEventTouchUpInside);
			jundui3ControlBtn->setPreferredSize(CCSizeMake(120,80));	// 點選區域
			if (i == 9)
			{
				jundui3ControlBtn->setPreferredSize(CCSizeMake(150,100));
			}
			this->addChild(jundui3ControlBtn,0,i);
		}
	}
	// 基輔會戰
	else if (bl_showNumber == 4)
	{
		// 坐标
		int position2_4[9][2] = {{82,324}, {182,390}, {246,484}, {372,456}, {460,344}, {580,360}, {630,470}, {806,512}, {866,368}};

		// 各個軍隊的點選圖檔
		for (int i=1; i<=9; i++)
		{
			CCControlButton* jundui4ControlBtn = CCControlButton::create(CCScale9Sprite::create(CCString::createWithFormat("battle/4/%d.png", i)->getCString()));
			jundui4ControlBtn->setPosition(ccp(position2_4[i-1][0],position2_4[i-1][1]));
			jundui4ControlBtn->addTargetWithActionForControlEvents(this,cccontrol_selector(BattleShowLayer::jundui4UpInside),CCControlEventTouchUpInside);
			jundui4ControlBtn->setPreferredSize(CCSizeMake(120,80));	// 點選區域
			if (i == 9)
			{
				jundui4ControlBtn->setPreferredSize(CCSizeMake(150,100));
			}
			this->addChild(jundui4ControlBtn,0,i);
		}
	}
	

	return true;
}

// 兵臨華沙戰役中各個軍隊按鈕點選回調函數
void BattleShowLayer::jundui1UpInside(CCObject* pSender, CCControlEvent controlEvent)
{

}

// 馬其諾防線戰役中各個軍隊按鈕點選回調函數
void BattleShowLayer::jundui2UpInside(CCObject* pSender, CCControlEvent controlEvent)
{

}

// 敦刻爾克戰役中各個軍隊按鈕點選回調函數
void BattleShowLayer::jundui3UpInside(CCObject* pSender, CCControlEvent controlEvent)
{

}

// 基輔會戰戰役中各個軍隊按鈕點選回調函數
void BattleShowLayer::jundui4UpInside(CCObject* pSender, CCControlEvent controlEvent)
{

}
           

(7)BattleZuoLayer.h

#pragma once

// 戰役界面左側的選項欄layer

#include "cocos2d.h"
#include "cocos-ext.h"
#include "CityScene.h"				// 為了引人全局變量
#include "BattleBGLayer.h"			// 為了引人全局變量

using namespace cocos2d;
using namespace cocos2d::extension;


//****************************************變量begin**********************************
// 聲明全局變量
extern CityScene* theAScene_global;		// theAScene_global用來儲存CityScene,讓其他地方也能使用CityScene對象

// 聲明全局變量
extern int bl_showNumber;		// 選擇的是哪個戰役
//****************************************變量end*************************************


class BattleZuoLayer : public CCLayer
{
public:
	BattleZuoLayer(void);
	~BattleZuoLayer(void);

public:
	// init
	virtual bool init();

	CREATE_FUNC(BattleZuoLayer);

public:
	// myMenu空回調函數
	void myNullCallback(CCObject* pSender);

	// 戰役圖檔點選回調函數
	void btn_battleControlBtnUpIn(CCObject* pSender, CCControlEvent controlEvent);

	// 四個戰役按鈕圖檔的點選回調函數
	void zhanyiControlBtn1UpInside(CCObject* pSender, CCControlEvent controlEvent);

	// 選中戰役後的按鈕圖檔的點選回調空函數
	void zhanyiControlBtn2UpInside(CCObject* pSender, CCControlEvent controlEvent);

	// 戰役介紹的文字内容顯示函數
	void china2Show(int i);

	// 各個戰役顯示函數
	void zhanyiShow(int i);
};
           

(8)BattleZuoLayer.cpp

#include "BattleZuoLayer.h"
#include "positionResource.h"
#include "BattleShowLayer.h"
#include "MyMenu.h"

// 轉碼的
#include "UTFTools.h"


BattleZuoLayer::BattleZuoLayer(void)
{
}

BattleZuoLayer::~BattleZuoLayer(void)
{
}

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

	// winSize
	CCSize winSize = CCDirector::sharedDirector()->getWinSize();

	// 底部遮擋圖檔(用來屏蔽下面事件被觸發)(MyMenu)
	CCMenuItem* myItem = CCMenuItemImage::create("battle/bg_dlg.png","battle/bg_dlg.png",this,menu_selector(BattleZuoLayer::myNullCallback));
	MyMenu* myMenu = MyMenu::create(myItem,NULL);
	myMenu->setPosition(_BL_ZUOBGCONTROLBTN_POS);
	this->addChild(myMenu,99,99);
	
	// 側邊欄
	CCSprite* zuoBGPic = CCSprite::create("battle/bg_dlg.png");
	zuoBGPic->setPosition(_BL_ZUOBGCONTROLBTN_POS);
	this->addChild(zuoBGPic,100,100);

	// "戰役"點選的圖檔
	CCControlButton* btn_battleControlBtn = CCControlButton::create(CCScale9Sprite::create("battle/btn_battle_over.png"));
	btn_battleControlBtn->setPosition(_BL_BTN_BATTLECONTROLBTN_POS);
	btn_battleControlBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(BattleZuoLayer::btn_battleControlBtnUpIn), CCControlEventTouchUpInside);
	btn_battleControlBtn->setPreferredSize(CCSizeMake(22,136));
	zuoBGPic->addChild(btn_battleControlBtn);

	// 底圖框1(文字介紹底圖框)
	CCScale9Sprite* ditukuang1 = CCScale9Sprite::create("cityBuilding/cityBuildingInfo/kuang1.png");
	ditukuang1->setContentSize(CCSizeMake(200,180));
	ditukuang1->setPosition(_BL_DITUKUANG1_POS);
	zuoBGPic->addChild(ditukuang1);

	// 四個戰役按鈕圖檔
	int position1[4][2] = {{140,220},{140,170},{140,120},{140,70}};
	for (int i=1; i<=4; i++)
	{
		CCControlButton* zhanyiControlBtn1 = CCControlButton::create(CCScale9Sprite::create("battle/greenbtn01.png"));
		zhanyiControlBtn1->setPosition(ccp(position1[i-1][0],position1[i-1][1]));
		zhanyiControlBtn1->addTargetWithActionForControlEvents(this,cccontrol_selector(BattleZuoLayer::zhanyiControlBtn1UpInside),CCControlEventTouchUpInside);
		zhanyiControlBtn1->setPreferredSize(CCSizeMake(116,36));	// 點選區域
		zhanyiControlBtn1->setZoomOnTouchDown(false);		// 點選是否放大
		zuoBGPic->addChild(zhanyiControlBtn1,0,200+i);
	}

	// 選中戰役後的按鈕圖檔(起初預設在第一個)
	CCControlButton* zhanyiControlBtn2 = CCControlButton::create(CCScale9Sprite::create("battle/greenbtn02.png"));
	zhanyiControlBtn2->setPosition(ccp(position1[0][0],position1[0][1]));
	zhanyiControlBtn2->addTargetWithActionForControlEvents(this,cccontrol_selector(BattleZuoLayer::zhanyiControlBtn2UpInside),CCControlEventTouchUpInside);
	zhanyiControlBtn2->setPreferredSize(CCSizeMake(116,36));	// 點選區域
	zhanyiControlBtn2->setZoomOnTouchDown(false);		// 點選是否放大
	zuoBGPic->addChild(zhanyiControlBtn2,10,210);

	// 四個按鈕圖檔上面的文字
	for (int i=1; i<=4; i++)
	{
		std::string arr[] = {"兵臨華沙", "馬其諾防線", "敦刻爾克", "基輔會戰"};
		std::string china1_label = arr[i-1];
		GBKToUTF8(china1_label, "gbk", "utf-8");
		CCLabelTTF* labelTTF1 = CCLabelTTF::create(china1_label.c_str(), "Marker Felt", 14);
		labelTTF1->setPosition(ccp(position1[i-1][0],position1[i-1][1]));
		zuoBGPic->addChild(labelTTF1,20);
	}

	// 戰役介紹的文字内容
	BattleZuoLayer::china2Show(1);


	return true;
}


// myMenu空回調函數
void BattleZuoLayer::myNullCallback(CCObject* pSender){}

// "戰役"圖檔點選回調函數
void BattleZuoLayer::btn_battleControlBtnUpIn(CCObject* pSender, CCControlEvent controlEvent)
{
	// 側邊欄進/出
	if (this->getChildByTag(100)->getPositionX() == -250)
	{
		this->getChildByTag(100)->runAction(CCMoveBy::create(0.3,ccp(470,0)));
		this->getChildByTag(99)->runAction(CCMoveBy::create(0.3,ccp(470,0)));
	}
	else
	{
		this->getChildByTag(100)->runAction(CCMoveBy::create(0.3,ccp(-470,0)));
		this->getChildByTag(99)->runAction(CCMoveBy::create(0.3,ccp(-470,0)));
	}
}

// 四個戰役按鈕圖檔的點選回調函數
void BattleZuoLayer::zhanyiControlBtn1UpInside(CCObject* pSender, CCControlEvent controlEvent)
{
	// theTag   
	int theTag = ((CCNode*)pSender)->getTag();

	// 選中效果的圖檔的坐标改變
	this->getChildByTag(100)->getChildByTag(210)->setPosition(this->getChildByTag(100)->getChildByTag(theTag)->getPosition());

	// 相關戰役文字介紹
	BattleZuoLayer::china2Show(theTag-200);

	// 切換到相關戰役界面
	BattleZuoLayer::zhanyiShow(theTag-200);
}

// 選中戰役後的按鈕圖檔的點選回調空函數
void BattleZuoLayer::zhanyiControlBtn2UpInside(CCObject* pSender, CCControlEvent controlEvent){}

// 戰役介紹的文字内容顯示函數
void BattleZuoLayer::china2Show(int i)
{
	// 移除之前顯示的文字
	if (this->getChildByTag(100)->getChildByTag(300))
	{
		this->getChildByTag(100)->removeChildByTag(300,true);
	}

	// 文字顯示
	std::string arr[] = {"聯合帝國突襲波蘭,數天之後便占領但澤走廊,并且以每天60公裡的速度向波蘭首都華沙推進。在帝國軍隊狂轟亂炸下,暫時的安全處所已經成為了波蘭人民奢華的享受。",\
		"為防止聯合帝國入侵而建造的鋼筋混領土壁壘。1940年5月,帝國部隊施展調虎離山計成功的從防禦薄弱的地方繞過了馬其諾防線。", \
		"同樣式1940年,因比利時投降,近40萬盟軍被困敦刻爾克。為儲存有生力量,盟軍在敦刻爾克上演了一次大規模撤退奇迹。", \
		"基輔會戰是戰争史上規模最大的一次圍殲戰。對帝國來說是一次空前的傑作,但很多人認為:這場漂亮的圍殲戰讓帝國失去了戰争史上最偉大的戰争。"};
	std::string china2_label = arr[i-1];
	GBKToUTF8(china2_label, "gbk", "utf-8");
	CCLabelTTF* labelTTF2 = CCLabelTTF::create(china2_label.c_str(), "Marker Felt", 16, CCSizeMake(180,160), kCCTextAlignmentLeft,kCCVerticalTextAlignmentTop);
	labelTTF2->setPosition(_BL_DITUKUANG1_POS);
	this->getChildByTag(100)->addChild(labelTTF2,0,300);
}

// 各個戰役界面顯示函數
void BattleZuoLayer::zhanyiShow(int i)
{
	// 移除之前顯示過的圖層
	if (theAScene_global->getChildByTag(103)->getChildByTag(1000))
	{
		theAScene_global->getChildByTag(103)->removeChildByTag(1000,true);
	}

	// 顯示場景界面layer
	bl_showNumber = i;
	BattleShowLayer* battleShowLayer = BattleShowLayer::create();
	theAScene_global->getChildByTag(103)->addChild(battleShowLayer,0,1000);

	// 底部遮擋圖檔重新再加載(cocos2d-x的touch處理機制貌似是後addChild先響應,再看會不會往下傳遞,是以為了不向下傳遞必須在要屏蔽的對象後再加載一遍)
	if (this->getChildByTag(99))
	{
		this->removeChildByTag(99,true);
	}
	CCMenuItem* myItem = CCMenuItemImage::create("battle/bg_dlg.png","battle/bg_dlg.png",this,menu_selector(BattleZuoLayer::myNullCallback));
	MyMenu* myMenu = MyMenu::create(myItem,NULL);
	myMenu->setPosition(this->getChildByTag(100)->getPosition());
	this->addChild(myMenu,99,99);

	// 四個戰役按鈕圖檔重新再加載
	for (int i=1; i<=4; i++)
	{
		this->getChildByTag(100)->removeChildByTag(200+i,true);
	}
	int position1[4][2] = {{140,220},{140,170},{140,120},{140,70}};
	for (int i=1; i<=4; i++)
	{
		CCControlButton* zhanyiControlBtn1 = CCControlButton::create(CCScale9Sprite::create("battle/greenbtn01.png"));
		zhanyiControlBtn1->setPosition(ccp(position1[i-1][0],position1[i-1][1]));
		zhanyiControlBtn1->addTargetWithActionForControlEvents(this,cccontrol_selector(BattleZuoLayer::zhanyiControlBtn1UpInside),CCControlEventTouchUpInside);
		zhanyiControlBtn1->setPreferredSize(CCSizeMake(116,36));	// 點選區域
		zhanyiControlBtn1->setZoomOnTouchDown(false);		// 點選是否放大
		this->getChildByTag(100)->addChild(zhanyiControlBtn1,0,200+i);
	}
}
           

這裡面代碼(1)(2)是MyMenu的例子,(7)(8)裡面控制touch傳遞的例子