天天看点

cocos2d-x for android:士兵听我的命令移动开始

上一篇文章讲述了利用cocos2d-x构建精灵的动画效果,今天打算以此为引子,创建一个在移动时同时指挥角色到我手指触摸的移动地点,那么就开始吧。

开始

本篇要点

  1. 角色(Sprite)缓存
  2. 动画(Animation)缓存
  3. 触摸(Touch)精灵到我指定的移动地点
  4. 动作(Action)移动和切换

涉及到的要学的学习点:

  1. 角色移动点击由此进入–>cocos2d-x for android:SimpleGame分析
  2. 播放动画点击由此进入–>cocos2d-x for android:CCSprite 精灵动画­

角色缓存

角色缓存使用CCSpriteFrameCache ,配合CCSpriteBatchNode将图片*.plist和*.png 加载进内存,方便以后调用。

cocos2d-x for android:士兵听我的命令移动开始

以上为动作序列图,图片名称为:sg.png.图片来源于博客园:nowpaper.

角色缓存代码如下:

CCSpriteFrameCache* cache=CCSpriteFrameCache::sharedSpriteFrameCache();

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文件,代码如下

CCAnimationCache *animCache = CCAnimationCache::sharedAnimationCache();

animCache->addAnimationsWithFile(

sg.plist

“);

在将plist文件添加完后,即可以通过动画Animation将每一个动画的Animation添加进CCAnimationCache了,这里我写了一个函数,代码见下方

CCAction* HelloWorld::createAction(

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 里面通过捕获触摸位置指定精灵移动,代码见下方

CCTouch* touch=(CCTouch*)(touches->anyObject());

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的动作,代码如下:

sprite->stopAllActions(); //因为Touch是无时无刻的,所以每当touch一次即停止当前的action

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

1

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); 与

CCAnimation *attackAnimation =CCAnimation::createWithSpriteFrames(attackArray);因为站立action才一帧,所以我不打算指定时间,但是如果不指定时间,它无法成功切换action,这个目前还不清楚是为什么。

最后实现的效果如下:

cocos2d-x for android:士兵听我的命令移动开始

由于是在ubuntu下开发,好像没有什么抓取屏幕gif 图片的软件可用,简单截一屏!!!

代码没有做任何的处理,很多多余的代码,做个DEMO可以看看就行!!!

代码下载:https://github.com/terryyhl/SpriteAnimation.git

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/110285.html原文链接:https://javaforall.cn