1. 程式人生 > >Cocos2d-x例項:單點觸控事件

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例項觸控事件

為了讓大家掌握Cocos2d-x中的事件機制,下面我們以觸控事件為例,使用事件觸發器實現單點觸控事件。該例項如圖8-3所示,場景中有三個方塊精靈,顯示順序如圖8-3所示,拖拽它們可以移動它們,事件響應優先順序是按照它們的顯示順序。下面我們再看看具體的程式程式碼,首先看一下HelloWorldScene.h檔案

cocos2d-x處理觸控事件

這篇文章真的很菜鳥,但是出於考慮到cocos2d-x的資料真的不好查,網上又是千古文章一大抄,抄了很多還是很多的錯誤,所以還是寫一篇部落格。 cocos2d-x的觸控事件有多種方式,單點觸控最為簡單。 首先我們新建一個Cocos2d-win32 Application,轉到

cocos2d-x-lua 觸控事件

示例程式碼: local player = cc.Sprite:create(fileName) player:runAction(self:flyaction()) -

cocos2d-x 3.5】Lua觸控事件

程式碼1 local listenner = cc.EventListenerTouchOneByOne:create() listenner:registerScriptHandler(function(touch, event) local location

cocos2d-x 3.0 動畫與觸控事件總結

動畫與觸控 動畫 動畫分為兩部分  animation   與 animate   將動畫類比為連環畫,則 animation相當於造書的過程而 animate則為快速翻書的動作通常會再新增一個repeateForever的動作,確保動畫一直繼續下去 1️⃣animatio

Cocos2d-x 觸控--讓精靈隨手指移動起來

效果圖: CCTouch類裝載了觸控點的資訊,包括觸控點的橫縱座標值和觸控點的ID號,如獲取觸控點轉GL座標: CCPoint point = pTouch->getLocationInView(); point = CCDirector::sharedD

cocos2d-x觸控觸控同用實現

    有時遊戲中有的介面要使用單點觸控,有的介面要使用多點觸控,但是單點和多點又不能同時註冊,因為同時註冊時,單點觸控的優先順序高於多點觸控,所以會響應單點觸控,多點觸控被遮蔽。    因為在寫遊戲的時候自定義層的基類中是註冊了單點觸控,所以每個繼承該基類的層都會有單點觸控

HTML5觸控事件(多觸控

本文轉自:http://www.360us.net/article/9.html HTML5的觸控API支援處理單點和多點的觸控事件處理。 介面 1、TouchEvent:代表了一個觸控事件。 主要屬性: TouchEvent.chang

cocos2dx學習之路----第九篇(深入理解觸控事件機制)

上一篇我們簡單接觸了關於單點觸控的實現。 這一篇我們繼續進一步的理解單點觸控的事件分發的優先順序問題。 我們來回顧一下實現觸控的過程: 1.建立新的監聽器; 2.為新的監聽器分配回撥函式(而我們在上一篇中用到了Lamda表示式來實現); 3.註冊分發監聽器。 好,這一篇就是

關於cocos2d-x 3.0的擊交互處理

clipboard 3.0 static php 此外 eas -h con spl 轉自:http://blog.csdn.net/fansongy/article/details/12716671 1、概述 遊戲也好,程序也好,僅僅有能與

Android零基礎入門第66節RecyclerView事件處理

系統 ava oid 文章 click事件 需要 spin 圖像 line 前面兩期學習了RecyclerView的簡單使用,並為其item添加了分割線。在實際運用中,無論是List還是Grid效果,基本都會伴隨著一些點擊操作,那麽本期就來一起學習RecyclerVi

登錄與權限管理本質登錄介紹

單點登錄繼續介紹「單點登錄與權限管理」系列的第一部分:單點登錄與權限管理本質,前兩篇介紹了session與cookie 和 HTTP重定向 ,有了他們,瀏覽器就可以在多個系統間自動交互,實現自動登錄。 本篇介紹下單點登錄,所謂單點登錄,就是說用戶只需在一個地方登錄,訪問其他相關系統時,不需要重復登錄,隱式地自

淺談架構之路登錄 SSO

用戶體驗 們的 建設 驗證機制 一個 簡單的 用戶登錄 集中 不同 前言:SSO 單點登錄   “半吊子”的全棧工程師又來了,技術類的文章才發表了兩篇,本來想先將主攻的幾個系列都開個頭(Nodejs、Java、前端、架構、全棧等等),無奈博客起步太晚,寫博文的時間又沒有很多

54-高級路由重分發特性重分發路由反饋

nag ast ria null process sum fig 查看 null0 一、實驗拓撲:二、實驗要求:在R1上將EIGRP 90 重分發進OSPF 110,再將OSPF重分發進RIP,查看R2、R3、R4路由表將收到哪些路由條目?三、命令部署:R1(config)

quick-cocos2d-x 學習系列之十三 觸控

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

quick-cocos2d-x例項之挑戰記憶極限設計文件

                1.  來源QuickV3 sample專案中的2048樣例遊戲,以及最近《最強大腦》娛樂節目。將2048改造成一款挑戰玩家對數字記憶的小遊戲。微信公眾號:HopToad2.  邏輯可選擇簡單,中等,困難三種難度遊戲。開局UI每種難度進入後有多個選項如下:2.1        

線段樹基礎更新,區間最值(和)查詢

單點更新,區間查詢 線段樹可以解決一類區間問題,例如最基礎的單點更新,區間最值查詢。 程式碼如下: #include<bits/stdc++.h> using namespace std; const int maxn = 10000; //原

#133. 二維樹狀陣列 1修改,區間查詢

題目描述 這是一道模板題。 給出一個 n\times mn×m 的零矩陣 AA,你需要完成如下操作: 1 x y k:表示元素 A_{x,y}Ax,y​ 自增 kk;

Android觸控技術,對圖片進行平移,縮放,旋轉操作

相信大家使用多點對圖片進行縮放,平移的操作很熟悉了,大部分大圖的瀏覽都具有此功能,有些app還可以對圖片進行旋轉操作,QQ的大圖瀏覽就可以對圖片進行旋轉操作,大家都知道對圖片進行縮放,平移,旋轉等操作可以使用Matrix來實現,Matrix就是一個3X3的矩陣,對圖片的處理可

EventListenerTouchOneByOne::create() 觸控

void HelloWorld::onEnter() { Layer::onEnter(); log("HelloWorld onEnter"); // 建立一個事件監聽器 OneByOne 為單點觸控 auto listener = EventListenerT