zoukankan      html  css  js  c++  java
  • cocos2dx加载骨骼动画,获取骨骼位置

    2015/05/13

    需求:

    (1)希望在骨骼上绑定一个粒子特效

    (2)获取骨骼的位置

    (3)获取骨骼动画的大小

    (4)lua

    1. cocostudio动画编辑器

    (1)绑定粒子特效(跟随骨骼的移动移动)

            local boneNew  = ccs.Bone:create("particle")
                boneNew:addDisplay(particle, 0)
                --设置是否跟随骨骼一起移动
                boneNew:setIgnoreMovementBoneData(true)
                --显示骨骼上绑定的内容(这里是粒子特效,换装也是同样的接口)
                boneNew:changeDisplayWithIndex(0, true)
                --设置层级关系
                boneNew:setLocalZOrder(1)
                --Layer22为骨骼动画中想绑定的骨骼,设置为该骨骼为粒子特效所在骨骼的父骨骼
                armature:addBone(boneNew, "Layer22")


    * 其他的和骨骼的绑定也是通过此方式实现,感觉比较好用

    (2)获取骨骼位置

    修改源代码,从getWorldInfo中获取数据,在Bone类中加一个接口

    cocos2d::Vec2 Bone::getBonePosition() const
    {
        BaseData *pData = getWorldInfo();
        return Vec2(pData->x, pData->y);
    }

    使用tolua++导出来之后如下(当然,自己也可以写一个,就不用导出来这个步骤了):

    int lua_cocos2dx_studio_Bone_getBonePosition(lua_State* tolua_S)
    {
        int argc = 0;
        cocostudio::Bone* cobj = nullptr;
        bool ok  = true;
    
    #if COCOS2D_DEBUG >= 1
        tolua_Error tolua_err;
    #endif
    
    
    #if COCOS2D_DEBUG >= 1
        if (!tolua_isusertype(tolua_S,1,"ccs.Bone",0,&tolua_err)) goto tolua_lerror;
    #endif
    
        cobj = (cocostudio::Bone*)tolua_tousertype(tolua_S,1,0);
    
    #if COCOS2D_DEBUG >= 1
        if (!cobj) 
        {
            tolua_error(tolua_S,"invalid 'cobj' in function 'lua_cocos2dx_studio_Bone_getBonePosition'", nullptr);
            return 0;
        }
    #endif
    
        argc = lua_gettop(tolua_S)-1;
        if (argc == 0) 
        {
            if(!ok)
                return 0;
            cocos2d::Vec2 ret = cobj->getBonePosition();
            vec2_to_luaval(tolua_S, ret);
            return 1;
        }
        CCLOG("%s has wrong number of arguments: %d, was expecting %d 
    ", "getBonePosition",argc, 0);
        return 0;
    
    #if COCOS2D_DEBUG >= 1
        tolua_lerror:
        tolua_error(tolua_S,"#ferror in function 'lua_cocos2dx_studio_Bone_getBonePosition'.",&tolua_err);
    #endif
    
        return 0;
    }


    (3)获取骨骼动画大小

    cocostudio导出来加载后的Armature本身就是一个node,直接getContentSize就可以了。但是spine的动画就不行,getContentSize的结果为0,要使用别的接口,看下面。

    2. spine动画编辑器

    (1)绑定粒子特效(跟随骨骼的移动移动)

      没有办法做到,但是可以通过获取骨骼的位置之后,添加一个特效到整个骨骼动画的这个位置上,不过是不能跟随骨骼一起移动的,一起移动看到有两种方法,不过都没有试过,就先记录在这里,想用再来试一下

    * update函数每帧获取骨骼的位置,把粒子特效重现设置位置

     参考:[1]

    * 重写spine骨骼的的接口,每个骨骼和一个node对应

     参考:[2]

    (2)获取骨骼位置

      同studio(因为lua没有导出函数接口),修改代码,导出lua,在类中增加一个函数:

    Vec2 Skeleton::getBonePosition(const char* boneName) const
    {
        spBone *pBone = findBone(boneName);
        if (pBone)
            return cocos2d::Vec2(pBone->worldX, pBone->worldY);
        return cocos2d::Vec2(0, 0);
    }

    导出后的c++代码如下,同样的可以自己写:

    int lua_cocos2dx_spine_Skeleton_getBonePosition(lua_State* tolua_S)
    {
        int argc = 0;
        spine::Skeleton* cobj = nullptr;
        bool ok  = true;
    
    #if COCOS2D_DEBUG >= 1
        tolua_Error tolua_err;
    #endif
    
    
    #if COCOS2D_DEBUG >= 1
        if (!tolua_isusertype(tolua_S,1,"sp.Skeleton",0,&tolua_err)) goto tolua_lerror;
    #endif
    
        cobj = (spine::Skeleton*)tolua_tousertype(tolua_S,1,0);
    
    #if COCOS2D_DEBUG >= 1
        if (!cobj) 
        {
            tolua_error(tolua_S,"invalid 'cobj' in function 'lua_cocos2dx_spine_Skeleton_getBonePosition'", nullptr);
            return 0;
        }
    #endif
    
        argc = lua_gettop(tolua_S)-1;
        if (argc == 1) 
        {
            const char* arg0;
    
            std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp); arg0 = arg0_tmp.c_str();
            if(!ok)
                return 0;
            cocos2d::Vec2 ret = cobj->getBonePosition(arg0);
            vec2_to_luaval(tolua_S, ret);
            return 1;
        }
        CCLOG("%s has wrong number of arguments: %d, was expecting %d 
    ", "getBonePosition",argc, 1);
        return 0;
    
    #if COCOS2D_DEBUG >= 1
        tolua_lerror:
        tolua_error(tolua_S,"#ferror in function 'lua_cocos2dx_spine_Skeleton_getBonePosition'.",&tolua_err);
    #endif
    
        return 0;
    }

    (3)获取骨骼动画大小

      这个比较重要!!不能使用接口getContentSize,得出来的是0,但是Skeleton类提供了另外一个接口,也导出了lua接口:

    Rect Skeleton::getBoundingBox () const {
        float minX = FLT_MAX, minY = FLT_MAX, maxX = FLT_MIN, maxY = FLT_MIN;
        float scaleX = getScaleX();
        float scaleY = getScaleY();
        float vertices[8];
        for (int i = 0; i < skeleton->slotCount; ++i) {
            spSlot* slot = skeleton->slots[i];
            if (!slot->attachment || slot->attachment->type != ATTACHMENT_REGION) continue;
            spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
            spRegionAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot->bone, vertices);
            minX = min(minX, vertices[VERTEX_X1] * scaleX);
            minY = min(minY, vertices[VERTEX_Y1] * scaleY);
            maxX = max(maxX, vertices[VERTEX_X1] * scaleX);
            maxY = max(maxY, vertices[VERTEX_Y1] * scaleY);
            minX = min(minX, vertices[VERTEX_X4] * scaleX);
            minY = min(minY, vertices[VERTEX_Y4] * scaleY);
            maxX = max(maxX, vertices[VERTEX_X4] * scaleX);
            maxY = max(maxY, vertices[VERTEX_Y4] * scaleY);
            minX = min(minX, vertices[VERTEX_X2] * scaleX);
            minY = min(minY, vertices[VERTEX_Y2] * scaleY);
            maxX = max(maxX, vertices[VERTEX_X2] * scaleX);
            maxY = max(maxY, vertices[VERTEX_Y2] * scaleY);
            minX = min(minX, vertices[VERTEX_X3] * scaleX);
            minY = min(minY, vertices[VERTEX_Y3] * scaleY);
            maxX = max(maxX, vertices[VERTEX_X3] * scaleX);
            maxY = max(maxY, vertices[VERTEX_Y3] * scaleY);
        }
        Vec2 position = getPosition();
        return Rect(position.x + minX, position.y + minY, maxX - minX, maxY - minY);
    }

    说明:
    * 返回四个值:x, y, height, width

    * 说明:(x, y)左下角的坐标,相对于rootbone的原点;height, width就是整个骨骼动画的大小

    * rootbone可以理解为cocos里面的锚点

    * 【重要】在调用该接口之前,需要调用update接口初始化一遍数据,不然也是没有数据的,参考[3] 

    3. 总结

    (1)获取位置都是需要新加接口的

    (2)虽然spine编辑器要好用,但是对于程序来说spine绑定特效还没有cocostudio方便

    (3)cocostudio的位置最好不要直接拿来用,例如转换为全局坐标,最好直接addBone的方式

    (4)spine的坐标也是直接骨骼动画addChild

    4. 参考

    [1]http://www.cnblogs.com/mrblue/p/3414158.html

    [2]http://blog.csdn.net/n5/article/details/21795265

    [3]http://blog.csdn.net/wk3368/article/details/38903095

  • 相关阅读:
    URL中增加BASE64加密的字符串引起的问题(java.net.MalformedURLException:Illegal character in URL)
    读《暗时间》总结
    假设写一个android桌面滑动切换屏幕的控件(一)
    JDBC Connection Reset问题分析
    深度学习工具caffe具体安装指南
    TS2
    TS 函数解析
    typescript
    响应式网页设计:rem、em设置网页字体大小自适应
    一看就懂得移动端rem布局、rem如何换算
  • 原文地址:https://www.cnblogs.com/pk-run/p/4500917.html
Copyright © 2011-2022 走看看