Cocos2D 學習筆記 (3) - 移動及動畫

Cocos2D

接續前一篇的範例,現在我們要讓火箭往前移動。

移動 Sprite

要移動 Sprite 只要簡單的兩行程式碼,請把以下程式碼加入 init 中 addChild 之後:
CGSize size = [[CCDirector sharedDirector] winSize];

CCMoveBy *move = [CCMoveBy actionWithDuration:2.0f position:ccp(0, size.height/2)];
[rocket runAction:move];
CCMoveBy 是依目前 Sprite 所在座標往 x, y 軸各加多少 pixel 的位置移動。 在 position 中,x = 0, y = size.height/2,表示在 x 軸不會有任何改變,y 軸則往上移動螢幕一半的距離。actionWithDuration:2.0f 表示這個動作要花 2 秒的時間完成。

呼叫 rocket sprite 的 runAction 去指定要執行的動作,它就會從現在的位置(螢幕中央)移到螢幕上方。
註:由於 Sprite 的原點在正中央,所以如果要讓火箭剛好移出螢幕,必須在加上火箭的高度的一半,也就是它的中心點會移到螢幕外加上本身高度一半的地方。

另外一個移動的方式是使用 CCMoveTo,如下:
CCMoveTo *moveTo = [CCMoveTo actionWithDuration:2.0f position:ccp(size.width/2, size.height)];
CCMoveTo 是依絕座標來移動,也就是從現在的位置,移動到螢幕上的某個點,所以這裡指定 x = size.width/2,和原本的 x 相同,y = size.height 則是螢幕高度。這個動作會移動到和前面的 CCMoveBy 同一個位置,你可比較兩者座標的差異。

依序執行動作

我們讓 Sprite 執行一連串的動作,利用 CCSequence 來達到。程式碼如下:
//movie to
CCMoveTo *moveTo = [CCMoveTo actionWithDuration:2.0f position:ccp(size.width/2, size.height)];

//out to die
CCCallBlockN *outToDie = [CCCallBlockN actionWithBlock:^(CCNode *node){
    [node removeFromParentAndCleanup:YES];
}];

CCAction *seqAction = [CCSequence actions:moveTo, outToDie, nil];
[rocket runAction:seqAction];
我們使用 CCMoveTo 將火箭從螢幕中央移動到螢幕上方。

CCCallBlockN 用來製作回呼函數。我們用來移除 Sprite 。

CCSequence actions: 可以加入多個 action,它會依序執行。我們指定第一個動作是移動到螢幕上方,第二個動作是把自己移除掉。

最後將 CCSequence 指定給 rocket runAction: 去執行。

觸碰後才動作

前面的動作在一載入時就會立即執行,我們將把它修改成,觸碰火箭後才執行往前的動作。
因為程式碼要修改的地方有點多,先貼出來再解釋。

GameLayer.m

//
//  GameLayer.m
//  HelloCocos2D
//
//  Created by Tony on 13/10/17.
//  Copyright (c) 2013年 TonyCubeSoft. All rights reserved.
//

#import "GameLayer.h"
#import "cocos2d.h"

@interface GameLayer()

@property (nonatomic,strong) CCSprite *rocket;

@end


@implementation GameLayer
@synthesize rocket;

- (id)init
{
    if( (self=[super init]) ) {
        CGSize size = [[CCDirector sharedDirector] winSize];

        rocket = [CCSprite spriteWithFile:@"rocket.png"];
        [rocket setPosition:ccp(size.width/2, size.height/2)];
        [self addChild:rocket];

        self.touchEnabled = YES;
    }

    return self;
}

- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSLog(@"touch");
    //觸碰的座標
    UITouch *myTouch = [touches anyObject];
    CGPoint location = [myTouch locationInView:[myTouch view]];
    location = [[CCDirector sharedDirector] convertToGL:location];
    //火箭的矩形範圍
    CGRect rect = CGRectMake(rocket.position.x - rocket.contentSize.width/2,
                             rocket.position.y - rocket.contentSize.height/2,
                             rocket.contentSize.width,
                             rocket.contentSize.height);
    //判斷是否有觸碰到火箭
    if (CGRectContainsPoint(rect, location)) {
        [self rocketLaunch];
    }
}

- (void)rocketLaunch
{
    CGSize size = [[CCDirector sharedDirector] winSize];

    //move by
//    CCMoveBy *moveBy = [CCMoveBy actionWithDuration:2.0f position:ccp(0, size.height/2)];
//    [rocket runAction:moveBy];

    //movie to
    CCMoveTo *moveTo = [CCMoveTo actionWithDuration:2.0f position:ccp(size.width/2, size.height)];

    //out to die
    CCCallBlockN *outToDie = [CCCallBlockN actionWithBlock:^(CCNode *node){
        [node removeFromParentAndCleanup:YES];
    }];

    CCAction *seqAction = [CCSequence actions:moveTo, outToDie, nil];
    [rocket runAction:seqAction];

}
說明:
要讓觸碰有反應,要
  1. 在 init 中將 self.touchEnabled 設為 YES,
  2. 實作 - (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event 方法。
首先將 rocket sprite 提取成成員變數,方便觸碰方法中判斷時使用。接著在觸碰中判斷觸碰的位置是否在火箭所在的矩形範圍內,如果是就執行動作。

角色動畫

動畫是指幾張圖片不斷的播放,看起來就像在動一樣,所以製作方法也是如此。我把原本的火箭圖檔稍做修改,讓火焰變小,於是當兩張圖片快速輪流播放時,火焰就會動了。原本火箭改名為 rocket1.png,加入新的圖檔 rocket2.png。

程式碼如下:
- (void)rocketAnimation
{
    CCAnimation *rocketAnim = [CCAnimation animation];
    [rocketAnim addSpriteFrameWithFilename:@"rocket1.png"];
    [rocketAnim addSpriteFrameWithFilename:@"rocket2.png"];
    [rocketAnim setDelayPerUnit:0.1f];
    [rocketAnim setRestoreOriginalFrame:YES];

    CCAnimate *rocketAnimationAction = [CCAnimate actionWithAnimation:rocketAnim];
    CCRepeatForever *repeatRocketAnimation = [CCRepeatForever actionWithAction:rocketAnimationAction];
    [rocket runAction:repeatRocketAnimation];
}
在 init 中的 self.touchEnabled = YES; 之後加入
[self rocketAnimation];
就完成了。說明:
  • CCAnimation 用來加入動畫用的圖檔,並且要設定每張圖片延遲的時間,這裡設為 0.1 秒。
  • CCAnimate 指定要使用哪個動畫來產成動作。
  • CCRepeatForever 指定動畫要永遠重覆執行。
  • 最後讓 rocket sprite 去執行這個 action。
本文網址:http://blog.tonycube.com/2013/10/cocos2d-3.html
Tony Blog 撰寫,轉載時請註明出處及文章連結,謝謝 😀

我要留言

留言小提醒:
1.回覆時間通常在晚上,如果太忙可能要等幾天。
2.請先瀏覽一下其他人的留言,也許有人問過同樣的問題。
3.程式碼請先將它編碼後再貼上。(線上編碼:http://bit.ly/1DL6yog)
4.文字請加上標點符號及斷行,難以閱讀者恕難回覆。
5.感謝您的留言,您的問題也可能幫助到其他有相同問題的人。