cocos2dx-3.0(23) ScrollView 缩放 及 touch新用法

cocos2dx-3.0(23) ScrollView 缩放 及 touch新用法,第1张

概述转自 http://blog.csdn.net/ac_huang/article/details/37740515 ScrollView在3.0里面依然存在于extensions下面,看他的继承关系,他最终也是继承node,我们在来看看他的头文件应该怎么包含 1. 在头文件中添加 #include "cocos-ext.h" 在添加使用域  USING_NS_CC_EXT; 2. 添加多继承 pu

转自http://blog.csdn.net/ac_huang/article/details/37740515

ScrollVIEw在3.0里面依然存在于extensions下面,看他的继承关系,他最终也是继承node,我们在来看看他的头文件应该怎么包含

1. 在头文件中添加 #include "cocos-ext.h" 在添加使用域 USING_NS_CC_EXT;

2. 添加多继承public ScrollVIEwDelegate,如下:

@H_419_19@

[cpp] view plain copy classHelloWorld:publicLayercolor,publicScrollVIEwDelegate
我们转到ScrollVIEwDelegate里面,发现这是一个抽象基类,里面有两个纯虚函数,我们需要自己实现

@H_419_19@

copy /** *@JsNA *@luaNA */ virtualvoIDscrollVIEwDIDScroll(ScrollVIEw*vIEw)=0; /** *@JsNA *@luaNA */ voIDscrollVIEwDIDZoom(ScrollVIEw*vIEw)=0;
所以我们还需要在自己的类中添加这两行代码

@H_419_19@

copy //scrollvIEw滚动的时候会调用 voIDscrollVIEwDIDScroll(extension::ScrollVIEw*vIEw); //scrollvIEw缩放的时候会调用 voIDscrollVIEwDIDZoom(extension::ScrollVIEw*vIEw);
我们为了达到用鼠标点击图片移动时,出现缩小放大效果且能像相册一样切换图片,那么我们还需要添加触摸事件

@H_419_19@

copy boolontouchBegan(touch*touch,Event*pEvent); voIDontouchmoved(touch*touch,Event*pEvent); voIDontouchended(touch*touch,Event*pEvent);
下面直接看看在头文件中代码

@H_419_19@

copy #ifndef__HELLOWORLD_SCENE_H__ #define__HELLOWORLD_SCENE_H__ #include"cocos2d.h" #if(CC_TARGET_PLATFORM==CC_PLATFORM_ANDROID) #include"extensions/cocos-ext.h" #else #include"cocos-ext.h" #endif #include"cocostudio/CocoStudio.h" #include"CocosGUI.h" USING_NS_CC; USING_NS_CC_EXT; usingnamespacecocostudio; namespaceui; #definePHOTO_COUNT11 publicScrollVIEwDelegate { public: //there'sno'ID'incpp,sowerecommendreturningtheclassinstancepointer staticcocos2d::Scene*createScene(); //Here'sadifference.Method'init'incocos2d-xreturnsbool,insteadofreturning'ID'incocos2d-iphone virtualboolinit(); //aselectorcallback voIDmenuCloseCallback(cocos2d::Ref*pSender); voIDscrollVIEwDIDZoom(extension::ScrollVIEw*vIEw); //添加触摸 voIDaddListener(); //添加粒子系统test voIDaddParticle(); //implementthe"staticcreate()"methodmanually CREATE_FUNC(HelloWorld); //骨骼动画 Armature*m_armature; //添加UI voIDaddUI(); //添加场景(区别是我自定义的函数) voIDaddMyScene(); private: //根据手势滑动的距离和方向滚动图层 voIDadjustScrollVIEw(floatoffset); //voIDsetback(); //存放所有图片 Vector<Sprite*>m_spVec; //当前的ScrollVIEw extension::ScrollVIEw*m_scrollVIEw; //touchBegen时的触摸位置 Pointm_touchPoint; //当前是第几张图片 intm_currentPage; }; #endif//__HELLOWORLD_SCENE_H__
上面有很多不是我们这相例子里面的,不过不影响

在来看看源文件里面

@H_419_19@

copy boolHelloWorld::init() ////////////////////////////// //1.superinitfirst if(!Layercolor::initWithcolor(color4B(120,120,255))) returnfalse; } autovisibleSize=Director::getInstance()->getVisibleSize(); autoorigin=Director::getInstance()->getVisibleOrigin(); /*autoscrollLayer=Layercolor::create(color4B(0,255)); scrollLayer->setContentSize(Size(640,480)); scrollLayer->setAnchorPoint(Point(0.5,0.5)); scrollLayer->setposition(Point(visibleSize.wIDth/2-320,visibleSize.height/2-240)); this->addChild(scrollLayer);*/ m_scrollVIEw=extension::ScrollVIEw::create(Size(visibleSize.wIDth,visibleSize.height)); charspritename[15]; Layer*photolayer=Layer::create(); for(inti=1;i<=PHOTO_COUNT;++i) memset(spritename,sizeof(spritename)); sprintf(spritename,"XJ%d.jpg",i); autosprite=Sprite::create(spritename); sprite->setposition(Point(visibleSize.wIDth*(i*1.0-0.5),visibleSize.height*0.5)); //缩小一倍 //sprite->setScale(0.5); photolayer->addChild(sprite); m_spVec.pushBack(sprite); } //设置layer到滚动层容器中 m_scrollVIEw->setContainer(photolayer); //重新设置滚动层的大小,这点很重要。 m_scrollVIEw->setContentSize(Size(PHOTO_COUNT*visibleSize.wIDth,0); background-color:inherit">//设置代理 m_scrollVIEw->setDelegate(this); m_scrollVIEw->setposition(Point::ZERO); //我们只在水平方向上滚动。 m_scrollVIEw->setDirection(extension::ScrollVIEw::Direction::HORIZONTAL); m_scrollVIEw->setContentOffset(Point(0,0)); this->addChild(m_scrollVIEw); m_currentPage=0; //注册触摸,和2.x的不同了,还有一种lambda表达式的写法 /************************************************************************ *lambda表达式的写法 *autoListener1=EventListenertouchOneByOne::create(); *Listener1->ontouchBegan=[](touch*touch,Event*event) *{ *//dosomething *}; *Listener1->ontouchmoved=[](touch*touch,0); background-color:inherit">*Listener1->ontouchended=[=](touch*touch,0); background-color:inherit">*_eventdispatcher->addEventListenerWithSceneGraPHPriority(Listener,this); ************************************************************************/ autoListener=EventListenertouchOneByOne::create(); //设置是否想下传递触摸 Listener->setSwallowtouches(true); Listener->ontouchBegan=CC_CALLBACK_2(HelloWorld::ontouchBegan,248)"> Listener->ontouchmoved=CC_CALLBACK_2(HelloWorld::ontouchmoved,153); Font-weight:bold; background-color:inherit">this); Listener->ontouchended=CC_CALLBACK_2(HelloWorld::ontouchended,0); background-color:inherit">//将触摸监听添加到eventdispacher中去 _eventdispatcher->addEventListenerWithSceneGraPHPriority(Listener,0); background-color:inherit">//注册触摸结束 true; } 我们在也不需要使用settouchEnabled这个函数了,你会发现你用了以后,编译时会提示这个函数已经被否决了,可以用setEnable();代替看看如何。

对于上面的触摸我们要重点说说,说完了在继续分析 ScrollVIEw!!!

一、触摸监听Listener的创建方式有两种,

1、EventListenertouchOneByOne
2、EventListenertouchAllAtOnce,
顾名思义EventListenertouchOneByOne的意思单点触摸,EventListenertouchAllAtOnce是多点触摸
而不需要再用设置Delegate的方式来做了。
3.0触摸机制还有个不同的地方,只要是放在最上面的那个精灵,那它的触摸优先级就最高。
我们用的按钮Menu 就是用这种方式设置触摸优先级的。

二、Listener的调试优先级
我们进入addEventListenerWithSceneGraPHPriority的定义中看一下,有下面这一行代码:

@H_419_19@

copy Listener->setFixedPriority(0);


它将精灵的触摸优先级设置成0,从这里我们可以引申出两个问题,一个就是当我们要给精灵设置触摸优先级时,

因为0已经被“官府”征用了,另一个问题就是:如果自己想设置精灵的触摸优先级,那应该怎么做呢?
下面是提供的另外一种添加Listener的方法:

@H_419_19@ copy _eventdispatcher->addEventListenerWithFixedPriority(Listener1,fixedPriority); 在第二个参数里设置触摸优先级,这样就可以了。

三、多个目标如何添加触摸监听
如果多个精灵都想实现拖动的功能,那么这些精灵都可以使用Listener1这一个触摸监听,
例如我们有三个精灵,sprite,sprite2,sprite3,他们调用Listener1的方式:

@H_419_19@

copy _eventdispatcher->addEventListenerWithSceneGraPHPriority(Listener1,sprite1); _eventdispatcher->addEventListenerWithSceneGraPHPriority(Listener1->clone(),sprite2); _eventdispatcher->addEventListenerWithSceneGraPHPriority(Listener1->clone(),sprite3);
当我们进入到clone函数里面,你会发现他实现了复制触摸函数,也就是clone是专门用来这么干这的

@H_419_19@

copy EventListenertouchOneByOne*EventListenertouchOneByOne::clone() autoret=newEventListenertouchOneByOne(); if
(ret&&ret->init()) { ret->autorelease(); ret->ontouchBegan=ontouchBegan; ret->ontouchmoved=ontouchmoved; ret->ontouchended=ontouchended; ret->ontouchCancelled=ontouchCancelled; ret->_claimedtouches=_claimedtouches; ret->_needSwallow=_needSwallow; else CC_SAFE_DELETE(ret); returnret; }
四、 删除触摸监听

如果想移除sprite的触摸移动,可以这么做:

@H_419_19@

copy _eventdispatcher->removeEventListeners(EventListener::Type::touch_ONE_BY_ONE);
看完了新版 touch 我们继续看scrollVIEw中的委托方法,实现效果是对象在某个坐标范围内移动时会有缩放效果。

@H_419_19@ copy voIDHelloWorld::scrollVIEwDIDScroll(extension::ScrollVIEw*vIEw) //往右移动x坐标为正,往左移为负 autooffPos=vIEw->getContentOffset(); //log("offsetpos%f%f",offPos.x,offPos.y); for(autosp:m_spVec) //获得当前对象的X坐标(不管怎么滚动,这个坐标都是不变的) autopointX=sp->getpositionX(); //将精灵的X坐标+偏移X坐标 floatoffX=pointX+offPos.x; //我的屏幕大小设置为了480*640,我的图片为320*480,我让图片居中显示(Point(160,320)--->Point(320,320)) //图片与图片之间的间隔是一个屏幕(480),我移动图片时不想让他缩放的太小,即只在80-240之间缩放,由于要对称,所以 //相应的240-400也会产生和80-240之间相同的缩放比例,这样后一种需要用480-offx if(offX>80&&offX<=240) floatscaleX=offX/240; sp->setScale(scaleX); //log("scaleX1%f",scaleX); elseif(offX>240&&offX<=400) floatscaleX=(480-offX)/240; //log("scaleX2%f",0); background-color:inherit">//对于在80-400之外的,我们保持同一缩放比例 sp->setScale(80*1.0/240); }
我们应该知道,对象放到滚动层上,那么不管对象在scrollVIEw上如何移动,它获得的坐标都是不会变的(如sp->getposition()是不变的数值),这种情况下,如果我们想实现对象在某个坐标范围内会有缩放效果,那么只是去获取对象的坐标肯定是行不通的,所以肯定要找一个时刻在变化的”参照物”来利用下,该找什么呢?没错,就是scrollVIEw的偏移坐标(scrollVIEw->getContentOffset())!只要scrollVIEw移动一下,那么它的 偏移量也随之改变。我这里就是利用对象的坐标与scrollVIEw的偏移坐标之间不可告人的秘密,从而实现当前的目的。

实现了缩放,怎么去实现图片切换了,我们需要在触摸结束后,来切换ScrollVIEw的偏移来达到切换效果

@H_419_19@ copy boolHelloWorld::ontouchBegan(touch*touch,Event*pEvent) m_touchPoint=Director::getInstance()->convertToGL(touch->getLocationInVIEw()); log("beginx=%f,y=%f",m_touchPoint.x,m_touchPoint.y); }
获得一个触摸初始值,将来与结束值对比来做出一些约束

@H_419_19@ copy voIDHelloWorld::ontouchended(touch*touch,108); List-style:decimal-leading-zero outsIDe; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> PointendPoint=Director::getInstance()->convertToGL(touch->getLocationInVIEw()); floatdistance=endPoint.x-m_touchPoint.x; log("endx=%f,endPoint.x,endPoint.y); //当我们移动的距离太小了,默认为不移动,也可以防止不小心碰了一下就切换了 if(fabs(distance)<=240) log("thisis1"); adjustScrollVIEw(0); if(fabs(distance)>240) log("thisis2"); adjustScrollVIEw(distance); } 去看看adjustScrollVIEw里面实现了什么?

@H_419_19@ copy <spanstyle="Font-family:Arial;Font-size:14px;">voIDHelloWorld::adjustScrollVIEw(floatoffset) if(offset<0) ++m_currentPage; if(offset>0) --m_currentPage; if(m_currentPage<0) if(m_currentPage>=PHOTO_COUNT) m_currentPage=1; autovisibleSize=Director::getInstance()->getVisibleSize(); //注意这里为负的visibleSize.wIDth,我开始写成正的,一直不出效果 PointcurPoint(-visibleSize.wIDth*m_currentPage,0); this->m_scrollVIEw->setContentOffset(curPoint); //setback }</span><spanstyle="Font-family:Simsun;Font-size:14px;"> </span>
此程序依然存在一些BUG,比如一下子滑动了很远的距离,那样图片的切换就会变得杂乱无章,这个依然可以在 触摸结束里面使用distance 来限制,留给以后去完善吧!!

下面看看效果:

@H_419_19@

总结

以上是内存溢出为你收集整理的cocos2dx-3.0(23) ScrollView 缩放 及 touch新用法全部内容,希望文章能够帮你解决cocos2dx-3.0(23) ScrollView 缩放 及 touch新用法所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1029847.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-23
下一篇 2022-05-23

发表评论

登录后才能评论

评论列表(0条)

保存