본문 바로가기

포트폴리오

[포트폴리오]Dropking & PunchKing

 DropKing & PunchKing


시연영상



GITHUB

Punchking : https://github.com/tooOpen/Punchking

Dropking : https://github.com/tooOpen/Dropking


작품 요약서

n  Basic  Data

작품명

Punchking, Dropking

지원분야

소프트웨어

개발인원

1

본인역할

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

개발기간

2014.01

~ 2014.03

개발환경

Android, cocos2d-x

개발언어

Java, C++

개발툴

Eclipse

작품소개

(요약)

㈜솔미테크에서 개발한 SHC-M1이라는 모바일 건강측정기(이하 SHC)을 사용하였습니다. 또한 솔미테크에서 제공한 라이브러리들을 직관적으로 모듈화하여 개발자로 하여금 라이브러리에서 제공하는 함수들을 쉽게 사용할 수 있고 자신이 원하는 값을 별다른 연산 없이 편하게 구할 수 있는 미들웨어인 KMUsensor인터페이스와 그것을 상속 받은 KMUsolmi 클래스를 만들었습니다.

이 라이브러리들을 베이스로 위로 안드로이드 게임2개를 개발하였습니다. Punchking SHC를 손에 잡고 타이밍에 맞추어 손을 휘두르면 가속도 변량에 따라 점수를 얻게 됩니다.

Dropking은 블록쌓기 게임인데 아래의 블록을 보고 같은 위치에서 SHC를 흔들면 블록이 떨어지게 쌓아지는 게임입니다.

두 게임 모두 SQLite를 사용하여 랭킹을 구현하였고 jni를 통하여 SHC로부터 받은 값을 자바에서 C++로 넘겨주어 처리합니다.

작품내용

솔미테크에서 제공받은 라이브러리인 SHCM1LIBv2, protocolrev3를 분석하여 개발 시 실제 사용하는 함수들인 connect나 값을 받기 위한 콜백함수를 등록하는 setCallbackfunc같은 함수들로 모듈화하였습니다. 이는 이후 SHC와 연동하는 방법을 잘 모르는 개발자들도 쉽게 개발 할 수 있게 만들어 주는 편리한 도구가 되어 줄 것입니다.

두 게임의 진행 방법은 우선 FindDeviceActivity라는 액티비티를 intent시킵니다. 이 액티비티는 블루투스가 꺼져있다면 켜고 켜져 있다면 사용 가능한 기기를 검색하여 선택된 기기의 기기 값을 가져오는 역할을 합니다.

기기 값을 가져온 후에는 그 값으로 기기와 연결을 하게 되고 연결이 정상적으로 완료 되었다면 게임의 시작 버튼이 활성화 되게 됩니다. 또한 두 게임에 사용되는 스프라이트와 사운드, 데이터베이스는 각각의 매니저를 통해서 관리됩니다.

Punchking는 스테이지 방식으로 정해진 스테이지를 모두 클리어하면 게임이 종료되고 게임 중 파워를 근거로 점수를 계산하여 랭킹에 올라가게 됩니다.

반면 Dropking은 스테이지가 없이 무한대로 쌓을 수 있는 방식입니다. 사용자가 탑을 무너트릴 때까지 쌓게 되고 최종적으로 쌓은 블록의 개수를 가지고 랭킹에 오르게 되는 방식입니다. Dropking Box2d를 사용하여 더 리얼한 효과를 보여줍니다.

개발내용

(본인 구현부분)

두 게임의 베이스를 바치고 있는 것은 솔미테크에서 제공받은 라이브러리인 SHCM1LIBv2, protocolrev3를 모듈화한 KMUSensor KMUSolmi입니다. 우선 KMUSensor는 인터페이스로서 SHC뿐만 아니라 기기로부터 값을 받는 모든 프로그램에서 기본적으로 필요한 요소들을 선언해놓은 것입니다.

여기에는 연결, 연결 종료, 값을 받기 위한 콜백함수 등록, 로그 저장, 기기설정 등이 있습니다.

다음으로 KMUSolmi SHC를 위해 구현된 클래스인 SolmiBroker를 가지고 있습니다. SolmiBroker에서 재정의된 각각의 구현된 내용들은 제공받은 SHCM1LIBv2, protocolrev3를 분석하여 연결이나 값을 얻기 위한 자잘한 설정이나 함수호출을 모듈화 하여 하나의 함수 호출만으로 가능하게 만들었습니다.

1. SHC 가속도 값을 통한 게임진행 -> 사용자가 기기를 움직였을 시 기기에서 보내는 값은 KMUSolmi를 통해 등록된 콜백함수를 호출하고 액티비티에서는 받은 각 축의 가속도 값을 오브젝트로 저장한 다음 JNI사용하여 C++의 네이티브 함수를 호출하여 값이 저장된 오브젝트를 jobject로 전달하게 됩니다. 그럼 호출 받은 C++함수에서는 각축의 가속도 값을 얻어와 Datapossessor객체에 저장하게 되고 이 객체를 이용하여 게임 내 값 처리를 하게 됩니다.

2. Box2d 사용-> Dropking에서는 Box2d물리엔진을 사용하여 블록이 떨어지는 부분과 쌓여있던 블록과의 충돌체크를 하기 때문에 실제로 블록을 쌓는 느낌을 느낄 수 있습니다

3. 리소스 매니저 구현 -> 이미지와 사운드 리소스들을 각각의 규칙을 정해 아이디 만으로 어느 씬에 사용되는지 어디에 사용되는지 구분하여 실제 좌표를 얻거나 사운드 재생을 할 때도 아이디를 넘겨주어 처리하게 됩니다.

4. 랭킹 시스템 –> SQLite3를 이용하여 데이터베이스를 만들고 관리합니다.

기타

이 게임은 ㈜솔미테크에서 외주 받은 게임으로 앱의 일부분인 미니게임 입니다. 이 게임들은 실제 안드로이드 플레이스토어에서 받아보실 수 있습니다.


기기 연동 모듈 


Punchking Dropking을 기기와 연동하게 하는 베이스가 되는 것이 solmibroker 클래스입니다. Solmibroker SensorBroker 인터페이스를 구현한 클래스로 SensorBroker에는 일반적으로 센서를 사용하는 기기를 연동할 때 필요한 함수들을 선언해 놓은 인터페이스 입니다. Solmibroker에서 SensorBroker를 구현할 때는 솔미테크회사로부터 제공받은 SHCM1LIBv2, protocolrev3를 분석하여 구현하였습니다. 예를 들어 연결 부분을 보면 기기와 연결을 할 때 설정해야 하는 부분들과 호출해야 하는 함수들을 정리하여 실제 모듈을 사용하는 개발자라면 connect함수 하나만 호출을 하면 모듈 내부에서 선택한 기기와 블루투스 연결을 처리해줍니다.

이렇게 SolmiBroker SHC와 앱을 개발하는 개발자 사이의 미들웨어의 기능을 합니다. 물론 SHCM1LIBv2, protocolrev3 이 라이브러리들이 있어야 하지만 사용자는 이 라이브러리에 대하여 조금도 알 필요가 없는 것입니다.


리소스 관리 매니저


게임에 사용되는 사운드와 이미지는 모두 매니저를 통해서 관리됩니다. 이 매니저들이 리소스를 관리할 때 사용하는 것이 각 리소스들의 ID입니다. ID ResourceNameRule에 정의 되어있는 규칙을 바탕으로 ResourceID에 저장됩니다. 이때 규칙이라는 것은 10진수로 된 숫자들의 조합입니다. 예를 들어 메인 메뉴 씬에 사용된 이미지이고 스테이지에 상관이 없다면 TYPE_IMAGE + SCENE_MAINMENU + STAGE_NONE 이렇게 enum형으로 저장됩니다. 이렇게 저장하면 enum의 값만 보아도 어느 씬에 언제 사용되는지 알 수 있고 이 후 리소스를 검색하는 일이 생길 때도 전체를 검색할 필요 없이 해당되는 씬이나 스테이지에서 검색을 하면 빨리 검색을 하여 알아낼 수 있습니다.

코드에서는 이미지들의 ID만 저장되어 있지 실제의 값은 저장되어 있지 않습니다. 실제 값들은 ID와 같이 텍스트파일로 다른 리소스들과 같이 저장되어 있습니다. 이는 좌표정보를 모듈화 하여 코드에 대해 잘 알지 못하는 디자이너라도 텍스트파일의 좌표만 수정하여 게임을 수정할 수 있게 하기 위해서 입니다.

AudioManager에서도 ID를 통해 배경 음과 효과음을 재생하고 정지를 하는 일을 하게 됩니다.



클래스 다이어그램



우선 이 프로젝트의 씬은 위와 같이 4개로 이루어져 있습니다. 그 외에 리소스와 랭킹을 관리하는 매니저가 있고 안드로이드 액티비티인 Dropking Punchking이 있고 SHC디바이스를 검색하고 보여주는 FindDeviceActivity가 있습니다.

Dropking,Punchking : 앱이 시작될 때 처음 오는 곳으로 이곳에서 모듈을 이용하여 SHC와 연결하고 값을 받고 JNI를 사용하여 C++코드로 보내주는 역할을 한다.

FindDeviceActivity: 블루투스를 켜주고 현재 사용 가능한 장비를 검색하여 화면에 보여줍니다. 사용자가 기기를 선택하면 onActivityResult를 재 정의하여 선택한 기기의 기기값을 얻어오게 됩니다.

MainMenuScene : 게임의 시작부분으로 시작버튼과 Tutorial버튼이 있습니다. 시작 버튼은 SHC와의 연결이 완료될 때까지 활성화 되지 않습니다. 연결이 완료되면 활성화되면서 사용자는 게임을 시작 할 수 있게 됩니다.

TutorialScene : 게임의 Tutorial이 있는 씬입니다..

DropkingGamePlayScene : 게임이 진행되는 부분입니다. Box2D를 사용해 월드를 만들고 statemachine을 사용하여 각각의 상태마다 처리를 달리합니다. 쌓이는 블록에 맞추어

카메라를 translate시킵니다.

 

PunchkingGamePlayScene : 게임이 진행되는 부분입니다. 스테이지 별로 각각 처리를 하며 게임오버와 클리어를 판단합니다.

DataPocessor : SHC로부터의 값을 JNI를 통해 얻어와 이 클래스객체에 저장하게 됩니다. 개발자는 별다른 처리 없이 Datapossessor의 값을 가지고 처리하면 됩니다.

GameResultScene : RankManager를 사용하여 값을 넘겨주고 5위까지의 값을 받아 화면에 출력해주는 씬입니다. 게임의 재 시작과 종료를 선택할 수 있습니다.

RankManager : SQLite3를 사용하여 데이터베이스를 만들고 테이블을 만듭니다. GameResultScene으로부터 받은 데이터를 쿼리문을 사용하여 insert하고 select하여 지금까지의 순위 데이터를 넘겨줍니다.

AudioManager : ResourceID를 사용하여 사운드를 재생, 정지합니다.

CoordinationManager : ResourceID를 사용하여 텍스트파일에서 읽어온 좌표를 찾아 반환하는 매니저입니다.


SHC로부터 가속도 값을 받아 cocos2d-x class로 넘겨주는 과정


위 플로우차트는 SHC로부터 받은 값을 C++코드인 cocos2d-x class까지 넘겨주는 과정을 보여주고 있습니다. 이러한 값 전달을 위해 총 2개의 콜백 인터페이스가 사용됩니다. 우선 스마트폰과 연결된 기기는 값을 보내주게 되는데 이때 사용하는 콜백 객체는 SHCM1LIBv2라이브러리의 인터페이스인 BTCallback을 사용하게 됩니다. BTCallback을 모듈인 SolmiBroker안에서 재정의되며 객체를 생각하고 그 객체를 SHCM1LIBv2함수를 통해 등록시켜 줍니다. 그 후 모듈에서 만든 콜백 인터페이스를 실제 모듈을 사용하는 게임 액티비티에서 재정의하여 똑같이 모듈에 등록시켜 줍니다.

그 후 기기로부터 들어오는 값은 SHCM1LIBv2에 등록된 콜백 인터페이스 객체의 rcvedData함수를 호출하며 넘겨주게 됩니다. 그러면 rcvedData함수에서는 받은 값의 타입과 사용자가 연결 시에 요청한 데이터 타입을 근거로 필요한 값을 sevent객체에 담아 한 계 아래의 콜백인 게임 액티비티에 재정의된 모듈콜백의 리시브함수를 호출하면서 넘겨줍니다. sevent객체를 받은 모듈콜백은 JNI를 이용해 cocos2d-x class로 넘겨주게 되고 C++에서는 값을 파싱 후 Datapossessor객체에 저장하며 값을 갱신합니다.

결국 사용자는 내부 사정을 알 필요 없이 Datapossessor의 값을 호출하여 처리하면 자동으로 값이 적용되게 되는 것입니다.

이미지 리소스 좌표 

게임 내에 사용되는 모든 이미지들은 좌표를 가지고 있고 그 좌표는 코드안에 있는 것이 아니라. 텍스트 파일로 따로 빼내어 관리합니다. 이렇게 되면 디자이너가 이 후 좌표를 수정할 때도 코드를 건드릴 필요가 없게 됩니다.

우선 텍스트 파일에 리소스ID,X좌표,Y좌표 이렇게 저장되게 됩니다. 그러면 싱글톤으로 된 CoordinationManager가 처음 인스턴스화 될 때 텍스트 파일로부터 좌표를 얻어오게 됩니다. 구현한 split함수를 거처서 저장되게 됩니다. 정보들은’,’(콜론)을 기준으로 나뉘게 Map에 저장됩니다. ID key String으로 저장되고 X,Y좌표는 coordinatePoint 라는 구조체로 싸여서 value로 들어가게 됩니다.

그 후 프로그램에서 CoordinationManager에게 값을 요구할 때 ResourceID에서 정의된 enum ID를 통해서 호출하게 됩니다. 그럼 enum형의 Int값을 map key로 찾아 String ID를 얻고 그것을 이전에 텍스트파일의 좌표를 지정했던 map에서 찾아 coordinatePoint객체를 얻어 반환해줍니다. 그럼 사용자는 반환되는 객체에서 x,y좌표를 사용합니다.