在之前,笔者写过一编博客,通过lua在加载场景加载spineAnimation动画精灵,保存在table中,然后在游戏中创建动画精灵时,提取加载好的spineAnimaiton中的

spSkeletonData来创建spineAnimation,但后来笔者发现重复创建spineAnimation时,全部相同spSkeletonData会重用同一个spSkeletonData,以下是spSkeletonData拷贝方法的源代码:

spSkeleton* spSkeleton_create (spSkeletonData* data) {

int i, ii;

_spSkeleton* internal = NEW(_spSkeleton);

spSkeleton* self = SUPER(internal);

CONST_CAST(spSkeletonData*, self->data) = data;

self->bonesCount = self->data->bonesCount;

self->bones = MALLOC(spBone*, self->bonesCount);

for (i = 0; i < self->bonesCount; ++i) {

spBoneData* boneData = self->data->bones[i];

spBone* parent = 0;

if (boneData->parent) {

/* Find parent bone. */

for (ii = 0; ii < self->bonesCount; ++ii) {

if (data->bones[ii] == boneData->parent) {

parent = self->bones[ii];

break;

}

}

}

self->bones[i] = spBone_create(boneData, self, parent);

}

CONST_CAST(spBone*, self->root) = self->bones[0];

self->slotsCount = data->slotsCount;

self->slots = MALLOC(spSlot*, self->slotsCount);

for (i = 0; i < self->slotsCount; ++i) {

spSlotData *slotData = data->slots[i];

/* Find bone for the slotData's boneData. */

spBone* bone = 0;

for (ii = 0; ii < self->bonesCount; ++ii) {

if (data->bones[ii] == slotData->boneData) {

bone = self->bones[ii];

break;

}

}

self->slots[i] = spSlot_create(slotData, bone);

}

self->drawOrder = MALLOC(spSlot*, self->slotsCount);

memcpy(self->drawOrder, self->slots, sizeof(spSlot*) * self->slotsCount);

self->r = 1;

self->g = 1;

self->b = 1;

self->a = 1;

self->ikConstraintsCount = data->ikConstraintsCount;

self->ikConstraints = MALLOC(spIkConstraint*, self->ikConstraintsCount);

for (i = 0; i < self->data->ikConstraintsCount; ++i)

self->ikConstraints[i] = spIkConstraint_create(self->data->ikConstraints[i], self);

spSkeleton_updateCache(self);

return self;

}

在拷贝当中,骨骼数据确实新开辟一个内存,拷贝了一份新的spSkeletonData,但是,由于spSkeletonData属于在table中保存的SkeletonAnimation中,受到SkeletonAnimation的影响,所以不能使用SkeletonAnimation中的spSkeletonData去创建另外一个SkeletonAnimation。

笔者也试过从lua中创建spSkeletonData数据,保存在table中,然后在游戏中传递spSkeletonData去创建SkeletonAnimation,

但在切换场景过程中,spSkeletonData会被释放掉,所以不能被复用。

后来笔者从c++入手,将spSkeletonData保存在c++静态的字典中,通过键值提取spSkeletonData去创建SkeletonAnimation,避免释放问题。

以下是实现方法:

//SpineAnimation_new.h

#include <stdio.h>

#include "cocos/editor-support/spine/SkeletonAnimation.h"

#include "cocos/editor-support/spine/spine.h"

#include "spine/SkeletonRenderer.h"

#include "cocos2d.h"

using namespace spine;

using namespace std;

class SpineAnimation_new:spine::SkeletonAnimation

{

public:

static SpineAnimation_new *createWithSkeletonData(spSkeletonData* skeletonData);

static SpineAnimation_new *createWithKey(const std::string& key);

virtual ~SpineAnimation_new();

spAnimationState* getState() {return SkeletonAnimation::getState();}

spSkeletonData* getSkeletonData()

{

spSkeletonData*skData =SkeletonRenderer::getSkeleton()->data;

return skData;

}

static spSkeletonData*loadSkeletonData(const std::string& atlasFile,const std::string& jsonFile,const std::string& key);

static map<const std::string,spSkeletonData*> skeletonDataMap;

static void clear();

private:

SpineAnimation_new(spSkeletonData*skeletonData);

SpineAnimation_new(const std::string& skeletonDataFile, const std::string& atlasFile, float scale = 1);

};

#endif

//SpineAnimation_new.cpp

#include "SpineAnimation_new.h"

#include "cocos2d.h"

#include "cocos/scripting/lua-bindings/manual/cocos2d/LuaScriptHandlerMgr.h"

#include "CCLuaStack.h"

#include "CCLuaEngine.h"

USING_NS_CC;

map<const std::string,spSkeletonData*> SpineAnimation_new::skeletonDataMap;

SpineAnimation_new *SpineAnimation_new::createWithSkeletonData(spSkeletonData* skeletonData)

{

SpineAnimation_new* node = new (std::nothrow)SpineAnimation_new(skeletonData);

node->autorelease();

return node;

}

spSkeletonData*SpineAnimation_new::loadSkeletonData(const std::string& atlasFile,const std::string& jsonFile,const std::string& key)

{

spAtlas* atlas = spAtlas_createFromFile(atlasFile.c_str(), 0);

spSkeletonJson* json = spSkeletonJson_create(atlas);

json->scale = 1;

spSkeletonData* sd = spSkeletonJson_readSkeletonDataFile(json, jsonFile.c_str());

SpineAnimation_new::skeletonDataMap.insert(pair<const std::string,spSkeletonData*>(key,sd));

return sd;

}

SpineAnimation_new *SpineAnimation_new::createWithKey(const std::string& key)

{

map<const std::string,spSkeletonData*>::iterator iter = SpineAnimation_new::skeletonDataMap.find(key);

spSkeletonData* sd = iter->second;

SpineAnimation_new*sa = createWithSkeletonData(sd);

return sa;

}

SpineAnimation_new::~SpineAnimation_new()

{

ScriptHandlerMgr::getInstance()->removeObjectAllHandlers((void*)this);

}

SpineAnimation_new::SpineAnimation_new(spSkeletonData*skeletonData):

SkeletonAnimation(skeletonData)

{

}

SpineAnimation_new::SpineAnimation_new(const std::string& skeletonDataFile, const std::string& atlasFile, float scale):SkeletonAnimation(skeletonDataFile,atlasFile,scale)

{

}

void SpineAnimation_new::clear()

{

SpineAnimation_new::skeletonDataMap.clear();

}

(转载时请注明出处,from 博客园:HemJohn)

cocos2x (c++/lua) spine 文件的预加载的更多相关文章

  1. 使用lua实现Spine动画的预加载

    创建spine动画有两种方法,分别是createwithfile和createwithdata. createWithFile是通过加载动作数据马上进行创建,如果spine动画中的json文件大小超过 ...

  2. vue-cli3 chainWebpack配置,去除打包后文件的预加载prefetch/preload(已解决)

    //细节配置修改 chainWebpack: config => { console.log(config,'chainWebpack') // 移除 prefetch 插件 config.pl ...

  3. spine实现预加载(一)

    前言 本文实现了spine动画的预加载,解决在战斗等大量加载spine动画的时候出现卡顿现象. 这里使用和修改三个类,直接修改的源码,当然你也可以继承LuaSkeletonAnimation,自己封装 ...

  4. Javascript图片预加载详解

    预加载图片是提高用户体验的一个很好方法.图片预先加载到浏览器中,访问者便可顺利地在你的网站上冲浪,并享受到极快的加载速度.这对图片画廊及图片占据很大比例的网站来说十分有利,它保证了图片快速.无缝地发布 ...

  5. 利用CSS、JavaScript及Ajax实现图片预加载的三大方法

    预加载图片是提高用户体验的一个很好方法.图片预先加载到浏览器中,访问者便可顺利地在你的网站上冲浪,并享受到极快的加载速度.这对图片画廊及图片占据很大比例的网站来说十分有利,它保证了图片快速.无缝地发布 ...

  6. 图片预加载和AJAX的图片预加载

    利用js实现图片预加载,加载所需要图片的路径与名称即可,很容易实现,该方法尤其适用预加载大量的图片: <div class="hidden"> <script t ...

  7. 使用ajax预加载图片

    使用Ajax 上面所给出的方法似乎不够酷,那现在来看一个使用Ajax实现图片预加载的方法.该方法利用DOM,不仅仅预加载图片,还会预加载CSS.JavaScript等相关的东西.使用Ajax,比直接使 ...

  8. 详解HTML5中rel属性的prefetch预加载功能使用

    在HTML5中,有个很有用但常被忽略的特性,就是预先加载(prefetch),它的原理是: 利用浏览器的空闲时间去先下载用户指定需要的内容,然后缓存起来,这样用户下次加载时,就直接从缓存中取出来,效率 ...

  9. CSS和JavaScript以及Ajax实现预加载图片的方法及优缺点分析

    预加载图片是提高用户体验的一个很好方法.图片预先加载到浏览器中,访问者便可顺利地在你的网站上冲浪,并享受到极快的加载速度.这对图片画 廊及图片占据很大比例的网站来说十分有利,它保证了图片快速.无缝地发 ...

随机推荐

  1. 图论2 最近公共祖先LCA

    模板 吸取洛谷P3379的教训,我决定换板子(其实本质都是倍增是一样的),把vector换成了边表 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下 ...

  2. 10.Python初窥门径(函数进阶)

    Python(函数进阶) 一.函数的传参(接上期) 形参角度(一共四种,后两种) 动态参数(万能参数)* # 定义一个函数时,*所有的位置参数聚合到一个元组中 def func(*args): # * ...

  3. HBase中报错 java.lang.NoClassDefFoundError: com/google/protobuf/LiteralByteString

    Protobuf(全称 Protocol Buffers)是 Google 开发的一种数据描述语言,能够将结构化数据序列化,可用于数据存储.通信协议等方面.在 HBase 里面用使用了 Protobu ...

  4. acwing 3 完全背包

    习题地址 https://www.acwing.com/problem/content/description/3/ 题目描述有 N 种物品和一个容量是 V 的背包,每种物品都有无限件可用. 第 i ...

  5. jQuery EasyUI/TopJUI基本的数字输入框(保留两位小数,带前缀后缀...)

    jQuery EasyUI/TopJUI基本的数字输入框(保留两位小数,带前缀后缀...) numberbox(数值输入框) HTML required:必填字段,默认为false:prompt:显示 ...

  6. python进阶09 MySQL高级查询

    python进阶09 MySQL高级查询 一.筛选条件 # 比较运算符 # 等于:= 不等于:!= 或<> 大于:> 小于:< 大于等于>= 小于等于:<= #空: ...

  7. Codeforces 161E(搜索)

    要点 标签是dp但搜索一发就能过了. 因为是对称矩阵所以试填一下就是一个外层都填满了,因此搜索的深度其实不超过5. 显然要预处理有哪些素数.在这个过程中可以顺便再处理出一个\(vector:re[le ...

  8. PHPstudy安装redis扩展

    PHPstudy安装redis扩展 第一步:查看PHP版本(phpinfo) 第二步:下载所需的扩展(http://pecl.php.net/package/redis   .   http://wi ...

  9. 关于使用rancher部署k8s集群的一些小问题的解决

    问题一: 在rancher的ui上,不能创建k8s的master节点的高可用集群.创建k8s集群,添加节点的时候,可以添加多个master,但是多个master又没有高可用,只要其中一个出问题了,那么 ...

  10. WebStorm技巧-常用快捷键

      Ctrl+/ 或 Ctrl+Shift+/ 注释(// 或者/*-*/ ) Shift+F6 重构-重命名 Ctrl+X 删除行 Ctrl+D 复制行 Ctrl+G 查找行 Ctrl+Shift+ ...