COCOS2D-X 솔루션에서 프로젝트를 만들면 빌드하기 편하지만, 신규 솔루션에서 하려면 어떻게 해야 할까?

우선 COCOS2D-X WIN32 프로젝트를 생성하자.
프로젝트명은 Game으로 생성해서 D:\에 생성했다고 하자.

1. 소스 파일
cocos2d-1.0.1-x-0.11.0에 있는 프로젝트 중에서 쓴 프로젝트들을 폴더채로 D:Game에 복사한다.

2. LIB 파일
쓴 Lib 파일들을 D:\Game\Game에 복사한다.

3. DLL 파일
쓴 DLL 파일들을 D:\Game\Debug.win32에 복사한다.


Reference
[1]  http://www.iphonedevsdk.com/forum/iphone-sdk-tutorials/78980-cocos2d-x-win32-install-deploy-tutorial.html 
[2]   http://junghong456.tistory.com/entry/Cocos2D-XInstall-Deploy-tutorial
신고

Leave a Comment

COCOS2D-X 설치!! 어렵지잉~ 않아요오오~~

* COCOS2D-X 설치 및 테스트
1. VS 2008 or VS 2010 설치
2. COCOS2D-X 다운로드
3. 압축해제 (압축 푸는 곳이 설치장소)
4. install-templates-msvc 실행
5. build-win32.bat 실행
6. cocos2d-win32.vc2008 or  cocos2d-win32.vc2010 맞춰서 실행
7. HelloWorld 프로젝트를 시작 프로젝트로 설정
8. 빌드 및 실행


COCOS2D-X Download (  http://www.cocos2d-x.org/projects/cocos2d-x/wiki/Download  ) 




테스트 Hello World





설치가 끝나면 다음 COCOS2D-X UserGuide창이 뜬다. 도움이 되는 글이니 참고하자.
( http://www.cocos2d-x.org/projects/cocos2d-x/wiki/Cocos2d-x_Application_Wizard_for_Visual_Studio_User_Guide )



Reference
[1] 인스톨 도움 받은 블로그 1 ( http://www.cocos2d-x.org/projects/cocos2d-x/wiki/Download )
[2] 인스톨 도움 받은 블로그 2 ( http://junghong456.tistory.com/entry/Cocos2D-XInstall-Deploy-tutorial ) 
[3] COCOS2D-X를 이용하여 해상도 고정시키기 ( http://junghong456.tistory.com/entry/Cocos2D-XInstall-Deploy-tutorial )
신고

Comments

  1. 손님 2012.07.18 15:16 신고 Permalink Modify/Delete Reply

    개발은 어떤가요??? 할만하신가요? cocos2d-x ㅠㅠ 지금 선택할까 고민중이라....

  2. 손님2 2012.11.05 15:01 신고 Permalink Modify/Delete Reply

    build-win32 빌드 중에 the solution file has two projects named 이런식으로 에러가 나는데 혹시 아시는거 있으세요?
    참고로 제가 vc 2012를 사용합니다. 빌드하는 중에 자주 라이브러리를 사용할수 없다고 나오는데,, 따로 라이브러리를 로드 해줘야 하나요?

  3. 손님3 2013.04.01 12:25 신고 Permalink Modify/Delete Reply

    왜 build - win32에서 오류가뜨죠 ㅠㅠ
    OS는 window 8입니다 ㅠㅠ

  4. 손님3 2013.04.01 12:26 신고 Permalink Modify/Delete Reply

    왜 build - win32에서 오류가뜨죠 ㅠㅠ
    OS는 window 8입니다 ㅠㅠ

Leave a Comment

음, 안드로이드에서 COCOS2D를 쓰면 쓸수록 삽질을 많이 한다.
특히나 아이폰에 맞춰 만들어진 것을 안드로이드용으로 포팅하면서 많은 문제가 아직 남아있다는 걸 느낀다.

지난 게임 관련 포스팅을 할 때 COCOS2D 안드로이드 엔진에 대한 문제를 몇 가지 적어놓았다.
이번에는 드래그 앤 드랍을 안드로이드용으로 하는 소스를 써보려 한다.

아래 소스를 참조하자.
[1]을 보고 만든 것이다. Objective C를 자바 형태로 센스있게 바꾸면서 작업했다.
Objective C에 있는 메소드나 클래스명이 거의 그대로 자바 엔진에 있었다. 메소드명이나 파라미터 형태가 조금 다른게 몇 개 있었지만 나름 잘 짜여져 있었다. 

다만 몇 가지 문제가 있었는데.
문제 1. 아이폰에서는 ccTouchesMoved(드래그중 호출되는 메소드) 메소드에서 UITouch라는 클래스의 객체를 받고 이전 터치값을 받아올 수 있지만 안드로이드에서는 이게 빠져있다. 그래서 이전 값을 갖는 부분과 계산해주는 방법을 추가해주었다.

문제 2. Sprite 드래그 앤 드랍을 잘 되었다. 그러나 배경 드래그를 할 때는 좌표값 계산에 문제가 생긴다. 화면위치와 현재 드래그 위치를 계산해주는 convertTouchToNodeSpace 메소드에 문제가 있는 것으로 생각되어서 직접 이 메소드를 구현해 보았지만 웃기게도 똑같은 결과가 나온다. 이 문제는 좌표 계산한 결과값이 오차가 크게 나오면서 배경을 드래그 할 때 배경 위치값이 왔다갔다하면서 화면이 치직거리는듯한 모양을 보여줘버린다.
 그래서 이 것을 해결하기 위해서 배경을 드래그 할 떄는 MotionEvent의 값만을 사용해서 계산했다.

힘들게 만든 후에 너무 짜증나서 포스팅하고 싶은 마음도 없었지만, 나 같이 안드로이드이서 COCOS2D 사용하느랴고 고생하는 사람들을 배려하기 위해 포스팅을 한다. 안드로이드 COCOS2D 개발 문서는 정말 너무 없으니까 말이다. 

import java.util.ArrayList;

import org.cocos2d.actions.base.CCRepeatForever;
import org.cocos2d.actions.interval.CCRotateBy;
import org.cocos2d.actions.interval.CCRotateTo;
import org.cocos2d.actions.interval.CCSequence;
import org.cocos2d.events.CCTouchDispatcher;
import org.cocos2d.layers.CCColorLayer;
import org.cocos2d.nodes.CCDirector;
import org.cocos2d.nodes.CCSprite;
import org.cocos2d.types.CGPoint;
import org.cocos2d.types.CGRect;
import org.cocos2d.types.CGSize;
import org.cocos2d.types.ccColor4B;

import android.view.MotionEvent;

public class GameLayer extends CCColorLayer {
private CCSprite background;
private CCSprite selSprite;
private ArrayList<CCSprite> movableSprites;
private CGPoint oldTouchLocation = CGPoint.zero();
private CGSize winSize;
GameLayer(ccColor4B color) {
super(color);

// get View Size
winSize = CCDirector.sharedDirector().winSize();

// set Background
background = CCSprite.sprite("bg_game.jpg");
background.setAnchorPoint(CGPoint.make(0.0F, 0));
background.setPosition(0, 0);
this.addChild(background, 0);

// init
movableSprites = new ArrayList<CCSprite>();
//
for(int i=1; i < 5; i++) {
CCSprite sprite = CCSprite.sprite("icon.png");
sprite.setAnchorPoint(CGPoint.zero());
sprite.setPosition(i * 100, winSize.height/2);
this.addChild(sprite, 1);
movableSprites.add(sprite);
}

this.setIsTouchEnabled(true);

CCTouchDispatcher.sharedDispatcher().addTargetedDelegate(this, 0, true);
}

public void selectSpriteForTouch(CGPoint touchLocation) {
CCSprite newSprite = null;
for (CCSprite sprite : movableSprites) {
if (CGRect.containsPoint(sprite.getBoundingBox(), touchLocation)) {            
newSprite = sprite;
break;
}        
}

if (newSprite != selSprite) {
if(selSprite != null) {
selSprite.stopAllActions();
selSprite.runAction(CCRotateTo.action(0.1F, 0));
}

if(newSprite != null) {
CCRotateBy rotLeft = CCRotateBy.action(0.1F, -4.0F);
CCRotateBy rotCenter = CCRotateBy.action(0.1F, 0.0F);
CCRotateBy rotRight = CCRotateBy.action(0.1F, 4.0F);
CCSequence rotSeq = CCSequence.actions(rotLeft, rotCenter, rotRight, rotCenter);
newSprite.runAction(CCRepeatForever.action(rotSeq));
}
selSprite = newSprite;
}
}

public CGPoint boundLayerPos(CGPoint newPos) {
CGSize winSize = CCDirector.sharedDirector().winSize();
CGPoint retval = newPos;
retval.x = Math.min(retval.x, 0);
retval.x = Math.max(retval.x, - background.getContentSize().width+winSize.width);
retval.y = this.position_.y;
return retval;

}

public void panForTranslation(CGPoint translation) {
if (selSprite != null) {
CGPoint newPos = CGPoint.ccpAdd(selSprite.getPosition(), translation);
selSprite.setPosition(newPos);
} else {
CGPoint newPos = CGPoint.ccpAdd(this.position_, translation);
this.setPosition(boundLayerPos(newPos));      
}  
}

@Override
public boolean ccTouchesMoved(MotionEvent event) {
CGPoint touchLocation, translation;
if(selSprite == null) {
// background
touchLocation = CGPoint.ccp(event.getX(), event.getY());
} else {
// sprite
touchLocation = convertTouchToNodeSpace(event);
}
translation = CGPoint.ccpSub(touchLocation, oldTouchLocation);
panForTranslation(translation);
oldTouchLocation = touchLocation;
return true;
}
@Override
public boolean ccTouchesBegan(MotionEvent event) {
CGPoint touchLocation = this.convertTouchToNodeSpace(event);
selectSpriteForTouch(touchLocation);
if(selSprite == null) {
oldTouchLocation.set(event.getX(), event.getY());
} else {
oldTouchLocation.set(selSprite.getPosition().x, selSprite.getPosition().y);
}
return true;
}
}

GameLayer.java



추가로 자체적으로 만들어본 convertMyTouchToNodeSpace메소드. ( convertTouchToNodeSpace와 결과가 같기에 별로 쓸 필요는 없다;)

private CGPoint convertMyTouchToNodeSpace(MotionEvent event) {
CGPoint eventPoint = CGPoint.ccp(event.getX(), winSize.height - event.getY());
CGPoint curPoint = getPosition();
curPoint.set(-curPoint.x, curPoint.y);
return CGPoint.ccpAdd(curPoint, eventPoint);
}




Reference
[1] iPhone COCOS2D 드래그 앤 드랍 (  http://www.raywenderlich.com/2343/how-to-drag-and-drop-sprites-with-cocos2d  ) 
신고

Comments

  1. HeyLee 2012.04.10 18:14 신고 Permalink Modify/Delete Reply

    감사합니다. 생각보다 큰 도움이 되었습니다.
    CGPoint좌표로 바꾸고 난 다음에 해야된다는걸 이글보고 꺠달았네요...=_=;;;

  2. 개발노비 2012.07.06 19:29 신고 Permalink Modify/Delete Reply

    좋은 자료네요... 감사합니다...^^

Leave a Comment

처음 안드로이드에서 게임을 개발해보고자 마음 먹었던 것은 2011년도 10월쯤이었던 것 같다.
처음 게임을 만들었던 것은 초등학교 시절 RPG쭈꾸르, 95, 2000로 만들었지만 정작 프로그래머가 된 이후에 스스로 제대로 된 게임을 만들어 본 적은 없었다.

 나는 프로그래머지만, 게임 프로그래머가 아니다. 프레임워크나 애플리케이션단을 주로 개발하기 때문에 게임을 어떻게 개발하는지도 모르고 게임업계에 종사하고 있지도 않다. 그러나 게임을 만드는 것은 프로그래머의 로망이 아닌가 싶다.

 게임을 만들기로 마음 먹은 이후 우선은 안드로이드로 만들기로 했다.
 시작하는데는 아이폰이 더 좋을것 같지만, 안드로이드를 선택한 이유는 맥북이 없다는 점과 내가 Java나 안드로이드 개발 스킬이 뛰어나고(?) GIS 안드로이드용 엔진을 개발했으니 괜찮겠다라는 생각 때문이었다. 지금 생각은 맥북을 당장 사고 싶을 뿐이지만 사지 못하는 이유는 지금까지 공부한 것들이 아깝고 또한 안드로이드 게임 앱으로 조금이라도 광고 수익을 낸 이후에 사겠다는 목표를 세웠기 때문이다.

 처음에는 게임을 만드는 법을 배워야했다. 웹에서 다양한 강좌를 보고 공부를 했다.
지금까지 내가 공부해온 길은 다음과 같다.

1. VIew, SurfaceView
2. GLSurfaceView
3. Android Game Engine
4. COCOS2D



1. VIew, SurfaceView 
처음에는 View에 그림을 그리는 것부터 시작했다. GIS 안드로이드 엔진을 View에 그리는 형식으로 했기 때문에 쉬웠다. 스레드를 돌려서 이미지를 계속 그려주는게 아닌 이벤트가 발생했을 때만 그려주면 되기 때문이다.

그러나 게임에서는 당연히 적합하지 않다. 끊임없이 그려줘야 하기 때문에 SurfaceView를 써야 한다는 걸 알았다. 웹에서나 몇몇 책에서는 이 방식을 통해서 게임을 개발하는 방법을 소개한다. 그러나 나는 이 방식이 마음에 들지 않았다. 무엇보다 메모리를 많이 잡아먹고, 속도도 느리며 이렇게 개발해서는 제대로 된 게임을 개발하기는 힘들어 보였다. 

2. GLSurfaceView 
 안드로이드 커뮤니티에서 관련 게임 강좌를 보던 중에 제대로 된 게임 소스를 먼저 분석해야겠다고 생각했다.
문제는 괜찮은 게임 소스를 찾기가 힘들었는데 웹에서 찾던 중에 girlaem님의 블로그에서 아이폰 및 안드로이드용 게임을 만든 것을 소스를 공개한 것을 찾았다. (지금 가보니 블로그를 닫으셨는지 없어졌다.)
 소스를 분석해보니 GLSurfaceView를 사용하는 완전 새로운 형태인 것이다. OPENGL ES 사용경험이 없던 나는 그때부터 신세계였다. 책과 웹에서 OPENGL ES 관련 강좌를 찾아서 보기 시작했다. 이미지 하나를 텍스쳐로 출력하는데까지 꾀 오랜 시간이 걸렸다. 마지막에 이미지가 에뮬레이터에서는 출력이 되는데 실기에는 출력이 되지 않아서 고생했는데 알고보니 OPENGL ES에서 쓰는 이미지의 사이즈는 2의 배수(2, 4, 8, 16, 32, 64, 128 ...)가 되어야 하는 것이었다.

3. Android Game Engine 
 OPENGL ES를 기껏 공부해놓고는, 게임 엔진을 찾아서 조사를 시작했다.
사실 처음부터 엔진을 사용해서 쓸까하다 포기한 이유는 공부 차원에서 엔진에서 하는 일을 직접 만들어서 사용하고 싶은 생각이 있었기 때문이다. 물론 괜찮은 생각이었고 잘 진행되고 있었지만 공부를 하면서 하다보니 개발속도가 너무 느렸다. 게다가 퇴근 후 틈틈히 하다보니 시간도 절대적으로 부족했다. 이대로 가면 언제 완성될지도 모르겠고 게임 퀄리티도 높을지 미지수였다.
 그래. 결론은 엔진이다. 라는 생각이었다. 엔진 사용법을 공부해야 한다는 것이 단점이지만 어쩔 수 없다.
처음 눈여견 본 것은 rocken이라는 엔진인데 이것이 없어지고 AndEngine이라는 것이 대체되었다. Android에서 최적화 되어 있다는 점이 매우 맘에 들어서 AndEngine을 사용하려고 했다.
 그러나 타 엔진들도 마찬가지지만 가장 큰 문제에 직면했다. 어떻게 사용하는지를 모르겠다는 것이다. 아니 대체 왜 게임엔진들은 문서가 이렇게 없다는 말이냐, 아니면 예제 게임 소스라도 구하기 쉬워야 할 것 아니냐는 말이다

* AndEngine의 문제
 - 안드로이드에만 최적화 된것이 장점이자 단점
 - 구조가 OOP답지 않다. 맘에 안 든다.
 - 문서 및 튜토리얼이 너무 없다. 내가 못 찾는지 몰라도 영문 블로그나 포럼을 찾는데도 너무 힘들다.
    (위에 말한대로 다른 엔진들도 거의 마찬가지..)

여러가지 엔진들을 보다보니 각각의 엔진들의 장단점이 있기 마련인데 제일 좋은 엔진은 언리얼 엔진인 것 같다. 멀티 플랫폼이 가능하고 상용 엔진중에서는 제일 좋지 않은가 싶다. 아이폰이나 안드로이드 부분은 가격도 저렴하다. 내가 살 수 있을 정도는 아니고, 업데이트 할 때마다 추가 구매해야 하지만 좋은 엔진임에는 틀림이 없다.

멀티 플랫폼 얘기가 나와서 말인데, 전문 게임 업계 종사자도 프로그래머도 아닌 나로서는 너무나 힘든 부분이다. 각각의 플랫폼에 맞춰서 개발을 각각 한다는 것은 개발자로서는 정말 최악이다. 각각의 환경에 최적화시키는게 좋을지는 몰라도 유지보수나 일관성 면에서는 떨어지기 때문이다. 

커뮤니티에서 보다보니, 보통은 아이폰에 맞춰서 개발을 한다 한다.  안드로이드의 백버튼이나 메뉴버튼은 무시하고 말이다. 그리고 개발은 C++로 개발하고 아이폰이나 안드로이드에 맞춰 포팅한다고 한다. 
 근래 나한테는 제일 매력적으로 보이는 엔진이 COCOS2D인데 VisualStudio환경에서 C++로 개발한 후에 아이폰과 안드로이드로 포팅한다고 한다. 정말 매력적이지 아니한가 >.<

 남은 하나의 과제는 아이폰이 기기가 몇 안되는 반면에, 안드로이드는 기기별 화면 크기가 다양하다. 이를 어떻게 맞추는지가 아직 미지수다. 화면 크기별로 따로 개발하는 방법도 있지만 이는 역시 좋은 방법이 아닌듯하다. 혹시 이 방법에 대해서 잘 아는 게임전문가분이시라면 답변 좀 달아주시기 바랍니다.

4. COCOS2D 
 나의 선택은 COCOS2D였다. COCOS2D X가 많이 끌렸지만 우선은 COCOS2D로 개발하기로 했다.

* 장점
 - iPhone과 관련하여 개발 문서가 많다.
 - 구조가 잘 되어 있다.
 - 무료 엔진
 - 공부하고 나서 아이폰 개발이나 COCOS2D-X로 개발해도 좋을것 같다 

* 단점
 - COCOS2D엔진 자체가 아이폰에 최적화되어 개발된 것을 안드로이드용으로 만든 것
 - 아직 버그가 많다. (내가 느끼기엔)
 - 안드로이드용 문서나 자료가 별로 없다

우선 당장은 어제 COCOS2D로 개발하다가 짜증이 폭발했다. 콜백이 안되고 OPENGL ES가 이미지를 제대로 출력하지 않는 문제가 계속 발생했다. 내가 뭔가 잘못한지 알고 적은 안드로이드 문서나 아이폰용 소스를 많이 찾아보았다.

그런데 결과는 엔진 문제였다. 아직 문제가 많은 것 같다. 이 문제는 최신 버전의 COCOS2D로 바꾸고 나니 해결되었다. 다만 엔진 버전이 바뀌면서 클래스명이나 메소드 규격에 변화가 있으니 조심해야 한다.
 대표적인 것으로서 구버전은 MenuItem의 콜백이 public void 콜백메소드명()으로 되지만, 최신 버전의 경우에는
public void 콜백메소드명(Object o)로 되어 있다. 이게 틀리면 해당 메소드명을 찾을 수 없다는 예외가 나버린다.


Reference
[1] 언리얼 코리아 ( http://www.udk.com/kr/index.html )










 



 
신고

Comments

  1. 디치리 2012.01.31 22:42 신고 Permalink Modify/Delete Reply

    안녕하세요. ^^ 게임업계에 종사하고 있습니다. 안드로이드 기기들의 다양한 해상도에 대한 대응은 결론부터 말씀드리면 이미지리소스의 리사이징밖에 답이 없습니다. 보통 800*480 사이즈에 최적화를 시키고 나머지는 조금 늘리거나 남는 공간을 버려버리거나 하는 방법을 사용합니다. 부족한 답변이지만 도움되셨으면 좋겠습니다.

    • 아틴 2012.02.02 10:10 신고 Permalink Modify/Delete

      안녕하세요 디치리님.
      너무 감사드립니다.

      이미지 리사이징이나 해상도별 개발방법에 따라서 고민은 해보았지만 어떻게 해야할지에 대해서 잘 몰랐거든요.

      좋은 답변 감사드립니다. ^^

  2. 아즈라엘 2012.01.31 23:52 신고 Permalink Modify/Delete Reply

    반갑습니다. cocos2dx를 사용하게 될 경우 안드로이드에서는 jni 방식으로 구현하게 됩니다.
    게다가 소스 호환성이 높아져서 포팅에 유리한 잇점이 많이 생기게 되고요..

    현재 cocos2d-android 는 jar 형태로 java단에서 작업하는데 이보다 low 레벨이지만
    cocos2dx로 c++로 개발하시는게 앞으로 공부하시는데 더욱 좋을듯 합니다. ^^

    • 아틴 2012.02.02 10:14 신고 Permalink Modify/Delete

      안녕하세요 아즈라엘님. 답변 감사드립니다.
      그렇군요. ㅎㅎ 아 역시 게임개발은 C++이군여.

      이번에는 한번 게임개발을 완성해보고, COCOS2D-X로 넘어가봐야겠습니다. 조언 감사합니다.

  3. 케이_ 2012.11.13 15:06 신고 Permalink Modify/Delete Reply

    댓글을 안 달 수가 없네요.
    다 읽고 창을 닫을 수가 없어서 댓글 달고 갑니다.
    잘 읽었습니다.
    별 내용 없는 글인데도 근래 보기 드문 지식이 담겨있군요.
    진짜 개발자가 맞으시네요.
    요즘 이런 내용을 적는 개발자가 점점 줄어들고 있네요.
    한 일주일 날려보낼 시간을 한 페이지 글로 다 배워갑니다.
    감사합니다.

    • 아틴 2012.11.13 16:26 신고 Permalink Modify/Delete

      감사합니다. 요즘 다른 일이 바빠서 개발을 이어서 하지 못하고 있는데 댓글을 보니 힘이 나네요. 시간 나서 더 개발해보고 좋은 포스팅하도록 노력하겠습니다. ^^

Leave a Comment

요즘 COCOS2D를 공부하고 있다.
COCOS2D 자체가 아이폰용에 맞춰 개발된 것을 안드로이드용으로 추가로 개발된 것이기에 안드로이드용 관련 자료가 별로 없다. 그래서 나도 아이폰용 강좌나 자료를 보고 공부했다.

기본적인 개념을 알고나면 다른 엔진에 비해 쉬운 것 같다.
그래서 AndEngine을 쓰려고 하다가 포기하고 자체 엔진을 개발하고 있던 나는 일단 COCOS2D를 이용해서 개발하기로 결심했다.

참고로 여기 좋은 포스팅이 많이 있습니다.
http://self-toeic.tistory.com/

아래는 FPS를 재는 기본 소스이다.
주석에서 나오는 것처럼 FPS를 재려면 asset디렉토리에 fps_images.png가 있어야 한다. 물론 엔진 jar파일도 당연히 포함시켜야 하고 말이다.


package com.tistory.atin;

import org.cocos2d.events.CCTouchDispatcher;
import org.cocos2d.layers.CCLayer;
import org.cocos2d.layers.CCScene;
import org.cocos2d.nodes.CCDirector;
import org.cocos2d.nodes.CCLabel;
import org.cocos2d.opengl.CCGLSurfaceView;
import org.cocos2d.types.CGPoint;

import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.Window;
import android.view.WindowManager;

public class TestActivity extends Activity {
private CCGLSurfaceView mGLSurfaceView;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        // set the window status, no tile, full screen and don't sleep
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        
        mGLSurfaceView = new CCGLSurfaceView(this);
        
        setContentView(mGLSurfaceView);
        
        // attach the OpenGL view to a window
        CCDirector.sharedDirector().attachInView(mGLSurfaceView);

        // no effect here because device orientation is controlled by manifest
        CCDirector.sharedDirector().setDeviceOrientation(CCDirector.kCCDeviceOrientationPortrait);
        
        // show FPS
        // set false to disable FPS display, but don't delete fps_images.png!!
        CCDirector.sharedDirector().setDisplayFPS(true);

        // frames per second
        CCDirector.sharedDirector().setAnimationInterval(1.0f / 60);
        
        CCScene scene = TemplateLayer.scene();

        // Make the Scene active
        CCDirector.sharedDirector().runWithScene(scene);
    }
    
    @Override
    public void onStart() {
        super.onStart();        
    }

    @Override
    public void onPause() {
        super.onPause();

        CCDirector.sharedDirector().pause();
    }

    @Override
    public void onResume() {
        super.onResume();

        CCDirector.sharedDirector().resume();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        CCDirector.sharedDirector().end();
    }
    
    
    static class TemplateLayer extends CCLayer {
        CCLabel lbl;
        
    public static CCScene scene() {
    CCScene scene = CCScene.node();
    CCLayer layer = new TemplateLayer();
   
    scene.addChild(layer);
   
    return scene;
    }

        protected TemplateLayer() {

        this.setIsTouchEnabled(true);

            lbl = CCLabel.makeLabel("Hello World!", "DroidSans", 24);

            addChild(lbl, 0);
            lbl.setPosition(CGPoint.ccp(160, 240));

        }

        @Override
        public boolean ccTouchesBegan(MotionEvent event) {
            CGPoint convertedLocation = CCDirector.sharedDirector()
            .convertToGL(CGPoint.make(event.getX(), event.getY()));

            String title = String.format("touch at point(%.2f, %.2f)",
            convertedLocation.x, convertedLocation.y);

            if (lbl != null) {
            lbl.setString(title);
            }
            
            return CCTouchDispatcher.kEventHandled;
        }

    }









신고

Leave a Comment

OnGestureListener를 사용해보려고 구현을 하였는데 로그를 찍어보니 호출이 되지를 않았다.
어떤 문제인지 찾다가 곧 이유를 알게 되었다. 이 인터페이스는 메소드를 구현된다고 호출이 되지 않는다.
이 인터페이스를 사용할 경우 같이 사용해야 하는 것이  GestureDetector라는 것이다.
이  GestureDetector를 멤버 함수로 갖고 있으면서, onTouchEvent의 발생시에 GestureDetector를 통해 리턴을 해줘야 OnGestureListener의 메소드들이 올바로 호출이 된다.

아래는 참고 소스이다.



import android.app.Activity;
import android.os.Bundle;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.GestureDetector.OnGestureListener;

public class GestureActivity extends Activity implements OnGestureListener {
private GestureDetector mGesDetector;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mGesDetector = new GestureDetector(this);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
return mGesDetector.onTouchEvent(event);
}
@Override
public boolean onDown(MotionEvent e) {
// TODO Auto-generated method stub
return false;
}

@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
// TODO Auto-generated method stub
return false;
}

@Override
public void onLongPress(MotionEvent e) {
// TODO Auto-generated method stub

}

@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
// TODO Auto-generated method stub
return false;
}

@Override
public void onShowPress(MotionEvent e) {
// TODO Auto-generated method stub

}

@Override
public boolean onSingleTapUp(MotionEvent e) {
// TODO Auto-generated method stub
return false;
}

}
[GesutreActivity.java]

 
신고

Leave a Comment

이전 포스팅에서는 기본적인 View와 SurfaceView를 사용하는 기본 구조에 대해 포스팅했다.
그러나 OPENGL ES를 사용한다면 GLSurfaceView를 사용해야 하며 이 구조는 이전과는 또 상이하다.

import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.view.Window;

public class Main extends Activity {

private GLSurfaceView mView = null;
private MainRenderer mRenderer = null;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

// No Title
requestWindowFeature(Window.FEATURE_NO_TITLE);

mRenderer = new MainRenderer(this);
mView = new GLSurfaceView(this);

setContentView(mView);
}

@Override
protected void onResume() {
super.onResume();
mView.onResume();
}
@Override
protected void onPause() {
super.onPause();
mView.onPause();
}
}
[Main.java]


import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.content.Context;
import android.opengl.GLSurfaceView.Renderer;

public class MainRenderer implements Renderer {
private Context mContext;
MainRenderer(Context context) {
mContext = context;
}
@Override
public void onDrawFrame(GL10 gl) {
}

@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
}

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
}
}
[MainRenderer.java]


Reference
[1]  http://blog.naver.com/PostView.nhn?blogId=jadefan&logNo=70088416075 



 
신고

Leave a Comment

1. View
View는 onDraw를 통해 그림을 그려주고 invalidate를 호출하면 다시 onDraw()가 호출된다.
하지만, 안드로이드에서는 invalidate()를 호출하면 에러가 난다. Handler를 사용하거나 postInvalidate()를 호출해야 한다.

import android.content.Context;
import android.graphics.Canvas;
import android.view.View;

public class MyView extends View{
public MyView(Context context) {
super(context);
// invalidate
postInvalidate();
}
@Override
protected void onDraw(Canvas canvas) {
// draw
}
}



2. SurfaceView
SurfaceView는 기본적으로 더블버퍼링을 사용하며, 3D도 지원되기 때문에 게임에서 주로 사용된다.

import android.content.Context;
import android.graphics.Canvas;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;

public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback{
private SurfaceHolder mHolder;
private DrawThread mThread;

public MySurfaceView(Context context) {
super(context);

mHolder = getHolder();
mHolder.addCallback(this);
mThread = new DrawThread(mHolder);
}
@Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {

}

@Override
public void surfaceCreated(SurfaceHolder holder) {
mThread.start();
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
while(retry){
mThread.interrupt();
retry = false;
}
}
// call surfaceDestroyed
public void close() {
setVisibility(View.GONE);
}

class DrawThread extends Thread{
public DrawThread(SurfaceHolder holder) {
mHolder = holder;
}

public void run(){
Canvas canvas = null;
while(!isInterrupted()) {
try{
canvas = mHolder.lockCanvas();
synchronized(mHolder){
// draw 
}
}finally{
if(canvas != null) mHolder.unlockCanvasAndPost(canvas);
}
}
}
}
}



 
신고

Leave a Comment

안드로이드 게임 엔진이 많다.

전부터 찾다보니 더 생기기도 하고 중단하기도 한 엔진이 있는데 이중에서 AndEngine라는게 제일 괜찮아 보여서 이걸 조금씩 보고 있는 중이다.

AndEngine Refenence
[1] AndEigine (http://www.andengine.org/forums/
[2] AndEngine 분석글 (http://sgap.springnote.com/pages/7399251
[3] Tiled 이용글 (http://togalaxy.tistory.com/4
[4] AndEngine 설명 링크글 (http://blog.naver.com/badskyblood?Redirect=Log&logNo=30113071726)
[5] AndEngine Tutorial list (http://www.andengine.org/forums/tutorials/mimminito-s-tutorial-list-t417.html)
[6] Image (http://hyungsok7.tistory.com/11)


그러나 AndEngine은 안드로이드에 최적화되어 있기는 하지만, 후에 다른 플랫폼쪽에 개발도 신경 쓴다면 그렇게 탁월하지만은 않은 선택이다.

무료이면서 멀티 플랫폼을 지원해준다는 점에서는 cocos2d가 좋은 것 같다. 게임 개발쪽에서는 경험이 없다보니 이것저것 알아보다 픽스를 하지 못하고 공부만 계속 하고 있다;;;;
다만 .cocos2d는 아이폰에 우선적으로 개발되었기 때문에 성능면에서는 안드로이드쪽에 좋지 않다고 한다. 그래도 뭐 무료니깐.

cocos2d Reference
[1] 한글 가이드 ( http://www.cocos2d-iphone.org/wiki/doku.php/ko:prog_guide:index )





 
신고

Comments

  1. 레드락 2012.02.15 13:46 신고 Permalink Modify/Delete Reply

    andengine 공부중인 사람이에요~ 담아갈께요~

Leave a Comment

안드로이드에서 
설정 > 응용프로그램 > 응용프로그램 관리  >

에서 앱을 하나 선택하면, 'SD 카드로 이동', '디바이스로 이동'을 눌러서 저장위치를 선택할 수 있다. 물론 되는 앱도 있고 그렇지 않은 앱도 있다.

이 기능은 안드로이드 2.2부터 지원되는 기능이다.
따라서, 폰 펌웨어 자체가 2.1 이하라면 어떠한 앱도 이 기능을 지원하지 않는다.

펌 웨어 2.2이상 폰에서는, 이 기능을 지원하도록 설정해준 앱들만 사용 가능하다. 


개발시, 이것을 지원해주기 위해서는 Platform 2.2, API Level 8이 필요하다.
AndroidManifest.xml 에서 두가지만 잘 설정해주면 된다.
<uses-sdk android:minSdkVersion="8" /> 과 같이 최소 SDK 버전 8이상을 설정해주고
 
<manifest
        xmlns:android="http://schemas.android.com/apk/res/android"
android:installLocation="auto"
        ..... >
...

manifest태그에 android:installLocation="auto"을 지정해주면 된다.

그러나, 이 기능을 지원해주기 위해서 2.1 사용자들을 버리는 것은 올바르지 않은 것으로 여겨진다. 2.1과 2.2를 따러 배포해주는 것을 추천한다. APK 버전별 배포는 내 이전 글을 참고하기 바란다. (http://atin.tistory.com/395)

 
신고

Leave a Comment


to Top

티스토리 툴바