失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 从0开发游戏引擎之游戏引擎中2D序列帧动画控制器的实现

从0开发游戏引擎之游戏引擎中2D序列帧动画控制器的实现

时间:2020-10-23 07:00:51

相关推荐

从0开发游戏引擎之游戏引擎中2D序列帧动画控制器的实现

这种序列帧动画要求每一帧的宽高必须一一致,否则动画播起来会出问题。

需要的图片类似图1.1 会把所有的动作拼接到一张图上,这样做也是为了节省内存和减少DrawCall,切换动作的时候只需要重新计算图片的UV,然后把算出来的UV作为新区域贴在原来的那张纹理面片上即可。

图1.1

Animate是Animation的一部分,一个Animation可以保存多个Animate,也可以理解成Animate只是一个动画片段,Animation是完整的动画控制器。这个结构其实有点像Unity的AnimateClip和Animator。

不多说,上代码,自己去看代码吧,实现不是很难,不多讲了。

程序1.1

Animate.h 完整代码

#pragma oncenamespace U2D{enum MovementEvent{START,COMPLETE,};class CAnimate :public CPicture{friend class CAnimation;private:char name[50];//动画名UINT frameWidth;//每一帧的宽度UINT frameHeight;//每一帧的高度UINT rows;//总行数UINT cols;//总列数UINT startIndex;//开始的索引编号UINT endIndex;//结束的索引编号UINT curIndex;//当前的索引编号bool isPlaying;//是否播放bool isLoop;//是否循环UINT frameSpeed;//每一帧的速度UINT frameTimer;//每一帧的时间animate_selector listener_movementEvent; //动画事件监听public:CAnimate(char *fileName, UINT rows, UINT cols);CAnimate(CCTexture *tex, UINT rows, UINT cols);void setName(char *name) { strcpy(this->name, name); }char *getName() { return this->name; }void setFrameIndex(UINT startIndex, UINT endIndex){this->startIndex = startIndex;this->endIndex = endIndex;curIndex = startIndex;}Vector2 getFrameSize() { return Vector2(frameWidth, frameHeight); }UINT getFrameCount() { return endIndex - startIndex + 1; }void play() { isPlaying = true; }void stop() { isPlaying = false; }void repeat(bool isLoop) { this->isLoop = isLoop; }void setDelayUnit(UINT frameSpeed) { this->frameSpeed = frameSpeed; }void setMovementEventCallFunc(animate_selector fun_movementEvent);//设置动画事件的回调函数void draw();void all_Anchor_0_0();void all_Anchor_05_05();public:CAnimate() {}~CAnimate(void) {}};}

程序1.2

Animate.cpp完整代码

#include "Engine.h"namespace U2D{CAnimate::CAnimate(char *fileName, UINT rows, UINT cols):CPicture(fileName){strcmp(this->name, fileName);this->rows = rows;this->cols = cols;isPlaying = true;isLoop = true;frameSpeed = 10;frameWidth = pTexture->getWidth() / cols;frameHeight = pTexture->getHeight() / rows;startIndex = 0;endIndex = rows*cols - 1;curIndex = startIndex;}CAnimate::CAnimate(CCTexture *tex, UINT rows, UINT cols):CPicture(tex){strcmp(this->name, tex->getName());this->rows = rows;this->cols = cols;isPlaying = true;isLoop = true;frameSpeed = 10;frameWidth = tex->getWidth() / cols;frameHeight = tex->getHeight() / rows;startIndex = 0;endIndex = rows*cols - 1;curIndex = startIndex;}void CAnimate::setMovementEventCallFunc(animate_selector fun_movementEvent){this->listener_movementEvent = fun_movementEvent;}void CAnimate::draw(){if (isPlaying){if (frameTimer++%frameSpeed == 0){if (curIndex == startIndex){if (listener_movementEvent){if (parent != NULL){(parent->*listener_movementEvent)(this, MovementEvent::START);}else(parent->*listener_movementEvent)(this, MovementEvent::START);}}if (curIndex == endIndex + 1){if (isLoop){curIndex = startIndex;}else{isPlaying = false;curIndex = endIndex;}if (listener_movementEvent){if (parent != NULL){if (parent != NULL){(parent->*listener_movementEvent)(this, MovementEvent::COMPLETE);}else(parent->*listener_movementEvent)(this, MovementEvent::COMPLETE);}}}(&srcRect,curIndex%cols*frameWidth,curIndex / cols*frameHeight,(curIndex%cols + 1)*frameWidth,(curIndex / cols + 1)*frameHeight);curIndex++;}}CPicture::draw();}void CAnimate::all_Anchor_0_0(){}void CAnimate::all_Anchor_05_05(){}}

程序1.3

Animation.h 完整代码

#pragma oncenamespace U2D {class CAnimation :public CElement{friend class CPlayer;protected:list<CAnimate*> animateList;//动画的链表用名字判断,有就返回,没有就new一个CAnimate *animate;//当前播放的动画animation_selector listener_movementEvent;//动画集事件监听void animateEvent(CAnimate* animate, MovementEvent type);UINT rows;UINT cols;char*fileName;public:CAnimation();CAnimate* addAnimate(char *animName, char *fileName, UINT rows, UINT cols);CAnimate* addAnimate(char *animName, CCTexture *tex, UINT rows, UINT cols);CAnimate* findAnimate(char *animName);void setAnimate(char *animName);Vector2 getFrameSize() { return animate->getFrameSize(); }UINT getFrameCount() { return animate->getFrameCount(); }void play() { animate->play(); }void stop() { animate->stop(); }void repeat(bool isLoop) { animate->repeat(isLoop); }void setDelayUnit(UINT frameSpeed) { animate->setDelayUnit(frameSpeed); }void setFrameIndex(UINT startIndex, UINT endIndex) { return animate->setFrameIndex(startIndex, endIndex); }void setName_FrameIndex(char*name, UINT startIndex, UINT endIndex);void setMovementEventCallFunc(animation_selector fun_movementEvent);void draw();void setCurrentAllanchor(float ox, float oy);RECT getBoundBox();~CAnimation();};}

程序1.4

Animation.cpp完整代码

#include "Engine.h"namespace U2D{CAnimation::CAnimation(){animate = NULL;listener_movementEvent = NULL;}CAnimate* CAnimation::addAnimate(char *animName, char *fileName, UINT rows, UINT cols){CAnimate* anim = findAnimate(animName);//查找这个动画名字,如果找不到就会返回空if (anim != NULL)//如果不为空就说明找到了return anim;this->rows = rows;this->cols = cols;this->fileName = fileName;anim = new CAnimate(fileName, rows, cols); //如果为空就new一个对象压进去。并且把名字设置好anim->setName(animName);//设置动画名字anim->setParent(this);//CAnimation是CNode的子类,子类拥有父类的所有数据,所以压入CAnimation就等同于压入了CNode。anim->setMovementEventCallFunc(animate_selector(&CAnimation::animateEvent));//回调函数animateList.push_back(anim);//压进链表setAnimate(animName);//设置动画return animateList.back();//把刚压进去的对象返回出去}CAnimate* CAnimation::addAnimate(char *animName, CCTexture *tex, UINT rows, UINT cols){CAnimate* anim = findAnimate(animName);if (anim != NULL)return anim;this->rows = rows;this->cols = cols;anim = new CAnimate(tex, rows, cols);anim->setName(animName);anim->setParent(this);anim->setMovementEventCallFunc(animate_selector(&CAnimation::animateEvent));animateList.push_back(anim);setAnimate(animName);return animateList.back();}CAnimate* CAnimation::findAnimate(char *animName){list<CAnimate*>::iterator iter;for (iter = animateList.begin(); iter != animateList.end(); iter++){if (strcmp((*iter)->name, animName) == 0){return *iter;}}return NULL;}void CAnimation::setAnimate(char *animName){animate = findAnimate(animName);animate->startIndex = animate->startIndex;//这个写的不对、明天去参考伟哥的写法//animate->curIndex = animate->startIndex;animate->isPlaying = true;animate->frameTimer = 0;}void CAnimation::setName_FrameIndex(char*name, UINT startIndex, UINT endIndex){CAnimate* anim = findAnimate(name);anim = new CAnimate(fileName, rows, cols);//如果为空就new一个对象压进去。并且把名字设置好anim->setName(name);//设置动画名字anim->setParent(this);//CAnimation是CNode的子类,子类拥有父类的所有数据,所以压入CAnimation就等同于压入了CNode。anim->setFrameIndex(startIndex, endIndex);anim->frameTimer = 0;animateList.push_back(anim);//压进链表setAnimate(name);//设置动画}void CAnimation::draw(){Matrix3 scaleMatrix;Matrix3 rotateMatrix;Matrix3 transMatrix;//放缩图片Scale(scaleMatrix, scale.x, scale.y);//水平翻转if (flip == true)scaleMatrix._11 *= -1;//旋转图片Rotate(rotateMatrix, angle);// 平移图片到我们的指定位置Translate(transMatrix, pos.x, pos.y);local_matrix = scaleMatrix*rotateMatrix*transMatrix;if (parent == NULL){world_color = local_color;world_matrix = local_matrix;}else{sColor col = parent->getWorldColor();world_color.r = local_color.r*col.r;world_color.g = local_color.g*col.g;world_color.b = local_color.b*col.b;world_color.a = local_color.a*col.a;world_matrix = local_matrix*parent->getWorldMatrix();}if (visible == false)return;animate->draw();}void CAnimation::setCurrentAllanchor(float ox, float oy){}void CAnimation::setMovementEventCallFunc(animation_selector fun_movementEvent){listener_movementEvent = fun_movementEvent;}void CAnimation::animateEvent(CAnimate* animate, MovementEvent type){if (listener_movementEvent){if (parent != NULL)(parent->*listener_movementEvent)(this, type, animate->name);else(this->*listener_movementEvent)(this, type, animate->name);}}RECT CAnimation::getBoundBox(){return animate->getBoundBox();}CAnimation::~CAnimation(){}}

谢谢大家

如果觉得《从0开发游戏引擎之游戏引擎中2D序列帧动画控制器的实现》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。