目前看来Cocos2d-x播放动画的方式只有2种:
-
第一种:是播放序列帧动画,即将动画的每一帧都加载进缓存里,需要播放时再使用Animation类来播放,这种方法简单暴力,应对一些细节要求低的动画场景的时候,这么干无伤大雅。但是当动画帧数稍高的时候就会需要大量的图片,消耗资源很大。
-
第二种:是由Cocos2d-x提供的Action类来播放动画,这种动画是在帧循环中靠调整每次渲染的坐标来打到动画效果,由于帧循环是1/60秒刷新一次,会让这样播放的动画非常流畅,而且不需要每一帧图片的资源。这种方案的缺点是播放动画的节点只能加载一张图片资源,当我们要实现一个如下的动画时,
如果单从代码实现需要创建多个精灵,还要绑定各个精灵之间的协调和联动,总之会非常非常的麻烦。
骨骼动画可以兼容以上两种方法的优点,同时不包含它们的缺点。所以现在越来越多的公司使用Cocos Studio来制作动画。
要使用CocosStudio首先要到官网下载你需要的Studio版本,由于Cocos2d-x引擎本身的版本迭代速度比较快,有些版本的Studio并不能与引擎兼容,这里附上论坛上一个较为详细的版本对应下载。我使用的是刚发布不久的3.2版引擎,Cocos Studio1.5.0.1能够对其兼容。
初次使用我想完成两个学习目标:
-
第一是学会制作骨骼动画,这个链接里有详细的描述,跟着一步一步来就可以了,我就不做复述了。
-
第二是在Cocos2d-x工程中使用Studio制作的动画。
首先在Cocos2d-x的根目录下找到cocos2d-x-3.2\cocos\editor-support目录,将cocostudio目录以及其包含的文件复制到你新建工程所在目录下。然后用vs打开新建的项目,右击解决方案-》添加-》现有项目,把cocostudio添加进工程。接着右键你的工程-》属性-》c\c++-》常规-》附加包含目录,把cocostudio的目录导入进去。最后接着右键你的工程-》属性-》通用属性-》引用-》添加新引用。
现在我们可以开始写代码了,首先要设计有个Hero类,用他来播放动画,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
#ifndef __HERO_H__
#define __HERO_H__
#include "cocos2d.h"
#include "cocos-ext.h"
#include "CocoStudio.h"
USING_NS_CC;
using
namespace
cocostudio;
USING_NS_CC_EXT;
enum
DIRECTION { LEFT, RIGHT, NONE };
class
Hero:
public
Sprite
{
public
:
CREATE_FUNC(Hero);
bool
init();
void
runLeft(
float
dt);
void
runRight(
float
dt);
void
attack();
void
death();
void
stop();
DIRECTION dir;
Size size;
Armature* armature;
bool
isAniRunLeft;
bool
isAniRunRight;
};
#endif
|
我们在Hero的init函数里初始化动画,并调用一个stop函数加载一个站立时的动画:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
#include "Hero.h"
bool
Hero::init()
{
Sprite::init();
size = Director::getInstance()->getWinSize();
ArmatureDataManager::sharedArmatureDataManager()->addArmatureFileInfo(
"Hero0.png"
,
"Hero0.plist"
,
"Hero.ExportJson"
);
armature = Armature::create(
"Hero"
);
armature->setScale(0.7f);
armature->setPosition(Vec2(size.width / 2, size.height / 2));
addChild(armature);
stop();
dir = NONE;
isAniRunLeft =
false
;
isAniRunRight =
false
;
return
true
;
}
void
Hero::stop()
{
armature->getAnimation()->play(
"loading"
);
}
void
Hero::runLeft(
float
dt)
{
float
dis = dt * 200;
setPositionX(getPositionX() - dis);
}
void
Hero::runRight(
float
dt)
{
float
dis = dt * 200;
setPositionX(getPositionX() + dis);
}
void
Hero::attack()
{
armature->getAnimation()->play(
"attack"
);
}
void
Hero::death()
{
armature->getAnimation()->play(
"death"
);
}
|
接着我们需要一个场景类,让我们的Hero在这个场景里面动起来:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__
#include "cocos2d.h"
#include "cocos-ext.h"
#include "CocoStudio.h"
#include "Hero.h"
USING_NS_CC_EXT;
class
menuDelegate
{
public
:
virtual
void
stopstate() = 0;
};
class
Panel :
public
Menu
{
public
:
menuDelegate* exm;
MenuItem* getSelectItem()
{
return
_selectedItem;
}
static
Panel* create()
{
Panel* ret =
new
Panel;
ret->init();
ret->autorelease();
return
ret;
}
bool
init()
{
Menu::init();
scheduleUpdate();
return
true
;
}
void
update(
float
dt)
{
if
(
this
->getSelectItem() &&
this
->getSelectItem()->isSelected())
this
->getSelectItem()->activate();
else
{
exm->stopstate();
}
}
};
class
HelloWorld :
public
cocos2d::Layer,
public
menuDelegate
{
public
:
// there's no 'id' in cpp, so we recommend returning the class instance pointer
static
cocos2d::Scene* createScene();
// Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
virtual
bool
init();
// a selector callback
void
menuCloseCallback(cocos2d::Ref* pSender);
// implement the "static create()" method manually
CREATE_FUNC(HelloWorld);
void
stopstate();
void
update(
float
dt);
void
moveRight();
void
moveLeft();
void
moveAttack();
void
moveDead();
void
loadMenu();
Hero* hero;
Panel* menu;
};
#endif // __HELLOWORLD_SCENE_H__
|
以下是场景类的cpp文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
#include "HelloWorldScene.h"
USING_NS_CC;
using
namespace
cocostudio;
Scene* HelloWorld::createScene()
{
// 'scene' is an autorelease object
auto scene = Scene::create();
// 'layer' is an autorelease object
auto layer = HelloWorld::create();
// add layer as a child to scene
scene->addChild(layer);
// return the scene
return
scene;
}
// on "init" you need to initialize your instance
bool
HelloWorld::init()
{
//
// 1. super init first
if
( !Layer::init() )
{
return
false
;
}
Size visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();
/
// 2. add a menu item with "X" image, which is clicked to quit the program
// you may modify it.
// add a "close" icon to exit the progress. it's an autorelease object
auto closeItem = MenuItemImage::create(
"CloseNormal.png"
,
"CloseSelected.png"
,
CC_CALLBACK_1(HelloWorld::menuCloseCallback,
this
));
closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/2 ,
origin.y + closeItem->getContentSize().height/2));
// create menu, it's an autorelease object
auto menu = Menu::create(closeItem, NULL);
menu->setPosition(Vec2::ZERO);
this
->addChild(menu, 1);
/
// 3. add your codes below...
// add a label shows "Hello World"
// create and initialize a label
auto label = LabelTTF::create(
"Hello World"
,
"Arial"
, 24);
// position the label on the center of the screen
label->setPosition(Vec2(origin.x + visibleSize.width/2,
origin.y + visibleSize.height - label->getContentSize().height));
// add the label as a child to this layer
this
->addChild(label, 1);
loadMenu();
hero = Hero::create();
addChild(hero);
scheduleUpdate();
return
true
;
}
void
HelloWorld::update(
float
dt)
{
if
(hero->dir == RIGHT)
{
hero->runRight(dt);
}
if
(hero->dir == LEFT)
{
hero->runLeft(dt);
}
}
void
HelloWorld::loadMenu()
{
Size size = Director::getInstance()->getWinSize();
auto closeItem1 = MenuItemImage::create(
"CloseNormal.png"
,
"CloseSelected.png"
, CC_CALLBACK_0(HelloWorld::moveLeft,
this
));
auto closeItem2 = MenuItemImage::create(
"CloseNormal.png"
,
"CloseSelected.png"
, CC_CALLBACK_0(HelloWorld::moveRight,
this
));
auto closeItem3 = MenuItemImage::create(
"CloseNormal.png"
,
"CloseSelected.png"
, CC_CALLBACK_0(HelloWorld::moveAttack,
this
));
auto closeItem4 = MenuItemImage::create(
"CloseNormal.png"
,
"CloseSelected.png"
, CC_CALLBACK_0(HelloWorld::moveDead,
this
));
menu = Panel::create();
menu->addChild(closeItem1);
menu->addChild(closeItem2);
menu->addChild(closeItem3);
menu->addChild(closeItem4);
menu->alignItemsHorizontally();
menu->setPositionY(menu->getPositionY() / 2);
menu->exm =
this
;
addChild(menu);
}
void
HelloWorld::moveRight()
{
if
(hero->dir == NONE)
hero->armature->getAnimation()->play(
"run"
);
float
num = hero->armature->getRotationY();
if
(num == -180)
{
hero->armature->setRotationY(0);
}
hero->dir = RIGHT;
}
void
HelloWorld::moveLeft()
{
if
(hero->dir == NONE)
hero->armature->getAnimation()->play(
"run"
);
float
num = hero->armature->getRotationY();
if
(num == 0 )
{
hero->armature->setRotationY(-180);
}
hero->dir = LEFT;
}
void
HelloWorld::moveDead()
{
hero->death();
}
void
HelloWorld::moveAttack()
{
hero->attack();
}
void
HelloWorld::stopstate()
{
if
(hero->dir == NONE)
return
;
float
num = hero->armature->getRotationY();
if
(num == 0)
{
hero->stop();
CCLOG(
"111111"
);
}
else
if
(num == -180)
{
hero->stop();
hero->armature->setRotationY(-180);
}
hero->dir = NONE;
}
void
HelloWorld::menuCloseCallback(Ref* pSender)
{
#
if
(CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
MessageBox(
"You pressed the close button. Windows Store Apps do not implement a close button."
,
"Alert"
);
return
;
#endif
Director::getInstance()->end();
#
if
(CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit
(0);
#endif
}
|
来源网址:http://blog.csdn.net/wxq_wuxingquan/article/details/38615183