저번 주에 한주 강좌를 올리지 않았더니 이번주에 만드는 데 좀 힘들었습니다. ^^; 한주 쉬었더니 역쉬 다시 시작하기 힘들더군요.

그래도 강좌를 기다리신다는 쪽지를 보내신 분도 있고 제 글을 읽어주신다니 뿌듯할 뿐입니다. 


이번에는 기본적인 애니메이션을 구현하는 방법에 대해서 알아보겠습니다. 원래 움직이는 것이라 이미지를 많이 넣어야 하는데 이미지를 화나하나 캡춰하는 것이 좀 힘들더군요. 그래도 소스를 첨부했으니 해당 소스를 보시고 하나씩 따라하시면 쉽게 이해하실 수 있을 겁니다. 


자 그럼 본격적으로 강좌를 시작하겠습니다. 



Cocos2d로 애니메이션 구현하기 1


Cocos2d에서 애니메이션은 Sprite와 Action을 사용해서 구현할 수 있다. 내가 Cocos2d로 제작을 결정하게 했던 가장 큰 이유가 애니메이션을 쉽게 구현할 수 있다는 것이었다. Cocoa로 애니메이션을 구현하려면 여러가지 설정을 많이 해줘야 한다. 물론 랩핑을 해서 간단하게 만들 수 있지만 필요할 때마다 매번 만들어 줘야 한다는 것은 여간 불편한 것이 아니다. 그런데 Cocos2d는 이러한 것들을 단순히 Action을 상속한 클래스들을 사용해서 해당 애니메니션의 모션을 정의해 준 다음에 runAction을 호출해주면 애니메이션이 간단하게 구현된다. 뭔가 짜릿함을 느끼는 순간이다. (나만 그런가, 해킨토시에서 처음으로 Hello의 동영상을 음성과 함께 볼 때의 그 희열과 짜릿함과 같은 느낌이었다. ㅋㅋㅋ)


Cocos2d에서는 애니메이션을 편의상 다음과 같이 4개의 Action군으로 분류를 했다. 

  1. Transformation Actions
  2. Composable Actions
  3. Ease Actions
  4. Mics Actions

어짜피 편의상 분류를 했기 때문에 이해할 때만 이런식으로 구분했구나를 이해하고 사용할 때는 아무렇게나 마구 써도 상관없다. 어짜피 모두다 Action 클래스를 상속했기 때문에 모두다 결합해서 사용할 수 있기 때문이다.

애니메이션 구현은 위에서도 말했듯이 정말 간단한데 먼저 action 인스턴스를 생성한다. 

    id actionTo = [MoveTo actionWithDuration:2.0f position:ccp(s.width - 40, s.height - 40)];

여 기서는 MoveTo를 예시로 했는데 다른 것들도 비슷하게 생성할 수 있다. actionWithDuration은 애니메이션을 동작 시간을 초단위로 입력한다. 위 예제는 해당 위치까지 2초 동안 ccp(s.width - 40, s.height - 40)로 이동하라고 정의하는 것이다. 

그런다음에 이런 action 인스턴스를 실행시키려면 움직이려고 하는 Sprite의 runAction을 호출해준다.

    [someSprite runAction:actionTo];

이렇게 입력되는 순간부터 someSprite는 움직이기 시작해서 2초의 시간을 두고 해당 위치로 이동을 한다. 
전 에 내가 Java로 모바일 게임을 제작할 때 애니메이션을 구현할 때에는 매 프레임시간마다 해당 위치를 계산해서 매번 그려줬어야 하는데 Cocos2d는 그럴 필요없이 간단히 위와 같이 해주면 중간 계산도 알아서 해서 화면에 출력해 준다. 정말 대단하지 않은가...... ㅋㅋ

그리고 애니메이션은 Sprite에 줄 수 있기 때문에 여러개의 Sprite가 동시간에 각각 다른 움직임을 처리할 수 있다. 
이렇게 구현할 수 있는 애니메이션의 종류가 이동시키기, 회전하기 등등 여러개가 있는데 그것들을 몽땅 하나씩 살펴보도록 하자.

1. Transformation Action

Transformation Action은 Sprite의 이동, 회전 등 일회성의 움직임이나 효과를 분류해 놓은 것들이다. 

1.1 Move


Sprite를 이동시키는 Action으로 MoveTo와 MoveBy가 있다. 그리고 다음과 같이 사용할 수 있다. 

    id actionTo = [MoveTo actionWithDuration: 2 position:ccp(200, 200)];

    id actionBy = [MoveBy actionWithDuration:2  position: ccp(80,80)];

MoveTo 는 해당 위치로 이동을 하는 것이고 MoveBy는 현재 위치에서 position으로 지정한 좌표만큼을 이동한다. 위의 예제에서 보자면  actionTo는 Sprite가 어디에 위치해 있든지 200, 200의 위치로 이동을 한다. 그렇지만 actionBy는 sprite가 현재 있는 위치에서 80, 80을 더한 위치로 이동한다.


1.2 Rotate

Sprite에서 회전을 시키는 Action으로는 RotateTo와 RotateBy가 있는데, Move에서는 position을 설정해 주었는데 Rotate에서는 회전할 각도를 다음과 같이 설정해 주어야 한다. 

    id actionTo = [RotateTo actionWithDuration: 2 angle:45];
    id actionBy = [RotateBy actionWithDuration:2  angle: 180];

RotateTo 는 어떤 각도에 있든 angle로 설정한 각도록 회전한다. 하지만 RotateBy는 angle각 만큼을 회전을 한다. 위의 예제로 예를 들자면 actionTo는 어떤한 각도에 있더라도 기울기가 45도로 회전하지만, actionBy는 어떠한 각도에 있어도 현재 각도에서 360도를 회전한다. 그래서 actionTo는 애니메이션이 끝나면 항상 45도이지만 actionBy는 만약 0도에서 시작하면 180도에서 끝나고 45도에서 시작했으면 225도에서 애니메이션이 끝난다.

이제 To와 By의 차이점을 어느 정도 알 수 있지 않을까? To는 절대적인 위치나 각도 등에 절대적인 값을 설정한든데, By는 현재 값에 추가되는 상대적인 값을 설정하는 것이다.


1.3 Scale

Sprite 의 크기를 변경하는 Action으로는 ScaleTo와 ScaleBy가 있고, ScaleTo는 scale로 설정한 배율로 크기를 변경한다. 1보다 작으면 작게 1보다 크면 해당 배수만큼 scale값으로는 1.0f와 같은 실수값을 설정한다.

    id actionTo = [ScaleTo actionWithDuration:2 scale:0.5f];
    id actionBy = [ScaleBy actionWithDuration:2  scale: 2];

위의 예제에서 actionTo는 0.5배의 크기로 Sprite를 2초동안 변환시키고, actionBy는 2초동안 현재 크기의 2배로 크기를 변경시킨다.


1.4 Jump

Cocos2d 에서는 애니메이션에서 특이하게 Jump도 설정할 수 있는데, JumpTo와 JumpBy로 Jump를 설정할 수 있는데 To와 By의 차이점은 각각 position에 대한 값의 절대적 상대적 차이로 설정된다. 즉, JumpTo는 절대적으로 설정한 position 위치로 Jump를 하면서 이동을 하는데 JumpBy는 현재 위치에서 position으로 설정된 값만큼을 더한 위치로 Jump하면서 이동한다.

    id actionTo = [JumpTo actionWithDuration:2 position:ccp(300,300) height:50 jumps:4];
    id actionBy = [JumpBy actionWithDuration:2 position:ccp(300,0) height:50 jumps:4];

위 의 예제에서는 actionTo는 2초동안 300, 300의 위치로 높이는 50픽셀로 4번의 점프를 하면서 이동을 한다. actionBy는 2초동안 현재 위치에서 가로로만 300픽셀을 더한 위치로 높이는 50픽셀로 4번 점프를 하면서 이동을 한다.


1.5 Bezier(곡선)


Sprite 가 이동할 경로를 곡선을 하고 싶을 때에는 BezierBy actionWithDuration:bezier:를 사용한다. Bezier 를 설정할 때에는 이동할 경로를 잘 계산을 해야 한다. 다음의 그림을 보면서 확인해 보자.


Cocos2d 곡선 애니1.png 


위의 그림에서와 같이 파란색으로 된 부분을 point로 start, controlPoint_1, controlPoint_2, end의 네군데를 point로 설정하면 빨간색으로 된 곡선을 이동 경로로 Sprite가 이동하게 된다. 
그 런데 여기서 Sprite가 위치한 현재 위치에서 설정한 상대적인 위치로 이동한다, 즉 다시 말해서 0,0에서 시작한다면 위의 그림의 빨간색 경로로 이동을 하지만 100,100에서 시작을 한다면 다음과 같이 중간의 경로는 변경없이 시작위치만 변경된 경로로 이동을 하게된다.


Cocos2d 곡선 애니2.png 


bezier의 파라미터로는 ccBezierConfig의 값을 설정해서 입력한다.

    ccBezierConfig bezier;
    bezier.startPosition = ccp(0,0);
    bezier.controlPoint_1 = ccp(0, s.height/2);
    bezier.controlPoint_2 = ccp(300, -s.height/2);
    bezier.endPosition = ccp(300,100);

    id bezierForward = [BezierBy actionWithDuration:3 bezier:bezier];

아무래도  Bezier를 사용할 때에는 확실히 계산을 하고 사용해야할 것 같다. ^^


1.6 Blink

Blink는 Sprite를 깜박이게 만든다. Blink actionWithDuration:blinks: 메소드를 사용하는데 여기서 blinks로 actionWithDuration에 설정한 시간만큰 깜박일 횟수를 설정한다.

    id action1 = [Blink actionWithDuration:2 blinks:10];

위 예제는 2초동안 10회 깜박이게 하는 Action의 예제이다.


1.7 Fade

Sprite 를 점점 나타나게도 점점 사라지게도 할 수 있는데 이렇게 할 수 있도록 하는 Action이 FadeIn과 FadeOut이다. FadeIn과 FadeOut은 간단하게 나타나거나 사라질 시간을 설정을 하면 된다. (FadeIn/Out은 Opacity를 사용하는 것이기 때문에  나타나게 하려면 먼저 Opacity값을 0으로 해서 먼저 안보이게 해야한다.)

    id action1 = [FadeIn actionWithDuration:1.0f];
    id action2 = [FadeOut actionWithDuration:1.0f];

위의 예제에서 action1은 1초 동안 점점 나타나게, action2는 1초 동안 점점 사라지게 한다.


1.8 Tint

Sprite 의 농도를 마음대로 변경도 할 수 있다. 이는 TintTo actionWithDuration:red:green:blue: 와 TintBy actionWithDuration:red:green:blue:를 사용해서 수정할 수 있다. 앞에서도 많이 경험했다 싶이 이번에도 To와 By가 나와았는데 To는 절대적으로 rgb에 맞는 농도가 변경되고 By는 현재의 값에서 rgb가 추가되어 색상이 변경되어 진다. 

다음은 이를 사용한 예제이다. 

    id action1 = [TintTo actionWithDuration:2 red:255 green:0 blue:255];
    id action2 = [TintBy actionWithDuration:2 red:0 green:-127 blue:-127];


1.9 Animate

지금까지는 하나의 Sprite를 가지고 이동시키거나 크기를 변경시키거나 회전시키는 등의 애니메이션을 살펴봤는데 이번에는 여러개의 Sprite이미지들을 사용해서 각각을 연속적으로 보여주면서 하나의 애니메이션을 출력하는 것을 알아보려고 한다. 

이를 위해서는  기존과 다른 방식을 사용해야하는데 우선 Animation 인자를 먼저 생성하고,

    Animation* animation = [Animation animationWithName:@"dance" delay:0.2f];

 여기에 이 애니메이션에서 출력할 이미지들의 파일이름으로 로드해서 적재하게 한다.

    for( int i=1;i<15;i++)
        [animation addFrameWithFilename: [NSString stringWithFormat:@"dance_%02d.png", i]];

그런 다음에 이 애니메이션을 Action으로 생성한다.

    id action = [Animate actionWithAnimation: animation];

이를 다음과 같이 실행하면 된다. 

    [someSprite runAction:action];


지금까지 아주 기본적인 애니메이션을 구현하는 법을 공부해 봤다. 
이것만 가지고도 같단한 애니메이션을 구현할 수 있는데 좀 더 복잡한 Sprite가 커지면서 이동하는 등의 애니메이션을 구현을 하려면 몇가지만 더 알면 된다. 이것은 다음에 알아보려고 한다. 


위에서 설명한 내용들을 Cocos2d의 SpriateTest를 가지고 강좌에 맞도록 수정한 소스를 첨부합니다. 

공부하시면서 보면 쉽게 이해하실 수 있으실 것입니다. SpriteTest.zip