一些自由落体 以及 动画改变速度的例子scheduler test
没有用物理引擎,所以只能重新造轮子了,不过这是很简单的一个模拟。
首先我们学过简单的物理知识知道,跳上去的时候,有一个初速度V,越高,速度就越小,直到速度为0的时候就掉下来,掉下来的时候速度越来越大。
如果我们能模拟这个过程那就完成了。其实很好模拟
这个函数是写在schedule的update(float dt) 函数里面
每秒默认的60帧,dt就相当于 1/60秒,这个叫做单位时间。
先别看代码,下面我们来列一个简单的公式 s=vt+1/2at^2, 其中s是高度,v是初速度,a是加速度,t是时间
对两边取微分 ds=v*dt+at*dt, 化简 ds=(v+at)dt , 这里ds就是位移增量,就是在每个dt时间内移动的长度, v+at就是t时刻的速度如果时间越久速度变化就越大。
扯了一堆公式呵呵,反正意思就大概那样。下面看实现过程吧
我们规定一个初速度 jumpSpeed。我初始化在init()函数里面的是200.然后每时每刻都在变化 jumpSpeed=jumpSpeed-flagY*150*dt,
其中flagY是上升下落的标志,flagY=1就是上升 速度就成了 jumpSpeed-150*dt. 就是每个dt时间减少150dt ,相当于一秒钟总共减少150,但是分60帧进行
然后位移就是setPosition(). 里面的heroPoint.y相当于位移s , heroPoint.y+flagY*jumpSpeed*dt. 速度乘以时间自然就是位移量了,没帧改变他的大小,就实现了加速移动,自由落体
当然还有一个判断函数当上升到最高点的时候flagY要变成-1 ,就开始下落了
以后你想跳的时候,就在事件里设个初速度jumpSeed=200.然后他就自然跳上去啦。
=================================================================================================================
原文:http://blog.csdn.net/xiaominghimi/article/details/7009503
最近也一直在忙,所以也只能每周的某一天抽出时间来分享一些知识点给童鞋们,希望童鞋们体谅下~
那么废话不多说了,本篇知识点两个:
1.利用CCSpeed当精灵执行CCAnimate动作途中设置其播放的速度;
2.设置游戏的速率,让你自由设置整个游戏的速度;
首先介绍第一个知识点:
对于第一个知识点,精灵执行CCAnimate动作途中设置播放速度,说白一点就是当主角或者怪物播放一套帧动作(动画)的时候,可能突然受到其他因素影响希望主角或者怪物等动作放慢,也就是慢动作的感觉,那么这时候我们就需要设置动作的播放速度拉,也就是今天要介绍的CCSpeed这个类;可能Himi这里哇哇哇的说这么多还是没亭台明白吧...=。 = 那么下面我们来看看代码等就应该明白了;
至于精灵如何利用CCAnimate实现帧集合动画教程在之前已经讲述过,那么这里就不在赘述,如果还不清楚如何利用很多帧形成动画让精灵播放的童鞋请移步到:【iOS-Cocos2d游戏开发之二十一 】自定义精灵类并为你的精灵设置攻击帧(指定开始帧)以及扩展Cocos2d源码的CCAnimation简化动画创建!
直接上一段代码如下:
[[CCSpriteFrameCache sharedSpriteFrameCache]addSpriteFramesWithFile:@"animationsFrames.plist"];
CCSprite*mySprite=[CCSprite spriteWithSpriteFrameName:@"himi1.png"];
mySprite.position=ccp(120,150);
[self addChild:mySprite];
CCAnimation*anim=[CCAnimation animationWithFrame:@"himi" frameCount:12 delay:0.1];
CCAnimate* animate = [CCAnimate actionWithAnimation:anim];
CCSequence *seq = [CCSequence actions:animate,nil];
CCRepeatForever* repeat = [CCRepeatForever actionWithAction:seq];
[mySprite runAction:repeat];
以上代码创建一个帧动画(帧资源都在animationFrames.plist加载到内存中了),然后创建一个精灵并让其永久循环执行这个帧动画;
童鞋们想一想,如果在这个永久动作执行后,你想在一个任意时间设置这个动画播放的速度,那么就利用CCSpeed来实现了,代码如下:
[[CCSpriteFrameCache sharedSpriteFrameCache]addSpriteFramesWithFile:@"animationsFrames.plist"];
//左侧正常速度的播放
CCSprite*mySprite=[CCSprite spriteWithSpriteFrameName:@"himi1.png"];
mySprite.position=ccp(120,150);
[self addChild:mySprite];
CCAnimation*anim=[CCAnimation animationWithFrame:@"himi" frameCount:12 delay:0.1];
CCAnimate* animate = [CCAnimate actionWithAnimation:anim];
CCSequence *seq = [CCSequence actions:animate,nil];
//让你的永久动作放入speed中
CCSpeed *speed =[CCSpeed actionWithAction:[CCRepeatForever actionWithAction:seq] speed:1.0f];
[speed setTag:888];//设置tag能任意获取到其实例,并且对其进行操作
[mySprite runAction:speed];
这段代码和第一段代码不同点就是第二段将CCRepeatForever永久动作又包装到了CCSpeed中,整个动作等同与交给了CCSpeed来控制了,那么下面我还设置了[speed setTag:888];这个是留出接口,当你需要设置整个CCSpeed包装的动作速度的时候利用tag获取到,这个大家肯定很熟悉,那么获取动作方式如下:
CCSpeed *speed=(CCSpeed*)[sprite getActionByTag:88];
获取的时候是你之前runAction的精灵来利用getActionByTag来获取的!
那么下面继续添加代码,我们让一个由CCSpeed包装一个帧动画并让精灵执行后的5秒后让其速度变成原有播放速度的一半,代码如下:
CCSprite *mySpriteByF =[CCSprite spriteWithSpriteFrameName:@"himi1.png"];
mySpriteByF.position=ccp(360,150);
[self addChild:mySpriteByF z:0 tag:66];
anim=[CCAnimation animationWithFrame:@"himi" frameCount:12 delay:0.1];
animate = [CCAnimate actionWithAnimation:anim];
seq =[CCSequence actions:animate, nil];
CCSpeed *speed =[CCSpeed actionWithAction:[CCRepeatForever actionWithAction:seq] speed:1.0f];
[speed setTag:88];
[mySpriteByF runAction:speed];
[self schedule:@selector(slowForHimi) interval:5];
-(void)slowForHimi{
[self unschedule:@selector(slowForHimi)];//解除此选择器
CCSprite*sprite=(CCSprite*)[self getChildByTag:66];
CCSpeed *speed=(CCSpeed*)[sprite getActionByTag:88];
[speed setSpeed:0.5];//放慢原有速度的0.5倍
}
-(void)slowForHimi{
[self unschedule:@selector(slowForHimi)];//解除此选择器
CCSprite*sprite=(CCSprite*)[self getChildByTag:66];
CCSpeed *speed=(CCSpeed*)[sprite getActionByTag:88];
[speed setSpeed:0.5];//放慢原有速度的0.5倍
}
CCSpeed的创建很简单,那么设置速率的方法如下:
[CCSpeed* setSpeed:XX];
这里的XX参数指的是倍率,传入1表示原速,大于1表示增快,小于1表示放慢速度~
下面直接给出全部测试项目代码:
//
// HelloWorldLayer.m
// SLowAnimationByHimi
//
// Created by 华明 李 on 11-11-21.
// Copyright Himi 2011年. All rights reserved.
//
// Import the interfaces
#import "HelloWorldLayer.h"
#import "CCAnimationHelper.h"
// HelloWorldLayer implementation
@implementation HelloWorldLayer
+(CCScene *) scene
{
// 'scene' is an autorelease object.
CCScene *scene = [CCScene node];
// 'layer' is an autorelease object.
HelloWorldLayer *layer = [HelloWorldLayer node];
// add layer as a child to scene
[scene addChild: layer];
// return the scene
return scene;
}
//CCJumpTo实现,抛物线
//
// on "init" you need to initialize your instance
-(id) init{
if( (self=[super init])) {
CCLabelTTF *label = [CCLabelTTF labelWithString:@"暂缓动作&设置整个游戏加速/减速" fontName:@"Marker Felt" fontSize:24];
label.position = ccp(260,260);
[self addChild: label z:0 ];
label = [CCLabelTTF labelWithString:@"正常速度的播放" fontName:@"Marker Felt" fontSize:12];
label.position = ccp(120,220);
[self addChild: label z:0 tag:99];
label = [CCLabelTTF labelWithString:@"左侧动态放慢的速度的动作" fontName:@"Marker Felt" fontSize:12];
label.position = ccp(350,220);
[self addChild: label z:0 ];
[[CCSpriteFrameCache sharedSpriteFrameCache]addSpriteFramesWithFile:@"animationsFrames.plist"];
//左侧正常速度的播放
CCSprite*mySprite=[CCSprite spriteWithSpriteFrameName:@"himi1.png"];
mySprite.position=ccp(120,150);
[self addChild:mySprite];
CCAnimation*anim=[CCAnimation animationWithFrame:@"himi" frameCount:12 delay:0.1];
CCAnimate* animate = [CCAnimate actionWithAnimation:anim];
CCSequence *seq = [CCSequence actions:animate,nil];
CCRepeatForever* repeat = [CCRepeatForever actionWithAction:seq];
[mySprite runAction:repeat];
//左侧动态放慢的速度的动作
CCSprite *mySpriteByF =[CCSprite spriteWithSpriteFrameName:@"himi1.png"];
mySpriteByF.position=ccp(360,150);
[self addChild:mySpriteByF z:0 tag:66];
anim=[CCAnimation animationWithFrame:@"himi" frameCount:12 delay:0.1];
animate = [CCAnimate actionWithAnimation:anim];
seq =[CCSequence actions:animate, nil];
CCSpeed *speed =[CCSpeed actionWithAction:[CCRepeatForever actionWithAction:seq] speed:1.0f];
[speed setTag:88];
[mySpriteByF runAction:speed];
[self schedule:@selector(slowForHimi) interval:5];
}
return self;
}
-(void)slowForHimi{
[self unschedule:@selector(slowForHimi)];//解除此选择器
CCSprite*sprite=(CCSprite*)[self getChildByTag:66];
CCSpeed *speed=(CCSpeed*)[sprite getActionByTag:88];
[speed setSpeed:0.5];//放慢原有速度的0.5倍
}
// on "dealloc" you need to release all your retained objects
- (void) dealloc
{
// in case you have something to dealloc, do it in this method
// in this particular example nothing needs to be released.
// cocos2d will automatically release all the children (Label)
// don't forget to call "super dealloc"
[super dealloc];
}
@end
运行截图如下: (图片中有个"左"写错了,应该是"右",懒得改了,大家知道就行了 娃哈哈)
从截图中可能童鞋们看不出什么效果。等文章最后放出源码,大家运行就可以看到效果了-。 -
这里备注下:除了利用CCSpeed来实现慢动作之外,还有其他的一些方法,不怕麻烦的童鞋甚至可以尝试当需要慢动作的时候,取出当前的帧下标,然后利用指定帧下标的方法创建一个新的帧动画同时增加播放时间即可;(在上一节《iOS-Cocos2d游戏开发之二十一》中Himi封装了一个指定帧下标进行创建帧动画的方法,还没有看过的童鞋请移步到这里:【iOS-Cocos2d游戏开发之二十一 】自定义精灵类并为你的精灵设置攻击帧(指定开始帧)以及扩展Cocos2d源码的CCAnimation简化动画创建!);再或者直接去修改Cocos2d-iphone引擎的源码;
Himi当时做的时候因为用CCSpeed方式有问题一直不行,就去改了源码弄的。后来才发现CCSpeed正确用法,我去了=。 =
这里Himi必须强调一点!!!!!!!
很多时候你的主角的动作利用CCAction来实现,移动则是在update刷帧函数或者一些选择器的方法中进行的,那么为了让你的主角慢动作比较逼真,那么Himi建议不要使用scheduleUpdate函数,因为这个你无法修改每次调用update的时间默认都是每帧都调用,那么你应该自己定义一个选择器当刷逻辑的函数,这样就能配合CCSpeed实现逼真慢动作拉~
下面我们来介绍第二个知识点:设置游戏速度
对于游戏速度最常见的出现在塔防游戏中,当玩家创建好防守的东东后开始出怪后,可能怪物移动速度慢,而玩家着急看到结果,那么我们就会人性化的加上加快游戏速度的按钮拉~那么这个功能在Cocos2d引擎中封装好的,一句代码即可完成,如下代码即可:
[[CCScheduler sharedScheduler] setTimeScale:XX];
这里的XX仍然是倍率:传入1表示原速,大于1表示增快,小于1表示放慢速度~
================================================================================================================
cocos2d-x动画加速与减速
动画是游戏的必然要素之一,在整个游戏过程中,又有着加速、减速动画的需求。以塔防为例子,布塔的时候希望能够将游戏减速,布好塔后,则希望能将游戏加速;当某个怪被冰冻后,移动速度减缓,而其他怪的移动速度不变。cocos2d-x引擎为我们提供了很强大的接口,下面就将我实验的过程复述一遍,也方便他人。
1)实现全局的加速、减速。
通过设置Scheduler的timeScale,可以实现全局的加、减速。代码非常简单:
CCScheduler* pScheduler = CCDirector::sharedDirector()->getScheduler();
pScheduler->setTimeScale(2.0f); //实现加速效果
pScheduler->setTimeScale(0.5f);//实现减速效果
2)实现对某个CCActionInterval动作的加速、减速
方法一:很容易想到的一个方法就是改变CCAnimation的delay unit。代码如下:
CCAnimation* pAnimation = CCAnimationCache::sharedAnimationCache()->animationByName(“xxx”);
pAnimation->setDelayUnit(pAnimation->getDelayUnit()*0.2f); //速度为原来的5倍
这个方法有一个缺点:改变了CCAnimationCache中这个animation的delay unit。也就是说以后即使再从CCAnimationCache中获取这个animation,其delay unit已经是原来的0.2倍了。
方法二:cocos2d-x提供了CCSpeed的类,可以实现动画速度的调节。用法如下:
CCActionInterval* pActionInterval = CCMoveTo::create(5.0f, ccp(500.0f, 100.0f));
CCSpeed* pSpeed= CCSpeed::create(pActionInterval, 1.5f); //1.5倍速运行
CCSpeed* pSpeed1 = CCSpeed::create(pActionInterval, 0.2f);// 0.2倍速运行
pSprite->runAction(pSpeed);
注意,如果pSprite有已经运行的动作,要用pSprite->stopActionByTag()停掉之前的动作,不然两个动作就叠加到一起了。
—————————————————————–华丽丽的分割线————————————————————————–
来自HIMI的提示:
很多时候你的主角的动作利用CCAction来实现,移动则是在update刷帧函数或者一些选择器的方法中进行的,那么为了让你的主角慢动作比较逼真,那么Himi建议不要使用scheduleUpdate函数,因为这个你无法修改每次调用update的时间默认都是每帧都调用,那么你应该自己定义一个选择器当刷逻辑的函数,这样就能配合CCSpeed实现逼真慢动作拉~
3)对某个CCFiniteTimeAction类型动作的加速、减速
大部分时候,一个游戏人物的动作并非由单一一个CCActionInterval类型的动作构成,而是一串动作连起来,构成一个Sequence。用CCSequence::create(…)创建的对象都是CCFinteTimeAction类型的,CCSpeed并不适用。在CCSpeed类的说明里,明确指出”This action can’t be Sequenceable because it is not an CCIntervalAction”。那对于Sequence就束手无策了吗?非也。cocos2d-x引擎自带例子中,schedulerTest给我们展示了如何控制某个sprite的scheduler的timescale。废话少说,直接看代码。
在class TwoSchedulers中定义了两个customer的scheduler和两个CCActionManager。
CCScheduler *sched1;
CCScheduler *sched2;
CCActionManager *actionManager1;
CCActionManager *actionManager2;
在onEnter函数中,分别对两个sprite设置customer的ActionManager.
CCScheduler *defaultScheduler = CCDirector::sharedDirector()->getScheduler();
// Create a new scheduler, and link it to the main scheduler
sched1 = new CCScheduler();
defaultScheduler->scheduleUpdateForTarget(sched1, 0, false);
// Create a new ActionManager, and link it to the new scheudler
actionManager1 = new CCActionManager();
sched1->scheduleUpdateForTarget(actionManager1, 0, false);
// Replace the default ActionManager with the new one.
pSprite1->setActionManager(actionManager1);
通过以上的代码,就可以通过改变sched1的timescale来改变pSprite1的动作的快慢了。有了这种方法,那么就可以放弃CCSpeed的那种方法了。