导入动画 spine

导入动画 spine
spine 是一款2d动画制作工具,具体介绍见:http://zh.esotericsoftware.com/

我们让我们的引擎支持它制作的动画。
首先从github下载官方runTimes,这里选择spine-c。
然后我们要处理的是它的渲染与创建。
/********************************************************************
 Copyright(C), 2012-2013,
 FileName:SkeletonAnimation.h
 Description:
 Author:cloud
 Created:2014/11/07
 history:
7:11:2014 15:41 by
*********************************************************************/
#pragma once
#include "export/Node.h"
#include "spine/spine.h"
#include "base/GLFix.h"
#include "base/render/Quad.h"

namespace cloud
{
	class SkeletonAnimation :public Node
	{
	public:
		SkeletonAnimation(const char* atasPath,const char* jsonPath);
		~SkeletonAnimation();		
		void initialize(const char* atasPath,const char* jsonPath);
		void update(float dt);
		void createTexture(const char* texturePath);
		void removeTexture();
		void render(const Mat4& parentMat4);
		Size getTextureSize();
		void playAnimation(const char* animationName,bool isLoop);
		void stopAnimation(int endTrackIdx = -1);
	protected:
		std::string _animationName;
		spAnimationState* _state;
		spSkeleton* _skeleton;
		GLuint _textureID;
		Size _textureSize;
		std::string _texturePath;
		QuadCommand      _quadCommand;
		Quad* _quads;
		BlendFunc        _blendFunc; 
		int _totalQuads;
	};
}

/********************************************************************
 Copyright(C), 2012-2013,
 FileName:SkeletonAnimation.cpp
 Description:
 Author:cloud
 Created:2014/11/07
 history:
7:11:2014 15:42 by
*********************************************************************/
#include "base/TextureManager.h"
#include "spine/SkeletonAnimation.h"
#include "base/render/Renderer.h"
#include "base/EngineLog.h"

//TODO:未加入事件回调


namespace cloud
{	
	SkeletonAnimation::SkeletonAnimation(const char* atasPath,const char* jsonPath):_skeleton(NULL),_state(NULL),_quads(NULL),_totalQuads(0)
	{
		_blendFunc = BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		std::string dirPath = atasPath;
		int pos = dirPath.rfind("/");
		if (pos > -1)
		{
			dirPath = dirPath.substr(0,pos+1);
		}
		else
		{
			dirPath = "";
		}
		
		initialize(atasPath,jsonPath);


		_totalQuads = _skeleton->slotsCount;
		_quads = (Quad*)malloc( _totalQuads * sizeof(Quad));
		memset(_quads, 0, _totalQuads * sizeof(Quad));
		
	}

	SkeletonAnimation::~SkeletonAnimation()
	{
		if (_quads)
		{
			free(_quads);
		}
		spAnimationState_dispose(_state);
		spSkeleton_dispose(_skeleton);
	}

	void SkeletonAnimation::initialize(const char* atasPath,const char* jsonPath)
	{
		spAtlas* atlas = spAtlas_createFromFile(atasPath,this);
		spSkeletonJson* json = spSkeletonJson_create(atlas);		
		spSkeletonData* skeletonData = spSkeletonJson_readSkeletonDataFile(json, jsonPath);
		spSkeletonJson_dispose(json);

		_skeleton = spSkeleton_create(skeletonData);		
		_state = spAnimationState_create(spAnimationStateData_create(_skeleton->data));	

		
	}
	
	void SkeletonAnimation::playAnimation(const char* animationName,bool isLoop)
	{		
		_animationName = animationName;
		spAnimationState_setAnimationByName(_state, 0, animationName, isLoop);	
		if(!isScheduleUpdate())
			scheduleUpdate();
	}

	void SkeletonAnimation::stopAnimation(int endTrackIdx)
	{
		if(isScheduleUpdate())
			unscheduleUpdate();

		if (endTrackIdx != -1)
		{
			spAnimationState_setAnimationByName(_state, endTrackIdx, _animationName.c_str(), false);			
		}
	}

	void SkeletonAnimation::update(float dt)
	{
		//spBone* rootBone = _skeleton->bones[0];
		spSkeleton_update(_skeleton,dt);
		spAnimationState_update(_state, dt);
		spAnimationState_apply(_state, _skeleton);
		spSkeleton_updateWorldTransform(_skeleton);
	}

	void SkeletonAnimation::createTexture(const char* texturePath)
	{
		int textureWidth;
		int textureHeight;
		_textureID = TextureManager::getInstance()->createTexture(texturePath,textureWidth,textureHeight);
		_textureSize = Size(textureWidth,textureHeight);
		_contentSize = _textureSize;
		_texturePath = texturePath;
	}

	void SkeletonAnimation::removeTexture()
	{
		TextureManager::getInstance()->removeTexture(_texturePath.c_str());
		_texturePath = "";
	}

	void SkeletonAnimation::render(const Mat4& parentMat4)
	{
		//
		
		float vertices[8];
		for (int i = 0, n = _skeleton->slotsCount; i < n; i++)
		{
			spSlot* slot = _skeleton->drawOrder[i];
			if (!slot->attachment || slot->attachment->type != SP_ATTACHMENT_REGION) continue;
			spRegionAttachment* regionAttachment = (spRegionAttachment*)slot->attachment;
			spRegionAttachment_computeWorldVertices(regionAttachment, slot->bone, vertices);
			float r = slot->r;
			float g = slot->g;
			float b = slot->b;
			float a =slot->a;

			Quad* quad = _quads+ i;

			quad->bl._color.r = r;
			quad->bl._color.g = g;
			quad->bl._color.b = b;
			quad->bl._color.a = a;
			quad->tl._color.r = r;
			quad->tl._color.g = g;
			quad->tl._color.b = b;
			quad->tl._color.a = a;
			quad->tr._color.r = r;
			quad->tr._color.g = g;
			quad->tr._color.b = b;
			quad->tr._color.a = a;
			quad->br._color.r = r;
			quad->br._color.g = g;
			quad->br._color.b = b;
			quad->br._color.a = a;
			
			quad->bl._position.x = vertices[SP_VERTEX_X1];
			quad->bl._position.y = vertices[SP_VERTEX_Y1];
			quad->tl._position.x = vertices[SP_VERTEX_X2];
			quad->tl._position.y = vertices[SP_VERTEX_Y2];
			quad->tr._position.x = vertices[SP_VERTEX_X3];
			quad->tr._position.y = vertices[SP_VERTEX_Y3];
			quad->br._position.x = vertices[SP_VERTEX_X4];
			quad->br._position.y = vertices[SP_VERTEX_Y4];

			quad->bl._texCoord.x = regionAttachment->uvs[SP_VERTEX_X1];
			quad->bl._texCoord.y = regionAttachment->uvs[SP_VERTEX_Y1];
			quad->tl._texCoord.x = regionAttachment->uvs[SP_VERTEX_X2];
			quad->tl._texCoord.y = regionAttachment->uvs[SP_VERTEX_Y2];
			quad->tr._texCoord.x = regionAttachment->uvs[SP_VERTEX_X3];
			quad->tr._texCoord.y = regionAttachment->uvs[SP_VERTEX_Y3];
			quad->br._texCoord.x = regionAttachment->uvs[SP_VERTEX_X4];
			quad->br._texCoord.y = regionAttachment->uvs[SP_VERTEX_Y4];		
		}

		_quadCommand.init(_quads,_textureID,_totalQuads,_blendFunc,this->transform(parentMat4));


		Renderer::getInstance()->addQuadCommand(&_quadCommand);

	}

	Size SkeletonAnimation::getTextureSize()
	{
		return _textureSize;
	}
}

还要实例化它的三个函数:
#include "extension.h"
#include "base/fileUtils/FileUtils.h"
#include "SkeletonAnimation.h"
void _spAtlasPage_createTexture (spAtlasPage* self, const char* path)
{
	
	cloud::SkeletonAnimation* skeletonAnimation = (cloud::SkeletonAnimation*) self->atlas->rendererObject;
	if(skeletonAnimation)
	{
		skeletonAnimation->createTexture(path);
		self->width = skeletonAnimation->getTextureSize().width;
		self->height = skeletonAnimation->getTextureSize().height;
	}
}

void _spAtlasPage_disposeTexture (spAtlasPage* self)
{
	cloud::SkeletonAnimation* skeletonAnimation = (cloud::SkeletonAnimation*) self->atlas->rendererObject;
	if(skeletonAnimation)
		skeletonAnimation->removeTexture();
}

char* _spUtil_readFile (const char* path, int* length)
{
	unsigned char* outData = NULL;
	unsigned int outLen = 0;
	cloud::FileUtils::getInstance()->readFile(path,&outData,outLen);
	*length = outLen;
	return (char*)outData;
}

调用代码如下:
SkeletonAnimation* ske = new SkeletonAnimation("spineboy.atlas","spineboy.json");
		ske->setScale(0.3f);
		ske->setPosition(Point(winSize.width* 0.5,winSize.height * 0.3));
		ske->playAnimation("walk",true);
		addChild(ske,3);

要注意的几点是:
_spAtlasPage_createTexture里要被纹理的长宽,重新赋值回去。
spin的纹理为png,而且默认是上下颠倒了的。

你可能感兴趣的:(游戏引擎设计)