我忘了我这篇测试的主要目的是干啥了...。
就算往项目上靠靠吧,我项目里面要用到CCArmature这个,给这个实现单指拖拽,双指缩放功能。
新建类MyArmature,和MySprite类似,如下:
MyArmature.h
1 // 2 // MyArmature.h 3 // TouchesTest 4 // 5 // Created by HanHongmin on 13-12-29. 6 // 7 // 8 9 #ifndef __TouchesTest__MyArmature__10 #define __TouchesTest__MyArmature__11 12 #include "cocos2d.h"13 #include "cocos-ext.h"14 using namespace cocos2d;15 using namespace cocos2d::extension;16 class MyArmature:public CCArmature,public CCTouchDelegate{17 public:18 static MyArmature* create(const char* name,int nPriority);19 20 virtual void onEnter();21 virtual void onExit();22 void draw();//for Test23 24 // optional25 virtual void ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent);26 virtual void ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent);27 virtual void ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent);28 virtual void ccTouchesCancelled(CCSet *pTouches, CCEvent *pEvent);29 void setPriority(int nPriority);30 int getPriority();31 protected:32 int _nPriority;33 };34 35 #endif /* defined(__TouchesTest__MyArmature__) */
MyArmature.cpp
1 // 2 // MyArmature.cpp 3 // TouchesTest 4 // 5 // Created by HanHongmin on 13-12-29. 6 // 7 // 8 9 #include "MyArmature.h" 10 11 MyArmature* MyArmature::create(const char *name,int nPriority){ 12 MyArmature *armature = new MyArmature(); 13 if (armature && armature->init(name)) 14 { 15 armature->setPriority(nPriority); 16 armature->autorelease(); 17 return armature; 18 } 19 CC_SAFE_DELETE(armature); 20 return NULL; 21 } 22 void MyArmature::setPriority(int nPriority){ 23 _nPriority = nPriority; 24 } 25 int MyArmature::getPriority(){ 26 return _nPriority; 27 } 28 29 void MyArmature::onEnter(){ 30 CCDirector::sharedDirector()->getTouchDispatcher()->addStandardDelegate(this, _nPriority);//多点触控 31 CCArmature::onEnter(); 32 } 33 void MyArmature::onExit(){ 34 CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this); 35 CCArmature::onExit(); 36 } 37 38 void MyArmature::draw(){ 39 CCArmature::draw(); 40 CCRect rect = this->boundingBox(); 41 42 ccDrawColor4B(255, 0, 0, 255); 43 ccDrawRect(convertToNodeSpace(rect.origin), convertToNodeSpace(ccp(rect.getMaxX(), rect.getMaxY()))); 44 } 45 46 47 // optional 48 void MyArmature::ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent){ 49 //CCLog("ccTouchesBegan touches point count:%i",pTouches->count()); 50 CCLog("origin:%f,%f",this->boundingBox().origin.x,this->boundingBox().origin.y); 51 } 52 void MyArmature::ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent){ 53 //CCLog("ccTouchesMoved touches point count:%i",pTouches->count()); 54 CCDictionary* touchesDic = CCDictionary::create(); 55 CCSetIterator iter = pTouches->begin(); 56 CCRect rect = this->boundingBox(); 57 CCLog("rect:%f,%f",rect.size.width,rect.size.height); 58 for (; iter != pTouches->end(); iter++){ 59 CCTouch* pTouch = (CCTouch*)(*iter); 60 if(rect.containsPoint(pTouch->getLocation())){ 61 touchesDic->setObject(pTouch, CCString::createWithFormat("%d",pTouch->getID())->getCString()); 62 } 63 } 64 CCArray* keys = touchesDic->allKeys(); 65 //两个手指 66 if (touchesDic->count() >= 2){ 67 //CCLog("****ccTouchesMoved*"); 68 CCArray* keys = touchesDic->allKeys(); 69 CCTouch *touch1 = (CCTouch*)touchesDic->objectForKey(((CCString*)keys->objectAtIndex(0))->getCString()); 70 CCTouch *touch2 = (CCTouch*)touchesDic->objectForKey(((CCString*)keys->objectAtIndex(1))->getCString()); 71 72 CCPoint p1End = touch1->getLocation(); 73 CCPoint p2End = touch2->getLocation(); 74 CCPoint p1Start = touch1->getPreviousLocation(); 75 CCPoint p2Start = touch2->getPreviousLocation(); 76 77 float startDistance = ccpDistance(p1Start,p2Start); 78 float endDistance = ccpDistance(p1End,p2End); 79 80 //CCLog("startDistance:%f,endDistance:%f",startDistance,endDistance); 81 float scale = this->getScale()*(endDistance/startDistance); 82 CCLog("scale %f",scale); 83 if(scale<1.0f){ 84 scale = 1.0f; 85 }else if(scale>3.0f){ 86 scale = 3.0f; 87 } 88 this->setScale(scale); 89 90 pTouches->removeObject(touch1); 91 pTouches->removeObject(touch2); 92 }else if(touchesDic->count() ==1){ //单点 93 CCTouch *pTouch = (CCTouch*)touchesDic->objectForKey(((CCString*)keys->objectAtIndex(0))->getCString()); 94 CCPoint start = pTouch->getPreviousLocation(); 95 CCPoint end = pTouch->getLocation(); 96 //计算位移,直接使用point充当position的话,会有偏差,比如点住图片的一角进行拖动,setPosition的时候是依据AnchorPoint进行设置的 97 CCPoint sub = ccpSub(end, start); 98 CCPoint newPosition = ccpAdd(this->getPosition(),sub); 99 this->setPosition(newPosition);100 101 pTouches->removeObject(pTouch);102 }103 }104 void MyArmature::ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent){105 //CCLog("****ccTouchesEnded*");106 }107 void MyArmature::ccTouchesCancelled(CCSet *pTouches, CCEvent *pEvent){108 //CCLog("****ccTouchesCancelled*");109 }
draw方法是测试用的,因为在测试时发现boundingBox的位置不准,所以把它描绘出来看看。后面再说这个吧。
HelloWorld的init方法
bool HelloWorld::init(){ if ( !CCLayer::init() ) { return false; } CCArmatureDataManager::sharedArmatureDataManager()->addArmatureFileInfo("run.png", "run.plist", "run.xml");//加载动画资源 MyArmature* armature = MyArmature::create("run",1); armature->setPosition(VisibleRect::center()); armature->setScale(2.0f); this->addChild(armature,0); /** MySprite* pSprite2 = MySprite::create("Icon-114.png",2);//优先级数值越小越优先响应 pSprite2->setPosition(VisibleRect::center()); pSprite2->setScale(2.0f); this->addChild(pSprite2, 1); */ MySprite* pSprite = MySprite::create("HelloWorld.png",0); pSprite->setPosition(VisibleRect::center()); this->addChild(pSprite, 1); return true;}
CCArmature是 cocos2dx 扩展包里的东西,别忘了下面两行
#include "cocos-ext.h"using namespace cocos2d::extension;
然后就应该可以看看效果了。
是不是发现boundingBox不是想得那么回事?因为Armature中有子Armature的关系吧,我猜的。
在论坛发帖问了,还没得到回复,自己尝试hack了一下源码,没想到啊,还好使了。。。
修改CCArmature::boundingBox如下:
CCRect CCArmature::boundingBox(){ float minx, miny, maxx, maxy = 0; bool first = true; CCRect boundingBox = CCRectMake(0, 0, 0, 0); CCObject *object = NULL; CCARRAY_FOREACH(m_pChildren, object) { if (CCBone *bone = dynamic_cast(object)) { CCArmature* child = bone->getChildArmature(); //CCRect r = bone->getDisplayManager()->getBoundingBox();//hack by HanHongmin 2013-12-29 CCRect r; if(child!=NULL){ r = child->boundingBox(); }else{ r = bone->getDisplayManager()->getBoundingBox(); } //hack finish if(first) { minx = r.getMinX(); miny = r.getMinY(); maxx = r.getMaxX(); maxy = r.getMaxY(); first = false; } else { minx = r.getMinX() < boundingBox.getMinX() ? r.getMinX() : boundingBox.getMinX(); miny = r.getMinY() < boundingBox.getMinY() ? r.getMinY() : boundingBox.getMinY(); maxx = r.getMaxX() > boundingBox.getMaxX() ? r.getMaxX() : boundingBox.getMaxX(); maxy = r.getMaxY() > boundingBox.getMaxY() ? r.getMaxY() : boundingBox.getMaxY(); } boundingBox.setRect(minx, miny, maxx - minx, maxy - miny); } } return CCRectApplyAffineTransform(boundingBox, nodeToParentTransform());}
运行之,看看吧。
改的对不对我不知道哈,反正跟我要的效果差不多了。
等着看论坛帖子下文吧:
恩,现在两个自定义类了,可能大家早就发现了,能够提取出来公共代码。
虽然复制粘贴不麻烦,但是我想,大多数程序员都应该有代码洁癖吧。。。
各位自行搞一搞吧,我尝试了一下不会弄T_T,谁弄好了告诉我一声。
还有一点,如果涉及到x轴Y轴单向翻转的话,缩放哪里要注意,X,Y要分开。
setScale方法会把scaleX和scaleY都设置了,相当于调用了setScaleX和setScaleY。