Bezier곡선은 그래픽툴의 펜툴과 같은 기능이라고 보면 된다. 포인트로 하여금 사이의 곡선을 구하는 생각보다 친숙한 개념이다. (자세하진 않지만 참고할 수 있는 관련 포스트 링크 : http://sharphail.tistory.com/61 )
기본적인 베지어 곡선 샘플을 몇개 만들어 놓고 변형하여 사용할 수 있도록 차근차근 본 포스트를 작성할 예정입니다.
1. 보다 이해하기 쉽고 빠른 변형을 위하여 예제들은 CCBezierBy를 기준으로 만들었습니다.
2. cocos2d를 아무리 뒤져보도 2차원 곡선밖에 지원을 안하는것 같아서 예제들은 '2차원 곡선'을 기준으로 합니다.
3-1. BezierBy인만큼 startPosition의 위치는 크게 상관없다고 생각하여 별도 표시하지 않았습니다.
3-2. 컨트롤포인트의 설정값과 실위치를 매칭(표시)해놓지 않았는데, 그리드를 참고하시어 이해해주시기 바랍니다.
3-3. 보시면 아시겠지만 그리드 간격은 10픽셀로 생각하시면 됩니다.
4-1. reverse의 경우 CCMoveBy의 reverse와 같은 개념이 맞습니다. 하지만 굴곡의 정도가 변하지 않으니 이점 유의하시기 바랍니다.
#1. 반구모양
CCBezierConfig moveBezier; moveBezier.controlPoint_1 = ccp(0,20); //11시방향 moveBezier.controlPoint_2 = ccp(30,20); //1시방향 moveBezier.endPosition = ccp(30,0); //3시방향 [CCBezierBy .... bezier:moveBezier];
#2. 구(원)모양
CCBezierConfig moveBezier; CCBezierConfig moveBezier_2; moveBezier.controlPoint_1 = ccp(0,20); //11시방향 moveBezier.controlPoint_2 = ccp(30,20); //1시방향 moveBezier.endPosition = ccp(30,0); //3시방향 moveBezier_2.controlPoint_1 = ccp(0,-20); //4시방향 moveBezier_2.controlPoint_2 = ccp(-30,-20); //6시방향 moveBezier_2.endPosition = ccp(-30,0); //8시방향 [CCSequence [CCBezierBy .... bezier:moveBezier], [CCBezierBy .... bezier:moveBezier2]]; //반구모양의 BezierConfig를 두개 적용시킨 형태입니다. //By개념에 따라 하나의 베지어 곡선이 끝날때를 기준으로 거리를 계산하시면 됩니다. //곡선간의 굴곡이 딱맞아떨어진다면 위와 같이 시퀀스를 이용하여 부드러운 다차원의 곡선을 만들수 있습니다.
#3. 8자 모양
CCBezierConfig moveBezier; CCBezierConfig moveBezier_2; moveBezier.controlPoint_1 = ccp(0,10); moveBezier.controlPoint_2 = ccp(20,10); moveBezier.endPosition = ccp(30,0); moveBezier_2.controlPoint_1 = ccp(10,-10); moveBezier_2.controlPoint_2 = ccp(30,-10); moveBezier_2.endPosition = ccp(30,0); [CCSequence [CCBezierBy .... bezier:moveBezier], [CCBezierBy .... bezier:moveBezier_2], [[CCBezierBy .... bezier:moveBezier]reverse], [[CCBezierBy .... bezier:moveBezier_2]reverse]]; //2차원 곡선을 여러개(2개) 생성하여 reverse로 하여금 간단하게 4번의 베지어 곡선을 기반으로 만들었습니다. //모든 베지어 곡선의 변형은 '반구 상태의 모양'을 기준으로 접근하는게 베지어 곡선을 쉽게 만드는 방법같습니다.
==========================================================
3개의 원형태의 케이스를 만들다보니, 나머지는 응용부분이라 더이상의 '형태' 작성은 무의미한것 같아,
변수를 활용하여 좀 더 유동적인 곡선 변형 예제들을 첨부해놓겠습니다.
예제에 앞서 reverse와 ccpNeg에 대해 간단히 이미지를 첨부합니다.
reverse는 다들아시다시피 액션을 반대로 행하는 것이며, 내부 함수구조로는 ccpNeg라는 메소드와 각 포지션간의 연산을 통해 reverse 액션이 만들어집니다.
여기서 ccpNeg란 손쉽게 포지션값을 반대로 만들어주는 역할을하며, 이를 응용하여 좀 더 손쉽게 베지어 곡선을 만들수 있었습니다. ( cocos2d-iphone.org의 CGPoint 함수 목록 )
그림1. 2차원 곡선 A |
그림2. 2차원 곡선 A의 reverse |
그림3. 2차원 곡선 A의 ccpNeg |
그림4. 2차원 곡선 A의 ccpNeg의 reverse |
글이 길어져서 시간 관계상 정라하지 못한 상태로 그냥 올릴게요.. ㅠㅠ
float circleWidth = 90.0f; float circleHeight = 25.0f; float fluidWidth = 0.4f; float fluidHeight = 1.25f; moveBezier1.controlPoint_1 = ccp(0,-(circleHeight-circleHeight/3)); moveBezier1.controlPoint_2 = ccp(-(circleWidth*fluidWidth),-((circleHeight-circleHeight/3)*fluidHeight)); moveBezier1.endPosition = ccp(-(circleWidth),0); moveBezier2.controlPoint_1 = moveBezier1.controlPoint_1; moveBezier2.controlPoint_2 = ccp((circleWidth*fluidWidth),-((circleHeight-circleHeight/3)*fluidHeight)); moveBezier2.endPosition = ccp(circleWidth,0);
float의 값들은 기본적으로 곡선과 원형태를 그릴때 어느정도의 크기를 기준으로 할것인지 정하는 부분입니다.
위의 BezierConfig는 그림의 곡선 A와 같은 형태이며, 이를 좀 더 응용해서
moveBezier3.controlPoint_1 = ccpNeg(moveBezier1.controlPoint_1); moveBezier3.controlPoint_2 = ccpNeg(moveBezier1.controlPoint_2); moveBezier3.endPosition = ccpNeg(moveBezier1.endPosition); moveBezier4.controlPoint_1 = ccpNeg(moveBezier2.controlPoint_1); moveBezier4.controlPoint_2 = ccpNeg(moveBezier2.controlPoint_2); moveBezier4.endPosition = ccpNeg(moveBezier2.endPosition); moveSequence = [CCSequence actions: [CCBezierBy actionWithDuration:moveSpeed/4 bezier:moveBezier1], [[CCBezierBy actionWithDuration:moveSpeed/4 bezier:moveBezier3] reverse], [CCBezierBy actionWithDuration:moveSpeed/4 bezier:moveBezier2], [[CCBezierBy actionWithDuration:moveSpeed/4 bezier:moveBezier4] reverse],nil];
위처럼 유동적으로 값을 조절할수 있는 8자 형태의 다차원 곡선을 만들수 있습니다.
물론 8자 형태가 아닌 쌍곡선이라던지 깊이있는 굴곡의 표현도 가능합니다.
위의 그림을 잘 떠올리시고, 베지어 곡선을 마음껏 변형해 보시기 바랍니다.
http://alecjacobson.com/programs/bezier-curve/ (베지어 곡선을 그려볼수 있는 어느 한 외국 사이트(?))
'Dev > Cocos2D' 카테고리의 다른 글
CCSpriteBatchNode의 기본 사용법 (0) | 2013.08.21 |
---|---|
cocos2d의 터치 우선순위(priority)는 낮은것부터 ! (0) | 2013.08.07 |
패턴등의 이미지 배열시 검은 줄 제거 (0) | 2013.06.04 |
스케쥴(Schedule) 액션(RunAction) 등이 오류없이 실행되지 않을때는 isRunning_ 을 살펴보자 (0) | 2013.04.05 |
CCBezier(베지어 곡선)를 사용할땐 controlPoint(컨트롤 포인트)를 조심하자 (0) | 2013.03.13 |