zoukankan      html  css  js  c++  java
  • 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经验都没有,各位见笑了 文章中如有错误或者不全面或者有更好的解决办法,请指出,不胜感激
  • 相关阅读:
    关于Asp.net应用程序生命周期
    xmlHttpRequest 以Post方式发数据到Asp.net页,在gb2312编码下的解决办法
    Asp.net中TreeView gb2312状态PopulateNodesFromClient乱码问题
    Subsonic中的MarkOld与MarkNew的一些使用
    非递归一次性加载分类数据到TreeViw
    Atitit rss没落以及替代品在线阅读器
    Atitit 2016年attilax事业成就表
    Atitit HTTP 认证机制基本验证 (Basic Authentication) 和摘要验证 (Digest Authentication)attilax总结Atitit HT
    Atitit 项目语言的选择 java c#.net  php??
    atitit 商业项目常用模块技术知识点 v3 qc29
  • 原文地址:https://www.cnblogs.com/hanhongmin/p/3496717.html
Copyright © 2011-2022 走看看