cocos2dx学习之自定义你的CCSprite(二)监测长按和双击
上一篇我们介绍了如何给你自定义的CCSprite添加Touch监听,但是你会发现无论你点击屏幕的哪里,我们的精灵都会收到Touch事件,为什么会这样呢,主要是CCTouchDispatcher只是实现触摸事件分发,所以每一个添加到CCTouchDispatcher上的CCTouchDelegate,都是一层,屏幕大小,这也是为什么有时候我们点击到层的外面也能接受到Touch监听的原因。不管怎么说,这是我们不想看到的。其实这里cocos2dx的源代码中已经给出了解决办法,那就是CCMenu,看看它的源代码你会发现它是做了判断Touch区域的操作。我们这里也这么做。代码如下
bool TestSprite::isInSprite(CCTouch *theTouch){
// 返回当前触摸位置在OpenGL坐标
CCPoint touchPoint=theTouch->getLocation();
// 将世界坐标转换为当前父View的本地坐标系
CCPoint reallyPoint=this->getParent()->convertToNodeSpace(touchPoint);
// 获取当前基于父view的坐标系
CCRect rect=this->boundingBox();
// CCnode->convertToNodeSpace 或者 convertToWorldSpace 是基于当前Node的 与当前Node相关
if(rect.containsPoint(reallyPoint)){
return true;
}
returnfalse;
}
这样子我们就能知道我们点击是不是我们的精灵了。下面我们来判断双击。代码如下
// 获取当前时间 精确到毫秒数
static inline long millisecondNow()
{
struct cc_timeval now;
CCTime::gettimeofdayCocos2d(&now, NULL);
return (now.tv_sec * 1000 + now.tv_usec / 1000);
}
// 判断是不是 双击
static inline bool isDoubleTouch(){
static long lastTouchTime=0;
long thisTouchTime=millisecondNow();
if(abs(thisTouchTime-lastTouchTime)<250){
lastTouchTime=0;
return true;
}
else{
lastTouchTime=millisecondNow();
return false;
}
}
就是简单的做一下两次点击的时间间隔,如果小于250毫米,就算做双击。单机我们给解决了,那么现在就是长按了,长安其实也是很简单就是,如果你touch的时间长于两秒,那么我们算做它长按。或不多说,上代码
void TestSprite::checkLongPress(){
this->unschedule(schedule_selector(TestSprite::checkLongPress));
if (isInTouch&&!isInMove) {
CCLog("LONGLONG");
this->setScale(2);
this->setOpacity(200);
afterLongPress=true;
}
}
bool TestSprite::ccTouchBegan(CCTouch *pTouch,CCEvent *pEvent){
if (this->isInSprite(pTouch)) {
isInTouch=true;
if (isDoubleTouch()) {
this->doubleClickSprite();
this->touchBeginTime=millisecondNow();
}else{
this->singleClickSprite();
this->touchBeginTime=millisecondNow();
this->schedule(schedule_selector(TestSprite::checkLongPress), 2);
}
return true;
}
returnfalse;
}
void TestSprite::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent) {
CCPoint deltaPoint=pTouch->getDelta();
CCLog("x=%f,y=%f",deltaPoint.x,deltaPoint.y);
if(fabs(deltaPoint.x)>1||fabs(deltaPoint.y)>1){
isInMove=true;
}
}
void TestSprite::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent) {
isInTouch=false;
isInMove=false;
afterLongPress=false;
// 恢复 精灵
this->setScale(1);
this->setPosition(orignalPoint);
this->setOpacity(255);
}
void TestSprite::ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent){
isInTouch=false;
isInMove=false;
afterLongPress=false;
// 恢复 精灵
this->setScale(1);
this->setPosition(orignalPoint);
this->setOpacity(255);
}
当然我们这里也是做了一个简单的判断,如果touch了一直没有move超过两秒我们才算做长按的。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?