cocos2d-x自定義可點選/可處理事件/可接受觸屏訊息的Sprite
本篇大部分摘自http://blog.csdn.net/onerain88/article/details/7550009(寫的好清楚)
一般經常用到的觸屏的情況有兩種:一種是Layer統一接收觸屏訊息,然後由程式根據需要分發給不同位置的精靈;另一種情況是自定義一個可以接收觸屏訊息的Sprite,比如類似於Button功能的Sprite,這就需要在定義Sprite的時候就要定義好觸屏所觸發的操作!
1.Layer接收觸屏訊息(請參考原文)
總結下就是:在layer中的sprite,他們可能會處於同一層,那麼,最重要的就是怎麼把事件傳遞給希望處理事件的sprite。方法就是通過優先順序去“接收事件”,如果不處理,ccTouchBegin的返回值就設定為false,如果處理,就設定為true,表示攔截此訊息。這樣,事件就不會往更低優先順序的sprite傳遞了。
2.自定義可以接收觸屏訊息的Sprite
首先要先繼承CCSprite或者其父類,以滿足精靈形狀,位置等資訊的要求,另外還需要繼承觸屏事件委託CCTargetedTouchDelegate,CCTargetedTouchDelegate中定義了接收觸屏資訊的回撥虛擬函式,而這些虛擬函式,正是我們需要覆寫的部分,程式碼如下
class TouchableSprite: public CCSprite, public CCTargetedTouchDelegate
{
public:
TouchableSprite();
virtual ~TouchableSprite();
static TouchableSprite *touchSpriteWithFile(const char *file);
bool initWithFile(const char *file);
virtual void onEnter();
virtual void onExit();
CCRect rect();
bool containsTouchLocation(CCTouch *touch);
virtual bool ccTouchBegan(CCTouch *touch, CCEvent *event);
virtual void ccTouchMoved(CCTouch *touch, CCEvent *event);
virtual void ccTouchEnded(CCTouch *touch, CCEvent *event);
};
重點在於判斷自定義Sprite是否被點選,這時就需要得到精靈所在的矩形了,這時又有兩種判斷方式
(1)得到觸屏所在位置,然後根據精靈所在位置的矩形區域和觸屏的點判斷是否包含,如果包含,則說明觸控到了Sprite。這裡寫了一個得到精靈當前所在矩形的方法
CCRect TouchableSprite::rect()
{
CCSize size = getContentSize();
CCPoint pos = getPosition();
return CCRectMake(pos.x - size.width / 2, pos.y - size.height / 2, size.width, size.height); }
然後在每次點選的時候都需要將當前觸屏位置轉換為GL座標的位置,然後和Sprite所在矩形做包含判斷
bool TouchableSprite::containsTouchLocation(cocos2d::CCTouch *touch)
{
CCPoint touchPoint = touch->locationInView(touch->view()); //這裡由於版本更新,改為touch->getLoactionInView()
touchPoint = CCDirector::sharedDirector()->convertToGL(touchPoint);
return CCRect::CCRectContainsPoint(rect(), touchPoint);
}
轉載作者補充:
可以使用getLocation()取代上面那兩句程式碼,cocos2d-x相關原始碼如下:
// returns the current touch location in screen coordinates
CCPoint CCTouch::getLocationInView() const
{
return m_point;
}
// returns the current touch location in OpenGL coordinates
CCPoint CCTouch::getLocation() const
{
return CCDirector::sharedDirector()->convertToGL(m_point);
}
這裡要提下座標系統,getLocationInView獲取的是螢幕座標,不同裝置座標系統不同,例如ios是左上角為原點。而cocos2d-x是左下角為原點。所以在cocos2d-x中做運算時候,要轉為GL座標系,即cocos2d-x預設的“可視螢幕的座標系統”。
(2)其實cocos2d為我們提供了一種相對簡單的方法,但是原理類似,呼叫CCNode中定義的convertTouchToNodeSpaceAR()方法,將觸屏點轉化為相對於結點的相對座標
CCRect TouchableSprite::rect()
{
CCSize size = getTexture()->getContentSize();
return CCRectMake(-size.width / 2, -size.height / 2, size.width, size.height);
}
bool TouchableSprite::containsTouchLocation(cocos2d::CCTouch *touch)
{
return CCRect::CCRectContainsPoint(rect(), convertTouchToNodeSpaceAR(touch));
}
關於事件處理還可以參考本文
http://blog.linguofeng.com/archive/2012/09/12/cocos2d-x-touch.html
可以借鑑該文點選事件處理方法
void MyLayer::ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent) {
// 單點
CCTouch *pTouch = (CCTouch*)(pTouches->anyObject());
// 所有點
for(CCSetIterator iterTouch = pTouches->begin(); iterTouch != pTouches->end(); iterTouch++) {
CCTouch *pCurTouch = (CCTouch*)(*iterTouch);
}
// 獲取點在檢視中的座標(左上角為原點)
CCPoint touchLocation = pTouch->getLocationInView();
// 把點的座標轉換成OpenGL座標(左下角為原點)
touchLocation = CCDirector::sharedDirector()->convertToGL(touchLocation);
// 把OpenGL的座標轉換成CCLayer的座標
CCPoint local = convertToNodeSpace(touchLocation)
// 大小為100x100,座標為(0, 0)的矩形
CCRect * rect = CCRectMake(0, 0, 100, 100);
// 判斷該座標是否在rect矩形內
bool flag = rect.containsPoint(local)
if(flag) {
// 回撥
} else {
// 不執行
}
}
其它處理方法,可以借鑑CCTableView
http://blog.csdn.net/xzongyuan/article/details/9177421
觸屏傳遞順序
另外需要主要的是
virtual bool ccTouchBegan(CCTouch *touch, CCEvent *event);
方法,其返回值是對此觸屏訊息有影響的,簡單來說,如果返回false,表示不處理ccTouchMoved(),ccTouchEnded(),ccTouchCanceld()方法,而交由後續接收觸屏訊息的物件處理;如果返回true,表示會處理ccTouchMoved(),ccTouchEnded(),ccTouchCanceld()方法,並且消耗掉此觸屏訊息。
最後,要在進入時候新增觸屏介面
void TouchableSprite::onEnter(){
CCSprite::onEnter();
CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this,0,true);
}
void TouchableSprite::onExit(){
CCSprite::onExit();
CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);
}
相關文章
- 自定義事件相容處理物件事件物件
- 移動端VUE點選、滑動和長按等事件處理(自定義指令)Vue事件
- Flutter視訊編輯軌道 | 自定義View實現UI互動效果 | 觸控事件處理FlutterViewUI事件
- tabbar凸起點選事件處理tabBar事件
- cmp是可選的自定義比較函式函式
- iOS 環信 EaseUI 的使用一:可傳送類似名片自定義的訊息iOSUI
- 科學家發明人工突觸:可處理複雜資訊
- js 建立和觸發事件 和 自定義事件JS事件
- 如何在Mac上設定自定義鎖屏訊息?Mac
- 如何使用JSR303驗證及自定義訊息統一處理JS
- Mac使用技巧_蘋果鎖屏介面如何自定義鎖屏訊息?Mac蘋果
- Flutter自定義折線圖並新增點選事件Flutter事件
- 如何在丟失的Mac上設定自定義鎖屏訊息Mac
- Netty中自定義事件處理程式和監聽器Netty事件
- hadoop自定義許可權Hadoop
- ASPxGridView中Command列自定義按鈕點選事件概要View事件
- ros|自定義訊息型別ROS型別
- flutter seekbar 可拖拽可點選的進度條Flutter
- Android事件傳遞、多點觸控及滑動衝突的處理Android事件
- 元件間通訊--自定義事件元件事件
- node那點事(二) — Writable streams(可寫流)、自定義流
- node那點事(二) -- Writable streams(可寫流)、自定義流
- android動態許可權到自定義許可權框架Android框架
- Flutter利用註解生成可自定義的路由Flutter路由
- Siri自定義Intent以及處理Intent
- 語音訊號處理獲取 NFFT 的自定義函式音訊FFT函式
- 阿里雲訊息佇列 RocketMQ 5.0 全新升級:訊息、事件、流融合處理平臺阿里佇列MQ事件
- Android自定義字型--自定義TextView(可擴充套件不同ttf字Android自定義字型TextView套件
- nodejs開發微信公眾號中控服務(處理訊息、獲取token及jssdk簽名、自定義選單)NodeJS
- 直播平臺開發,TabLayout的使用和自定義紅點訊息提示TabLayout
- 修改button的可點選區域
- 【讀書筆記】:《編寫可維護的JavaScript》第07章 事件處理筆記JavaScript事件
- DoorDash使用 Kafka 和 Flink 構建可擴充套件的實時事件處理Kafka套件事件
- RabbitMQ如何保證訊息的可達性MQ
- WIN32傳送自定義訊息Win32
- 【爬坑日記】iview使用render自定義渲染觸發事件View事件
- 【Django】DRF自定義異常處理Django
- DRF內建許可權元件之自定義許可權管理類元件