본문 바로가기

포트폴리오

[포트폴리오] Shake Coke


Shake Coke


시연 영상



GITHUB : https://github.com/tooOpen/ShakeCokie

작품 요약서

n  Basic  Data

작품명

Shake Coke

지원분야

소프트웨어

개발인원

1

본인역할

개발, 기획, 설계, 테스트

개발기간

2014.01

~ 2014.03

개발환경

Android,cocos2d-x

개발언어

Java, c++

개발툴

Eclipse

작품소개

(요약)

㈜솔미테크에서 개발한 SHC-M1이라는 모바일 건강측정기(이하 SHC)내부에 있는 자이로센서를 이용하여 흔들리는 가속도 값을 구하고, 이를 블루투스를 통하여 전달 받은 후, 이 가속도 값을 이용하여 안드로이드폰의 게임화면에 콜라를 위 아래로 움직이게 하여 게임을 진행합니다. 게임을 하면서 간단한 운동도 할 수 있고 기계가 작기 때문에 제한된 공간에서도 쉽게 운동을 할 수 있습니다. 또한 자신이 얼마나 흔들었는지를 시각적으로 재미있게 표현하여 게임에 쉽게 지루해지지 않게 만들었습니다.

자신이 얼마나 흔들었는지를 데이터베이스에 저장하기 때문에 친구들과 경쟁하며 친구가 기록한 점수보다 많은 점수를 얻기 위해 계속하다 보면 자신도 모르게 운동을 열심히 하는 자신을 보게 될 것 입니다.

작품내용

게임은 총 5개의 장면인 준비,게임, 폭파, 상승, 랭크로 나누어져 있습니다.

우선 게임을 시작하기 전 우선 안드로이드 폰의 블루투스를 켜고 SHC와 연결을 하게 됩니다. 블루투스 연결이 완료되면 게임의 준비화면이 나오게 되는데 이때 도움말 버튼으로 게임의 진행방법에 대하여 알 수 있습니다. 시작 버튼을 누르면 3초 카운트다운 후 게임이 시작화면으로 넘어가게 됩니다. 게임은 20초동안 진행되며 그 시간 안에 SHC를 흔들어 화면의 콜라를 흔들면 됩니다. 자신이 어느 정도 흔들었는지는 화면 하단의 콜라 게이지를 통해 실시간으로 확인 할 수 있습니다. 정해진 시간이 지나면 콜라가 터지는 애니메이션이 나오는 폭파 장면이 나오고, 콜라가 하늘 위로 상승하는 화면이 나오며 자신의 기록이 나오게 됩니다. 마지막으로 랭크화면 창에서 자신의 점수와 자신의 등수를 확인 할 수 있고 게임을 종료할지 재 시작 할지 선택할 수 있습니다.

개발내용

(본인 구현부분)

프로젝트 안에는 이미지를 다루고 관리하는 앱 매니저, 게임의 진행과 전체적인 관리를 하는 SurfaceView와 서브 스레드가 있는 프레임워크, Surface View를 부르는 Main Activity가 있는 게임패키지, 화면의 출력되는 객체들이 있는 Graphic Objects, 배경 음과 효과음을 관리하는 Sound Manager, SQLiteOpenHelper를 쓰기 위한 SQLite패키지로 이렇게 총 6개의 패키지로 이루어져 있습니다.

우선 기본 게임 Activity를 만들고 기본적인 SurfaceView와 서브 스레드를 만들었습니다. 그 후 게임에 필요한 오브젝트들 추가하기 위해 원활한 이미지 관리를 위해 AppManager를 만들고 그래픽오브젝트들을 만들었습니다. 그 중 애니메이션이 필요한 것은 SpriteAnimation클래스를 상속받게 하였습니다. SoundManager를 만들어 게임의 배경 음과 효과음을 넣어 게임의 재미를 더하였습니다. 기본적인 게임의 골격이 완성된 후 SQLiteOpenHelper를 통해 데이터베이스를 구현하였습니다. 전체적인 게임이 구현된 후 SHC에서 값을 받아들이는 작업을 하였습니다. 우선 Activity에서 SHC로부터 받은 값을 Handler를 통해 SurfaceView로 넘겨주고 SurfaceView에서는 다시 Handler를 통해 그 값을 받아 처리해주는 방식으로 구현하혔습니다. SHC에서 데이터를 보낼 때마다 ActivityHandlerSurfaceViewHandler로 메시지를 넘겨주고 그곳에서 적용시키는 것입니다.

1. SHC 가속도 값을 통한 게임진행 -> 값의 처리는 자이로센서를 통해 사용자가 SHC를 위로 들었을 때 낮은 값이 나오고 낮게 내렸을 때 높은 값이 나오는 것을 이용하여 그 값을 을 각도 값으로 바꾸어 콜라 이미지를 각도에 맞게rotation시켜 위아래로 움직이게 합니다. 또한 값을 받을 때마다 이전 값과 비교하여 그 차이만큼 게이지가 증가하게 됩니다.

2. 더블 버퍼링 –> 안드로이드의 모든 view는 기본적으로 더블 버퍼링이 됩니다. 하지만 그냥 view GDI스레드를 사용하기 때문에 느리고 입력도 받을 수 없습니다. 그래서 SurfaceView와 별도의 스레드를 사용하여 SurfaceHolder를 통해 lockcanvas로 캔버스를 잠근 후 버퍼에 draw를하고 unlockcanvas를 통해 view에 그려주는 방식으로 더블 버퍼링을 구현 하였습니다.

3. 게임 중 홈버튼 적용 -> 홈버튼을 눌러 잠시 게임 밖으로 나갔을 때에도 오류가 뜨지 않고 언제든지 자신이 했던 부분부터 다시 시작 할 수 있게 Activity onResume, onPause 함수를 오버라이드 하여 스레드를 멈추었다 돌렸다 할 수 있게 하였습니다.

4.게임 사운드 –> 게임의 효과음과 배경음악을 안드로이드의 SoundPool MediaPlayer를 통하여 처리하였습니다..

5. 랭킹 시스템 –> SQLiteOpenHelper클래스를 상속받아 테이블을 생성하고 게임이 끝났을 때 쿼리를 이용하여 데이터베이스에 저장하고 화면에 보여줄 때는 점수를 기준으로 내림차순으로 정렬하여 보여줍니다.

기타

이 게임은 ㈜솔미테크에서 외주 받은 게임으로 앱의 일부분인 미니게임 입니다. 전체 앱이 완성되면 곧 상용화에 들어가는 것으로 알고 있습니다.

 






게임 구성의 흐름도


우선 게임을 시작하면 준비화면이 나오게 됩니다. 이곳에서 스타트버튼을 누르면 게임이 시작되는데 SHC와 블루투스가 연결되어있지 않다면 블루투스 연결을 하게 됩니다. 게임을 시작 전 도움말 버튼은 터치하면 도움말이 떠 게임의 진행방법을 알려 줍니다. 스타트 버튼을 누르면 게임이 시작되고 20초 동안 사용자가 흔드는 SHC에서 가속도 값을 지속적으로 받습니다. 현재 받은 가속도 값과 이전에 저장한 가속도 값을 비교하여 임계 치 이상이면 게이지의 값을 증가시켜 줍니다. 20초의 시간이 모두 끝나면 콜라가 터지는 화면이 나오며 자신의 점수가 어느 정도인지 판별할 수 있는 ‘great’, ‘nice’,good’,bad’가 화면에 출력되고 콜라가 터져 상승하는 장면이 나오며 자신이 흔들었던 수치가 미터로 바뀌어 0에서부터 숫자가 올라가며 출력됩니다. 자신의 기록까지 숫자가 올라가면 화면 위에서 콜라가 쏟아져 내려오며 랭크화면으로 화면을 전환하게 됩니다. 랭크화면에서는 이제까지 플레이 한 기록들이 나오게 되는데요 점수를 기준으로 내림차순 하여 6위까지 나오게 됩니다. 그리고 방금 플레이 한 게임의 점수와 자신이 랭크에서 몇 위 정도인지는 랭크 아래에 표시되게 해놓았습니다. 플레이어는 랭크화면에서 게임을 끝내고 밖으로 나가고 싶다면 exit버튼을 눌러 나가면 되고 만약 다시 한판 더 즐기고 싶다면 again버튼을 눌러 게임을 재 시작 할 수 있습니다..







클래스 다이어그램

우선 이 프로젝트의 패키지는 위와 같이 6개로 이루어져 있습니다. Activity가들어있는 Main패키지, GameView GameThread가들어있는 GameView패키지, 각각의 매니저 클래스가 들어있는 SoundManager AppManager패키지, GameSQLite가 있는 SQLite패키지 마지막으로 게임에 필요한 GraphicObject들이 들어있는 GraphicObjects패키지가 있습니다.

Main-CokeGameActivity : SHC값을 받아 SurfaceView로 넘겨주며 onPause, onResume함수를 오버라이드하여 게임도중 홈 버튼을 눌렀을 때에도 스레드가 죽지 않게 관리합니다.

 

GameView- CokeGameView : 전체적인 게임의 관리를 하는 View 입니다. 터치를 입력 받고 장면마다 다르게 Update Rendering을 해줍니다. 게임 종료 시에는 out of memory가 나지 않게 비트맵들을 모두 recycle해줍니다.

 

GameView- CokeGameThread : Run함수를 계속 돌리며 SurfaceView Update 함수를 호출하고 SufaceHolder를 이용하여 View에 그려주는 역할을 합니다.

 

Sound-SoundManger : MediaPlayer SoundPool형의 변수들로 사운드 리소스를 관리하는 클래스 입니다. 싱글톤으로 구현되어 있습니다.

 

App-AppManger : 프로젝트의 그래픽 리소스를 관리합니다. 싱글톤으로 구현되어 있습니다.

 

SQLite-CokeGameSQL : SQLiteOpenHelper를 상속받아 데이터 베이스와 테이블을 만들고 getWritableDatabase함수를 호출하여 데이터베이스에 정보를 넣고 getReadableDatabase함수를 호출하여 데이터베이스의 정보를 보여줍니다.

 

GraphicObjects-GraphicObject : 이미지가 화면에 출력되기 위한 기본적인 정보가 들어있는 클래스로 GraphicObjects에 있는 모든 클래스는 모두 이 클래스를 상속받습니다.

 

GraphicObjects-SpriteAnimation: 단순히 출력되는 이미지가 아니라 계속해서 움직이는 애니메이션이 요구되는 객체일 경우 이 클래스를 상속받습니다. 애니메이션을 구현하기 위한 기본적인 정보들이 들어가 있습니다. SpriteAnimation또한 GraphicObject를 상속 받습니다



SHC-M1 데이터 수신

SHC로부터 가속도 값을 받기 위해 사용하는 함수들입니다. BindService onActivityResult같은 경우 블루투스를 연결하고 받는 부분인데 이 부분은 제가 만든 것이 아닙니다. 제가 외주를 받았을 때 이미 회사에서 구현되어 있었던 부분입니다. 하지만 데이터를 받은 후 그 값을 Activity에서 SurfaceView로 넘겨주는 부분은 제가 구현한 부분인데요 Activity->View로 넘겨주는 건 바로 넘겨줄 수가 없기 때문에 고민한 끝에 handler의 메시지와 함수를 사용하여 Activity에서 View 객체를 생성 후 mHander로 받은 메시지를 함수로 넘겨주고 함수에서 다시 bhandler로 메시지를 보냄으로써 정보를 받게 됩니다.


SHC로부터 가속도 값을 받아 SurfaceView로 넘겨주는 과정


위 세 함수는 SHC로부터 가속도 값을 받아 SurfaceView로 보내주는 역할을 하는 함수들입니다. 사용자가 SHC를켜고 게임을 실행 시키면 블루투스 연결이 되고 게임이 시작되면 우선 ActivityrcvedData함수로 SHC의 데이터가 넘어 오는데 이때 M1DATA형식으로 넘어오게 됩니다. 여기에는 기계에서 받는 모든 값인 가속도 심박도 등 여러 데이터가 있어서 우리가 받은 데이터 타입이 가속도 값인지 확인을 한 후에 현재 상태가 게임을 하는 중일 때만 그 값을 메시지에 넣어 mHandler로 보냅니다. 그러면 mHandler에서는 받은 메시지를 그대로 Activity에 생성된 SurfaceView의 객체의 함수인 getmessage함수의 매개변수로 넘겨주게 됩니다. 메시지를 받은 getmessage에서는 매개변수를 다시 SurfaceView bHandler의 메시지로 보내기 위하여 매개변수로 받은 메시지의 내용들을 bHandler메시지로 보내게 됩니다 이 과정은 SHC가 블루투스를 통해 안드로이드 폰에 데이터를 보낼 때 마다 호출 되게 되어있습니다




SHC의 가속도 값에 따라 콜라의 각도 조절함수


Handler SHC로부터 받은 값을 콜라의 각도 값으로 바꾸는 함수입니다. 우선 받은 메시지의 타입이 가속도 값인 판별하고 메시지의 객체를 얻어와 각 축의 가속도 값을 받습니다. 플레이어가 어느 축으로 움직여도 게임을 진행 할 수 있게 각축의 가속도를 더한 다음 3으로 나누어 전체 가속도의 평균을 구합니다. 그 평균값을 100으로 나눈 다음 다시 3을 곱한 값을 15에서 빼줍니다. 여기서 15에서 빼는 이유는 콜라가 가장 밑으로 갈 때가 15도 가장 위로 갈 때가-15도로 설정해놓았기 때문입니다. 그렇게 나온 각도 값이 바로 적용되는 것이 아니라 5개로 나뉘어진 단계 중 어느 단계에 속하는 지 판별한 후 포함되는 단계의 각도 값이 적용됩니다. 이렇게 한 이유는 SHC에서 보내는 가속도 값은 1초에 100정도 오는데 그때마다 로테이트를 하면 위아래로 움직인다기 보다는 그냥 팔을 떠는 것처럼 보이기 때문에 움직이는 단계를 5단계로 나누어 적용 하였습니다. 그렇게 각도 값이 정해지게 되면 CokeGameShake객체의 setDif를 호출하여 콜라이미지를 로테이트 시켜줍니다.



SHC 가속도 값을 이용하여 게이지 값으로 바꾸기


우선 게이지 증가는 기기로부터 x,y,z 방향의 가속도 값을 얻어와 모두 더한 뒤 3으로 나누어 평균값을 구합니다. 그리고 값을 받을 때마다 이전 값을 저장한 prevalue와 비교해 그 차이를 variance라는 변수에 저장한 다음 계속해서 더합니다. 그리고 devicecounter 10이 되면 이제까지 더해진 값을 (250000/screenWidth)로 나눕니다. 그 이유는 화면 크기에 따라 게이지 크기가 다른데 그래서 휴대폰화면에 맞추어 게이지를 증가하기 위해 위와 같은 식을 사용했습니다. 그렇게 게임 시간 동안 증가시킨 게이지 값이랑 기본 포인트 300을 더하면 유저의 점수가 됩니다.


화면 해상도에 독립적인 게임


안드로이드의 고질적인 문제는 바로 해상도(Resolution)인데요 종류가 많지 않은 아이폰과는 달리 다양한 해상도가 많아 최대한 해상도에 독립적으로 프로그래밍을 해주어 야합니다. 이 프로젝트 같은 경우에는 ㈜솔미테크에서 원했던 기본 해상도가 16:9여서 거기에 맞추어 제작한 다음 다른 해상도에서 돌아갈 경우 화면 양끝에 BlackBar를 넣어 늘어짐현상을 방지하고 있습니다. 대부분의 GraphicObject들이 화면 해상도를 기준으로 그려지기 때문에 BlackBar부분을 빼고 화면 해상도를 계산하여가 하기 때문에 resolutionStartSpot이라는 변수에 블랙의 width를 저장하여 width계산시에는 0부터가아니라 resolutionStartSpot부터시작하게 하였습니다.


게임 중 홈 화면으로 나갔을 때 처리.


게임 중 홈 버튼을 눌러 강제로 홈 화면으로 나간다면 스레드가 죽게 되고 음악도 멈추지 않게 됩니다. 이러한 부분을 처리하기 위해 Activity의 생명주기를 보고 onResume, onPause함수가 나갔다 들어올 때 호출된다는 사실을 알게 되었고 이 두 함수를 오버라이드하여 해결하였습니다.

onPause : 홈 화면으로 나갈 때 호출됩니다. SurfaceView pauseS함수를 호출하여 모든 음악을 일시 정지해줍니다. 스레드 또한 잠시 멈추게 합니다. 만약 이렇게 하지 않는다면 스레드는 그냥 죽고 다시 살아나지 않습니다.

onresume : 이곳에서는 음악을 다시 재생시켜주고 스레드를 다시 시작하게 해줍니다.



'포트폴리오' 카테고리의 다른 글

[포트폴리오]Air Hockey Together  (0) 2015.11.10
[포트폴리오]After Earth  (0) 2015.11.10
[포트폴리오]Thinking Snake Game  (0) 2015.11.10
[포트폴리오] Afro Run  (0) 2015.11.10
[포트폴리오] Smart Wash Helper  (0) 2015.11.10