cocos2dx 触摸测试四 Armature

我忘了我这篇测试的主要目的是干啥了...。

就算往项目上靠靠吧,我项目里面要用到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 Test
23     
24     // optional
25     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__) */
View Code

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 }
View Code

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<CCBone *>(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());
}

运行之,看看吧。

改的对不对我不知道哈,反正跟我要的效果差不多了。

等着看论坛帖子下文吧:

http://www.cocos2d-x.org/forums/6/topics/41700

http://www.cocoachina.com/bbs/read.php?tid=176727

恩,现在两个自定义类了,可能大家早就发现了,能够提取出来公共代码。

虽然复制粘贴不麻烦,但是我想,大多数程序员都应该有代码洁癖吧。。。

各位自行搞一搞吧,我尝试了一下不会弄T_T,谁弄好了告诉我一声。

还有一点,如果涉及到x轴Y轴单向翻转的话,缩放哪里要注意,X,Y要分开。

setScale方法会把scaleX和scaleY都设置了,相当于调用了setScaleX和setScaleY。

我是cocos2dx初学者,Java5年,一点C++,OC经验都没有,各位见笑了 文章中如有错误或者不全面或者有更好的解决办法,请指出,不胜感激
原文地址:https://www.cnblogs.com/hanhongmin/p/3496717.html