在之前,笔者写过一编博客,通过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. 洛谷P2687 [USACO4.3]逢低吸纳Buy Low, Buy Lower

    P2687 [USACO4.3]逢低吸纳Buy Low, Buy Lower 题目描述 “逢低吸纳”是炒股的一条成功秘诀.如果你想成为一个成功的投资者,就要遵守这条秘诀: "逢低吸纳,越低越 ...

  2. cogs 721. [SDOI2007] 线性方程组

    721. [SDOI2007] 线性方程组 ★★   输入文件:gaess.in   输出文件:gaess.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述] 已知 n 元 ...

  3. Tyvj P1520 树的直径

    P1520 树的直径 http://www.tyvj.cn/p/1520 时间: 1000ms / 空间: 131072KiB / Java类名: Main 描述 树的直径,即这棵树中距离最远的两个结 ...

  4. MySQL最佳客户端工具 -- SQLyog 13.1.1.0 安装与注册

    一.前言 SQLyog是一个易于使用的.快速而简洁的图形化管理MYSQL数据库的工具,它能够在任何地点有效地管理你的数据库!SQLyog是业界著名的 Webyog 公司出品的一款简洁高效.功能强大的图 ...

  5. 洛谷P2939 [USACO09FEB]改造路Revamping Trails

    题意翻译 约翰一共有\(N\))个牧场.由\(M\)条布满尘埃的小径连接.小径可 以双向通行.每天早上约翰从牧场\(1\)出发到牧场\(N\)去给奶牛检查身体. 通过每条小径都需要消耗一定的时间.约翰 ...

  6. php:一个题目,关于优先级,及$a++和$a=$a+1,

    这几天常看到微博上转发的一条微博:就做了下,竟做错了,所以就试着分析了下~~ 这是微博: 这是代码: <?php $c = 3; $b = 6; if ($c = 4 || $b = 4) { ...

  7. GDPR(Cookie处理)

    GDPR(Cookie处理) https://www.cnblogs.com/GuZhenYin/p/9154447.html 前言 时间一晃 ASP.NET Core已经迭代到2.1版本了. 迫不及 ...

  8. (转)Linux内核参数设置sysctl命令详解

    Linux内核参数设置sysctl命令详解 原文:https://www.zhukun.net/archives/8064 sysctl是一个允许您改变正在运行中的Linux系统的接口. 它包含一些 ...

  9. 使用history.replaceState 修改url 不跳转

    history.replaceState(null,null,this.urlR);  //关键代码 history.replaceState是将指定的URL替换当前的URL 注意:用于替换掉的URL ...

  10. jquery中使用each遍历。

    一直知道each这个方法,但是就是不太明白到底怎么用,今天两个地方都使用了each.真的太高兴了,太有成就感了. 东钿微信平台订单列表页 全部订单之前是按照产调,评估,借款的顺序依次排下来,华总说要按 ...