cocos2d study #13

애니메이션


애니메이션 구현 기법

애니메이션의 구현 기법은 이미지를 어떻게 처리하는지에 따라 크게 2가지 기법이 있다. 첫 번째는 여러 개의 그림 파일을 로드하여 애니메이션으로 만드는 방법이고, 두 번째는 여러 개의 프레임이 담긴 1개의 통짜 이미지를 잘라 사용하는 법이다.

첫 번째 방법은 이미지의 크기를 계산할 필요가 없는 장점이 있으나, 프레임 수가 많아지면 로드해야 하는 이미지 파일의 개수도 늘어나므로 코딩량이 많아진다는 단점이 있다.

두 번째 방법은 통으로 된 1개의 이미지 파일을 각 프레임 크기에 맞게 적절히 잘라내야 하기 때문에 귀찮아질 수 있고, 프레임 크기를 잘못 계산한 경우 의도한 대로 출력이 되지 않는다.

여러 개의 이미지 파일 사용

-(id) init
{
    if ( (self=[super init]) )
    {
        self.isTouchEnabled = YES;
 
        // CCAnimation은 action이 아니라 프레임만 담는다.
        CCAnimation *animation = [[CCAnimation alloc] init];
 
        // 한 프레임에 0.1초
        [animation setDelay:0.1];
 
        // 모든 이미지를 프레임으로 추가한다.
        [animation addFrameWithFilename:@"fire1.png"];
        [animation addFrameWithFilename:@"fire2.png"];
        [animation addFrameWithFilename:@"fire3.png"];
        [animation addFrameWithFilename:@"fire4.png"];
 
        // 아무 동작이 없을 때 보여주는 첫 스프라이트
        CCSprite *sprite = [CCSprite spriteWithFile:@"fire1.png"];
        sprite.position = ccp(240,160);
        [self addChild:sprite];
        
        // CCAnimate는 액션이다. 위에서 만든 animation을 넣어준다.
        CCAnimate *animate = [CCAnimate actionWithAnimation:animation];
        animate = [CCRepeatForever actionWithAction:animate];
        [sprite runAction:animate];
 
        // 애니메이션과 동시에 움직일 수 있다.
        id move = [CCMoveBy actionWithDuration:3 position:ccp(100,100)];
        [sprite runAction:move];
    }
    return self;
}

애니메이션도 액션과 비슷하게 사용하면 되는데, 먼저 addFrameWithFilename을 이용해 CCAnimaion에 프레임들을 담은 후, CCAnimate에 CCAnimation을 담아 액션으로 보내면 된다.

CCAnimation과 CCAnimate를 잘 구분해야 한다.

주의 사항으로는, 아무 동작이 없을 때 보여주는 첫 스프라이트를 추가해야 한다. 이것을 액션의 주체로서 사용하게 된다. (runAction)

하나의 이미지 파일 사용

-(id) init
{
    if ( (self=[super init]) )
    {
        self.isTouchEnabled = YES;
 
        // 걷는 장면이 들어있는 애니메이션 파일
        // 스프라이트가 아니라 텍스처이므로 addChild 하지 않는다.
        CCSprite *sprite = [CCSprite spriteWithFile:@"animation.png"];
 
        // CCAnimation은 action이 아니므로, 프레임만 담는다.
        CCAnimation *animation = [[CCAnimation alloc] init];
 
        // 1 프레임에 0.1초
        [animation setDelay:0.1];
        
        // 프레임 잘라내기
        for(int i=0;i<6;i++) {
            // 주의: 텍스처는 좌상단이 (0,0)이다.
            // 예제 이미지는 600x120의 이미지 파일을 사용한다고 가정한다.
            // 총 6프레임이므로, x좌표를 6번*100 증가시키며 프레임을 잘라낸다.
            [animation addFrameWithTexture:sprite.texture
                                      rect:CGRectMake(i*100, 0, 100, 120)];
        }
        
        // 아무 동작이 없을 때 보여주는 첫 스프라이트
        CCSprite *original = [CCSprite spriteWithFile:@"sprite1.png"];    
        original.position = ccp(240,160);
        original.tag = 1;    // 태그 1
        [self addChild:original];
 
        CCAnimate *animate = [CCAnimate actionWithAnimation:animation];
        animate=[CCRepeatForever actionWithAction:animate];    
        animate.tag = 2;    // 태그 2
        [original runAction:animate];
 
        id move = [CCMoveBy actionWithDuration:3 position:ccp(100,100)];
 
        // 콜백 함수 aniStop 호출
        id callback = [CCCallFunc actionWithTarget:self
                                          selector:@selector(aniStop)];
        
        // move, callback을 차례로 실행, nil 주의
        id total = [CCSequence actions:move, callback, nil];
 
        [original runAction:total];
 
    }
    return self;
}
 
// 애니메이션 멈추기
-(void)aniStop 
{
    // 태그 1을 가진 스프라이트를 얻는다.
    CCSprite *original = (CCSprite *)[self getChildByTag:1];
 
    // 태그 2를 가진 액션을 멈춘다.
    [original stopActionByTag:2];
}

첫 번째 예제와는 다르게 하나의 이미지만을 사용했으므로, for 루프를 통해 프레임을 잘라냈다. 프레임을 잘라내는 방법으로는 스프라이트의 텍스처 속성으로부터 하나의 프레임을 얻는 addFrameWithTexture를 사용하면 된다. (sprite.texture)

이 때 텍스처의 좌표는 아이폰처럼 좌측 상단이 (0,0)이므로 주의해야 한다.

영역의 크기는 CGRectMake로 알아내면 되는데, 예제에서는 각 프레임이 가로로 길게 늘어진 600x120 크기의 이미지라고 가정하고, x좌표를 프레임의 총 개수에 해당하는 여섯 번 반복 증가시켜 얻어냈다. y좌표는 변하지 않으므로 0을 써준다.

스프라이트와 액션에 태그를 준 이유는 콜백 함수에서 이것들을 호출하기 위해서이다. 콜백 함수를 호출하여 추가적인 동작을 실행할 수 있으며, 이 예제에서는 stopActionByTag를 이용하여 애니메이션의 동작을 멈추도록 했다.

즉, 총 6장의 애니메이션을 보여주면서 지정한 (100,100) 위치로 이동한 후 동작을 멈추게 된다. 최종 액션은 CCSequence를 썼기 때문에 모든 동작은 한 번만 실행하게 된다. 물론 CCRepeat 등을 이용하여 반복적인 동작을 구현할 수 있다.

'개발 > Cocos2d' 카테고리의 다른 글

cocos2d study #15  (0) 2012.10.26
cocos2d study #14  (0) 2012.10.26
cocos2d study #12  (0) 2012.10.26
cocos2d study #11  (0) 2012.10.26
cocos2d study #10  (0) 2012.10.26

+ Recent posts