1. 예제 분석 목적
==> scene 전환방법의 기본을 알고 scene action의 원리를 알아본다.
2.전체적 개요
전체 3개의 scene을 구성하면 각 scene당 Layer1 ,Layer2, Layer3 이 할당된다.
Layer1_Scene에서 Layer2_Scene로 전환될때는 push를 사용하고 이때 화면전환은
단순장면 전환 및 scene_action전환을 이용한다.
Layer2_Scene에서 Layer1_Scene로 전환은 push의 반대 개념은 pop를 이용한다.
Layer2_Scene에서 Layer3_Scene로 전환 될때는 replace를 사용하고 이때 화면전환은
단순장면 전환 및 scene_action전환을 이용한다.
Layer3_Scene에서 pop를 이용하면 Layer1_Scene로 이동한다.
==>MenuItem으로 3가지 메뉴를 만들고 클릭 되었을때 실행될 콜백을 각각 지정한다.
push에서 봤다 시피 Scene을 담는 통의 구조는 스택으로 구성되어 있다.
CCDirector.sharedDirector().runWithScene(scene);
코드를 사용하여 디렉터에서 기본적으로 화면에 보여줄 scene을 전달한후에는
CCDirector.sharedDirector().pushScene(scene);
CCDirector.sharedDirector().popScene();
CCDirector.sharedDirector().replaceScene(scene);
이용해서 장면전화을 한다.
replaceScene 는 별거 없는것이 . pop 한 후에 push 한것 뿐이다. 보다 쓰기 쉽게만들어
놓은 api 뿐이니 별 고민 할 필요 없다. 몰라도 된다 걍 남들이 쓰면 이런게 있다 정도로만
알아 두자 .
Scene 라고 별거 없다 그냥 layer 라고 생각하면 된다. 다만 디렉터에서 관리하는
Layer일 뿐이다.
디렉터에서 관리하는 Layer는 Scene이다.
==>Scene_Action 장면전환 효과가 있는 Scene 라고 하나의 패키지로 나와있는데
이것은 어이없는게도 CCNode+Action 일뿐이다.
이전 까지는 CCNode와 CCAction을 따로 선언하여 하나로 합쳐서 액션을
사용했지만. 장면전환효과가 있는 Scene라고 거창한 이름을 붙여놓은것은
CCScene에 기본 액션을 디폴트로 집어 놓았을뿐이다. 별거없다. 내부 함수들을
살펴보면 알겟지만 더이상 없다. 이런 기본적인 것들을 알아 보았으니
우리도 이와 비슷한것을 수십가지를 만들어 낼수 있다.
action에 action을 추가해서 CCSecne를 상속한 클래스에 박아 넣기만 하면
되니까 말이다.
나머지 Layer2와 Layer3도 별다른 차이점이 없다 여기서 설명한 내용이 전부 일뿐이다.
그런데 어떻게 글을쓰다 보니까 반말이 되었네요^^;;
글 수정하기도 ~~ 좀 그러니 ㅎㅎㅎ 이번만 양해 해주세요
0. EaseActionsTest 에 들어가며 ==> 기본클래스 심화에 EaseAction에서 상세히 다루어서 그 관련 글들만 잘 보신다면. 분석 하는데 별무리 없을듯 보입니다. 그래서 EaseAction클래스 심화내용중 중요부분만 발췌하여 이번 분석예제를 대체하고 자 합니다. 1.EaseAction의 기본 적인 내용
1. 클래스 설명
Base class for Easing actions
==> 액션을 쉽게 하게위한 기본 클래스 입니다.
==> 말그대로 쉬운 액션 입니다. 액션을 보다 쉽고 재밌게 쓰기 위한 기본클래스입니다.
==> 이렇게 클래스 소스에서 뽑아 낼수 있는 자료는 별로 없네요 그래서 홈페이지 있는
자료를 참고 해봅니다.
public static final float M_PI_X_2 = (float) (Math.PI * 2.0f);
protected CCIntervalAction other;
==>첫번째 멤버변수 M_PI_X_2 가 있는 것을 보니 액션을 사용할때 수학적인 요소를 사용하려
나 봅니다.
==>두번째 멤버변수 other CCIntervalAction을 멤버변수로 하나더 가지고 있습니다. 이걸 왜
가지고 있을까요? 위에서 설명한바와 같이 액션의 기간을 수정하기위함입니다.
이는 기본액션의 인스턴스를 생성자의 파라미터로 가지기 때문입니다.
그럼 기본액션들은 어떨까요?. 다른 기본액션들은 속성에 대한 데이터를 액션 생성자의
파라미터로 넘깁니다. 여기에 중요한 포인트입니다.
한마디로 EaseAction은 다른 기본액션을 담는 통이라는것입니다. 이와 유사한것을로
시퀀스, 리핏, 무한리핏 또한 이런류의 액션을 담는 통입니다.
==> 위를 6개묶음으로 분류한것은 내부액션의 기간 수정 방법에 대한것입니다.
(결과값을 만들어내는 수식의 종류에 따라)
5. 쓰이는 곳
==> 실제적으로 코드에서 사용할일은 없을듯합니다. CCEaseAction 클래스를 기반으로
확장된 클래스(4번참고)를 사용하세요
==> cocos2d는 아직 확장중인 엔진으므로 혹시 사용자가 나만의 EaseAction을 구현할때나
쓰일 것 입니다.
6. 최종정리 어떻게 하다보니 org.cocos2d.actions.ease 관련 클래스를 모두 정리하였습니다. 막상정리하고 보니 별것도 없고 그냥 그렇네요 그런데 어떤 EaseAction을 쓸것인가 에 대한 고민을 안할수가 없네요 . 어떻게 해야 할까요? 하나하나 정리 테스트 해보면 좋겟지만. 먼가 감도 안오고 흠... 그래서 준비 했습니다.
휘어지는 정도가 한눈에 보이네요 ㅎㅎㅎ 그럼 잘 골라서 쓰세요 ㅎㅎ
기존에는 텍스쳐를 이용한 렌더링을 하였습니다. 이제 모든 그리기 라이브러리의 기초인
기본도형 그리기를 cocos2d가 어떻게 구현하는지에 대해서 나와 잇습니다.
크게 어려운 부분이 없을뿐더러 소스에는 친절한 주석이 나와있으므로 이를 간단하게 해석하는
것으로 이번 강좌는 정리하겟습니다.
// TIP:
// If you are going to use always the same color or width, you don't
// need to call it before every draw
//
// Remember: OpenGL is a state-machine.
같은 색깔이나 동일한 두께를 표현하기 위해서 매번 따로 설정할필요 없습니다.
한번 바뀐 속성은 계속 지속됩니다.
이는 opengl이 정적이기 때문입니다. 이를 잘기억하세요
// TIP:
Every CocosNode has a "draw" method.
모든 cocosNode는 "draw" 함수를 가지고 있다
In the "draw" method you put all the code that actually draws your node.
이함수 안에서 node에 실제그려지므로 여기에 코드를 놓을수 있다.
And Test1 is a subclass of TestDemo, which is a subclass of Layer, which is a subclass of CocosNode.
TestDeomo는 Layer의 서브 클래스 이고 Layer는 CoccosNode의 서브 클래스이다.
As you can see the drawing primitives aren't CocosNode objects. They are just helper
여기에서는 cocosNode의 object를 그리지 않고 기본도형을 그리기볼수 있는데 이것들은
functions that let's you draw basic things like: points, line, polygons and circles.
기본적인 도형을 그리는것을 도와주는 함수 들이다.
//
TIP:
Don't draw your stuff outside the "draw" method. Otherwise it won't get transformed.
"draw"메서드 밖에서 그리지 마세요 . 그러면 재대로 적용이 되지 않는다.
//
TIP:
If you want to rotate/translate/scale a circle or any other "primtive", you can do it by rotating
1. 앵커의 정의화 position과의 관계
2. 부노노드의 앵커의 변화에 따른 자식노드에 끼치는 영향 과 부노노드에 액션이 작용할때
자식노드가 어떤 영향을 받는가?
3. Z-order에 대한 설명 간략히
4. Tag의 유일성과 중첩성(분류)
5. removechild()의 영향과 자식 노드의 재사용에 대해서
6. 부모노드가 할매노드에서 제거 될때 자식노드의 상태
액션 콜백과 콜백.
1.예제 분석 목적:
=>CCNode 주요속성의 변경방법과 속성이 변경될때 화면에 어떻게 나타 나는가를 확인
2.확인속성
Test1.class==>Transform Anchor
Test2.class==>Transform Anchor and Children
Test3.class==>Z Order
Test4.class==>Tags
Test5.class==>Remove
Test6.class==>Remove with Children
Test7.class==>Stress Test #1
* 코드 설명중 속성의 변화에 따른 액션 부분은 제외 하였습니다.
3-1 Test1 ( Transform Anchor )
사전 필요 지식
1. sprite는 기본적으로 앵커점을 0.5f 0.5f 로 잡고 시작합니다.(이미지의 센터점)
2. cocos2d의 좌표계는 Top-Left 가 아니라 Bottom-Left 입니다.
이에 반해 안드로이드의 화면 좌표계는 Top-Left 라서 처음 cocos2d를 접하시는 분들이
좀헷갈려합니다.
코드 설명
sp0, sp1,sp2 를 화면센터에 수평정렬입니다.
point0,point1,point2 는 sp0, sp1, sp2의 앵커 포인트를 가리키고 있습니다.
그리고 나서 sp0 sp1 sp2 의 앵커 포인트를 변형합니다. 그리고 나타난 화면은
처음 앵커 포인트를 알게된사람들은 언듯 이해가 가지 않습니다.
이에 대해서 자세한 설명은 앵커포인트와 비슷한 이름을 지닌 position 과 비교하면 좀 더
이해가 잘 될듯합니다.
position은 부모Node 의 0,0 좌표에서 얼마나 떨어져 있는 지를 x와 y로 나타 낸것입니다.
Node가 (100,200)이면 부모노드에서 x 100만큼 y 200만큼 떨어진 곳에 이란것입니다.
이때 자신의 기준은 무엇일까요? 머 앵커를 설명하는 자리니까 당연히 앵커가 되겟죠.
다시말해 사이즈 가로50 세로50인 이미지를 부모노드에서 (100,200)만큼 움직이라고 하는데
어디를 기준으로 잡아야 할까요? 이미지의 왼쪽아래? 오른쪽아래? 정가운데?
이게 바로 앵커입니다. Node의 크기가 사용자마다 다르니 특정 크기값으로 하지 말고
이미지=Node의 원래 사이즈를 가로 세로 1 로 잡고 그 비율로 나타낸것입니다.내부적으로 화면
에 표시 될때는 이미지크기에 맞추어 특정 좌표로 표현되지만 우리가 그것까지 볼필요는
업습니다.
(추후 강좌를 전체적인 업데이트 할 때 이미지도 포함하여 반영하겟습니다.)
이미 3-1에서 설명을 잘 이해 하셨다면 이번 내용은 어렵지 않겟 받아 들일것이라 생각합니다.
자식Node의 위치=position은 부모의 0.0 점을 기준으로 해서 결정된다 라고 위에서 이야기 드렸습니다. 그럼 그 부모노드가 속해있는 부모노드 그러니까 할배노드라 합시다.
부모노드의 position은 할배노드의 0,0을 기준하겟죠, 결국 자식노드의 위치는 부모노드뿐만 아니라 할배노드에게도 영향을 받습니다.
이것을 액션의 rotate(회전변화)을 이용하여 상당히 적절하게 표현되고 있습니다. 실제 코드를
돌려보기 전에 머리속으로 한번 그려보세요
할배노드 = Test2
부모노드 = sp1, sp2
자식노드 = sp3, sp4
입니다. 그와 더불어 부모노드에 대한 액션은 자식 노드에도 영향을 끼칩니다.
(강좌 업데이트때 이미지추가)
xy 축에 더불어 한가지 축 z축 입니다. z값이 양수면 화면앞 그러니까 사용자의 눈쪽
가까이 위치하고 음수면 ,화면 너머에 위치합니다. 그러니까 이미지가 겹쳐질때 맨위로 오느냐
맨뒤로 가서 가려지느냐의 차이를 설명한것입니다.
(참고이미지는 강좌 업데이트 하면서추가 하겟습니다.)
태그는 말그대로 꼬리표입니다.
안드로이드에서는 View클래스에 id 를 할당합니다.
그 아이디를 기반으로 R.java 클래스 변수로 등록되고 액티비티
어디에서든 접근 가능합니다.
그럼 cocos2d에 대한 구분자는 어떻게 할까요 ?
바로 TAG입니다
안드로이드 id는 유일한 값입니다 이는 어플리케이션 package에서 관리
하기때문입니다.
그럼 cocos2d에서는 tag는 어디서 관리할까요?
바로 자기 자신이 관리 합니다.
그럼 으로서 활용방법은 2가지 입니다.
Node의 독립성을 확보하기 위해 각기 고유 코드값으로 줄수도 있고
분류를 위한 비슷한 역활을 하는 Node들에서 공통의 값을 줄수도 있습니다.
부모노드에서 제거될때 자식노드의 상태에 대해서
기술됩니다. 이는 단지 화면에서만 사라지는 것이 아니라
자식노드가 가지고 있는 액션과 콜백/selector 는 어떻게 되는 것인가에 대한 예
보여 주고 있습니다
removeChild(sp1, false);
removeChild(sp2, true);
에서 보는 바와 같이 두번째 파라미터를 true로 하면 부모노드에서 자식노드를 삭제함과
동시에 자식노드의 액션과 콜백을 전부 초기화 하여 버립니다.
false로 한다면 액션과 콜백을 남겨두고 단지 소속만을 없애 버릴뿐입니다.
액션은 어디에 저장 되어 있을까?
removeChild(sp1, false);
removeChild(sp2, true);
분명 Layer의 child를 제거 했는데도 불구하고
액션이 남이 있다면 .child의 action은 최소한 부모에게로 등록되지 않는다.
그럼 ActionManager에 등록될때 child의 정보가 넘어간다는 소리인것 같은데 ㅎㅎ. ㅎ
소스 찾아 들어 가보니 역시 거기에 남아 있었다 .
ActionManager 의 ConcurrentArrayHashMap 에 저장 되어 있어다 .
private final ConcurrentArrayHashMap<CCNode, HashElement> targets;
그러니까 다시 활성화 되게 layer에 등록시키면 AcManager가 알아서 찾아서 쓴다
멀보고 할까?
addchild 안에 들어 가보면 뒤에 true와 false로 나뉜다
ActionManager는 이것을 보고 액션은 실행시킬지 말지를 결정한다.
무한 리핏액션이 아니면 액션이 종료되는 순간 이값은 false가 된다.
이번번 예제는 할배노드에서 부모노드를 삭제할때 자식노드의 액션과 콜백은 어떻게 되느
냐를 묻는 건데요.결론만 먼저 말하자면 모두 삭제 됩니다.
자세한 내용은 cocos2d 내부 소스를 보시면 이해가 빠를겁니다.^^ 결론은 간단한데
그 내부를 설명하려면 몇단계를 거쳐야 하기때문에 일단 여기서는 제외합니다.
1. 정의 스프라이트 별거 없습니다 그냥 2D이미지입니다.단지 용어가 익숙하지 않을뿐. 다시 반복하자면 에스. 피. 엘. 아이. 티. 이s p r i t e스프라이트.2D 이미지 간단히 사진이라 그림,글자 그림 이라고 생각하시면 됩니다.
==>cocos2d 를 배우는 이유가 화면에 이미지띄우고 왔다리 갔다리 하기위한거니까
생성방법은 숙지하세요... 사실 숙지고 머고간에 너무 간단해서 그냥 한번만 보면되요 ㅎ
==> 위와 같이 동일하게 파일 이름을 이용하지만 CGRect.make(top,left,bottm,rigth) 를 이용하여 이미지 파일의 특정영역으로 부터 CCSprite 객체를 생성합니다. ==> CGRect 클래스는 간단하게 자바클래스 RectF클래스와 유사하다고 생각해주세요 바로 보실분들은 보세요^^;;
package org.cocos2d.types;
publicclass CGRect {
public CGPoint origin;
public CGSize size;
public CGRect() {
this(0, 0, 0,
0);
}
public CGRect(final CGPoint origin, final CGSize
size) {
1. 라스트 정리
어떻게 하다보니 org.cocos2d.actions.ease 관련 클래스를 모두 정리하였습니다.
막상정리하고 보니 별것도 없고 그냥 그렇네요 그런데 어떤 EaseAction을 쓸것인가
에 대한 고민을 안할수가 없네요 . 어떻게 해야 할까요? 하나하나 정리 테스트 해보면
좋겟지만. 먼가 감도 안오고 흠... 그래서 준비 했습니다.
휘어지는 정도가 한눈에 보이네요 ㅎㅎㅎ 그럼
잘 골라서 쓰세요 ㅎㅎ
==> sin 함수,cos함수를 시뮬레이션화 한 클래스들 입니다.
==> 네이밍만 이 싸인함수라고했지만.
실제로는 CCEaseSineIn /CCEaseSineInOut 이 2개는 코사인 함수를 이용합니다. ==> 단지 MoveAction 만을 위한 클래스는 아니며 CCNode 속성에 있는 모든 값을 대상으로 합니다. ==> (참고 : EaseAction 이란 ?)
2. 클래스 관계도
3.추가된 멤버 변수 / 함수 ==>추가된 멤버 변수는 없습니다. ==> 없습니다. 라고 단호하게 말할까 했지만. 클래스 멤버 변수가 없다는것뿐이지 EaseAction의 핵심 함수 update(오버라이드됨)에 있습니다. 이는 EaseAction의 특성을 구별지을수 있는 핵심 부분이기에 각 클래스별 오버라이딩된 update(float t)를 살펴보겟습니다. ==> EaseAction의 동일한 반복입니다.
==> 클래스 관계도의 특성표는 위에 오버라이딩된 함수공식에 따른것입니다. ==> 바로 여기에서 알수 있듯이 CCEaseAction을 상속해서 여기처럼 update() 부분을 오버라이딩해서 쓴다면 사용자별 CCEaseRateAction을 만들수 있을것 입니다. (솔직히 저거 쓸수 있는 사람은 별로 안되겟죠^^)
4-4.사용법및 적용가능한곳.
public static CCEaseSineIn action(CCIntervalAction action) {
Base class for Easing actions with rate parameters
==> rate 파라미터롤 가속도를 나타냅니다. (시간변위당 속도변위) ==> 가속도 효과를 나타내기 위해서 내부 액션의 가속도를 변경 변경시키기 위한 추상화 클래스가 아닙니다. 기존에는 추상화 해놓고이거는 왜
추상화 안해 놓았는지 .... cocos2d가 아직 완성이 안되었다는걸가요? 흠...
조금더 고민을 해보아야 할듯합니다. ==> 단지 MoveAction 만을 위한 클래스는 아니며 CCNode 속성에 있는 모든 값을 대상으로 합니다. ==> (참고 : EaseAction 이란 ?)
2. 클래스 관계도
3.추가된 멤버 변수 / 함수 ==>추가된 멤버 변수는 이고
/** rate value for the actions */ float rate;
==> 추가된 멤버 함수(추상화 함수 가 아닌 단지 오버라이드 함수 입니다.) ==> 멤버변수가 늘어난것이니만큼 기존의 copy()와 reverse()를 새롭게 정의하는것은 당연합니다.
@Override
public CCEaseRateAction copy() {
return new CCEaseRateAction(other.copy(), rate);
}
@Override
public CCIntervalAction reverse() {
return new CCEaseRateAction(other.reverse(), 1 / rate);
}
4.CCEaseRateAction를 상속하는 클래스들
CCEaseIn.java
CCEaseInOut.java
CCEaseOut.java
==> 기존의 네이밍 규칙과 좀 다르네요 머 제가 한게 아니니까 일단 그려려니 할께요^^;; ==> 위의 클래스 설명을 따로 뺄까생각해보았지만. 좀 비효울적인듯 하여 아래에 추가로 올립니다.
4-1 CCEaseIn/ CCEaseInOut / CCEaseOut 클래스 설명
==>기존의 CCRateAction을 상속하여 지수함수를 시뮬레이션 합니다.
==>CCEaseExponential~~ 류의 클래스와 거의 비슷하게 나오지만 조금 다르네요 쪼끔...
개인적인 생각으로 굳이 이럴필요 있나 싶을정도로 말이죠.
4-2. 클래스 관계도
==> 진짜 보면 볼수록 너무 유사하군요. 왜 이런류의 클래스를 만들어서 사람 귀찮게시리 . 쯧..
4-3. 추가된 멤버변수/함수 ==> 없습니다. 라고 단호하게 말할까 했지만. 클래스 멤버 변수가 없다는것뿐이지 EaseAction의 핵심 함수 update(오버라이드됨)에 있습니다. 이는 EaseAction의 특성을 구별지을수 있는 핵심 부분이기에 각 클래스별 오버라이딩된 update(float t)를 살펴보겟습니다. ==> EaseAction의 동일한 반복입니다.
==> 클래스 관계도의 특성표는 위에 오버라이딩된 함수와 float rate변수 의 공식에 따른것입니다. ==> 바로 여기에서 알수 있듯이 CCEaseRateAction을 상속해서 여기처럼 update() 부분을 오버라이딩해서 쓴다면 사용자별 CCEaseRateAction을 만들수 있을것 입니다. (솔직히 저거 쓸수 있는 사람은 별로 안되겟죠^^)
4-4.사용법및 적용가능한곳.
public static CCEaseIn action(CCIntervalAction action, float rate) {
==>클래스 관계도의 특성표는 위에 오버라이딩된 함수의 공식에 따른것입니다. ==> 바로 여기에서 알수 있듯이 EaseAction을 오버라이딩하고 여기처럼 update() 부분을 오버라이딩해서 쓴다면 사용자별 EaseAction을 만들수 있을것 입니다. (수학책을 방정식 공석을 찾아 한번 해보세요 ㅎㅎㅎ 나중에 저도 도전해볼려고 합니다) ==> 오버라이딩된 함수 내부를 상세하게 설명할까 고민했지만 이건 별의미 없는것 같아서 패스 합니다.
4.사용법및 적용가능한곳.
public static CCEaseExponentialIn action(CCIntervalAction action) {
return new CCEaseExponentialIn(action);
}
public static CCEaseExponentialOut action(CCIntervalAction action) {
return new CCEaseExponentialOut(action);
}
public static CCEaseExponentialOut action(CCIntervalAction action) {
return new CCEaseExponentialOut(action);
}
==> 이처럼 동일합니다. ==> CCNode의 속성을 변경시키는 액션은 어떤것이든지 적용이 가능합니다만. CCSequence 또는 CCSpawn 액션은 자신이 원했던 결과물을 얻을수 있습니다.
These actions alters the time simulating an elastic. Elastic actions will use time values greater than 1 and lower than 0, so the inner action should be prepared to handle this special values.
==> 이 액션은 고무밴드를 시뮬레이션(흉내내는) 액션입니다. Elastic action은 사용되는 시간변수는 1보다 크고 0보다 작습니다. 내부부액션(EaseAction이 멤버변수로 가지고 있는
는 CCIntervalAction 레퍼런스변수) 이 특수한 변수를 다루기 위해서이다. ==> 말 그대로 탄력성이 느껴지는 효과를 나타내기 위해서 내부 액션의 가속도를 변경 변경시키기 위한 추상화 클래스입니다. ==> 단지 MoveAction 만을 위한 클래스는 아니며 CCNode 속성에 있는 모든 값을 대상으로 합니다. ==> (참고 : EaseAction 이란 ?)
2. 클래스 관계도
3.추가된 멤버 변수 / 함수 ==>추가된 멤버 변수는 이고
/** period of the wave in radians. default is 0.3 */ protected float period_;
==> 추가된 멤버 함수(추상화 함수 )
==> 멤버변수가 늘어난것이니만큼 기존의 copy()와 reverse()를 새롭게 정의하는것은
당연합니다.
@Override
public abstract CCEaseAction copy();
@Override
public abstract CCIntervalAction reverse();
4.CCEaseBounce 를 상속하는 클래스들
CCEaseElasticIn.java
CCEaseElasticInOut.java
CCEaseElasticOut.java
==> 위의 클래스 설명을 따로 뺄까생각해보았지만. 좀 비효울적인듯 하여 아래에 추가로 올립니다.
==> 음... 설명이 조금 애한데요 원활한 설명을 위해서 클래스 관계도 를 먼저 보겟습니다
4-2. 클래스 관계도
==> 이제 클래스 설명을 다시 보겟습니다. 애매한 단어가 "어떤 변수는 한번 이상을 트리거하게 됩니다" 이라는 말인데 위에 그림에 보면 이해가 좀더 잘 될것입니다 (여기서 변수라함은 시간변수입니다. update() 에 들어가는 시간값입니다.) ==> 바로 위에 설명은 반복되고 있어 뺄까 고민했지만. 아직은 필요한듯 하여 그냥 두기로 했습니다
==> 솔직히 이게 왜 탄력적인 느낌이 나는지 이해가 잘 안됩니다. 그냥 이런가보다 아~~ 하는
정도죠 ㅎㅎ
4-3. 추가된 멤버변수/함수 ==> 없습니다. 라고 단호라게 말할까 했지만. 클래스 멤버 변수가 없다는것뿐이지 EaseAction의 핵심 함수 update(오버라이드됨)에 있습니다. 이는 EaseAction의 특성을 구별지을수 있는 핵심 부분이기에 각 클래스별 오버라이딩된 update(float t)를 살펴보겟습니다. ==> EaseAction의 동일한 반복입니다.
==> 클래스 관계도의 특성표는 위에 오버라이딩된 함수와 period_변수 의 공식에 따른것입니다. ==> 바로 여기에서 알수 있듯이 CCEaseElastic 을 오버라이딩하고 여기처럼 update() 부분을 오버라이딩해서 쓴다면 사용자별 CCEaseElastic 을 만들수 있을것 입니다.
(솔직히 저거 쓸수 있는 사람은 별로 안되겟죠^^)
4-4.사용법및 적용가능한곳.
public static CCEaseElasticIn action(CCIntervalAction action) {
return new CCEaseElasticIn(action, 0.3f);
}
public static CCEaseElasticIn action(CCIntervalAction action, float period) {
==> 보시다 싶이 지금까지와는 달리 period 값을 추가로 줄수 있습니다. 실다면
디폴트로 0.3이 할당 됩니다. ==> CCNode의 속성을 변경시키는 액션은 어떤것이든지 적용이 가능합니다만. CCSequence 또는 CCSpawn 액션은 자신이 원했던 결과물을 얻을수 없을지도 모릅니다.
==> 말 그대로 공이 통통 튕기듯한 효과를 나타내기 위해서 내부 액션의 가속도를 변경
변경시키기 위한 추상화 클래스입니다.
==> 단기 MoveAction 만을 위한 클래스는 아니며 CCNode 속성에 있는 모든 값을
대상으로 합니다.
==>(참고 : EaseAction 이란 ?)
2. 클래스 관계도
==> CCAction 에서부터 많이 흘러 왔네요 어디까지 흘러갈지 저도 궁금합니다. ㅎㅎㅎ
3.추가된 멤버 변수 / 함수 ==>추가된 멤버 변수는 없습니다. ==>추가된 멤버 함수는 있습니다.
protected float bounceTime(float t) {
if (t < 1 / 2.75) {
return 7.5625f * t * t;
} else if (t < 2 / 2.75) {
t -= 1.5f / 2.75f;
return 7.5625f * t * t + 0.75f;
} else if (t < 2.5 / 2.75) {
t -= 2.25f / 2.75f;
return 7.5625f * t * t + 0.9375f;
}
t -= 2.625f / 2.75f;
return 7.5625f * t * t + 0.984375f;
}
==> 바운스 효과를 나타내기 위한 수학공식인듯합니다.
7.5625 / 2.75 / 2.25 / 0.984375
==> 이거 확인해봏수 있으면 좋지만 수학은 젬뱅이라. ㄷㄷ 어디 참고할만 거 없나요?
4.CCEaseBounce 를 상속하는 클래스들
CCEaseBounceIn.java
CCEaseBounceInOut.java
CCEaseBounceOut.java
==> 위의 클래스 설명을 따로 뺄까생각해보았지만.
좀 비효울적인듯 하여 아래에 추가로 올립니다.
4-1 CCEaseBounceIn /CCEaseBounceInOut / CCEaseBounceOut 클래스 설명
==> 음... 설명이 조금 애한데요 원활한 설명을 위해서 클래스 관계도 를 먼저 보겟습니다
4-2. 클래스 관계도
==> 이제 클래스 설명을 다시 보겟습니다. 애매한 단어가 "어떤 변수는 한번 이상을 트리거하게 됩니다" 이라는 말인데 위에 그림에 보면 이해가 좀더 잘 될것입니다 (여기서 변수라함은 시간변수입니다. update() 에 들어가는 시간값입니다.)
==> 바로 위에 설명은 반복되고 있어 뺄까 고민했지만. 아직은 필요한듯 하여 그냥 두기로
했습니다
4-3. 추가된 멤버변수/함수 ==> 없습니다. 라고 단호라게 말할까 했지만. 클래스 멤버 변수가 없다는것뿐이지 EaseAction의 핵심 함수 update(오버라이드됨)에 중요한 지역변수가 있습니다. 이는 EaseAction의 특성을 구별지을수 있는 핵심 부분이기에 각 클래스별 오버라이딩된 update(float t)를 살펴보겟습니다. ==> EaseAction의 동일한 반복입니다.
CCEaseBounceIn public void update(float t) {
float newT = 1 - bounceTime(1 - t);
other.update(newT);
}
CCEaseBounceInOut
@Override
public void update(float t) {
float newT = 0;
if (t < 0.5) {
t = t * 2;
newT = (1 - bounceTime(1 - t)) * 0.5f;
} else
newT = bounceTime(t * 2 - 1) * 0.5f + 0.5f;
other.update(newT);
}
CCEaseBounceOut
@Override
public void update(float t) {
float newT = bounceTime(t);
other.update(newT);
}
==> 클래스 관계도의 특성표는 위에 오버라이딩된 함수와 bounceTime() 의 공식에
따른것입니다. ==> 바로 여기에서 알수 있듯이 EaseAction을 오버라이딩하고 여기처럼 update() 부분을 오버라이딩해서 쓴다면 사용자별 EaseAction을 만들수 있을것 입니다. (수학책을 방정식 공석을 찾아 한번 해보세요 ㅎㅎㅎ 나중에 저도 도전해볼려고 합니다)
4-4.사용법및 적용가능한곳.
public static CCEaseBounceIn action(CCIntervalAction action) {
return new CCEaseBounceIn(action);
}
public static CCEaseBounceInOut action(CCIntervalAction action) {
return new CCEaseBounceInOut(action);
}
public static CCEaseBounceOut action(CCIntervalAction action) {
return new CCEaseBounceOut(action);
}
==> 이처럼 동일합니다. ==> CCNode의 속성을 변경시키는 액션은 어떤것이든지 적용이 가능합니다만. CCSequence 또는 CCSpawn 액션은 자신이 원했던 결과물을 얻을수 없을지도 모릅니다.
==> 음... 설명이 조금 애한데요 원활한 설명을 위해서 클래스 관계도 를 먼저 보겟습니다
2. 클래스 관계도 ==> 이제 클래스 설명을 다시 보겟습니다. 애매한 단어가 "어떤 변수는 한번 이상을 트리거하게 됩니다" 이라는 말인데 위에 그림에 보면 이해가 좀더 잘 될것입니다 (여기서 변수라함은 시간변수입니다. update() 에 들어가는 시간값입니다.)
3. 추가된 멤버변수/함수 ==> 없습니다. 라고 단호라게 말할까 했지만. 클래스 멤버 변수가 없다는것뿐이지 EaseAction의 핵심 함수 update(오버라이드됨)에 중요한 지역변수가 있습니다. 이는 EaseAction의 특성을 구별지을수 있는 핵심 부분이기에 각 클래스별 오버라이딩된 update(float t)를 살펴보겟습니다.
CCEaseBackIn 클래스
@Override
public void update(float t) {
float overshoot = 1.70158f;
other.update(t * t * ((overshoot + 1) * t - overshoot));
}
CCEaseBackInOut
@Override
public void update(float t) {
float overshoot = 1.70158f * 1.525f;
t = t * 2;
if (t < 1) {
other.update((t * t * ((overshoot + 1) * t - overshoot)) / 2);
} else {
t = t - 2;
other.update((t * t * ((overshoot + 1) * t + overshoot)) / 2 + 1);
}
}
CCEaseBackOut
@Override
public void update(float t) {
float overshoot = 1.70158f;
t = t - 1;
other.update(t * t * ((overshoot + 1) * t + overshoot) + 1);
}
==>클래스 관계도의 특성표는 위에 오버라이딩된 함수의 공식에 따른것입니다. ==> 바로 여기에서 알수 있듯이 EaseAction을 오버라이딩하고 여기처럼 update() 부분을 오버라이딩해서 쓴다면 사용자별 EaseAction을 만들수 있을것 입니다. (수학책을 방정식 공석을 찾아 한번 해보세요 ㅎㅎㅎ 나중에 저도 도전해볼려고 합니다) ==> 오버라이딩된 함수 내부를 상세하게 설명할까 고민했지만 이건 별의미 없는것 같아서 패스 합니다.
4.사용법및 적용가능한곳.
public static CCEaseBackIn action(CCIntervalAction action) {
return new CCEaseBackIn(action);
}
public static CCEaseBackInOut action(CCIntervalAction action) {
return new CCEaseBackInOut(action);
}
public static CCEaseBackOut action(CCIntervalAction action) {
return new CCEaseBackOut(action);
}
==> 이처럼 동일합니다. ==> CCNode의 속성을 변경시키는 액션은 어떤것이든지 적용이 가능합니다만. CCSequence 또는 CCSpawn 액션은 자신이 원했던 결과물을 얻을수 없을지도 모릅니다.
public static final float M_PI_X_2 = (float) (Math.PI * 2.0f);
protected CCIntervalAction other;
==>첫번째 멤버변수 M_PI_X_2 가 있는 것을 보니 액션을 사용할때 수학적인 요소를 사용하려
나 봅니다.
==>두번째 멤버변수 other CCIntervalAction을 멤버변수로 하나더 가지고 있습니다. 이걸 왜
가지고 있을까요? 위에서 설명한바와 같이 액션의 기간을 수정하기위함입니다. (기간 수정
이란 말은 액션의 속도를 바꾼다는 말입니다.)
위에 그림에서 보다 시피 실질적으로 쓰이는 부분은 CCOrbitCamera 입니다.
즉 카메라 관련 Action을 하려면 CCOrbitCamera 을 쓰세요
그럼 본격적으로 CCOrbitCamera 을 알아보고자 합니다.
일단 클래스 설명부터
/** CCOrbitCamera action
* Orbits the camera around the center of the screen using spherical coordinates
*/
구면자표계를 사용하여 화면가운데를 이동하는 카메라의 궤도이다? 정확안 해석은 아닌데
의미는 대충 알것네요.
(구면좌표계란 ? 중심에서의 거리, 방위각, 위도를 이용하여 3차원 위치를 표시하는 방법. 구면에서 나타나는 현상이 나 구면 형태로 전파되는 현상을 기술하기에 편리함.(출처 네이버 지식사전))
멤버변수로
float radius; 거리
float deltaRadius; 목표 거리
float angleZ; 방위각
float deltaAngleZ; 목표방위각
float deltaAngleX; 목표위도
float angleX; 위도 있습니다. 다른멤버 변수가 있기는 하지만. 이는 위에서 설정한 값을 라디언값으로 바꾸어 부분이므로 우리가 참고 할 필요는 없습니다.
생성자는 아래와 같습니다.
elapsed는 경과된,., 이니까 경과된시간. ...아~~~
CCFinteTimeAction 에 일정 시간이 있으니까
그 일정 시간과 비교할 다른 참고 변수를 가진다는거죠
그리고 멤버 함수를 보니 아니나 다를까 .
CCFinteTimeAction에서 선언한. duration과
CCIntervelAction 에서 선언한 elapsed을 비교하는 구문이 있었습니다.
바로 요놈 입니다.
public boolean isDone() {
return (elapsed >= duration);
}
참이면 stop가 호출 되겟고 아니면 step이 호출되겟죠ㅎ
여기서 한가지 의문점은 이럴꺼면 왜 궅이 CCFinteTimeAction 가 CCIntervelAction 을 분리시켰냐에 대한 의문이 들더군요, 단지 변수 하나 추가하고 함수 오버라이딩 할꺼면 한번에 다하면 되지 왜 궅이 이렇게 귀찮게 해야 하나 라는거죠
이렇게 클래스 분리함으로써 얻을수 있는 장점은 무엇일까요? 이를 설명하기 위해서는CCFinteTimeAction 을 상속한 또 다른 클래스 CCInstantAction을 알면 해결될수 있을것이라 생각합니다.
그럼 CCInstantAction 을 살펴보면
/** Instant actions are immediate actions. They don't have a duration like
the CCIntervalAction actions.
*/
즉시 실행되는 액션이고 CCIntervalAction처럼 duration을 가지지 않는다.
추가된 멤버변수도 없습니다.
오히려 생성자에서
protected CCInstantAction() {
super(0);
}
@Override
public boolean isDone() {
return true;
}
@Override
public void step(float dt) {
update(1.0f);
}
@Override
public void update(float t) {
// ignore
}
자신의 부모클래스의 멤버변수인 duration의 값을 0로 줘버리더군요 이말은 실행하는 즉시 결과가 화면에 도출된다는것을 의미합니다. 함수 오버라이딩 해놓은걸보면.
step 이 바로 1로써 업데이트 되어 버립니다.
음. 이렇게 살펴 보았지만 위의 의문점은 해결이 안되는군요 .
이럴꺼 전부 CCFinteTimeAction 과 CCIntervelAction 과 CCInstantAction 을 하나의 클래스로 만들어서 멤버 변수의 값만 바꿔주면 되지 않나? 라는 생각이 들더군요 .
의문점을 해결하고자 했는데 오히여 더 복잡해지네요 . . ㄷㄷㄷ
이에 대해서 좀더 알아보고자 한다면. 다른 클래스들을 살펴보아야겟네요. 파고 들어갈수록 점점 이상해지네요 . ㅋㅋㅋ 일단 의문점은 남겨두고 갈께요. Action에 대해서 어느 정도 정리가 되면 이 의문점에 대해서 생각해보겟습니다.
혹시 까먹을지도 모르니 아래와 같이 체크해놓고 ㅎㅎ
Q.이럴꺼 전부 CCFinteTimeAction 과 CCIntervelAction 과 CCInstantAction 을 하나의 클래스로 만들어서 멤버 변수의 값만 바꿔주면 되지 않나?
그럼 멤버 변수가 머 볼거 없으니 멤버 함수를 확인해 보니.
Action이 한프레임동안 하는 일들을 알수 있었습니다.
바로 아래와 같은데요.
//! called before the action start. It will also set the target.
public void start(CCNode aTarget) {
originalTarget = target = aTarget;
}
//! called after the action has finished. It will set the 'target' to nil.
//! IMPORTANT: You should never call "[action stop]" manually. Instead, use: "[target stopAction:action];"
public void stop() {
// target = null;
}
//! return YES if the action has finished
public boolean isDone() {
return true;
}
//! called every frame with it's delta time. DON'T override unless you know what you are doing.
public abstract void step(float dt);
//! called once per frame. time a value between 0 and 1
//! For example:
//! * 0 means that the action just started
//! * 0.5 means that the action is in the middle
//! * 1 means that the action is over
public abstract void update(float time);
멤버 함수별 상세한 설명은 안에 잘되어 있으니
하나의 프레임동안 호출되는 함수들의 순서를 정리하겟습니다.
바로 이렇습니다. 여기서 유추할수 있는건 이런 액션멤버변수들을 호출하는 무언가가 있다라는것이죠 일단 지금은 그정도로만 알고 있죠 무언가가 액션의 멤버 변수를 호출한다.그것도 체계적으로 말이죠
자 그럼 이제 무었이 필요할까요?
제목에서도 나와 있듯이 메뉴를 누르고 소리나고 난뒤에 다른 어플리케이션이 먼가 해주어야겟죠. 그대표적인 예가 다른장면. 메뉴를 눌렀으면 그에 합당한. 다른 화면이 나와워야고 생각합니다. 그장면 전환도 그냥 하는게 아니고 먼사 쌈박한게 해주면 좋겟죠 화려하게 ㅎㅎㅎ
그럼 이제 우리가 알아야 할것은 2가지입니다.
첫번째 : 장면전환 방법과
두번째 : 장면전환 효과
이렇게 2가지입니다.
그럼 그 첫번째 장면 전환 방법입니다.기본개념강좌에서 보앗듯이
장면 즉 Scene를 관리하는것은 Direction입니다. 그럼 Direction에 보면 장면
전환에 관련된 함수들이 있을거라고 예상할수 있죠.
실제 소스를 찾아보니 .
// Director
CCScene Management
/**Enters
the Director's main loop with the given CCScene.
* Call it to run only your FIRST CCScene.
* Don't call it if there is already a
running CCScene.
*/
publicvoid runWithScene(CCScene CCScene) {
assert CCScene != null : "Argument
must be non-null";
assertrunningCCScene_ == null : "You
can't run a CCScene if another CCScene is running. Use replaceCCScene or
pushCCScene instead";
pushScene(CCScene);
//startAnimation();
}
/**
Replaces the running CCScene with a new one. The running CCScene is terminated.
*
ONLY call it if there is a running CCScene.
*/
publicvoid replaceScene(CCScene CCScene) {
assert CCScene != null : "Argument
must be non-null";
int index = CCScenesStack_.size();
sendCleanupToCCScene_ = true;
CCScenesStack_.set(index -
1, CCScene);
nextCCScene_ = CCScene;
}
/**Suspends
the execution of the running CCScene, pushing it on the stack of suspended
CCScenes.
* The new CCScene will be executed.
* Try to avoid big stacks of pushed
CCScenes to reduce memory allocation.
* ONLY call it if there is a running
CCScene.
*/
publicvoid pushScene(CCScene CCScene) {
assert CCScene != null : "Argument
must be non-null";
sendCleanupToCCScene_ = false;
CCScenesStack_.add(CCScene);
nextCCScene_ = CCScene;
}
/**Pops
out a CCScene from the queue.
* This CCScene will replace the running
one.
* The running CCScene will be deleted.
*If there are no more CCScenes in the stack the execution is terminated.
* ONLY call it if there is a running
CCScene.
*/
publicvoid popScene() {
assertrunningCCScene_ != null : "A
running CCScene is needed";
CCScenesStack_.remove(CCScenesStack_.size() - 1);
int c = CCScenesStack_.size();
if (c == 0) {
end();
} else {
nextCCScene_ = CCScenesStack_.get(c - 1);
}
}
위와 같이 있더군요 .
runWithScene , replaceScene , pushScene , popScene runWithScene는 Scene를 시작하는거니까 일단패스
replaceScene 오케이 교체 요거 일단 접수.
어라 근데 push,pop 오호 ~~~ director는 Scene 관리는 스택 개념으로
하는구나 . ㅎㅎㅎ 좋았어
그리고 생각해봅시다.
장면의 전환을 할 때 2가지 경우가 있습니다.(이전과 이후 )
1. 이전 장면의 데이터를 보관해야 할때!(ex 게임중간에 설정으로 전환)
==>pushScene and popScene
2. 이전 장면의 데이터를 보관안해도 될때(ex 메뉴에서 게임 화면의로의 전환)
==>replaceScene 으로 사용하면 되겟네요 ㅎㅎ
두번째 장면 전환 효과입니다.
이것도 어떨때 어떻게 사용하라고 정의하면 좋겟지만 이거야 만들고 싶은 사람 마음니까
머라고 정의 할 수 없겟네요. 한가지 느낌점은 장면 전환이 Action과 상당히 유사성이 많게 보입니다. 실제 어떤 장면전화효과는 액션을 몇가지 썩어 놓기만 했네요. 비록 30 여개의 장면전환클래스가 있다지만 이것만이 전부가 아니겟지요. 일단 하나하나 테스트 해보세요 . 그리고 나서 자신만의 장면 정환 효과를 만들어 본다면 상당히 재미있을듯합니다.
아참 그전에 한가지 정리 할고 갈것이 있네요. 바로
CCScene에 장면효과를 주는 것이 아니고 장면효과를 가지는 CCScene(CCTransitionScene)를 만든다는것입니다. 언듯 보면 말장난 같지만 이 두가지의 차지점은 상당히 큽니다.
첫번째 인자는 Context
두번째 인자는 Raw 폴더에 있는 파일이름
세번째는 반복재생 할건지 말건지 입니다.(배경음 이니까 당연히 무한 반복 들어값니다.)
그리고 효과음입니다.
효과음이 필요한곳에다가 SoundEngine.sharedEngine().playEffect(app, R.raw.effect);
요렇게만 쓰면 됩니다.
첫번째 인자값은 컨택스트
구번째 인자값은 Raw 폴더에 있는 파일입니다.
진짜 초간단하죠 ㅎㅎㅎㅎ 너무 간단해서 어이가 없을 지경입니다.
홈피에서는 5초이상 쓰이는건 미디어 플레이어 쓰고 3초 이하 정도면
이펙트를 사용하는것을 추천합니다.
자이제 간단하게 사용하법 법을 보았습니다.
일단 비교 대상이 2개뿐이니까 이번엔 표로 한번 정리해볼까요?
배경음악
효과음
안드로이드와 연관성
MediaPlayer사용
soundpool 사용
적용시점
화면이 있을때
사용자의 반응에 대해서
끝나는 시점
어플종료 / 화면이 안보일때
일회성이므로 사용후바로 끝
배경음악의 시작시점을 보겟습니다 이건 어디서 알수 있을까요?
CCNode 관련 클래스가 화면에 나타날때(생성될 때) onEnter() 함수가 호출됩니다. Layer도 레이어니까 CCNode 클래스를 상속받았으니 OnEnter() 함수롤 오버라이드 한 바로이곳에서 배경음악을 실행합니다.
배연음악은 언제 안들리게 해야 하나요?
어플이 종료되었을때 와 어플이 화면에서 안보일때(background) 입니다. 그리고 커스텀하게 해당 레이어가 없어지거나 안보일때 입니다.
일단 레이어가 화면에서 사라지거나 어플이 background로 들어가는 것은 사용자 입장에서는 같다고 할 수 있습니다. 그럼 이때 일시정지를 하고 어플이 종료될때는 Mediaplayer를 realease 해줍니다. 그럼 레이어가 사라질때 호풀되는 함수가 먼고하니 바로
OnExit()입니다 여기에 바로 일시정지를 넣어줍니다.
그리고 어플이 종료될때 OnDestroy 입니다.여기서종료해 주는거죠 ]
cocos2d에 있는 예제는 워낙 단순하여(한개의레이어) 커스텀한경우는 없네요
차후 실제 게임 만들기 강좌에서 보다 자세히 다룰께요.
자 이번엔 효과음입니다. 효과음은 언제 이루어질까요?
사용자가 디바이스 어떤 동작을 취할때 입니다. 그때 호출되는 콜백 함수에
사용하면 됩니다. 보통 터치 이벤트가 발생했을때 사용됩니다.
* - You can add MenuItem objects in runtime using addChild:
* - But the only accecpted children are MenuItem objects
*/
특징과 제한
- CCMenuItem 인스턴스를 넣고 싶은때 언제나 멤버로 넣을수 있다 .
- 다만. CCMenuItem 이나 이를 상속한 클래스만 을 넣을수 있다 .
그럼 이제 CCMenuItem에는 어떤것들이 있나 보겟습니다.
총 6개가 아래와 같이 있습니다.
CCMenuItemAtlasFont
CCMenuItemFont
CCMenuItemImage
CCMenuItemLabel
CCMenuItemSprite
CCMenuItemToggle
위에 이놈들은 직접적이든 간접적이든 CCMenuItem을 상속 받았습니다.
)
다만 요놈들끼리도 상속 구조를 이루는 부분들이 있는데 확인해보게습니다.
일단 CCMenuItem을 사용처에따라 분류해봅니다.
1.이미지 메뉴아이템을 만들때 :
CCMenuItemSplite 을 사용하세요
그리고 좀더 편하게 사용한다면
CCMenuitemImage 를 사용하세요( 파일 이름으로 바로 생성가능 -관련 강좌 클릭)
2.글자 메뉴아이템을 만들때 :
CCMenuItemLable를 사용하세요
그러나 다른 폰트및 사용자 폰트를 사용하려면
CCMenuitemFont 와 CCMenuItemAtlasFont 를 사용하세요
CCMenuitemFont는 디바이스 내장 폰트 사용하고
CCMenuItemAtlasFont 사용자 폰트를 사용합니다.
(CCMenuItemLable 을 이용하여 사용자 폰트도 만들수 있지만. 개인적인 생각으로 는 분명 특화된 클래스가 있는데 그걸 사용하지않고 다른걸 기본클래스를 사용한다는 것은 시간낭비적
요소가 있지 않나 싶습니다.물론 세부적인 컨트롤이 가능하다는 측면이 있지만 그런일은 별로
없을듯 합니다. )
3.메뉴아이템을에 여러가지 상태값을 넣고 변경하고자 한다면
CCMenuItemToggle을 사용하세요
위 관련내용중 CCMenuItemSplite와 CCMenuItemImage를 제외하고
다른 메뉴아이템은 클릭시에 기본액션은 글자확대=>복귀 이 있습니다.
진짜 상세히는 못다루었지만. 이제 어떤메뉴라도 충분히 다룰수 있지 않았나 합니다.
지금까지 전체 MenuTest관련 5강좌를 전부 읽고도
메뉴를 만들지 못하신다면 문의 주세요 만들어 드립니다. ㅎㅎㅎ
바로 CCMenuItemToggle입니다. 자자 가볼까요 ?
토글 말그대로 입니다. 2가지의 상태변화 입니다.
A => B , B => A
입니다. CCMenuItemToggle item1 =
CCMenuItemToggle.item(this, "menuCallback",
CCMenuItemFont.item("On"), CCMenuItemFont.item("Off")};
별거 없죠
첫번째 파라미터 타겟 CCNode
두번째 파라미터는 콜백함수
세번째와 네번째는 상태변화 될 MenuItem 입니다.
상태변화도리 MenuItem은 몇개든지 추가 될수 있습니다.
CCMenuItemFont.item("On"), CCMenuItemFont.item("Off"), CCMenuItemFont.item("On1"), CCMenuItemFont.item("On2"), CCMenuItemFont.item("On3"), CCMenuItemFont.item("On4"), CCMenuItemFont.item("On5"), CCMenuItemFont.item("On6"), CCMenuItemFont.item("On7"), CCMenuItemFont.item("On8"), CCMenuItemFont.item("On9")};
이렇게 말이죠 메뉴아이템은 콜백과 별도로
상태변화MenuItem들을 순차적으로 변화시켜줍니다. 맨 끝으로 변화 되면 다시 첫번째가 나타납니다. 한마디로 루프죠 .
다르게 추가 하는방법은
바로 아래에 나오는데요. CCMenuItemToggle item4 = CCMenuItemToggle.item(this, "menuCallback",
CCMenuItemFont.item("Off"));
ArrayList<CCMenuItemFont>
more_items = new ArrayList<CCMenuItemFont>();
alignMenusH(); }
생성자에서 만들었네요
CCMenuItemImage 를 이용해서 이미지버튼을 3개 만들고
각 버튼의 크기를 셋팅합니다.
첫번째 CCMenuItemImage는 원래 사이즈에서 가로 1.5배
두번째 CCMenuItemImage는 원래 사이즈에서 세로를 0.5배
세번째 CCMenuItemImage는 원래 사이즈에서 가로 0.5배
이버튼들을 Menu에 넣었습니다. 그리고 수평정렬 함수를 호출합니다. centeredMenu의 값은 ( 0 , 0 ) 입니다 앵커의값이죠
갤럭시 기준으로 하면 480 800 인니까 240 에 400 이 되겟네요
------------------2011년 9월 10일 추가 내용 TAG--------------------
제가 이부분을 깝빡 했네요
menu.setTag(kTagMenu); addChild(menu, 0, 100+i);
태그는 말그대로 꼬리표입니다.
안드로이드에서는 View클래스에 id 를 할당합니다.
그 아이디를 기반으로 R.java 클래스 변수로 등록되고 액티비티
어디에서든 접근 가능합니다.
그럼 cocos2d에 대한 구분자는 어떻게 할까요 ?
바로 TAG입니다
안드로이드 id는 유일한 값입니다 이는 어플리케이션 package에서 관리
하기때문입니다.
그럼 cocos2d에서는 tag는 어디서 관리할까요?
바로 자기 자신이 관리 합니다.
그럼 으로서 활용방법은 2가지 입니다.
Node의 독립성을 확보하기 위해 각기 고유 코드값으로 줄수도 있고
분류를 위한 비슷한 역활을 하는 Node들에서 공통의 값을 줄수도 있습니다.(2011년 9월 26일 수정)
바로 부모 CCNode에서 관리합니다.
결국 이말은 부모만 다르다면 같은 TAG 값을 가져도 됩니다. 이명제의 대우는 무엇일까요?
같은 부모를 가지는 CCNode는 서로 다른 값을 가져야 한다는 말과 같습니다. 즉 유니크 해야 한다는거죠 ㅎㅎㅎ
Tag에 대해서 간단히 살펴 보았습니다.
메뉴를 불러와서 하나는 CCMenu 에 있는 MenuItem 간의 간격이 을 결정합니다.
디폴트로 5가 삽입되어있구요 밑에는 40이라는 상수 값을 주었네요 . menu.setPosition(CGPoint.ccpAdd(p, CGPoint.ccp(0,30)));
menu.setPosition(CGPoint.ccpSub(p, CGPoint.ccp(0,30)));
그리고 위에는 센터에서 y좌표값이 +30 이니까 화면에서 위로 올라 가겟고
아래는 센터에서 30 내려 가는 것이니까 화면에서 내려 가겟네요 ^^;
menu.setOpacity((byte) 128); } opacity 는 불투명도는 나타내죠 그런데 255로 변화 시키니까 아에 안보이고
이벤트도 안먹네요 흠... 이벤트 안먹히고 이건 따로 한번 알아 볼께요
사라지는것 까지는 이해 했는데 이벤트라 ... 아시는분 댓글좀^^;;
publicvoid menuCallbackAlign (Object sender) {
alignedH = ! alignedH;
if( alignedH )
alignMenusH();
else
alignMenusV();
}
기건머 2말 할필요없죠 ^^
자 그럼 여기까지가 . Layer2엿습니다.
여기서 새롭게 알게 된거는
1.CCMenuItem 할 때 크기를 따로 지정한다
item1.setScaleX(1.5f);
2.CCNode 의 TAG
CCNode는 자식간의 구별과 접근 용이성을 높이기 위해 TAG을 할당한다. 입니다.
3.CCMenu 수직 수평 정렬할때 padding값을 주어서 간격을
조절한다. menu.alignItemsVertically(40);
menu.alignItemsHorizontally(40);
requestWindowFeature(Window.FEATURE_NO_TITLE);
==>타이틀바 를 삭제 합니다.
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
==>상태바 (안테나 뜨는 부분을 삭제합니다)
mGLSurfaceView = new CCGLSurfaceView(this); setContentView(mGLSurfaceView); ==>CCGLSurfaceView 클래스 GLSurfaceView 를 상속합니다. 여기에 대해서 말할거리는 정말 많죠 그러나 일단은 성능 좋은 이미지뷰를 화면에
생성 한다 라고 만 알아둡시다 . 추후에 여기에 대해서 장기간에 걸쳐서 강좌를
진행해보겟습니다.
onCreate() 부분을 간단히 요약하자만 cocos2d를 사용하기 위해서
View 하나 생성 했다 입니다. 물론 전체 화면이니 나발이니 하는것은
하나의 옵션입니다. 이로써 준비는 끝났습니다. 실제 코드에 슬슬 들어 가보죠
주석이 참 친절하게 잘되어있네요 . CCDirector.sharedDirector().attachInView(mGLSurfaceView); 이전강좌에서 CCDirector의 개념을 잠시 언급한적이 있죠 감독이며 자혼자 뿐이라고
싱글스톤 입니다. CCDirecto 레퍼런스 변수 생성방법이 바로 요헐게
CCDirector.sharedDirector() 입니다. 그리고 난후에 위의 onCreate에서 생성했던 성능 좋은 이미지뷰를 감독에게 넘겨줍니다. 전권 위임입니다.
자그럼 프로그래머 입장에서 보면 감독을 한놈 정하고 그놈에서 전권을 맡긴 것이죠.
코드한줄에 주석이빠이 ㅎ. ㅎㅎ
CCDirector.sharedDirector().setLandscape(false);
이부분은 감독에서 세로모드로 영화를 찍어라고 하는겁니다
인자값이 true면 당연히 가로 16:9 와이드로 영화를 찍어라고 하는것이죠. 근데 막상 감독이라고 해놓고 보니 아직은 지혼자 할 줄 아는게 없네요 프로그래머가 일일이 지시해야 하고 에휴~~ 이래서 머리 좋은 시다바리를 둬야 한다는 거죠 . ㅎ 자자 각설하고
다음줄
CCDirector.sharedDirector().setDisplayFPS(true);
화면 귀퉁이 FPS를 숫자로 보여 줄것인가 말것인가를 감독에게 시킵니다. FPS는 초당 프레임수 초당 화면 갱신을 몇번하는가를 말합니다. 그러면 초당 몇번 보여라고 지정하는부분도 있겟죠 그게 바로 다음줄
CCDirector.sharedDirector().setAnimationInterval(1.0f / 60);
입니다. CCAction 기초강좌 에서도 보았듯이 cocos2d의 시간 단위는 1초입니다.
변수 타입은 float 입니다. 그러니까 1.0f는 1초 0.5f는 0.5초 입니다. 이를
60으로 나누었으니 초당 60번의 화면 갱신이 일어나게끔 한다는것입니다. 일반적인
에니메이션은 24프레임이고 디즈니가 36프레임인가로 알고 있는데 상당히 부드럽자나요 .
그것보다 더 부드럽게 움직이라고 하는겁니다. 실제 화면구동에서는 이보다 속도가 안나올수도있습니다 많이 내려갈때는 30프레임 까지 내려가더군요 . 그래도 상당히 아니 매우 빠른속도니까 화면의 대상은 부드럽게 움직입니다.
CCScene scene = CCScene.node();
드디어 이제 시작인가요 .ㅎ ㅎ 여기서 강좌끝내버리면 낚시겟죠 ㅎㅎ.
CCScene 인스턴스를 생성하는 방법입니다. 참쉽죠
CCScene.node();이렇게 클래스명적고 .node()라고 하면 되니까 ㅎ
이렇게 선언하면됩니다.
자기 이름도 영화관이면서 안에 1개짜리 영화관을 때려넣고 앞에 멀티플렉스라고 명명한
건물. 여기서도 동일하게 적용됩니다. CCLayer클래스인데 안에 멤버변수(ArryList)로 다른 CCLayer를 담을수 있는 이름도 거창한. CCMultiplexLayer 입니다.
그러고 보니까 안쪽에 레이어를 쳐담고 있죠 new로 생성해서요 .
" 어라 cocos2d에 Layer1()이란 클래스가 있었나 ?" 라는 궁긍증일어나겟죠
결론적으로 없습니다, 걍 다음 소스에서 도 나오겟지만. 예제 만든사람이 CCLaer클래스를 상속하여 만든것뿐입니다. 오해가 없으시길.
scene.addChild(layer, 0);
CCDirector.sharedDirector().runWithScene(scene);
어라 이제까지 우리가 만들어 놓은 걸 담고 있네요 . 이는 기본강좌 에도 나와 있지만. ^^ (거의 중간 광고 수준이네요 ㅋㅋㅋ 한번쯤 읽어 보라는 압력. ㄷㄷ )
CCDirector는 CCScene를 담을수 있고
CCSecen은 CCLayer를 담을수 있고
CCLayer는 CCSplite를 담을수 있습니다.
담는 방법은 위에 나와 있습니다.
scene.addChild(layer, 0);==>CCSecen은 CCLayer를 담을수 있고
CCDirector.sharedDirector().runWithScene(scene);==>CCDirector는 CCScene를 담을수 있고
입니다. add든 runWithScene든 결과는 담는 겁니다.
자이제 화면이 ON 되었습니다.
그럼 이제 화면이 어떻게 움직일까요? 우리가 보았듯이 이름만 거창한 멀플렉스레이어가 실제 우리 눈에 보이는 부분입니다.
그럼 이놈을 분석해보면 화면이 어떻게 돌아 가는지 알수 있겟죠 ㅎㅎ;
일단 중간 정리 한번하고 가죠 . OnCreate()에서 한일은
1.전체화면 만들기
2.성능좋은 이미지뷰 생성하기
OnStart()에서 한일은.
1. 감독을 만들어 성능 좋은이미지 뷰랑 연결해주기
2. 가로모드 세로모드 결정
3. FPS 정해주기
4. CCScene와 CCLayer를 생성
5. 그릇 순서에 따라 담기 .
자그럼 시간이 포함된 기본액션 클래스들을 보았으니 시간 변수가 표함 기본액션들을 살펴 보겟습니다.시간이 포함안되어있으니까 시간 관련 파라미터는 없겟고 기본액션이니까 하나의 속성을 변화 시키는거니까 음.. 그럼 파라미터는 한 개 겟네 ? 라고 생각할수 있습니다.과련 맞을까요?
They can execute actions (runAction, stopAction, etc)
액션을 실행시킬수 있다 . 이제야 글의 제목과 관련있는 부분이 나오네요. action과 node와의 관계 ㅎㅎㅎ 요기서 지금까지 알수있는 내용만으로 정리 한번 하자면 액션은 Node의 속성을 변화 시키고 그 시작은 Node가 한다. 이말은 액션변수를 파라미터로 하는 호출함수가 있다 또는 Node에 액션 변수가 있고 자신이 가지고 있는 액션을 시작하는 함수가 있다.
그럼 CCAction이 CCNode의 속성을변경한다는건데 그 속성이 먼지도 모르는데 어떻게 CCAction을 파악할수 있다는건지 . ㅎㅎ
그럼 이제 속성에 대해서 알아봅시다. 몇가지 있느냐 하면
- position - scale (x, y) - skew (x by degrees, y by degrees) - rotation (in degrees, clockwise) - CCCamera (an interface to gluLookAt ) - CCGridBase (to do mesh transformations) - anchor point - size - visible - z-order - openGL z position
이렇게 11가지 있습니다.
위치 ,크기,기울기,회전각,카메라,메쉬를 위한그리드베이스 ,축 위치,크기,보여줄것인가 말것인가,레이어 순서 ,그리고 좀 이해안되는 z-position 이거는3D 개념인데 왜있는거지 . ㄷㄷㄷ
위에궁금한 사항들을 제외한 나머지 속성들은 CCNode 클래스 정의를다시 생각해보면 충분히 이해가 가리라 생각합니다. 화면에 그려지는것과 그것을 포함하는것 화면에 어디에 그려그려질 것인가?원래 크기를 줄일것인가 말것인가?이미지 좀기울이면안되나? 시계방향으로 좀회전시킬가? 회전시킬때상단 맨위위를 기준으로 할까 아니면 중앙을 기분으로 할까? 이런게 변화된 이미지를 보여줘야하나 ? 잠시 빼버릴까? 최상위레이어를 배경으로 쓰면 어떨까? 등등
Some CCNode nodes provide extra functionality for them or their children.
Subclassing a CCNode usually means (one/all) of: - overriding init to initialize resources and
schedulecallbacks - create callbacks to handle the advancement of time - overriding draw to render the node
이런거라던지.
Order in transformations with grid disabled -# The node will be translated (position) -# The node will be rotated (rotation) -# The node will be skewed (skew) -# The node will be scaled (scale) -# The node will be moved according to the camera values (camera)
Order in transformations with grid enabled -# The node will be translated (position) -# The node will be rotated (rotation) -# The node will be skewed (skew) -# The node will be scaled (scale) -# The grid will capture the screen -# The node will be moved according to the camera values (camera) -# The grid will render the captured screen
요런거 실제 프로그래밍 하면 이런게 더 와닿을지도 모릅니다. 다만이건 음..머랄까 일조의 tip이라고 생각합니다 물론 여기에대해서도 다룰겁니다. 그러나 아직은 개념 잡기 위한거니 다음 예제를 직접 보면서 할수 있을 때 정리해보도록하겟습니다.
휴
~~ CCAction을 알아볼라고했는데 어떻게 CCNode에 대해서 알아보았네요 .근데 무엇에 대한 action인지 에 대해서 모른다면 충분히 사용할수 없다라는 생각에 이렇게 장문의 글이 되고 말았네요.잊지말것은 화면에 그려지는것과 그것을포함하는 것은 CCNode 를 상속한다. 입니다.
1.sprite 스프라이트 별거 없습니다 그냥 이미지입니다. 단지 용어가 익숙하지 않을뿐. 다시 반복하자면 에스. 피. 알. 아이. 티. 이s p r i t e 스프라이트.2D 이미지 간단히 사진이라 그림,글자 그림 이라고 생각하시면 됩니다. 이는 물론 이동 회전 크기 Action(에니메이션)을 적용가능한니다. 한마디로 사진을 밀었다 땡겻다 돌렸다 뒤집었다 할수 있다는 말이죠
2.Layer 두번째로 할 것은 레이어 입니다. 레이어는간단히 종이 한장입니다. 물론 이 종이는 투명한 비닐 종이 일수도 있도 시커먼 먹지일수 도 있으며 새하얀 종이일수도 있습니다. 여기 이 종이 위에 사진을 붙일수 있겟죠 즉 위에 서 설명한스. 프 .라. 이. 트 를 레이어 위에 배치할수 있다는 거죠즉 레이어는 스프라이트를 포함한다라고 정의해보겟습니다. 공식페이지서 설명한대로 게임 작업은 여기서 대부분에 시간을 보내게 됩니다.
3.Scene 그리고 3번째로 장면이라고 해석해놓은 scene !! Scene는 바로 레이어를 담는 그릇입니다. 하나의 scene에 하나의 레이어도 올수 있고 다수의 레이어가 올라 갈수도 있습니다.
지금까지의 배용을 정리하면 스프라이트는 레이어에 포함되고 레이어는 Scene에 포함된다 라고 할 수 있습니다.
4.Director 자 마지막으로 디렉터는 간단하게 Scene를관리합니다. 이scene 뒤에는 다음 씬이 나오고 다음 씬나오면 그다음씬 나오고 어라 생각해보나까 역순으로 돌리는 게 낮겟네 해서 씬순서 바꾸고… 한마디로감독이죠 그리고 영화에서 감독은 한명입니다. cocos2D에서도 디렉터는 하나분입니다. 프로그램 디자인에서 말하는 싱글톤.~~~
자 여기까지가 기본 개념입니다. 이제 세부 적으로들어가 봅시다. 물론 다음 강좌에서ㅎㅎ 아직 내용이 좀 허접합니다. ㅎ