閱讀476 返回首頁    go 阿裏雲 go 技術社區[雲棲]


Cocos2d-x實例:單點觸摸事件

為了讓大家掌握Cocos2d-x中的事件機製下麵我們以觸摸事件為例使用事件觸發器實現單點觸摸事件。該實例如圖8-3所示場景中有三個方塊精靈顯示順序如圖8-3所示拖拽它們可以移動它們事件響應優先級是按照它們的顯示順序。

下麵我們再看看具體的程序代碼首先看一下HelloWorldScene.h文件它的代碼如下

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__
 
#include "cocos2d.h"
typedef enum                                                                                                                                         ①
{
    kBoxA_Tag = 102
   ,kBoxB_Tag
   ,kBoxC_Tag
} SpriteTags;                                                                                                                                 ②
 
 
class HelloWorld : public cocos2d::Layer
{
public:
   static cocos2d::Scene* createScene();
   virtual bool init();          
    virtualvoid onEnter();                                                                                                                      ③
    virtualvoid onExit();                                                                                                                         ④
   
    booltouchBegan(cocos2d::Touch* touch, cocos2d::Event* event);                                          ⑤
   void touchMoved(cocos2d::Touch *touch, cocos2d::Event *event);                                       ⑥
   void touchEnded(cocos2d::Touch *touch, cocos2d::Event *event);                                       ⑦
 
   CREATE_FUNC(HelloWorld);
};
 
#endif // __HELLOWORLD_SCENE_H__

上述代碼第①~②行是定義個枚舉類型SpriteTags枚舉類型SpriteTags中定義了三個常量這三個常量對應場景中的三個精靈的標簽Tag屬性。代碼第③行聲明了層聲明周期的onEnter()函數我們將在該函數中注冊監聽器和初始化設置。第④行代碼是聲明了層聲明周期的onExit()函數我們將在該函數中注銷監聽器和釋放一些資源。代碼第⑤~⑥行是聲明單點觸摸事件回調函數。

HelloWorldScene的實現代碼HelloWorldScene.ccp文件它的HelloWorld::init()代碼如下

bool HelloWorld::init()
{
    if( !Layer::init() )
    {
         returnfalse;
    }
 
    SizevisibleSize = Director::getInstance()->getVisibleSize();
    Pointorigin = Director::getInstance()->getVisibleOrigin();
 
    //貼圖的紋理圖片寬高必須是2的n次冪128x128
    autobg = Sprite::create("BackgroundTile.png",
                                Rect(0,0, visibleSize.width, visibleSize.height));                                               ①
    //貼圖的紋理參數水平重複平鋪垂直重複平鋪
    Texture2D::TexParamstp = {GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT};                 ②
    bg->getTexture()->setTexParameters(tp);                                                                             ③
    bg->setPosition(origin+ Point(visibleSize.width/2, visibleSize.height/2));
    addChild(bg,0);                                                                                                                                ④
 
    Sprite*boxA = Sprite::create("BoxA2.png");                                                                                   ⑤
    boxA->setPosition(origin+Point(visibleSize.width/2,visibleSize.height/2) + Point(-120, 120));
    addChild(boxA,10, kBoxA_Tag);
 
    Sprite*boxB = Sprite::create("BoxB2.png");
    boxB->setPosition(origin+Point(visibleSize.width/2,visibleSize.height/2));
    addChild(boxB,20, kBoxB_Tag);
 
    Sprite*boxC = Sprite::create("BoxC2.png");
    boxC->setPosition(origin+Point(visibleSize.width/2,visibleSize.height/2) + Point(120, 160));
    addChild(boxC,30, kBoxC_Tag);                                                                                         ⑥
 
    returntrue;
}

我們在HelloWorld::init()函數中初始化了場景中的背景和三個方塊精靈。代碼第①~④行是創建並添加背景圖8-3所示的背景是由一個128x128紋理圖片BackgroundTile.png反複貼圖上這樣可以減少內存消耗在第①行代碼中創建背景精靈對象注意背景的大小仍然是整個屏幕。第②行代碼是設置貼圖的紋理的參數Texture2D::TexParams類型是一個結構體。第③行代碼是將參數設置到背景精靈的紋理上。第④行代碼是添加背景精靈到當前層。

代碼第⑤~⑥行是創建了三個方塊精靈在添加它到當前層的時候我們使用三個參數的addChild(Node* child,int localZOrder,int tag)函數這樣可以通過localZOrder參數指定精靈的顯示順序。

HelloWorldScene.ccp中的HelloWorld::onEnter()代碼如下
void HelloWorld::onEnter()
{
    Layer::onEnter();
    log("HelloWorldonEnter");
 
    autolistener = EventListenerTouchOneByOne::create();                                                             ①
   
    listener->setSwallowTouches(true);                                                                                      ②
    listener->onTouchBegan= CC_CALLBACK_2(HelloWorld::touchBegan, this);                         ③
    listener->onTouchMoved=  CC_CALLBACK_2(HelloWorld::touchMoved,this);                     ④
    listener->onTouchEnded=  CC_CALLBACK_2(HelloWorld::touchEnded,this);                     ⑤
 
    //添加監聽器
    EventDispatcher*eventDispatcher = Director::getInstance()->getEventDispatcher();              ⑥
    eventDispatcher->addEventListenerWithSceneGraphPriority(listener,
                                                                            getChildByTag(kBoxA_Tag));                                  ⑦
    eventDispatcher->addEventListenerWithSceneGraphPriority(listener->clone(),
                                                                            getChildByTag(kBoxB_Tag));                                  ⑧
    eventDispatcher->addEventListenerWithSceneGraphPriority(listener->clone(),
                                                                            getChildByTag(kBoxC_Tag));                                 ⑨
 
}

上述代碼第①行是創建一個單點觸摸事件監聽器對象。第②行代碼是設置是否吞沒事件如果設置為true那麼在onTouchBegan函數返回 true 時吞沒事件事件不會傳遞給下一個Node對象。第③行代碼是設置監聽器的onTouchBegan屬性回調函數。第④行代碼是設置監聽器的onTouchMoved屬性回調函數。第⑤行代碼是設置監聽器的onTouchEnded屬性回調函數。

代碼第⑥~⑨行是添加監聽器其中第⑦行使用精靈顯示優先級添加事件監聽器其中參數getChildByTag(kBoxA_Tag)是通過精靈標簽Tag實現獲得精靈對象。第⑧行和第⑨行代碼是為另外兩精靈添加事件監聽器其中listener->clone()獲得listener對象使用clone()函數是因為每一個事件監聽器隻能被添加一次addEventListenerWithSceneGraphPriority和addEventListenerWithFixedPriority會在添加事件監聽器時設置一個注冊標識一旦設置了注冊標識該監聽器就不能再用於注冊其它事件監聽了因此我們需要使用listener->clone()克隆一個新的監聽器對象把這個新的監聽器對象用於注冊。

HelloWorldScene.ccp中的觸摸事件回調函數代碼如下

bool HelloWorld::touchBegan(Touch*touch, Event* event)                                                            ①
{
    //獲取事件所綁定的 target
    autotarget = static_cast<Sprite*>(event->getCurrentTarget());                                                    ②
    PointlocationInNode = target->convertToNodeSpace(touch->getLocation());                         ③
    Sizes = target->getContentSize();                                                                                          ④
    Rectrect = Rect(0, 0, s.width, s.height);                                                                                         ⑤
 
    //點擊範圍判斷檢測
    if(rect.containsPoint(locationInNode))                                                                                         ⑥
    {
         log("spritex = %f, y = %f ", locationInNode.x, locationInNode.y);
         log("spritetag = %d", target->getTag());
         target->runAction(ScaleBy::create(0.06f,1.06f));                                                             ⑦
         returntrue;                                                                                                                                     ⑧
    }
    returnfalse;
}
 
void HelloWorld::touchMoved(Touch*touch, Event *event)                                                           ⑨
{
    log("onTouchMoved");
    autotarget = static_cast<Sprite*>(event->getCurrentTarget());
    target->setPosition(target->getPosition()+ touch->getDelta());                                                   ⑩
}
 
void HelloWorld::touchEnded(Touch*touch, Event *event)                                                           ⑪
{
    log("onTouchEnded");
    autotarget = static_cast<Sprite*>(event->getCurrentTarget());
    log("spriteonTouchesEnded.. ");
 
    PointlocationInNode = target->convertToNodeSpace(touch->getLocation());
    Sizes = target->getContentSize();
    Rectrect = Rect(0, 0, s.width, s.height);
    //點擊範圍判斷檢測
    if(rect.containsPoint(locationInNode))
    {
         log("spritex = %f, y = %f ", locationInNode.x, locationInNode.y);
         log("spritetag = %d", target->getTag());
         target->runAction(ScaleTo::create(0.06f,1.0f));
    }
}

上代碼第①行是定義回調函數touchBegan。第②行代碼是獲取事件所綁定的精靈對象其中event->getCurrentTarget()語句返回值是Node對象static_cast<Sprite*>是強製類型轉換為Sprite對象。第③行代碼是獲取當前觸摸點相對於target對象的本地坐標。第④行代碼是獲得target對象的尺寸。第⑤行代碼是通過target對象的尺寸創建Rect變量。第⑥行代碼rect.containsPoint(locationInNode)是判斷是否觸摸點在target對象範圍。第⑦行代碼是放大target對象。第⑧行代碼返回true表示可以回調第⑨行touchMoved函數和第⑪行touchEnded函數。第⑩行代碼是移動target對象的位置。

HelloWorldScene.ccp中的HelloWorld::onExit()代碼如下

void HelloWorld::onExit()
{
    Layer::onExit();
    log("HelloWorldonExit");
    Director::getInstance()->getEventDispatcher()->removeAllEventListeners();
}

上述HelloWorld::onExit()函數是退出層時候回調我們在這個函數中注銷所有的監聽事件。

提示 多點觸摸事件是與具體的平台有關係的在Win32平台下我們無法測試多點觸摸。事實上多點觸摸和單點觸摸開發流程基本相似這裏我們就不再贅述了。


《Cocos2d-x實戰 C++卷》現已上線各大商店均已開售

京東https://item.jd.com/11584534.html

亞馬遜https://www.amazon.cn/Cocos2d-x%E5%AE%9E%E6%88%98-C-%E5%8D%B7-%E5%85%B3%E4%B8%9C%E5%8D%87/dp/B00PTYWTLU

當當https://product.dangdang.com/23606265.html

互動出版網https://product.china-pub.com/3770734

《Cocos2d-x實戰 C++卷》源碼及樣章下載地址

源碼下載地址https://51work6.com/forum.php?mod=viewthread&tid=1155&extra=page%3D1 

樣章下載地址https://51work6.com/forum.php?mod=viewthread&tid=1157&extra=page%3D1

歡迎關注智捷iOS課堂微信公共平台

最後更新:2017-04-03 05:39:30

  上一篇:go graph driver-device mapper-03thin pool基本操作
  下一篇:go 配置 mysql/mariadb sphinxSE 錯誤解決 1st column must be bigint to accept 64-bit DOCID