在之前,笔者写过一编博客,通过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. LDAP理论知识

    整理改编自: https://www.cnblogs.com/yjd_hycf_space/p/7994597.html http://blog.51cto.com/407711169/1439623 ...

  2. nacos1.0.0 服务管理使用mysql

    在自己的MySQL中添加nacos_config数据库,在nacos\conf 下找到nacos-mysql.sql.拷贝里面的sql语句创建表和数据 INSERT INTO users (usern ...

  3. Django之Form组件归类

    目录: Django内置字段 Django内置插件 常用选择插件 创建Form类时,主要涉及到 [字段] 和 [插件],字段用于对用户请求数据的验证,插件用于自动生成HTML; Field requi ...

  4. 题解 BZOJ 1037 & Luogu P2592 [ZJOI2008]生日聚会

    BZOJ & Luogu 老师说是背包?并没看出来QAQ 设f[i][j][o][p]表示已经选了i个人,j个男生,男生比女生最多多o个,女生比男生最多多p个时的方案数 两种转移: <= ...

  5. Codeforces 1175E(倍增)

    要点 与cf 1168C相似的一点都是看某点x最远能拓展到哪里 看数据想要在logn内查询,考虑倍增步数 const int maxn = 2e5 + 5, X = 5e5 + 5, LOG = 25 ...

  6. @Column 注解详情

    @Column标记表示所持久化属性所映射表中的字段,该注释的属性定义如下: @Target({METHOD, FIELD}) @Retention(RUNTIME) public @interface ...

  7. D. Edges in MST 图论

    http://codeforces.com/contest/160/problem/D base on 克鲁斯卡尔, 首先每次都是对权值相同的边进行统一处理,假如加入了当前这条边出现了回路,那就能确定 ...

  8. Java 面向对象,封装,继承

    1相关概念的理解 1.1面向过程.面向对象 面向过程与面向对象都是编程中,编写程序的一种思维方式. 面向过程的程序设计方式,是遇到一件事时,思考“我该怎么做”,然后一步步实现的过程.(职员思想) 面向 ...

  9. Java并发(一):基础概念

    对于Java并发,我也是属初学阶段,用的参考书是:"Java并发编程实战",写博时也参考了很多类似主题的博客,博主意在记录自己的学习路程,供网友讨论学习之用; 周末写的差不多了,今 ...

  10. AngularJS(六):表单-复选框

    本文也同步发表在我的公众号“我的天空” 复选框 复选框只有两个值:true或者false,因此在AngularJS中,一般都是将复选框的ng-model绑定为一个布尔值属性,通过这两个布尔值来决定其勾 ...