上一篇文章讲述了利用cocos2d-x构建精灵的动画效果,今天打算以此为引子,创建一个在移动时同时指挥角色到我手指触摸的移动地点,那么就开始吧。
开始
本篇要点
- 角色(Sprite)缓存
- 动画(Animation)缓存
- 触摸(Touch)精灵到我指定的移动地点
- 动作(Action)移动和切换
角色缓存
角色缓存使用CCSpriteFrameCache ,配合CCSpriteBatchNode将图片*.plist和*.png 加载进内存,方便以后调用。
以上为动作序列图,图片名称为:sg.png.图片来源于博客园:nowpaper.
角色缓存代码如下:
cache->addSpriteFramesWithFile(
“
sg.plist
“);
sprite=CCSprite::createWithSpriteFrameName(
“
A1_6.png
“);
sprite->setPosition(ccp(size.width-sprite->getContentSize().width,size.height/
2));
spriteBatchNode=CCSpriteBatchNode::create(
“
sg.png
“);
spriteBatchNode->addChild(sprite);
addChild(spriteBatchNode);
以上代码,CCSpriteFrameCache负责加载sg.plist,CCSpriteBatchNode负责加载sg.png,然后创建一个精灵指定初始化位置和精灵纹理,并添加进CCSpriteBatchNode。通过上面的代码即可以将一个plist序列图加载进缓存了,你要做的就是将这些缓存的数据拿出来操作它。
动画缓存
上面己经将数据加载进缓存了,可以使用其中的那些节点来制作动画缓存了。
缓存动画使用 CCAnimationCache,该动画同样需要使用到plist文件,代码如下
animCache->addAnimationsWithFile(
“
sg.plist
“);
在将plist文件添加完后,即可以通过动画Animation将每一个动画的Animation添加进CCAnimationCache了,这里我写了一个函数,代码见下方
int begin,
int end,
char* cacheActionName,CCPoint point){
CCAnimationCache *animCache = CCAnimationCache::sharedAnimationCache();//得到一个缓存对象
CCArray *array = CCArray::createWithCapacity(end-begin);
char name[
20];
for(
int i = begin ;i<end;i++){
sprintf(name,
“
A1_%d.png
“,i);
CCSpriteFrame* frame =cache->spriteFrameByName(name);
array->addObject(frame);
}//以上创建一个动作序列集合
CCAnimation *plistAnimation = CCAnimation::createWithSpriteFrames(array,
0.2f);//通过动作序列集合创建animation
animCache->addAnimation(plistAnimation, cacheActionName);//添加进缓存并指定缓存名称
array->removeAllObjects();
CCAnimation *animation = animCache->animationByName(cacheActionName);//通过缓存名称得到一个动画
animation->setRestoreOriginalFrame(
true);
CCAnimate *ani=CCAnimate::create(animation);
CCActionInterval* plistSeq=(CCActionInterval*)(CCSequence::create(ani,
CCFlipX::create(point.x>
0?
true:
false),
ani->copy()->autorelease(),
NULL
));
return CCRepeatForever::create(plistSeq);//创建动画并返回Action
}
触摸精灵到我指定的移动地点
设定好让程序允许Touch之后,在回调函数ccTouchesEnded 里面通过捕获触摸位置指定精灵移动,代码见下方
CCPoint location = touch ->getLocation();
float offX=location.x-sprite->getPosition().x;
float offY=location.y-sprite->getPosition().y;
walkAction=createAction(
4,
6,
“
move
“,ccp(offX,offY));
sprite->setFlipX(offX>
0?
true:
false);
float realX=offY/offX;
CCPoint realDeast =ccp(location.x,location.y);
CCActionInterval *actionTo=CCMoveTo::create(
2.2f,realDeast);
CCAction *moveToAction=CCSequence::create(
actionTo,
CCCallFunc::create(
this,callfunc_selector(HelloWorld::moveDone)),
NULL
);
sprite->runAction(moveToAction);
ok了,精灵移动了,但你会发现,你想让精灵移动的时候不是一整张图片移动,而是边移动边两只脚在走路的移动,就像是我们人类一样,是走着过去的,而不是幽灵飘过去的,那么,我们要做些什么呢?
动作移动
其实,很简单 ,只要记住要精灵移动的时候即:MoveTo时,同时再让精灵执行一个动作即walk的动作,代码如下:
walkAction=createAction(
4,
6,
“
move
“,ccp(offX,offY));//构建一个walk的action
sprite->runAction(walkAction);//播放走的action
sprite->runAction(moveToAction);//播放moveTo的action
当到达指定地点时,希望让角色以站立的姿势站在屏幕上,这时我们需要在moveTo的callback函数里面调用,让其停止当前action,并重新执行站立的action,代码如下:
void HelloWorld::moveDone(){
sprite->stopAllActions();
CCAnimationCache *animCache = CCAnimationCache::sharedAnimationCache();
CCAnimation *standAnimation = animCache->animationByName(
“
stand
“);
standAnimation->setRestoreOriginalFrame(
true);
CCAnimate *standAni=CCAnimate::create(standAnimation);
CCActionInterval* s=(CCActionInterval*)(CCSequence::create(standAni,
standAni->copy()->autorelease(),
NULL
));
CCAction *frameAction=CCRepeatForever::create(s);
sprite->runAction(frameAction);
}
全部代码如下:
View Code
using
namespace cocos2d;
2
using
namespace CocosDenshion;
3
4
#define LOG_TAG “main” ||- function
5
#define LOGD(…) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
6
7 CCScene* HelloWorld::scene()
8 {
9
//
‘scene’ is an autorelease object
10
CCScene *scene = CCScene::create();
11
12
//
‘layer’ is an autorelease object
13
HelloWorld *layer = HelloWorld::create();
14
15
//
add layer as a child to scene
16
scene->addChild(layer);
17
18
//
return the scene
19
return scene;
20 }
21
22
//
on “init” you need to initialize your instance
23
bool HelloWorld::init()
24 {
25
//
26
//
1. super init first
27
if ( !CCLayer::init() )
28 {
29
return
false;
30 }
31
32
this->setTouchEnabled(
true);
33
34 CCSize size = CCDirector::sharedDirector()->getWinSize();
35 CCAnimationCache::purgeSharedAnimationCache();
36 CCAnimationCache *animCache = CCAnimationCache::sharedAnimationCache();
37
38 animCache->addAnimationsWithFile(
“
sg.plist
“);
39
40
41
42 cache=CCSpriteFrameCache::sharedSpriteFrameCache();
43 cache->addSpriteFramesWithFile(
“
sg.plist
“);
44
45 sprite=CCSprite::createWithSpriteFrameName(
“
A1_6.png
“);
46 sprite->setPosition(ccp(size.width-sprite->getContentSize().width,size.height/
2));
47 spriteBatchNode=CCSpriteBatchNode::create(
“
sg.png
“);
48 spriteBatchNode->addChild(sprite);
49 addChild(spriteBatchNode);
50
51 cache->addSpriteFramesWithFile(
“
hero.plist
“);
52 hero=CCSprite::createWithSpriteFrameName(
“
Hero02_0.png
“);
53 hero->setPosition(ccp(hero->getContentSize().width,size.height/
2));
54 heroBatchNode=CCSpriteBatchNode::create(
“
hero.png
“);
55 heroBatchNode ->addChild(hero);
56 hero->setFlipX(
true);
57
58 addChild(heroBatchNode);
59
60
61
62 attackArray =CCArray::createWithCapacity(
4);
63
char attackName[
20];
64
for(
int i=
0;i<
4;i++){
65 sprintf(attackName,
66
“
A1_%d.png
“,i);
67 CCSpriteFrame* frame =cache->spriteFrameByName(attackName);
68 attackArray->addObject(frame);
69 }
70 CCAnimation *attackAnimation =CCAnimation::createWithSpriteFrames(attackArray,
0.2f);
71 CCAnimationCache::sharedAnimationCache()->addAnimation(attackAnimation,
“
attack
“);
72
73 attackArray->removeAllObjects();
74
75
76
77 standArray= CCArray::createWithCapacity(
1);
78
char standName[
20];
79
for(
int i=
6;i<
7;i++){
80 sprintf(standName,
81
“
A1_%d.png
“,i);
82 CCSpriteFrame* frame =cache->spriteFrameByName(standName);
83 standArray->addObject(frame);
84 }
85 CCAnimation *standAnimation =CCAnimation::createWithSpriteFrames(standArray,
0.2f);
86 CCAnimationCache::sharedAnimationCache()->addAnimation(standAnimation,
“
stand
“);
87 standArray->removeAllObjects();
88
89
90
return
true;
91 }
92
93
void HelloWorld::moveDone(){
94
//
95
sprite->stopAllActions();
96 CCAnimationCache *animCache = CCAnimationCache::sharedAnimationCache();
97
98
99 CCAnimation *standAnimation = animCache->animationByName(
“
stand
“);
100 standAnimation->setRestoreOriginalFrame(
true);
101 CCAnimate *standAni=CCAnimate::create(standAnimation);
102 CCActionInterval* s=(CCActionInterval*)(CCSequence::create(standAni,
103 standAni->copy()->autorelease(),
104 NULL
105 ));
106 CCAction *frameAction=CCRepeatForever::create(s);
107
108
109 sprite->runAction(frameAction);
110 }
111
112 CCAction* HelloWorld::createAction(
int begin,
int end,
char* cacheActionName,CCPoint point){
113 CCAnimationCache *animCache = CCAnimationCache::sharedAnimationCache();
114 CCArray *array = CCArray::createWithCapacity(end-begin);
115
116
char name[
20];
117
for(
int i = begin ;i<end;i++){
118 sprintf(name,
“
A1_%d.png
“,i);
119 CCSpriteFrame* frame =cache->spriteFrameByName(name);
120 array->addObject(frame);
121 }
122
123 CCAnimation *plistAnimation = CCAnimation::createWithSpriteFrames(array,
0.2f);
124 CCAnimationCache::sharedAnimationCache()->addAnimation(plistAnimation, cacheActionName);
125
126 array->removeAllObjects();
127
128 CCAnimation *animation = animCache->animationByName(cacheActionName);
129 animation->setRestoreOriginalFrame(
true);
130 CCAnimate *ani=CCAnimate::create(animation);
131 CCActionInterval* plistSeq=(CCActionInterval*)(CCSequence::create(ani,
132 CCFlipX::create(point.x>
0?
true:
false),
133 ani->copy()->autorelease(),
134 NULL
135 ));
136
return CCRepeatForever::create(plistSeq);
137 }
138
139
140
void HelloWorld::registerWithTouchDispatcher(){
141 CCDirector::sharedDirector()->getTouchDispatcher()->addStandardDelegate(
this,
0);
142 }
143
void HelloWorld::ccTouchesEnded(cocos2d::CCSet * touches,cocos2d::CCEvent *
event){
144
145 sprite->stopAllActions();
146
147
148 CCTouch* touch=(CCTouch*)(touches->anyObject());
149 CCPoint location = touch ->getLocation();
150
float offX=location.x-sprite->getPosition().x;
151
float offY=location.y-sprite->getPosition().y;
152
153 walkAction=createAction(
4,
6,
“
move
“,ccp(offX,offY));
154
155 sprite->setFlipX(offX>
0?
true:
false);
156
157
158
float realX=offY/offX;
159 CCPoint realDeast =ccp(location.x,location.y);
160 CCActionInterval *actionTo=CCMoveTo::create(
2.2f,realDeast);
161 CCAction *moveToAction=CCSequence::create(
162 actionTo,
163 CCCallFunc::create(
this,callfunc_selector(HelloWorld::moveDone)),
164 NULL
165 );
166
167 sprite->runAction(walkAction);
168 sprite->runAction(moveToAction);
169 }
170
171
172
void HelloWorld::menuCloseCallback(CCObject* pSender)
173 {
174 CCDirector::sharedDirector()->end();
175
176
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
177 exit(
0);
178
#endif
179
注意点
CCAnimation *attackAnimation =CCAnimation::createWithSpriteFrames(attackArray,0.2f); 与
最后实现的效果如下:
由于是在ubuntu下开发,好像没有什么抓取屏幕gif 图片的软件可用,简单截一屏!!!
代码没有做任何的处理,很多多余的代码,做个DEMO可以看看就行!!!
代码下载:https://github.com/terryyhl/SpriteAnimation.git
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/110285.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...