现在的位置: 首页 > 综合 > 正文

spriter动画编辑器的cocos2d-x接口修正强化

2012年07月11日 ⁄ 综合 ⁄ 共 19383字 ⁄ 字号 评论关闭

目前我的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 <vector>
#include <string>
#include "JEvent.h"
#include "cocos2d.h"
#include "TouchSprite.h"
#include "tinyxml.h"


class CCSpriterX;
#define FILE_SPRITE_SIZE 128

namespace 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 <File *> 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 <Object *> mObjects;
		std::vector <ObjectRef *> 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 <Key *> 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 <Timeline *> 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 <Animation *> 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 <SCMLHelper::Folder *> mFolders;
	std::vector <SCMLHelper::Entity *> 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; i<FILE_SPRITE_SIZE; ++i){
			sprites[i] = 0;
		}
	}


	File::~File()
	{
		for(size_t i=0; i<FILE_SPRITE_SIZE; ++i){
			if(sprites[i] != NULL){
				sprites[i]->release();
			}
		}
	}

	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<std::string>("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;i<count;i++)
			CC_SAFE_DELETE(mFiles[i]);

		mFiles.clear();

	}


	int Folder::GetFileCount()
	{
		return mFiles.size();

	}

	
	File *Folder::GetFile(int index)
	{
		if (index < (int)mFiles.size())
			return mFiles[index];

		return NULL;

	}


	void Folder::Init(TiXmlNode *node)
	{
		TiXmlElement *element = node->ToElement();
		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 < 1){
				jlog("shit");
			}

			if (element->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;i<count;i++)
			CC_SAFE_DELETE(mObjects[i]);

		mObjects.clear();

		count = mObjectRefs.size();
		for (int i=0;i<count;i++)
			CC_SAFE_DELETE(mObjectRefs[i]);

		mObjectRefs.clear();

	}


	int Key::GetObjectRefCount()
	{
		return mObjectRefs.size();

	}


	ObjectRef *Key::GetObjectRef(int index)
	{
		if (index < (int)mObjectRefs.size())
			return mObjectRefs[index];

		return NULL;

	}


	int Key::GetObjectCount()
	{
		return mObjects.size();

	}


	Object *Key::GetObject(int index)
	{
		if (index < (int)mObjects.size())
			return mObjects[index];

		return NULL;

	}


	float Key::GetTime()
	{
		return mTime;
	}


	bool Key::IsSpinCounterClockwise()
	{
		return mSpinCounterClockwise;

	}


	void Key::Init(TiXmlNode *node, CCSpriterX *animator, int timelineId)
	{
		TiXmlElement *element = node->ToElement();
		if (element)
		{
			int intValue;
			float floatValue;
			if (element->QueryIntAttribute("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;i<count;i++)
		{
			CC_SAFE_DELETE(mKeyframes[i]);

		}

	}


	int Timeline::GetKeyframeCount()
	{
		return mKeyframes.size();

	}


	Key *Timeline::GetKeyframe(int index)
	{
		if (index < (int)mKeyframes.size())
		{
			return mKeyframes[index];
		}

		return NULL;

	}

	void Timeline::Init(TiXmlNode *node, CCSpriterX *animator)
	{
		int intValue;

		TiXmlElement *element = node->ToElement();

		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;i<count;i++)
			CC_SAFE_DELETE(mTimelines[i]);

		mTimelines.clear();

	}


	void Animation::Init(TiXmlNode *node, CCSpriterX *animator)
	{
		int intValue;
		float floatValue;

		TiXmlElement *element = node->ToElement();

		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;i<count;i++)
			{
				ObjectRef *ref = keyframe->GetObjectRef(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 < 0)
							angle = (objNext->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;i<count;i++)
		{
			ObjectRef *ref = keyframe->GetObjectRef(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;i<count;i++)
			CC_SAFE_DELETE(mAnimations[i]);

		mAnimations.clear();

	}


	void Entity::Update(float dt)
	{
		Animation *animation = mAnimations[mCurrAnimation];
		animation->Update(dt);
	}

    std::string Entity::CurrentAction()
    {
        return mAnimations[mCurrAnimation]->getName();
    }
	
	void Entity::StartWithEvent(const char * name, JEvent * event)
	{
		for(size_t i=0; i<mAnimations.size(); ++i){
			if(mAnimations[i]->getName() == 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; i<mAnimations.size(); ++i){
			if(mAnimations[i]->getName() == 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; i<FILE_SPRITE_SIZE; ++i){ 
			fileSprites[i].fileId = -1;
			fileSprites[i].id = -1; 
			fileSprites[i].folderId = -1;
	}
}


CCSpriterX::~CCSpriterX()
{
}


CCSpriterX *CCSpriterX::create(const char *filename)
{
	CCSpriterX *animator = new CCSpriterX();
	animator->type = 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 < (int)mFolders.size())
	{
		Folder *folder = mFolders[folderId];

		if (folder)
		{
			File *file = folder->GetFile(fileId);

			if (file){
				int id = this->fileSprites[timelineId].id;
				if(id == -1){
					for(int i=0; i<FILE_SPRITE_SIZE; ++i){
						if(fileSprites[i].fileId == fileId && fileSprites[i].folderId == folderId){
							++id;
						}
					}
					id += 1;
					fileSprites[timelineId].folderId = folderId;
					fileSprites[timelineId].fileId = fileId;
					fileSprites[timelineId].id = id;
				}
				
				if(file->sprites[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<string>("res")+"/"+filename;
	char *buffer = (char *)CCFileUtils::sharedFileUtils()->getFileData(path.c_str(), "rb", &filesize);
	
	if (buffer == NULL)
		return false;

	//加载大图
	string sfplist = workPath+gConfig->read<string>("res")+"/scml/"+name+".plist";
	string sfpng = workPath+gConfig->read<string>("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;

}
	

抱歉!评论已关闭.