导语
在游戏中,角色(cocos2d中的术语为精灵)
都是具有丰富的动作效果
,合理的使用这些动作比如闪烁,跳跃,翻转
,都会带来体验上的差异.cocos2d
为我们提供了多种CCAction类
,本文通过对CCAction
的简单使用示例,帮助大家了解在实际应用
中如何借助这些Action
实现自己的动画效果
.
CCActionMoveTo
在cocos2d 3.0
之前的版本中,位移动作是CCMoveTo
,在3.0新版本
之后所有的命名都发生了变化: CCAction+动作名称.
-
示例1:
(在MainScene.m的init 方法中添加代码)
// 设置背景 CCNodeColor *bg = [CCNodeColor nodeWithColor:CCColor.grayColor]; [self addChild:bg]; // 创建精灵 CCSprite *qq = [CCSprite spriteWithImageNamed:@"qq.png"]; qq.position = ccp(100, 100); [self addChild:qq]; // 添加动画 : 用2秒的时间移动到位置(300,100) CCActionMoveTo *moveAction = [CCActionMoveTo actionWithDuration:2.0 position:ccp(300, 100)]; [qq runAction:moveAction];
运行效果:
CCActionSequence
根据示例我们看到,在cocos2d
中实现动画非常简单! 但有时候我们需要游戏角色(精灵)
执行的动画
可能是比较复杂
的,例如移动一段距离
后翻转或者放大
或者闪烁
等,因此我们需要执行一组动作
才可以,cocos2d
已经为我们提供了一个CCActionSequence 动作队列
来实现这种需求.
-
示例2:
组合动画
// 创建精灵 CCSprite *qq = [CCSprite spriteWithImageNamed:@"qq.png"]; qq.position = ccp(100, 100); [self addChild:qq]; // 添加动画 CCActionMoveTo *moveAction = [CCActionMoveTo actionWithDuration:2.0 position:ccp(300, 100)]; // 添加动画2 CCActionMoveTo *action2 = [CCActionMoveTo actionWithDuration:2.0 position:ccp(300, 300)]; // 添加动画3 CCActionMoveTo *action3 = [CCActionMoveTo actionWithDuration:2.0 position:ccp(150, 300)]; // 添加动画4 : 闪烁3次 CCActionBlink *action4 = [CCActionBlink actionWithDuration:2.0 blinks:3]; // 添加动画5 : 放大2倍 CCActionScaleTo *action5 = [CCActionScaleTo actionWithDuration:2.0 scale:2]; // 创建动画执行队列,并添加需要执行的动作 CCActionSequence *sequence = [CCActionSequence actions:moveAction,action2,action3,action4,action5, nil]; // 运行动画 [qq runAction:sequence];
运行效果:
CCActionCallFunc
游戏开发中
我们经常需要在某个动作执行完毕
后再做一些业务逻辑上
的处理,这就需要我们监听某个动画
的完成情况.cocos2d中我们常常使用CCActionCallFunc
来监听一个动画结束
后的回调处理
.
-
示例3:
监听动画完成
// 创建精灵 CCSprite *qq = [CCSprite spriteWithImageNamed:@"qq.png"]; qq.position = ccp(100, 100); [self addChild:qq]; // 添加动画 CCActionMoveTo *moveAction = [CCActionMoveTo actionWithDuration:2.0 position:ccp(300, 100)]; // 添加动画回调动作 CCActionCallFunc *endAction = [CCActionCallFunc actionWithTarget:self selector:@selector(endMoveToAction)]; // 创建动画执行队列 CCActionSequence *sequence = [CCActionSequence actions:moveAction,endAction, nil]; [qq runAction:sequence];
动画完成回调方法:
- (void)endMoveToAction{
CCLOG(@"动画执行完毕 ~~");
}
运行效果:Touch(触摸)
cocos2d
中如果要响应触摸
,需要在显示的场景类(MainScene)中开启用户交互
:
// 设置开启触摸
self.userInteractionEnabled = YES;
然后实现触摸响应的方法即可:
- (void)touchBegan:(UITouch *)touch withEvent:(UIEvent *)event{
// 获取触摸位置
CGPoint p = [touch locationInNode:self];
// 创建动画
CCActionMoveTo *moveAction = [CCActionMoveTo actionWithDuration:2 position:p];
// 运行动画
[self.qq runAction:moveAction];
}
示例效果:运行上面触摸的例子后,如果你多次连续
点击屏幕,会发现精灵图片(本例中的qq图片)
移动的最后结果
与我们实际希望的
并不相同,甚至会移出屏幕
,不必担心,这是由于CCActionMoveTo类
自身的原因: 它本身可以被同时多次调用,但某一刻的结果是每个单次调用的总和,下面我们通过stopAction
来修正这个问题~
stopAction
在cocos2d
中我们可以任意的触发和停止action
,经常用到的方法是:
stopAction:(CCAction * action) : 停止指定的action
stopActionByTag:(NSInteger) : 停止指定tag值的action
stopAllActions : 停止所有action
在我们的触摸示例中,我们可以用stopActionByTag
的方式修正代码,只需要修改两个地方即可:
1. 在每次触摸事件开始(touchBegan)时停止上一个动画
2. 给动画设置一个tag值
修改后的代码如下:
- (void)touchBegan:(UITouch *)touch withEvent:(UIEvent *)event{
// 移除上一个动画效果
[self.qq stopActionByTag:0];
CGPoint p = [touch locationInNode:self];
CCActionMoveTo *moveAction = [CCActionMoveTo actionWithDuration:0.3 position:p];
// 给动画设置tag值
[moveAction setTag:0];
[self.qq runAction:moveAction];
}
边界处理
如果点击触摸在屏幕边缘
的时候,我们发现精灵
会有一部分内容超出屏幕
,导致显示不完整
.例如下图:
另外,我们希望
移动的时间
可以根据距离变化
而不同,最后的代码如下:
- (void)touchBegan:(UITouch *)touch withEvent:(UIEvent *)event{
[self.qq stopActionByTag:0];
CGPoint p = [touch locationInNode:self];
// 获取屏幕size
CGSize screenSize = [CCDirector sharedDirector].viewSize;
// 根据两点之间的距离计算移动时间
CGFloat duration = ccpDistance(p, self.qq.position) / 200.0;
// 限制边界值
p.x = clampf(p.x, self.qq.contentSize.width / 2, screenSize.width - self.qq.contentSize.width / 2);
p.y = clampf(p.y, self.qq.contentSize.height / 2,screenSize.height - self.qq.contentSize.height / 2);
CCActionMoveTo *moveAction = [CCActionMoveTo actionWithDuration:duration position:p];
[moveAction setTag:0];
[self.qq runAction:moveAction];
}
clampf是cocos2d
中提供的一个边界检测方法,只需要我们提供最大值
和最小值
,它就会确保我们的值
不会超过 这个范围
,其实它的实现也非常简单:
float clampf(float value, float min_inclusive, float max_inclusive) {
if (min_inclusive > max_inclusive) {
CC_SWAP(min_inclusive,max_inclusive);
}
return value < min_inclusive ? min_inclusive : value < max_inclusive? value : max_inclusive;
}
最终效果:
结束语
我们简单介绍了游戏开发中
会经常使用CCAction
的用法,很多看似复杂的效果
其实都是通过简单的动画组合
而成.而cocos2d
中提供的action
也非常丰富,希望大家能够通过基本的
练习可以触类旁通
,因为它们都用法都十分相近
,掌握起来也不会特别困难
.例如大家可以思考一下如何实现
一个始终运动
的游戏背景,就像下面这样:
悄悄提示: CCActionRepeatForever
可以实现不断重复的效果,然后再根据本文介绍的内容
就完全可以实现这样的需求
了,大家快动动手吧~~