adsense



[안드로이드] 위치즈 플라이트 포팅하기 (awt->안드로이드)


스크린샷을 띄워놓은게 아닙니다 ^_^;


※이번 포스팅은 안드로이드 앱 개발을 어느 정도 알고 있으셔야 합니다.
안드로이드 앱 액티비티의 생명주기나 SurfaceView의 이용 방법, 터치 이벤트 사용방법 등은 직접적으로 다루지 않고 포팅에 관련된 내용만 해설합니다.



지금까지 작업했던 자바 게임을 안드로이드로 포팅해 보겠습니다.
안드로이드 앱에서 비트맵 그래픽스를 사용한 게임을 만들려면 직접 openGl을 제어할게 아니라면 SurfaceView를 사용합니다.

SurfaceView를 사용하면 awt용 게임을 큰 노력 들이지 않고 포팅 가능합니다..만, 예 뭐 자세한 것은 이제부터.

그럼 프로젝트 파일 받고 시작하시겠습니다.

wflightand.zip (이클립스용 안드로이드 프로젝트입니다)



1. 이클립스에서 새 안드로이드 프로젝트를 생성합니다.

그러고는 기존 위치즈 플라이트 프로젝트에서 소스와 리소스 일체를 카피합니다.
리소스는 assets 폴더로 rsc 폴더를 카피합니다.
안드로이드에서 유저 디파인 패키지 이름은 소문자로 변경해 줍니다.

GameLib -> gamelib

당연히 에러가 우루루 쏟아지겠지만 무시합니다.

이제부터는 첨부한 프로젝트와 비교해가면서 봐 주시기 바랍니다.


2. 기존의 GameLib를 이식합니다.

이 부분이 이식 과정에서 비교적 복잡한 부분입니다.


안드로이드 앱을 작성해 보셨다면, 액티비티를 생성하고, 이 액티비티에 뷰를 연결한다는 기본 구조를 알고 계실 것입니다.
그것을 위해 주 패키지 하에 MainActivity 클래스를 생성하고, 이 클래스가 GameManager를 상속, 그리고 GameManager가 액티비티를 상속하는 기초 뼈대를 만들었습니다.



awt의 GameManager가 Frame을 생성하고 그에 대한 기초적인 처리를 했던 것과 마찬가지로, 앱의 GameManager에서도 액티비티 상속과 앱에 대한 기초적인 처리를 OnCreate 에서 해 주고 있습니다.


awt-어플리케이션 버전의 GameCanvas에서는, 묘화를 위한 Canvas와 처리를 위한 Runnable을 상속하여 GameManger에서 이것을 변경해주는 것으로 화면 전환을 했는데요,

안드로이드에서 Canvas의 역할을 해 주는 것은 SurfaceView 입니다.

그런데, 이 SurfaceView는 안드로이드 View의 일종으로, 액티비티에서는 setContentView를 통해 이 SurfaceView를 액티비티에 연결시켜줍니다. 어떤 의미에서는 자바 어플리케이션에서 Frame에 add, remove 해 주는 것과도 흡사합니다만,

그런 구조 때문에, 씬(scene)에 SurfaceView를 상속시켜서 이것을 변경시켜주려면 ViewFlipper를 통한 view 전환이 필요하게 됩니다.

그런데 원래 이 뷰 플리핑은, 서로 다른 종류의 View를 전환시켜주기 위해 필요한 것입니다.
우리가 쓸 뷰는 SurfaceView로 정해져 있기 때문에 뷰 플리핑을 통한 전환은 속도와 자원과 효율 면에서 바람직하지 못합니다.

그때문에 액티비티에 얹힌 뷰는 하나의 SurfaceView를 유지하면서, SurfaceView가 내부적으로 호출하는 그리기/처리 루틴만 scene에 따라 바꿔주는 구조를 만들기로 했습니다.

그것을 위해, 기존 어플리케이션 버전의 GameCanvas가 앱 버전에서는
- SurfaceView와 스레드를 상속하는 GameView와,
- SurfaceView 및 스레드에서 호출하는 dblpaint와 update를 실제 수행하기 위한 GameCanvas
의 두 개 클래스로 나눠집니다.


액티비티에서 setContextView는 GameView에 대해서만 이루어지고,


scene 전환은 GameCanvas를 상속한 클래스를 바꿔 이루어지고, 개발자는 여기서 dblpaint와 update를 구현시켜주기만 하고 SurfaceView와 스레드는 더 이상 신경쓰지 않아도 됩니다.



3. API의 차이를 중개하기 위한 중간 함수를 만듭니다.

예로 awt의 rect와 안드로이드의 rect는 인수의 의미가 다릅니다.

awt에서는 x, y, width, height으로 좌표와 너비 높이를 의미했는데,

안드로이드에서는 left, top, right, bottom으로 모두 좌표값을 의미합니다.

awt버전 rect를 안드로이드로 변환하면 x, y, x+width, y+height인 셈입니다.

이걸 일일이 기존에 rect를 사용한 부분을 찾아다니면서 수정하기엔 손이 가므로 아예 오리지널 rect 클래스인 Rectangle을 만들어 awt의 rect와 같은 역할을 하도록 하고 기존의 rect를 모조리 Rectangle로 바꿔버리면 됩니다.



그리고, 게임 지원을 위해 만들었던 GameManager의 기존 함수들도 안드로이드에 맞게 수정해 줍니다.

대개는 주로 Image 타입을 Bitmap 타입으로 바꾸는 것, 그리고 클리핑 방법의 차이 등입니다.

GameManager.java에서 다음 함수 목록을 확인해 보면 됩니다.

public Bitmap makeImage(String fname)
public void drawImageRect(Canvas gc, Bitmap img, int x, int y, int sx, int sy, int wd, int ht, int anc)
public void drawnum(Canvas gc, Bitmap img, int x, int y, int value, int digit, int anc)
public boolean LoadGame(String fname);
public boolean SaveGame(String fname);



참고로, 로드, 세이브 함수는 안드로이드에서 제공하는 간이 데이타 저장 기능인 SharedPreference로 변경했습니다.
환경설정 저장같은 용도에 쓰기 좋고 구현이 간단합니다.

단지, 드물게 SharedPreference로 저장한 파일이 소실된다는 보고가 있기 때문에, 환경설정같이 없어져도 무관한 데이터 정도에만 사용하는게 좋습니다.
게임 세이브 데이터 같이 사라질 경우 문제가 되는 자료 저장에는 권하기 어렵습니다.



4. 비교적 단순한 변경점

팝업창 제어에서 사용한 타이머 같은 경우, awt와는 달리 타이머를 cancel하면 안됩니다.
awt와는 달리 한 번 스케줄을 지정하면 1회만 실행되므로 굳이 별도로 타이머를 멈춰줄 필요는 없습니다.

Image형은 모두 Bitmap 형으로 바꿉니다.
그리고 Graphics형은 Canvas 형으로,

마지막으로 ImageObserver형은 Paint 형으로 바꾸는데, ImageObserver형 인수는 Canvas를 상속한 클래스 자신을 인수로 주면 되지만, 비트맵을 그릴 때 Paint형 인수는 모두 null로 줘도 관계 없기 때문에,

예를 들어
gContext.drawImage(pic, x,y, io);
같은 라인이 있다면 안드로이드에서는
gContext.drawBitmap(pic, x, y, null);
로 수정해주면 됩니다.


여기서 눈치채셨을텐데, 이렇게 단순 대응이 가능한 함수라면 3에서처럼 중개함수를 만들어도 됩니다.

예를 들면
ImageDraw()라는 함수를 만들고,

awt에서는
void ImageDraw(Graphics gContext, Image pic, float x, float y, ImageObserver ob){
gContext.drawImage(pic, x, y, ob);
}


안드로이드에서는
void ImageDraw(Canvas gContext, Bitmap pic, float x, float y, Paint ob){
gContext.drawBitmap(pic, x, y, null);
}


이렇게 각각 ImageDraw 함수만 다르게 만들고, 각 scene의 소스에서는 기존의 drawImage나 drawBitmap과 달리 ImageDraw를 사용하면 굳이 수정하지 않아도 됩니다.


이것이 cocos2d-x 같은 멀티플랫폼 엔진의 원리입니다.
같은 역할을 하는 같은 이름의 api를 만들어 놓되, 실제 api 구현에서는 각 플랫폼에 맞는 내용으로 코딩하는 것입니다.

과거라면 플랫폼 또는 하드웨어별 편차가 있어 어디에서는 사용 가능한 기능이 어디에서는 사용 불가가 된다던가 하여 서로 다른 플랫폼 간에 이식이 어려웠지만,(그리고 이런 차이점은 콘솔 게임기에서는 여전히 존재하지만)
최근에는 그런 기능의 편차보다는 퍼포먼스적인 차이가 대부분이고, 또 openGl(ES)라는 공통 기반 기술 위에서 구현되기 때문에 가능해진 일입니다.

(과거 피처폰 시절에도 WIPI<->BREW<->GNEX 같이 베이스 자체가 크게 다른 플랫폼간의 포팅도 이와 비슷한 식으로 일부 자동화하여 운용하곤 했습니다.)


5. 이제부터가 문제(?)다

지금까지는 기존 클래스를 거의 복붙하다시피하고, 오류나는 부분(문법상 다른 부분)들만 찾아서 위에서 기술한 요령대로 수정해주기만 하면 되는 부분들이었습니다.

어플환경과 앱 환경 사이에서 극단적으로 다른 부분은 완전히 새로 만들어줘야 합니다.

크게 나눠보면
단말기 별로 다양한 화면 크기에 대응하기 위한 방법과,
조작계 UI에 관련된 부분-키보드or마우스 조작과 터치의 차이입니다.

화면 크기에 대한 대비는 GameManager와 GameView에서 각각 해 줍니다.

우선 현재 LCD의 크기를 구하고


우리가 사용하는 캔버스 크기를 몇 배 하면 LCD의 크기가 되는지 비례값을 구하고


화면이 찌그러지지 않도록, 가로 세로 화면비를 동일하게 합니다.
화면 비가 다를 경우, 큰 쪽에 맞추면 남는 부분이 화면 밖으로 나가게 되고, 작은 쪽에 맞추면 레터박스 처리가 필요합니다.


우리는 화면비를 작은쪽에 맞춰 레터박스 처리를 할 것입니다.
이때, 화면이 정중앙에 오도록 좌표계를 이동시켜줄 필요가 있습니다.

위는 그러기 위한 값을 미리 구해두는 것입니다.

이상의 처리를 GameView에서 SurfaceHolder에 그림을 그려줄 때 미리 해 줍니다.
해당 라인의 주석으로 각각이 어떤 역할을 하는지 확인해 주세요.


이것으로 단말기 해상도에 맞추기 위한 준비는 다 됐습니다.


터치를 위해 UI 설계를 다시 할 필요가 있습니다. 일단 기초 시나리오입니다.

타이틀 화면
: P 마크를 터치하면 레벨 업. (골드가 부족하거나 최고 레벨이면 팝업)
: 팝업이 나와 있을 때 터치하면 팝업 닫기
: 위 두 가지 이외의 터치는 게임 시작

게임 화면
: 손가락의 위치에 캐릭터의 X좌표 맞춰주기
: 화면 최상단(점수/거리 영역)을 터치하면 일시정지(pause).
: 일시정지 상태에서는 아무곳이나 터치하면 재개(resume)

결과 화면
: 아무곳이나 터치하면 타이틀 화면으로


터치 처리는 GameManager에서 오버라이딩한 onTouchEvent가 GameCanvas의 OnTouchEvent를 호출하여 이루어집니다.

그러면 TitleScene의 OnTouchEvent를 보겠습니다.

if(event.getAction()==KeyEvent.ACTION_UP){

우선 이벤트 액션이 KeyEvent.ACTION_UP, 즉 터치한 손가락을 떼었을 때 처리하도록 하고 있습니다.

이것을 구분해주지 않으면 닿을 때(ACTION_DOWN), 닿은 손가락이 조금이라도 움직였을 때(ACTION_MOVE)에도 각각 이 이벤트 안으로 들어오게 됩니다.

어떤 액션에 대응할지 지정하지 않으면 터치 처리가 2회 이상 실행되는 일이 생기므로, 한 번만 처리해줘야 하는 경우에는 대개 UP에 대응해 줍니다.

//실제 터치 좌표를 화면 좌표로 환산한다
int myX = (int)(event.getX() / manager.scale_x);
int myY = (int)(event.getY() / manager.scale_y);


우리가 보는 화면은 480*800 화면을, 단말기 해상도에 맞춰 리사이징한 화면이기 때문에 그림의 좌표는 480*800 좌표계에 준합니다.

그런데, 터치 좌표는 실제 단말기 해상도의 좌표로 들어옵니다. 갤럭시S3 같으면 화면 우하단이 1280, 720이 되는 것이죠.

이것을 맞춰주기 위해, 아까 LCD 해상도를 맞추기 위해 구해뒀던 비율값을 적용합니다.


이제 비교값은 480*800 좌표계에 준해서 사용해주면 됩니다.


GameScene에서는 또 다른 처리가 필요합니다.

캐릭터를 터치로 조작해야 하므로 이번에는 ACTION_MOVE의 처리가 추가됩니다.

기본적으로는 터치 위치로 플레이어 캐릭터의 X좌표를 옮겨주면 됩니다.


단, 이렇게 하면 기존에 '키를 누르고 있으면 이동 방향으로 기울어지다가 손을 떼면 중립으로 되돌아오는' 프레임 애니메이션은 구동되지 않습니다.

이것을 가능하게 하기 위해서


최종적으로 터치에 의한 조작은 이와 같이 바뀝니다.

몇 가지 어색한 점으로
터치한 위치로 캐릭터가 워프(?)한다.
빠르게 조작하면 캐릭터의 좌우 기울어짐이 움직이는 방향에 싱크되지 않는다.

같은게 있겠는데,

실제 게임에서는 '터치한 위치를 기준으로 손가락이 움직이는 범위만큼 이동'시켜주는 처리를 하게 됩니다.
단지 이번에는 awt->안드로이드 포팅이 주 목적이므로, 그 부분까지는 다루지 않고 넘어가겠습니다.



마지막으로, 앞에서는 빼먹었는데..

awt하고 현저하게 쓰임새가 다른 것으로 비트맵이 아닌, 각종 기하도형을 그려내는 명령이 있습니다.

팝업창이나 버프아이템의 남은 시간 그래프를 그려주는 부분에 사용된 api들입니다.

지금까지 Bitmap을 그려줄 때는 Paint 객체를 null로 사용해도 상관없었지만, 기하도형을 그리기 위해서는 별도로 Paint 객체를 준비해 사용해야 합니다.
TitleScene에서 수정되는 부분을 보겠습니다.


그리고 팝업창을 그리는 부분은


위와 같이 변경됩니다.

마찬가지로 GameScene에서도 Paint 객체를 만들어주고, 트윈샷이나 마그넷의 그래프를 그려주는 부분을


이렇게 됩니다.
좌표가 복잡해지는 이유는 drawRect의 3, 4번째 파라미터가 너비, 높이가 아닌 오른쪽, 맨 아래 좌표값이기 때문입니다.(앞에서 Rect에서 설명한 것과 마찬가지로)


6. 앱 종료하기

iOS에 비하면 안드로이드는 이런 부분에 대한 어떤 통일된 가이드라인이 없는데요..
종료에는 주로 타이틀 화면에서 종료하기 메뉴를 선택하거나, Back키를 눌러 종료 팝업을 띄웁니다.

여담으로, iOS 심사 때 종료 메뉴가 존재하면 이거 리젝먹습니다.
그때문에 멀티플랫폼을 노리고 만들어진 최근 게임들은 대개 Back키로 종료 팝업을 띄우는게 일반적입니다.

그런데 요것도 게임마다 다르죠. 서브베뉴에서 Back키는 서브메뉴 닫기고 타이틀에서 Back키를 눌러야 종료 팝업이라던가.. 혹은 팝업 없이 바로 종료된다던가.

그래도 요즘은 게임 상태를 막론하고 Back키를 누르면 종료 팝업을 띄우는게 대세인 것 같습니다.

그걸 간단히 구현해 봅니다. GameManager에서 public boolean onKeyUp을 오버라이드하고 아래와 같이 코딩합니다.


cocos2d-x나 andengine으로 만든 게임에서도 써먹을 수 있는, 팝업창입니다. 개인적으로도 상용 게임 개발시에도 애용하고 있습니다.

주석으로 마킹해놓은 부분은, AlertDialog에 테마를 정해주는 부분입니다. 안드로이드 API level.11 (허니컴) 이상부터 지원되는 것이므로 최저 지원을 프로요(level. 8)로 해 놓은 경우는 해당 부분에서 컴파일 시 에러가 날 수 있어 막아놓았습니다.

HOLO_LIGHT 테마 팝업은 요즘 유행(?)인 플랫디자인의 팝업으로 제법 게임과 잘 어울리므로 허니컴 이상 쓰는 분들은 manifest에서 minSdk를 11 이상으로 수정한 후에 주석을 풀고 HOLO_LIGHT를 사용해 보세요.


7. 포팅 완료

자 굉장히 길게 설명했습니다만, 실제 제가 포팅에 사용한 시간은 하루가 채 안 됩니다.

본문에서는 미처 빼먹었을지도 모르겠지만, 일단 아무거나 프로요 이상이 설치된 안드로이드 단말을 연결하고 이클립스에서 프로젝트를 불러들여 실행..!


된다.. 된다...!

.....

....

느리다....

예, 이런 아케이드 게임을 구현하기에는 SurfaceView라도 느립니다. 그렇기 때문에 상용게임들이 openGl ES 기반 엔진으로 가는 것이죠.

그나마 그리기를 기존의 초당 60프레임에서 초당 30프레임으로 바꾸면 조금 빠르게 느껴집니다.


위 부분이 편법으로 그리기는 1/30초에 한 번, 처리는 1/60초에 한 번 하는 방법입니다.

처리 자체가 1/60초에 맞춰진 수치이기 때문에 이걸 두 번 해 줘야 1/30초 처리에 필요한 분량의 움직임이 나옵니다.
(정석대로라면 그리기와 프로세스가 각각 별개의 스레드로 돌아가야 합니다)

위와 같이 수정해서 다시 실행해 보면 조금 할만한 속도가 나옵니다. (주석처리 해 뒀으니까 풀어서 다시 빌드해 보시면 됩니다)



예, 뭐 이렇게 된 이상 다음 단계는 엔진을 다뤄봐야겠네요.

근데 엔진 포팅으로 가면 지금까지하고는 접근 방식이 확연하게 달라집니다. 포팅이라기 보다 완전 새로 만들어야 하는 거라서.

그래서 시간도 좀 오래 걸릴 듯 하고..
무엇보다 엔진을 쓰면 저도 구현하는데 급급해져서 다른 사람에게 설명을 제대로 하기가 어렵고 코드가 더러워집니다.

뭐 그건 그때 가서 걱정하고요. 오늘은 엔진을 사용하면 어떻게 되는가? 하는 간단한 맛보기 파일만 소개하고 넘어가겠습니다. (소스는 끔찍해서 차마 공개하기가.. ㅠ_ㅠ)

WFlightAE.apk (AndEngine을 사용해 타이틀 화면을 포팅한 예제)


2013년도 슬슬 끝이네요. 한 해 마무리 잘 하시고 복된 새해 맞이하시기 바랍니다.

감사합니다.



덧글

  • TOWA 2013/12/26 18:46 # 답글

    ......@_@
  • 펭귄대왕 2013/12/26 23:02 #

    ^_^; ?
  • TOWA 2013/12/27 00:34 #

    어려워서요[...]
  • 펭귄대왕 2013/12/27 08:08 #

    이번엔 스텝바이스텝이 아니라 다 된걸 한꺼번에 휙 던지는(?) 거다보니 좀 중구난방인 감도 있고, 안드로이드 개발 경험이 전제다보니 난이도가 좀 올라가긴 한 것 같습니다.
  • 펭귄대왕 2013/12/26 23:06 # 답글

    처음 올린 프로젝트 파일을 일부 수정했습니다.

    게임 중 갑자기 화면이 멈추고 터치에 캐릭터만 따라다니는 현상 - GameManager의 drawImageRect에서 간혹 너비나 높이값이 0 이하로 들어오는 경우가 있었습니다. 원래대로라면 원인을 파악해서 아예 그런 값이 못 들어오게 막아야 합니다만, 임시조치를 했습니다.

    화면회전을 설정한 경우 단말기를 기울이면 화면이 돌아가고 게임이 재시작되는 문제 - manifest의 activity 옵션에서 android:screenOrientation="portrait" 를 설정해 액티비티를 세로상태로 고정시킵니다. (만일 가로화면 게임이라면 android:screenOrientation="landscape"를 사용)

    적용된 파일로 교체되었습니다.
  • 슈크렐 2013/12/27 10:08 # 답글

    ......@_@? (2)
  • 펭귄대왕 2013/12/27 13:55 #

    ^_^;;
  • IEATTA 2013/12/27 16:19 # 답글

    @_@ (3)

    문과생인 나는 무슨 말인지 모르겠다.
    H2O는 산소입니다. (?)
  • 펭귄대왕 2013/12/27 19:03 #

    쪼금 난이도가 올라가기 시작하니까 설명하는 저도 횡설수설..
  • 휴이 2013/12/30 11:34 # 답글

    ios 심사에서 종료하기가 있으면 reject이라는 건 처음 알았네요. 그러게요. 안드로이드는 백버튼 누르면 종료여부를 묻는 팝업이 뜨는데 ios쪽은 그런 게 없었죠. 뭔가 예전부터 묘한 위화감이 있었는데 이런 거였군요.
  • 펭귄대왕 2013/12/30 22:12 #

    안드로이드 같은걸로 먼저 개발된 게임들이 iOS로 넘어가면서 UI가 교란되니까 생긴 모양이더라구요.
    정확히 언제부턴진 모르겠지만 2012년 중반에 런칭했던 것들은 종료메뉴 있는데도 통과됐다고 기억하는데..
  • 오류가 뜨네요 2014/10/07 13:28 # 삭제 답글

    Rectangle.java 에서 오류가 뜨길래 메세지를 보니

    Implicit super constructor Object() is undefined. Must explicitly invoke another constructor

    Project 마우스 오른쪽 메뉴버튼 클릭 -> Build Path -> Add Libraries -> JRE System Library -> Workspace default JRE(jre1.8) 선택

    을 해봤는데 Rectangle오류는 사라졌으나 문제는 나머지 모든 클래스가 오류가 뜹니다.
    뭐가 문제일까요 ㄷㄷ;;
  • 펭귄대왕 2014/10/07 14:36 #

    안드로이드 sdk 적용된 이클립스에서 불러들이신건가요? 이건 android.jar를 쓰기 때문에 외부 jre를 추가할 필요가 없는데요.(..하면 안됩니다)

    Rectangle.java 에는 변수 몇 개랑 이 변수에 초기값 할당하는 생성자밖에 없는, 아주 간단한 클래스입니다.
  • 추가 질문 2014/10/08 14:02 # 삭제 답글

    안드로이드 sdk 적용된 이클립스에서 불러들였는데요. JRE를 추가하지 않으면 Rectangle.java에서 오류가 발생합니다.
    그리고 JRE를 추가하지 않은 상태에서 겉으로 보기에 오류가 뜨지 않은 다른 클래스들도 (src 안에 든 클래스) 거의 전부가 소스를 들어가보면 오류가 뜹니다.
    오류가 뜨는 부분은 대체적으로 이미지와 관련된 canvas ,GameScene, Bitmap 등에서 일어나는 것 같습니다.
  • 추가 질문 2014/10/08 14:33 # 삭제 답글

    (추가) 위에 질문에 더해서 다른 안드로이드 프로젝트를 생성해서 생성한 프로젝트로 오류가 나는 클래스들을 옮기니 경고는 뜨지만 오류는 나지 않습니다.
  • 펭귄대왕 2014/10/08 15:16 #

    https://drive.google.com/file/d/0B6a0nZSpOjgMU0lYOU9EZTFsRUE/view?usp=sharing
    (혹시 이미지를 볼 수 없으면 알려주세요)

    이클립스에서 import->Existing Android Code Into Workspace 했을 때 폴더구조가 위의 그림처럼 나오는지요?
    폴더구조는 맞는데 소스에 에러가 뜨고 있다면 Project->Clean을 한 번 해주면 정상으로 돌아올 수도 있습니다.
  • 추가 질문 2014/10/08 15:40 # 삭제 답글

    넣는 방법이 잘못되어서 오류가 나다가 위의 알려주신 방법으로 import하니 [위의 알려주신 방법도 해 보았습니다.]

    http://postfiles16.naver.net/20141008_31/catarina7_1412750258555DWLN3_JPEG/ddd.JPG?type=w3 위 이미지와 같은 오류가 뜨네요.
  • 펭귄대왕 2014/10/08 15:44 #

    죄송합니다 이미지가 안보이네요.

    혹시 안드로이드 패키지쪽에 문제가 있다면,
    프로젝트를 오른클릭해서 Properties->Android로 들어가 Project Build Target에서 현재 설치되어 있는 것 중에서 적당한 안드로이드 API를 선택해주시고, Project->Clean을 해 주면 제대로 적용될 것 같습니다.
    (Clean 전에 Java Build Path->Order and Export에서 선택한 안드로이드 패키지에 체크가 되어있나 확인하고, 체크가 안되어있으면 체크해준 후 Clean하면 됩니다)

    만일 안드로이드 2.3 이하로 하게 되면 GameManager.java에서 AlertDialog.Builder 부분에서 오류가 날텐데,
    AlertDialog.Builder _dialog = new AlertDialog.Builder(this, AlertDialog.THEME_HOLO_LIGHT);
    이 부분을
    AlertDialog.Builder _dialog = new AlertDialog.Builder(this);
    이렇게 수정해주면 되던가.. 아마 그랬던 것 같습니다.

    안드로이드 4.3 이상으로 선택해주시면 문제 없을 것이고, 만일 Project Build Target에 안드4.3 이상이 없다면 Window->Android SDK Manager에서 추가 패키지를 설치하여 사용하면 됩니다.
  • 추가 질문 2014/10/08 15:48 # 삭제 답글

    http://blog.naver.com/catarina7/220144762896 이미지 다시 보여드립니다 ㅠㅠㅠ

    안드로이드는 4.3 이상으로 실행하였습니다.
    번거롭게 해드리는 점에 관하여 죄송합니다 ㅠㅠ
  • 펭귄대왕 2014/10/08 15:51 #

    올려주신 이미지상으로는 안드로이드 2.3.3 패키지가 적용이 되어 있네요.

    2.3대까지에서는 values 까지만 인식할거라 res폴더의 values-sw600dp, values-sw720dp-land, values-v11, values-v14 폴더와 그 내용은 모두 삭제해주시고, 혹시 drawable-xhdpi, drawable-xxhdpi에서 에러가 난다면 그것도 삭제해주세요.
    그 후에 다시 Clean 한 번 해주시면 될 것 같습니다.
  • 추가 질문 2014/10/08 16:18 # 삭제 답글

    덕분에 됩니다.. 죄송합니다. 아직 안드로이드에 관해서 초보라서 잘 모르고 여러가지 귀찮게 해 드렸네요 ㅠㅠㅠㅠ
    친절한 답변 감사합니다 ㅠㅠㅠㅠㅠ
  • 펭귄대왕 2014/10/08 16:29 #

    잘 되신다니 다행입니다 ^_^
    제가 도와드릴 수 있는 내용이라면 언제든 환영합니다. 혹시 또 궁금하신 부분 있으시거든 남겨주세요.
  • 으아 2015/10/15 00:55 # 삭제 답글

    제가 뭐를 잘못건드린건가요 ㅠㅠ
    최고점수는 변화있는데 밑에 골드가 전판에 얻은골드가 합산이안되고
    계속 0으로만 되어있는데 어느 자바파일에 어디를 바꿔야하나요
  • 펭귄대왕 2015/10/15 06:45 #

    이 포스팅에 첨부된 프로젝트를 기준으로,
    GameScene.java의 void myProcess() 에서 if(status == STATUS_FALL)
    에서 처리하는 내용 중에
    if(myY>GameManager.SCREEN_HEIGHT + 60){//화면 밖으로 사라졌으면
    이 부분에서
    manager._getGold =_gold; 로 현재 게임에서 얻은 골드를 임시 보존하고,
    ResultScene.java의 public void SceneStart()에서
    manager.gold += manager._getGold;//전체 골드에 획득한 골드를 합산
    이 부분에서 전체 골드에 게임에서 얻은 골드가 합산됩니다.
    그 후에 manager.SaveGame(GameManager.FILENAME); 로 점수나 골드를 세이브하고요.

    이상의 구현이 제대로 되어 있나, 제대로 흐름을 타고 있는가 확인해 볼 필요가 있겠습니다.
  • 2015/10/15 20:28 # 삭제

    확인했는데 설명써주신대로 이상없이 되있는데 왜안될까요 ㅠ
  • 2015/10/15 22:02 # 삭제

    여기첨부된 프로젝트랑
    말씀해주신거 비교해봤는데 다 똑같아요 ㅠㅠ
  • 펭귄대왕 2015/10/16 02:51 #

    어떤 문제가 있는지 이것만으로는 알 수가 없네요..
  • 2015/10/15 11:55 # 삭제 답글 비공개

    비공개 덧글입니다.
  • 펭귄대왕 2015/10/15 12:06 #

    상관없습니다.
  • ddd 2015/10/15 11:56 # 삭제 답글

    이미지를 바꾸려면 제목만 그대로하고 사진크기만 똑같이한다음에 덮어쓰기 하면되나요 png8 png24 상관없이?
  • 펭귄대왕 2015/10/15 12:07 #

    그렇게 하면 됩니다. png8, png24 상관없는데 png8은 알파채널이 투명 하나밖에 지원되지 않으니 png24쪽이 더 깨끗하게 보입니다.
  • ddd 2015/10/15 13:14 # 삭제

    사진 크기는 어떻게 맞춰야하는지도 여쭤볼게요 ㅠㅠ
  • 펭귄대왕 2015/10/15 15:22 #

    보통 포토샵을 사용합니다. 그래픽 툴의 사용방법까지는 제가 답해드리긴 좀 어렵겠네요.
댓글 입력 영역


Books

Geek라이프

게임 매니악스 슈팅 게임 알고리즘
마츠우라 켄이치로,츠카사 유키 공저/손정도 역/박민근,Pope Kim 감수

게임 매니악스 퍼즐 게임 알고리즘
마츠우라 켄이치로,츠카사 유키 공저/김병국 역

핵심강좌! Cocos2d-x
이재환 저

될 수 있어! SE 13
나츠미 코지 저/Ixy 그림/김경훈 역
예스24 | 애드온2