您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

spriter动画编辑器的cocos2d

2024/3/4 23:52:07发布26次查看
目前我的cocos2d-x编辑器的动画部分接口采用的是spriter动画编辑器提供的接口,spriter动画编辑器虽然简陋,但一般的需求基本上能够满足。可以在http://www.brashmonkey.com/spriter.htm下载,另外cocos2d-x的接口可以在论坛http://www.brashmonkey.com/foru
目前我的cocos2d-x编辑器的动画部分接口采用的是spriter动画编辑器提供的接口,spriter动画编辑器虽然简陋,但一般的需求基本上能够满足。可以在http://www.brashmonkey.com/spriter.htm下载,另外cocos2d-x的接口可以在论坛http://www.brashmonkey.com/forum/viewtopic.php?f=3&t=870下载。
接口导入进来之后,一切都很正常,然而在采用该接口进行开发时,发现有几个比较严重的问题。
问题1:资源采用多文件夹形式存储,渲染效率低
问题2:一个png只能有一个ccsprite,在编辑器是正常的,然而采用论坛那个接口导入到cocos2d-x就有问题。
问题3:精灵不能flip
问题4:不支持scale变换
陆续修改了上述4个问题
资源采用sprite frame实现
png的bug线性实现,时间复杂度o(1)
flip的实现参考cocos2d-x源码中cctransitionflipx的实现——摄像头换位
scale参考angle的变换就ok了
代码如下:
(代码中掺杂了编辑器部分的代码,精力有限,本代码仅供参考)
头文件:
//------------------------------------------------------------------------//// scmlanimator : kickstarter project spriter renderer for cocos2d-x.//// spriter website : http://www.kickstarter.com/projects/539087245/spriter//// licensed under the bsd license, see license in root for details.// // copyright (c) 2012 james hui (a.k.a. dr.watson)// // for latest updates, please visit http://jameshui.com////------------------------------------------------------------------------#ifndef _cc_spriter_x_h_#define _cc_spriter_x_h_#include #include #include jevent.h#include cocos2d.h#include touchsprite.h#include tinyxml.hclass ccspriterx;#define file_sprite_size 128namespace scmlhelper{ struct file { file(); ~file(); void init(tixmlnode *node); int id; std::string name; float width; float height; //一个文件可能有多个关联 cocos2d::ccsprite* sprites[file_sprite_size]; }; class folder { public: folder(); ~folder(); void init(tixmlnode *node); int getfilecount(); file *getfile(int index); private: int mid; std::string mname; std::vector mfiles; }; struct objectref { void init(tixmlnode *node); int id; int timeline; int key; int z_index; }; struct object { void init(tixmlnode *node, ccspriterx *animator, int timelineid); int folder; int file; float x; float y; float angle; float scalex; float scaley; float pivot_x; float pivot_y; int z_index; cocos2d::ccsprite *sprite; }; class key { public: key(); ~key(); void init(tixmlnode *node, ccspriterx *animator, int timelineid); int getobjectrefcount(); objectref *getobjectref(int index); int getobjectcount(); object *getobject(int index); float gettime(); bool isspincounterclockwise(); private: int mid; float mtime; bool mspincounterclockwise; std::vector mobjects; std::vector mobjectrefs; // will have bones later }; class timeline { public: timeline(); ~timeline(); void init(tixmlnode *node, ccspriterx *animator); int getkeyframecount(); key *getkeyframe(int index); private: int mid; std::vector mkeyframes; }; class animation { public: cc_synthesize(jevent *, event, event); cc_synthesize(std::string, afteraction, afteraction); ccspriterx * spr; public: void restart(); animation(ccspriterx * spr); ~animation(); void update(float dt); void init(tixmlnode *node, ccspriterx *animator); void render(); bool isdone(); public: std::string getname(){return mname;} private: int mid; std::string mname; float mlength; bool mlooping; bool mdone; timeline *mmainline; int mcurrkeyframe; std::vector mtimelines; float mtimer; cocos2d::ccpoint mposition; }; class entity { private: ccspriterx * spr; public: entity(ccspriterx * spr); ~entity(); void startwithevent(const char * name, jevent * event); std::string currentaction(); void update(float dt); void render(); void start(const char * name,const char* _afteraction); void setid(int id); void setname(const char *name); void addanimation(animation *animation); void nextanimation(); private: int mid; std::string mname; std::vector manimations; int mcurranimation; };}class ccspriterx : public touchsprite{ private: struct pit{ int fileid; int id; int folderid; }; pit filesprites[file_sprite_size]; cc_synthesize(cccolor3b, colorx, colorx);public: ccspriterx(); ~ccspriterx(); virtual void setflipx(bool bflipx); bool initwithfile(const char *filename); std::string currentaction(); virtual void draw(void); virtual void update(float dt); static ccspriterx * create(const char *filename); cocos2d::ccsprite * getsprite(int folderid, int fileid, int timelineid); void playnext(); void playwithevent(const char * name, jevent * event); void play(const char* name,const char* _afteraction = 0); private: std::vector mfolders; std::vector mentities; int mcurrentity;};#endif
源文件://------------------------------------------------------------------------//// ccspriterx : kickstarter project spriter renderer for cocos2d-x.//// spriter website : http://www.kickstarter.com/projects/539087245/spriter//// licensed under the bsd license, see license in root for details.// // copyright (c) 2012 james hui (a.k.a. dr.watson)// // for latest updates, please visit http://jameshui.com////------------------------------------------------------------------------#include ccspriterx.h#include common.h#include jerror.h using_ns_cc;namespace scmlhelper{ /////////////////////////////////////////////////////////////////////////////////// file::file() { for(size_t i=0; irelease(); } } } void file::init(tixmlnode *node) { tixmlelement *element = node->toelement(); if (element) { int intvalue; float floatvalue; if (element->queryintattribute(id, &intvalue) == tixml_success) id = intvalue; else id = 0; name = element->attribute(name); if (element->queryfloatattribute(width, &floatvalue) == tixml_success) width = floatvalue; else width = 0; if (element->queryfloatattribute(height, &floatvalue) == tixml_success) height = floatvalue; else height = 0; if (name.size()>0) { //资源全部放到scml目录中! std::string path = workpath+gconfig->read(res)+/; //sprite = ccsprite::create((path+scml/+name).c_str()); sprites[0] = ccsprite::createwithspriteframename(name.c_str()); sprites[0]->retain(); } } } /////////////////////////////////////////////////////////////////////////////////// folder::folder() : mid(0) { mfiles.reserve(50); } folder::~folder() { int count = mfiles.size(); for (int i=0;itoelement(); if (element) { int intvalue; if (element->queryintattribute(id, &intvalue) == tixml_success) mid= intvalue; mname = element->attribute(name)==0?.:element->attribute(name); for (tixmlnode* filenode = node->firstchild(); filenode; filenode = filenode->nextsibling()) { file *file = new file(); file->init(filenode); mfiles.push_back(file); } } } /////////////////////////////////////////////////////////////////////////////////// void objectref::init(tixmlnode *node) { tixmlelement *element = node->toelement(); if (element) { int intvalue; if (element->queryintattribute(id, &intvalue) == tixml_success) id = intvalue; else id = 0; if (element->queryintattribute(timeline, &intvalue) == tixml_success) timeline = intvalue; else timeline = 0; if (element->queryintattribute(key, &intvalue) == tixml_success) key = intvalue; else key = 0; if (element->queryintattribute(z_index, &intvalue) == tixml_success) z_index = intvalue; else z_index = 0; } } /////////////////////////////////////////////////////////////////////////////////// void object::init(tixmlnode *node, ccspriterx *animator, int timelineid) { sprite = null; float scalefactor = ccdirector::shareddirector()->getcontentscalefactor(); tixmlelement *element = node->toelement(); if (element) { int intvalue; float floatvalue; if (element->queryintattribute(folder, &intvalue) == tixml_success) folder = intvalue; else folder = 0; if (element->queryintattribute(file, &intvalue) == tixml_success) file = intvalue; else file = 0; if (element->queryfloatattribute(x, &floatvalue) == tixml_success) x = floatvalue/scalefactor; else x = 0; if (element->queryfloatattribute(y, &floatvalue) == tixml_success) y = floatvalue/scalefactor; else y = 0; if (element->queryfloatattribute(angle, &floatvalue) == tixml_success) angle = floatvalue; else angle = 0; if (element->queryfloatattribute(scale_x, &floatvalue) == tixml_success) scalex = floatvalue; else scalex = 1; if(scalex queryfloatattribute(scale_y, &floatvalue) == tixml_success) scaley = floatvalue; else scaley = 1; if (element->queryfloatattribute(pivot_x, &floatvalue) == tixml_success) pivot_x = floatvalue; else pivot_x = 0; if (element->queryfloatattribute(pivot_y, &floatvalue) == tixml_success) pivot_y = floatvalue; else pivot_y = 1; if (element->queryintattribute(z_index, &intvalue) == tixml_success) z_index = intvalue; else z_index = 0; sprite = animator->getsprite(folder, file, timelineid); } } /////////////////////////////////////////////////////////////////////////////////// key::key() : mid(0) , mtime(0) , mspincounterclockwise(true) { mobjects.reserve(50); mobjectrefs.reserve(50); } key::~key() { int count = mobjects.size(); for (int i=0;iqueryintattribute(id, &intvalue) == tixml_success) mid = intvalue; float time = 0; if (element->queryfloatattribute(time, &floatvalue) == tixml_success) // was in milliseconds, convert to seconds instead time = floatvalue/1000.0f; mtime = time; if (element->queryintattribute(spin, &intvalue) == tixml_success) mspincounterclockwise = !(intvalue == -1); for (tixmlnode* objnode = node->firstchild(); objnode; objnode = objnode->nextsibling()) { element = objnode->toelement(); const char *tabobj = element->value(); if (strcmp(tabobj, object_ref)==0) { objectref *ref = new objectref(); ref->init(objnode); mobjectrefs.push_back(ref); } else if (strcmp(tabobj, object)==0) { object *obj = new object(); obj->init(objnode, animator, timelineid); mobjects.push_back(obj); } } } } /////////////////////////////////////////////////////////////////////////////////// timeline::timeline() : mid(0) { mkeyframes.reserve(50); } timeline::~timeline() { int count = mkeyframes.size(); for (int i=0;itoelement(); if (element) { if (element->queryintattribute(id, &intvalue) == tixml_success) mid = intvalue; for (tixmlnode* keynode = node->firstchild(); keynode; keynode = keynode->nextsibling()) { element = keynode->toelement(); if (element) { key *keyframe = new key(); keyframe->init(keynode, animator, mid); mkeyframes.push_back(keyframe); } } } } /////////////////////////////////////////////////////////////////////////////////// animation::animation(ccspriterx * _spr) : mid(0) , spr(_spr) , mcurrkeyframe(0) , mmainline(null) , mdone(false) , mtimer(0) ,event(0),afteraction() { mtimelines.reserve(50); } animation::~animation() { int count = mtimelines.size(); for (int i=0;itoelement(); if (element) { if (element->queryintattribute(id, &intvalue) == tixml_success) mid = intvalue; mname = element->attribute(name); if (element->queryfloatattribute(length, &floatvalue) == tixml_success) mlength = floatvalue/1000.0f; // was in milliseconds, convert to seconds instead const char *looping = element->attribute(looping); // was set to false in alpha, but in fact looping all the time mlooping = true; for (tixmlnode* linenode = node->firstchild(); linenode; linenode = linenode->nextsibling()) { element = linenode->toelement(); const char *tabline = element->value(); if (strcmp(tabline, mainline)==0) // 1 mainline only { mmainline = new timeline(); mmainline->init(linenode, animator); } else if (strcmp(tabline, timeline)==0) { timeline *timeline = new timeline(); timeline->init(linenode, animator); mtimelines.push_back(timeline); } } } } bool animation::isdone() { return mdone; } void animation::restart() { mdone = false; mtimer = 0; mcurrkeyframe = 0; } float lerp(float a, float b, float t){ return a+(b-a)*t; } void animation::update(float dt) { mtimer += dt; if (mtimer >= mlength) { mdone = true; restart(); // always looping for now } int count = mmainline->getkeyframecount(); key *keyframe = mmainline->getkeyframe(mcurrkeyframe); float currtime = keyframe->gettime(); key *keyframenext = null; int next = mcurrkeyframe+1; if (next > count-1) // looping next = 0; keyframenext = mmainline->getkeyframe(next); if (keyframenext) { float nexttime = keyframenext->gettime(); if (next == 0) nexttime = mlength; if (mtimer >= nexttime) { mcurrkeyframe = next; keyframe = keyframenext; currtime = keyframe->gettime(); next = mcurrkeyframe+1; if (next > count-1) // looping next = 0; keyframenext = mmainline->getkeyframe(next); if (keyframenext == null) return; nexttime = keyframenext->gettime(); if (next == 0) nexttime = mlength; } float t = (mtimer-currtime)/(nexttime-currtime); int count = keyframe->getobjectrefcount(); for (int i=0;igetobjectref(i); objectref *refnext = keyframenext->getobjectref(i); if (ref && refnext) { key *keyref = mtimelines[ref->timeline]->getkeyframe(ref->key); object *obj = keyref->getobject(0); // should be only 1 object key *keyrefnext = mtimelines[refnext->timeline]->getkeyframe(refnext->key); object *objnext = keyrefnext->getobject(0); float x = lerp(obj->x, objnext->x, t); float y = lerp(obj->y, objnext->y, t); float scalex = lerp(obj->scalex, objnext->scalex, t); float scaley = lerp(obj->scaley, objnext->scaley, t); float angle = objnext->angle-obj->angle; if (keyref->isspincounterclockwise()) { if (angle angle+360)-obj->angle; } else { if (angle > 0) { angle = (objnext->angle-360)-obj->angle; } } if (ref->timeline != refnext->timeline) t = 0; angle = obj->angle+(angle)*t; if (angle >= 360) angle -= 360; float px = obj->pivot_x+(objnext->pivot_x-obj->pivot_x)*t; float py = obj->pivot_y+(objnext->pivot_y-obj->pivot_y)*t; ccpoint newpos = ccp(x, y); obj->sprite->setposition(newpos); obj->sprite->setrotation(-angle); obj->sprite->setscalex(scalex); obj->sprite->setscaley(scaley); obj->sprite->setanchorpoint(ccp(px, py)); } } } } void animation::render() { key *keyframe = mmainline->getkeyframe(mcurrkeyframe); int count = keyframe->getobjectrefcount(); for (int i=0;igetobjectref(i); if (ref) { key *keyref = mtimelines[ref->timeline]->getkeyframe(ref->key); object *obj = keyref->getobject(0); // should be only 1 object obj->sprite->setcolor(spr->getcolorx()); obj->sprite->visit(); } } } /////////////////////////////////////////////////////////////////////////////////// entity::entity(ccspriterx * _spr) : mcurranimation(0) , mid(0) , spr(_spr) { manimations.reserve(50); }; entity::~entity() { int count = manimations.size(); for (int i=0;iupdate(dt); } std::string entity::currentaction() { return manimations[mcurranimation]->getname(); } void entity::startwithevent(const char * name, jevent * event) { for(size_t i=0; igetname() == std::string(name)){ mcurranimation = i; manimations[i]->setevent(event); manimations[i]->restart(); } } } void entity::start(const char * name, const char * _afteraction) { for(size_t i=0; igetname() == std::string(name)){ mcurranimation = i; manimations[i]->setafteraction(_afteraction); manimations[i]->restart(); } } } void entity::render() { animation *animation = manimations[mcurranimation]; animation->render(); } void entity::nextanimation() { mcurranimation++; if (mcurranimation >= (int)manimations.size()) mcurranimation = 0; animation *animation = manimations[mcurranimation]; animation->restart(); } void entity::setid(int id) { mid = id; } void entity::setname(const char *name) { mname = name; } void entity::addanimation(animation *animation) { manimations.push_back(animation); }}///////////////////////////////////////////////////////////////////////////////////using namespace scmlhelper;ccspriterx::ccspriterx(){ mfolders.reserve(50); mentities.reserve(50); for(int i=0; itype = scml; animator->m_state = klivingstateungrabbed; if (animator && animator->initwithfile(filename)) { //由于是动画层,没有大小,这里设置大小,使之能够拾取 animator->setcontentsize(ccsizemake(100, 100)); animator->autorelease(); return animator; } cc_safe_delete(animator); return null;}void ccspriterx::update(float dt){ if (dt > 0.0167f) dt = 0.0167f; entity *entity = mentities[mcurrentity]; entity->update(dt); }void ccspriterx::draw(void){ entity *entity = mentities[mcurrentity]; entity->render();}std::string ccspriterx::currentaction(){ entity *entity = mentities[mcurrentity]; return entity->currentaction();}void ccspriterx::playwithevent(const char * name, jevent * event){ entity *entity = mentities[mcurrentity]; entity->startwithevent(name, event);}void ccspriterx::play(const char* name, const char * _afteraction){ entity *entity = mentities[mcurrentity]; entity->start(name, _afteraction == 0?:_afteraction);}void ccspriterx::playnext(){ entity *entity = mentities[mcurrentity]; entity->nextanimation();}ccsprite *ccspriterx::getsprite(int folderid, int fileid, int timelineid){ if (folderid getfile(fileid); if (file){ int id = this->filesprites[timelineid].id; if(id == -1){ for(int i=0; isprites[id] == 0){ file->sprites[id] = ccsprite::createwithspriteframename(file->name.c_str()); file->sprites[id]->retain(); } return file->sprites[id]; } } } return null;}void ccspriterx::setflipx(bool bflipx){ if(bflipx != m_bflipx){ float ex,ey,ez; this->getcamera()->geteyexyz(&ex, &ey, &ez); this->getcamera()->seteyexyz(ex, ey, bflipx?-fabs(ez):fabs(ez)); this->m_bflipx = bflipx; }}bool ccspriterx::initwithfile(const char *filename){ char cfilename[256]; strcpy(cfilename, filename); string name = strtok(cfilename, .); string suffix = strtok(cfilename, .); mcurrentity = 0; unsigned long filesize; string path = workpath+gconfig->read(res)+/+filename; char *buffer = (char *)ccfileutils::sharedfileutils()->getfiledata(path.c_str(), rb, &filesize); if (buffer == null) return false; //加载大图 string sfplist = workpath+gconfig->read(res)+/scml/+name+.plist; string sfpng = workpath+gconfig->read(res)+/scml/+name+.png; ccspriteframecache::sharedspriteframecache()->addspriteframeswithfile(sfplist.c_str(), sfpng.c_str()); tixmldocument doc; doc.parse(buffer); tixmlnode *root = doc.firstchild(spriter_data); if (root) { tixmlelement *element = root->toelement(); const char *version = element->attribute(scml_version); const char *generator = element->attribute(generator); const char *generatorversion = element->attribute(generator_version); for (tixmlnode* entitynode = root->firstchild(); entitynode; entitynode = entitynode->nextsibling()) { element = entitynode->toelement(); if (element) { const char *tab = element->value(); if (strcmp(tab, folder)==0) { folder *folder = new folder(); folder->init(entitynode); mfolders.push_back(folder); } else if (strcmp(tab, entity)==0) { int intvalue; entity *entity = new entity(this); if (element->queryintattribute(id, &intvalue) == tixml_success) entity->setid(intvalue); entity->setname(element->attribute(name)); for (tixmlnode* animationnode = entitynode->firstchild(); animationnode; animationnode = animationnode->nextsibling()) { animation *animation = new animation(this); animation->init(animationnode, this); entity->addanimation(animation); } mentities.push_back(entity); } } } } cc_safe_delete_array(buffer); this->scheduleupdate(); return true;}
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product