cocos2dx加载骨骼动画,获取骨骼位置

需求:

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

(2)获取骨骼的位置

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

(4)lua

1. cocostudio动画编辑器

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

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

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

(2)获取骨骼位置

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

 
  1. cocos2d::Vec2 Bone::getBonePosition() const
  2. {
  3. BaseData *pData = getWorldInfo();
  4. return Vec2(pData->x, pData->y);
  5. }

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

 
  1. int lua_cocos2dx_studio_Bone_getBonePosition(lua_State* tolua_S)
  2. {
  3. ;
  4. cocostudio::Bone* cobj = nullptr;
  5. bool ok = true;
  6.  
  7. #if COCOS2D_DEBUG >= 1
  8. tolua_Error tolua_err;
  9. #endif
  10.  
  11. #if COCOS2D_DEBUG >= 1
  12. ,,&tolua_err)) goto tolua_lerror;
  13. #endif
  14.  
  15. cobj = (cocostudio::Bone*)tolua_tousertype(tolua_S,,);
  16.  
  17. #if COCOS2D_DEBUG >= 1
  18. if (!cobj)
  19. {
  20. tolua_error(tolua_S,"invalid 'cobj' in function 'lua_cocos2dx_studio_Bone_getBonePosition'", nullptr);
  21. ;
  22. }
  23. #endif
  24.  
  25. argc = lua_gettop(tolua_S)-;
  26. )
  27. {
  28. if(!ok)
  29. ;
  30. cocos2d::Vec2 ret = cobj->getBonePosition();
  31. vec2_to_luaval(tolua_S, ret);
  32. ;
  33. }
  34. CCLOG();
  35. ;
  36.  
  37. #if COCOS2D_DEBUG >= 1
  38. tolua_lerror:
  39. tolua_error(tolua_S,"#ferror in function 'lua_cocos2dx_studio_Bone_getBonePosition'.",&tolua_err);
  40. #endif
  41.  
  42. ;
  43. }

(3)获取骨骼动画大小

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

2. spine动画编辑器

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

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

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

 参考:[1]

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

 参考:[2]

(2)获取骨骼位置

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

 
  1. Vec2 Skeleton::getBonePosition(const char* boneName) const
  2. {
  3. spBone *pBone = findBone(boneName);
  4. if (pBone)
  5. return cocos2d::Vec2(pBone->worldX, pBone->worldY);
  6. , );
  7. }

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

 
  1. int lua_cocos2dx_spine_Skeleton_getBonePosition(lua_State* tolua_S)
  2. {
  3. ;
  4. spine::Skeleton* cobj = nullptr;
  5. bool ok = true;
  6.  
  7. #if COCOS2D_DEBUG >= 1
  8. tolua_Error tolua_err;
  9. #endif
  10.  
  11. #if COCOS2D_DEBUG >= 1
  12. ,,&tolua_err)) goto tolua_lerror;
  13. #endif
  14.  
  15. cobj = (spine::Skeleton*)tolua_tousertype(tolua_S,,);
  16.  
  17. #if COCOS2D_DEBUG >= 1
  18. if (!cobj)
  19. {
  20. tolua_error(tolua_S,"invalid 'cobj' in function 'lua_cocos2dx_spine_Skeleton_getBonePosition'", nullptr);
  21. ;
  22. }
  23. #endif
  24.  
  25. argc = lua_gettop(tolua_S)-;
  26. )
  27. {
  28. const char* arg0;
  29.  
  30. std::, &arg0_tmp); arg0 = arg0_tmp.c_str();
  31. if(!ok)
  32. ;
  33. cocos2d::Vec2 ret = cobj->getBonePosition(arg0);
  34. vec2_to_luaval(tolua_S, ret);
  35. ;
  36. }
  37. CCLOG();
  38. ;
  39.  
  40. #if COCOS2D_DEBUG >= 1
  41. tolua_lerror:
  42. tolua_error(tolua_S,"#ferror in function 'lua_cocos2dx_spine_Skeleton_getBonePosition'.",&tolua_err);
  43. #endif
  44.  
  45. ;
  46. }

(3)获取骨骼动画大小

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

 
  1. Rect Skeleton::getBoundingBox () const {
  2. float minX = FLT_MAX, minY = FLT_MAX, maxX = FLT_MIN, maxY = FLT_MIN;
  3. float scaleX = getScaleX();
  4. float scaleY = getScaleY();
  5. ];
  6. ; i < skeleton->slotCount; ++i) {
  7. spSlot* slot = skeleton->slots[i];
  8. if (!slot->attachment || slot->attachment->type != ATTACHMENT_REGION) continue;
  9. spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
  10. spRegionAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot->bone, vertices);
  11. minX = min(minX, vertices[VERTEX_X1] * scaleX);
  12. minY = min(minY, vertices[VERTEX_Y1] * scaleY);
  13. maxX = max(maxX, vertices[VERTEX_X1] * scaleX);
  14. maxY = max(maxY, vertices[VERTEX_Y1] * scaleY);
  15. minX = min(minX, vertices[VERTEX_X4] * scaleX);
  16. minY = min(minY, vertices[VERTEX_Y4] * scaleY);
  17. maxX = max(maxX, vertices[VERTEX_X4] * scaleX);
  18. maxY = max(maxY, vertices[VERTEX_Y4] * scaleY);
  19. minX = min(minX, vertices[VERTEX_X2] * scaleX);
  20. minY = min(minY, vertices[VERTEX_Y2] * scaleY);
  21. maxX = max(maxX, vertices[VERTEX_X2] * scaleX);
  22. maxY = max(maxY, vertices[VERTEX_Y2] * scaleY);
  23. minX = min(minX, vertices[VERTEX_X3] * scaleX);
  24. minY = min(minY, vertices[VERTEX_Y3] * scaleY);
  25. maxX = max(maxX, vertices[VERTEX_X3] * scaleX);
  26. maxY = max(maxY, vertices[VERTEX_Y3] * scaleY);
  27. }
  28. Vec2 position = getPosition();
  29. return Rect(position.x + minX, position.y + minY, maxX - minX, maxY - minY);
  30. }

说明:
* 返回四个值: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

猜你喜欢

转载自blog.csdn.net/qq_21743659/article/details/107458726