시작하세요! 안드로이드 게임 프로그래밍

143

Post on 22-Jul-2016

279 views

Category:

Documents


21 download

DESCRIPTION

마리오 제흐너 지음 | 유윤선 옮김 | 게임 개발 시리즈 _ 001 | ISBN: 9788992939867 | 36,000원 | 2011년 09월 30일 발행 | 832쪽

TRANSCRIPT

Page 1: 시작하세요! 안드로이드 게임 프로그래밍
Page 2: 시작하세요! 안드로이드 게임 프로그래밍
Page 3: 시작하세요! 안드로이드 게임 프로그래밍

시작하세요!안드로이드 게임

프로그래밍

Page 4: 시작하세요! 안드로이드 게임 프로그래밍

iv

•목 차•

책의 대상 독자 .............................................................................................. xxiii

이 책의 구성 .................................................................................................. xxiv

소스 코드 내려 받기 ..................................................................................... xxiv

01장 __ 안드로이드, 뉴 키즈 온 더 블록 1안드로이드에 대한 간단한 소개 .......................................................................2

파편화 ..................................................................................................................3

구글의 역할 .........................................................................................................4

안드로이드 오픈소스 프로젝트 ..................................................................4

안드로이드 마켓 ..........................................................................................4

챌린지, 개발자 지원 프로그램, 구글 I/O ..................................................6

안드로이드의 기능과 아키텍처 ........................................................................7

커널 .............................................................................................................8

런타임과 달빅 ..............................................................................................8

시스템 라이브러리 ....................................................................................10

애플리케이션 프레임워크 .............................................................................. 11

소프트웨어 개발 킷 ......................................................................................... 12

개발자 커뮤니티 .............................................................................................. 13

기기, 기기, 기기! .............................................................................................. 14

하드웨어 .....................................................................................................14

1세대, 2세대, 차세대 .................................................................................16

Page 5: 시작하세요! 안드로이드 게임 프로그래밍

v

차세대 기기 ................................................................................................20

게임 컨트롤러 ............................................................................................21

모바일 게임의 차이점 ..................................................................................... 22

주머니 속으로 들어간 게임 기기 ..............................................................22

상시 접속 상태의 유지 ..............................................................................23

캐주얼 게임과 하드코어 게임 ...................................................................24

큰 시장과 적은 수의 개발자......................................................................25

정리 ................................................................................................................... 26

02장 __ 안드로이드 SDK 첫 걸음 29개발 환경의 설정 ............................................................................................. 29

JDK의 설정.................................................................................................30

안드로이드 SDK의 설정 ...........................................................................30

이클립스의 설치 ........................................................................................32

ADT 이클립스 플러그인의 설치 ..............................................................33

이클립스 간단히 살펴보기........................................................................36

안드로이드 방식의 Hello World ................................................................... 37

프로젝트의 생성 ........................................................................................38

프로젝트 내용 살펴보기 ...........................................................................39

애플리케이션 코드의 작성........................................................................41

Page 6: 시작하세요! 안드로이드 게임 프로그래밍

vi

안드로이드 애플리케이션의 실행과 디버깅 ................................................ 44

기기 연결 ....................................................................................................44

안드로이드 가상 기기의 생성 ...................................................................44

애플리케이션의 실행 ................................................................................46

애플리케이션 디버깅 ................................................................................49

로그캣과 DDMS ........................................................................................52

ADB의 활용 ...............................................................................................55

정리 ................................................................................................................... 57

03장 __ 게임 개발 101 59장르 - 각인각색 ............................................................................................... 60

캐주얼 게임 ................................................................................................60

퍼즐 게임 ....................................................................................................62

액션 및 아케이드 게임 ..............................................................................63

타워 디펜스 게임 .......................................................................................66

혁신 게임 ....................................................................................................67

게임 설계 - 펜은 코드보다 강하다. ................................................................ 68

핵심 게임 방식 ...........................................................................................69

게임 스토리와 아트 스타일.......................................................................71

화면과 화면 전환 .......................................................................................73

코드 - 핵심적인 세부 내용 ............................................................................. 79

애플리케이션과 창 관리 ...........................................................................80

입력 ...........................................................................................................81

파일 I/O ......................................................................................................86

오디오 .........................................................................................................87

그래픽 .........................................................................................................92

게임 프레임워크 ......................................................................................108

정리 ................................................................................................................. 117

Page 7: 시작하세요! 안드로이드 게임 프로그래밍

vii

04장 __ 게임 개발자를 위한 안드로이드 119안드로이드 애플리케이션의 정의 - 매니페스트 파일 ............................... 120

<manifest> 엘리먼트 .............................................................................121

<application> 엘리먼트 ..........................................................................122

<activity> 엘리먼트 ................................................................................124

<uses-permission> 엘리먼트 .................................................................127

<uses-feature> 엘리먼트 ........................................................................128

<uses-sdk> 엘리먼트 ..............................................................................130

10단계로 끝내는 안드로이드 게임 프로젝트 설정 ...............................131

게임의 아이콘 정의 .................................................................................133

안드로이드 API의 기본 ................................................................................ 135

테스트 프로젝트의 생성 .........................................................................135

액티비티 생명주기 ..................................................................................140

입력 기기의 처리 .....................................................................................149

파일 처리 ..................................................................................................170

오디오 프로그래밍 ..................................................................................178

효과음의 재생 ..........................................................................................178

음악 스트리밍 ..........................................................................................183

기본 그래픽 프로그래밍 .........................................................................188

모범 개발 방식 ............................................................................................... 218

정리 ................................................................................................................. 220

05장 __ 안드로이드 게임 개발 프레임워크 223공략 계획 ........................................................................................................ 223

AndroidFileIO 클래스 ................................................................................. 224

AndroidAudio, AndroidSound, AndroidMusic ....................................... 225

AndroidInput과 AccelerometerHandler ................................................... 232

AccelerometerHandler: 가속도계의 감지 ............................................232

Page 8: 시작하세요! 안드로이드 게임 프로그래밍

viii

Pool 클래스: 재사용은 좋은 것이다! .....................................................234

KeyboardHandler: 위, 아래, 왼쪽, 오른쪽 ............................................237

터치 핸들러 ..............................................................................................242

AndroidInput: 위대한 조율자 ................................................................251

AndroidGraphics과 AndroidPixmap: 두 개의 무지개 ............................. 254

각기 다른 화면 크기와 해상도의 처리 ...................................................254

AndroidPixmap: 사용자를 위한 픽셀 조정 ..........................................260

AndroidGraphics: 드로잉 작업의 수행 .................................................262

AndroidFastRenderView: 루프, 확장, 루프, 확장 ...............................267

AndroidGame: 모든 내용의 종합 ............................................................... 270

정리 ................................................................................................................. 276

06장 __ Mr. Nom 안드로이드를 침공하다 279자원의 생성 .................................................................................................... 279

프로젝트 설정 ................................................................................................ 282

MrNomGame: 메인 액티비티 ..................................................................... 282

Assets: 편리한 자원 저장소 ....................................................................283

Settings: 사용자 선택값과 하이스코어의 추적 .....................................285

LoadingScreen: 디스크로부터 자원 로드 .............................................287

메인 메뉴 화면 ............................................................................................... 289

HelpScreen 클래스(들) ................................................................................ 293

하이스코어 화면 ............................................................................................ 296

숫자 렌더링: 짧은 외출 ...........................................................................296

화면 구현 ..................................................................................................298

추상화... .......................................................................................................... 301

Mr. Nom의 게임 공간에 대한 추상화: 모델, 뷰, 컨트롤러 ..................302

GameScreen 클래스 ................................................................................316

정리 ................................................................................................................. 325

Page 9: 시작하세요! 안드로이드 게임 프로그래밍

ix

07장 __ 오픈GL ES의 간단한 소개 327오픈GL ES는 무엇이고 왜 알아야 하나? .................................................... 327

프로그래밍 모델: 비유 ............................................................................329

투영 .........................................................................................................331

정규화된 기기 공간과 뷰포트 .................................................................333

매트릭스 ...................................................................................................334

렌더링 파이프라인 ..................................................................................335

시작에 앞서 알아야 할 내용들 ..................................................................... 336

작업을 쉽게 도와주는 GLSurfaceView ....................................................... 337

GCGame: Game 인터페이스의 구현 .......................................................... 341

엄마, 내가 빨간색 삼각형을 그렸어! ........................................................... 351

뷰포트의 정의 ..........................................................................................351

투영 매트릭스의 정의 .............................................................................351

삼각형의 지정 ..........................................................................................356

내용 정리 ..................................................................................................361

정점 색상의 지정 ........................................................................................... 365

텍스처 매핑: 손 쉬운 이미지 배치 작업 ...................................................... 370

텍스처 좌표 ..............................................................................................370

비트맵 업로드 ..........................................................................................372

텍스처 필터링 ..........................................................................................374

텍스처의 정리 ..........................................................................................375

유용한 코드 조각 .....................................................................................376

텍스처 활성화 ..........................................................................................376

내용 정리 ..................................................................................................377

텍스처 클래스 ..........................................................................................380

인덱스를 갖는 정점 - 재사용은 항상 유용하다. ......................................... 382

내용 정리 ..................................................................................................385

Vertices 클래스 ........................................................................................387

Page 10: 시작하세요! 안드로이드 게임 프로그래밍

x

알파 블렌딩 .................................................................................................... 390

다양한 원시 도형 : 점, 선, 스트립, 팬 .......................................................... 395

2차원 변형: 모델-뷰 매트릭스를 활용한 재미있는 프로그래밍 ............... 397

세계 공간과 모델 공간 ............................................................................397

다시 살펴보는 매트릭스 .........................................................................399

변형을 활용한 첫 번째 예제....................................................................400

더 많은 변형 .............................................................................................406

성능 최적화 .................................................................................................... 411

프레임 레이트의 측정 .............................................................................411

안드로이드 1.5에서 실행되는 히어로의 문제 사례 ..............................413

오픈GL ES 렌더링을 느리게 만드는 요인 .............................................414

불필요한 상태 변화의 제거.....................................................................416

텍스처 크기를 줄이면 가져올 픽셀도 줄어든다 ...................................418

오픈GL ES/JNI 메서드 호출의 제한 ......................................................419

바인딩 정점 ..............................................................................................420

마무리하며 ...............................................................................................424

정리 ................................................................................................................. 425

08장 __ 2D 게임 프로그래밍 기법 427시작에 앞서 .................................................................................................... 427

태초에 벡터가 있었다 ................................................................................... 428

벡터의 활용 ..............................................................................................429

간단한 삼각함수 이론 .............................................................................432

Vector 클래스의 구현 ..............................................................................434

간단한 사용 예제 .....................................................................................439

간단한 2차원 물리 ......................................................................................... 444

뉴턴과 오일러, 영원한 좋은 친구들 .......................................................445

힘과 질량 ..................................................................................................446

Page 11: 시작하세요! 안드로이드 게임 프로그래밍

xi

이론적인 적용 ..........................................................................................447

실제 적용 ..................................................................................................448

충돌 감지와 2차원에서의 객체 표현 ........................................................... 453

경계 도형 ..................................................................................................454

경계 도형의 구성 .....................................................................................456

게임 객체의 어트리뷰트 .........................................................................459

광범위 충돌 감지와 미세 충돌 감지 .......................................................460

적용 예제 ..................................................................................................469

2차원 카메라 .................................................................................................. 486

Camera2D 클래스 ...................................................................................489

예제 .........................................................................................................491

텍스처 아틀라스: 공유는 관심이다 ............................................................. 493

예제 .........................................................................................................496

텍스처 영역, 스프라이드, 배치: 오픈GL ES 숨기기 .................................. 500

TextureRegion 클래스 ............................................................................501

SpriteBatcher 클래스 ..............................................................................502

스프라이트 애니메이션 ................................................................................ 514

Animation 클래스 ...................................................................................515

예제 .........................................................................................................517

정리 ................................................................................................................. 523

09장 __ 수퍼 점퍼 - 2D 오픈GL ES 게임 525핵심 게임 방식 ............................................................................................... 525

게임의 배경 이야기와 아트 스타일 ............................................................. 526

화면과 화면 전환 ........................................................................................... 527

게임 세계의 정의 ........................................................................................... 528

자원의 생성 .................................................................................................... 531

UI 요소 .....................................................................................................531

Page 12: 시작하세요! 안드로이드 게임 프로그래밍

xii

비트맵 폰트를 활용한 텍스트 처리 ........................................................533

게임 요소 ..................................................................................................536

텍스처 아틀라스 ......................................................................................538

음악과 효과음 ..........................................................................................539

수퍼 점퍼 게임의 구현 .................................................................................. 541

Assets 클래스 ...........................................................................................541

Settings 클래스 ........................................................................................545

메인 액티비티 ..........................................................................................547

Font 클래스 ..............................................................................................548

GLScreen ..................................................................................................550

메인 메뉴 화면 .........................................................................................551

도움말 화면 ..............................................................................................555

하이스코어 화면 ......................................................................................558

시뮬레이션 클래스 ..................................................................................561

WorldRenderer 클래스 ...........................................................................591

최적화하기 또는 최적화하지 않기 .............................................................. 596

정리 ................................................................................................................. 598

10장 __ 오픈GL ES를 활용한 3D 601시작에 앞서 .................................................................................................... 602

3D의 정점 ...................................................................................................... 602

Vertices3: 3D 위치의 저장 ......................................................................602

예제 .........................................................................................................605

시점 투영 - 가까이 있는 대상을 더 크게 ..................................................... 609

z버퍼 – 혼란 속에 질서를 부여하다 ............................................................ 612

이전 예제의 수정 .....................................................................................614

블렌딩 - 뒤에 아무도 없다 ......................................................................615

z버퍼의 정확도와 z 파이팅 .....................................................................618

Page 13: 시작하세요! 안드로이드 게임 프로그래밍

xiii

3D 메시의 정의 ............................................................................................. 620

큐브 - Hello World 3D ............................................................................621

예제 .........................................................................................................624

다시 살펴보는 매트릭스와 변형 .................................................................. 628

매트릭스 스택 ..........................................................................................629

매트릭스 스택을 갖춘 계층적 시스템 ....................................................631

간단한 나무상자 태양계 시스템 .............................................................632

정리하기 ...................................................................................................636

간단한 카메라 시스템 .............................................................................640

정리 ................................................................................................................. 644

11장 __ 3D 프로그래밍 트릭 647시작에 앞서 .................................................................................................... 647

3D에서의 벡터 .............................................................................................. 648

오픈GL ES에서의 빛 ..................................................................................... 654

빛의 적용 방식 .........................................................................................654

광원 .........................................................................................................656

재료 .........................................................................................................657

오픈GL ES가 빛을 계산하는 방법 - 정점 법선 .....................................658

실제 적용 ..................................................................................................659

오픈GL ES의 광원 사용과 관련한 몇 가지 참고 사항 ..........................676

밉매핑 ............................................................................................................. 677

간단한 카메라 ................................................................................................ 683

1인칭 카메라 또는 오일러 카메라..........................................................683

오일러 카메라 예제 .................................................................................687

관찰 카메라 ..............................................................................................694

모델의 로딩 .................................................................................................... 697

Wavefront OBJ 형식................................................................................697

Page 14: 시작하세요! 안드로이드 게임 프로그래밍

xiv

OBJ 로더의 구현 ......................................................................................699

OBJ 로더의 활용 ......................................................................................705

모델 로딩과 관련한 참고사항 .................................................................705

간단한 3D 물리 이론..................................................................................... 706

3D에서의 충돌 감지와 객체 표현 ................................................................ 707

3D에서의 경계 도형 ................................................................................707

경계 구의 충돌 검사 ................................................................................708

GameObject3D와 DynamicGameObject3D .......................................710

정리 ................................................................................................................. 712

12장 __ 드로이드 인베이더 - 그랜드 파이널 715핵심 게임 방식 ............................................................................................... 715

배경 이야기와 아트 스타일 .......................................................................... 717

게임 화면과 화면 전환 .................................................................................. 718

게임 세계의 정의 ........................................................................................... 719

자원의 생성 .................................................................................................... 721

UI 자원 .....................................................................................................721

게임 자원 ..................................................................................................722

음악과 효과음 ..........................................................................................724

접근 방법 ........................................................................................................ 725

Assets 클래스 ................................................................................................. 725

Settings 클래스 .............................................................................................. 729

메인 액티비티 ................................................................................................ 731

메인 메뉴 화면 ............................................................................................... 732

설정 화면 ........................................................................................................ 736

Page 15: 시작하세요! 안드로이드 게임 프로그래밍

xv

시뮬레이션 클래스 ........................................................................................ 739

Shield 클래스 ...........................................................................................740

Shot 클래스 ..............................................................................................740

우주선 클래스 ..........................................................................................741

인베이더 클래스 ......................................................................................744

세계 클래스 ..............................................................................................747

GameScreen 클래스 ..................................................................................... 755

WorldRender 클래스 .................................................................................... 764

최적화 ............................................................................................................. 771

정리 ................................................................................................................. 773

13장 __ 게임 배포 775테스트에 대한 조언 ....................................................................................... 775

개발자 등록 .................................................................................................... 777

게임 APK 서명 .............................................................................................. 778

마켓에 게임 배포 ........................................................................................... 781

자원 업로드 ..............................................................................................782

Listing Details ..........................................................................................783

배포 옵션 ..................................................................................................784

배포! .........................................................................................................784

마케팅 .......................................................................................................785

개발자 콘솔 .................................................................................................... 785

정리 ................................................................................................................. 787

Page 16: 시작하세요! 안드로이드 게임 프로그래밍

xvi

14장 __ 이제 어디로? 789게임의 소셜 연동 ........................................................................................... 789

위치 기반 게임 ............................................................................................... 790

멀티플레이어 기능 ........................................................................................ 790

오픈GL ES 2.0 및 그 외 기능 ........................................................................ 790

프레임워크와 엔진 ........................................................................................ 791

웹 자료 ............................................................................................................ 793

맺음말 ............................................................................................................. 793

찾아보기..............................................................................794

Page 17: 시작하세요! 안드로이드 게임 프로그래밍

xvii

나의 우상인 아버지와 어머니, 그리고 사랑하는 아내 스테파니에게

Page 18: 시작하세요! 안드로이드 게임 프로그래밍

xviii

•옮긴이 글•

전통적으로 게임 개발은 항상 어려웠다. 게임 개발이 어려운 이유는 파일 입출력(I/O), 사용자

입력 처리, 그래픽, 오디오 등의 기본적인 프로그래밍 요소를 잘 제어해야 함은 물론 게임 설계에

따라 게임 방식도 구현해야 하기 때문이다. 또 모바일 게임에서는 제한된 리소스 탓에 리소스 생

성을 최소화해야 하고, 안드로이드 플랫폼에서는 파편화에 대해서도 신경 써야 한다. 이렇게 문

제를 나열하고 보니 게임 개발이 더 어렵게만 느껴진다. 그럼 대체 어디서부터 시작해야 할까?

일단 생각해볼 수 있는 해결책 중 하나로 추상화가 있다. 이를테면 사용자 입력 처리 부분을

추상화하면 싱글터치와 멀티터치 기반의 각기 다른 사용자 입력을 얼마든지 처리할 수 있다. 또

그래픽 부분을 추상화하면 실제 구현체를 2D 그래픽으로 구현하든 오픈GL ES를 활용한 3D로

구현하든 문제가 되지 않는다. 또 프레임워크를 통한 개발도 해결책으로 생각해볼 수 있다. 물론

평범한 개발자가 프레임워크를 단기간에 만들기란 쉽지 않지만 이런 추상화를 통해 결합도를 줄

이고 견고한 코드 기반을 마련해 이를 토대로 게임을 개발하면 개발 생산성이 증대됨은 물론 이

후 게임을 추가로 개발하기도 훨씬 수월해진다.

이 책에서는 이와 같은 접근 방식을 통해 안드로이드 게임을 개발하는 법을 설명한다. 이 책의

저자인 마리오 제흐너는 오픈소스인 libgdx(http://code.google.com/p/libgdx/)의 주 개발자로

서 누구보다도 게임 프레임워크를 만드는 법을 잘 설명할 수 있는 저자다. 이 책에서는 게임 개발

의 기본이 되는 각 프레임워크 요소를 추상화하고 실제 예제 코드를 통해 각 프레임워크 요소를

적절히 구현함으로써 재사용할 수 있는 게임 프레임워크를 완성하는 법을 보여준다. 또 게임 로

직 구현에 도움이 되는 배경 지식을 설명하면서 충돌 감지, 비트맵 블리팅, 3D 그래픽 프로그래

밍 같은 고급 주제를 차례로 소개한다.

또 이 책에서는 안드로이드의 파편화 문제 같은 플랫폼 관련 이슈도 빠짐없이 다룬다. 이 책을

통해 독자는 가장 최신 API를 활용해 게임을 개발하는 동시에 가장 폭넓은 기기 사용자층을 공

략하는 법을 배울 수 있다. 또 각기 다른 화면 크기에 맞게끔 게임 화면을 그리는 법도 이 책에서

Page 19: 시작하세요! 안드로이드 게임 프로그래밍

xix

배울 수 있다. 이런 다양한 화면 크기는 안드로이드 플랫폼의 또 다른 파편화 요소인데, 이 책에

서는 프레임워크를 활용한 추상화를 통해 실제 게임 로직과 이런 프레젠테이션 로직을 완전히

분리하고 있다.

이 책은 하나의 게임 프레임워크를 만드는 법을 소개한 책이면서 동시에 이런 게임 프레임워크

를 활용해 각기 다른 안드로이드 게임을 개발하는 법을 소개한 책이다. 독자들이 이 책에서 효과

적인 게임 프레임워크 작성법을 익히고 이를 토대로 다음 번 안드로이드 히트 게임을 만들 수 있

게 되기를 바란다.

이 책의 대상 독자

이 책은 자바 언어에 대한 기본 지식이 있는 독자를 대상으로 한다. 이 책에서는 게임 개발에 필

요한 안드로이드 프레임워크 관련 지식을 모두 설명하므로 이 책의 독자는 안드로이드 개발 경험

이 전혀 없더라도 괜찮다. 게임 프레임워크를 통해 재사용할 수 있는 게임 코드 기반을 만들고 싶

은 독자, 안드로이드 게임 개발에 입문하고 싶은데 어디서부터 시작해야 할지 모르는 독자, 다른

플랫폼에서 개발한 게임을 안드로이드로 이식하고 싶은 독자 모두에게 이 책을 추천한다.

감사의 글

먼저 이 책의 번역을 맡겨주신 위키북스 박찬규 사장님과 김윤래 팀장님께 감사드린다. 오랜 번

역 기간에도 역자를 믿고 책을 맡겨주신 두 분께 이 자리를 빌어 진심으로 감사 인사를 드린다.

또 좋은 책을 집필해준 저자 마리오 제흐너와 오늘날 안드로이드를 있게 해준 앤디 루빈에게도

감사하고 싶다. 끝으로 사랑하는 가족과 항상 함께 하시는 하나님께 감사하다.

- 유윤선

Page 20: 시작하세요! 안드로이드 게임 프로그래밍

xx

•저자 소개•

마리오 제흐너 (Mario Zechner)

마리오 제흐너는 일과 시간에는 R&D 소프트웨어 엔지니어로 근무하고 저

녁에는 Badlogic Games라는 이름으로 게임을 개발해 출시하는 게임 개발

자로 일한다. 마리오는 수많은 프로토타입 게임과 소규모 게임을 비롯해 안

드로이드용 Newton 게임과 윈도우, 리눅스, 맥 OS X용 Quantum 게임을

개발했다. 현재 그는 libgdx라는 오픈소스 크로스플랫폼 게임 개발 솔루션

을 개발 중이다. 마리오는 코딩 작업 외에 게임 개발과 관련한 튜토리얼과 기술 문서 집필 활동도

열심히 하고 있다. 그가 쓴 글은 웹과 블로그(http://www.badlogicgames.com)에서 무료로 볼

수 있다.

Page 21: 시작하세요! 안드로이드 게임 프로그래밍

xxi

•기술 감수자 소개•

로버트 그린 (Robert Green)

로버트 그린은 포틀랜드 오리건 출신의 인디 비디오 게임 개발자로서,

Battery Powered Games라는 이름으로 게임을 출시하고 있다. 로버트는

Deadly Chambers, Antigen, Wixel, Light Racer, Light Racer 3D 등 6개

의 안드로이드 게임을 개발했다. 모바일 게임 개발을 전업으로 삼기 전에는

미네아폴리스와 시카고에 있는 IBM 인터랙티브 같은 소프트웨어 업체에

서 일했다. 로버트의 최근 관심사는 크로스플랫폼 게임 개발과 고성능 모바일 게임 개발이다.

Page 22: 시작하세요! 안드로이드 게임 프로그래밍

xxii

•감사의 글•

먼저 이 책이 나올 수 있게 해준 Apress 출판사에 감사한다. 특별히 필자의 바보 같은 질문에도

항상 지친 기색 없이 친절히 답해준 책의 편집자 캔더스 잉글리시와 아담 헬스에게 감사한다. 매

튜 무디는 필자가 각 절의 구조를 잡는 데 도움을 주었고 책을 한결 더 읽기 쉽게 만드는 데 많은

조언을 해주었다. 데이먼 라슨과 제임스 콤스톤은 필자의 문법 실수를 모두 교정해 주었다. 이분

들 덕분에 즐겁게 집필 작업을 할 수 있었다.

또 이 책의 기술 검토를 담당해준 필자의 친구 로버트 그린에게도 감사하다. 로버트는 필자의

두서 없는 글이 기술적으로 올바른지 모두 검토해주었다. 이제 독자들이 이 책에서 버그나 오류

를 찾아내더라도 로버트가 필자 대신 희생양이 돼줄 것이다.

아울러 책의 아이디어와 피드백을 전달해 준 전 세계 많은 친구들에게 특별히 감사한다. 특별

히 libgdx에서 필자와 함께 일하는 동료 개발자인 나단 스위트, 데이브 클레이톤, 데이브 프래스

카, 모리츠 포스트, 크리스토프 위둘, 토니 웽에게 감사하다. 스웨덴에 있는 필자의 오랜 코딩 동

료인 존 필과 알리 모자비안, 업무 시간에 즐겁게 일한 직장 동료인 로만 컨과 마커스 머에게도 감

사한다.

끝으로 오랜 시간 책을 집필하는 남편을 묵묵히 참고 견뎌준 사랑하는 아내 스테파니에게도

고맙다는 말을 전하고 싶다.

Page 23: 시작하세요! 안드로이드 게임 프로그래밍

xxiii

•서 문•

안드로이드 게임 개발 세계에 입문한 것을 환영한다. 필자의 이름은 마리오다. 이제부터 필자는

이어질 14개의 장에 걸쳐 여러분이 안드로이드 게임을 개발할 수 있게 도와주는 가이드가 돼줄

것이다. 이 책을 구매한 독자라면 안드로이드 게임 개발에 대해 배우려고 책을 구매했을 텐데 모

쪼록 필자를 통해 여러분의 꿈을 실현할 수 있기를 바란다.

이 책에서는 다양한 주제를 다룬다. 안드로이드의 기본 원리, 오디오와 그래픽 프로그래밍, 약

간의 수학과 물리 이론, 그리고 어렵게만 들리는 오픈GL ES 등이 우리가 다룰 내용이다. 이런 지

식을 기반으로 이 책에서는 세 개의 각기 다른 게임을 개발한다. 그중에는 물론 3D 게임도 들어

있다.

게임 프로그래밍은 여러분이 하고 있는 일을 제대로 알 때 비로소 쉬워진다. 그래서 이 책에서

는 재사용하기 쉬운 코드를 제시하는 것뿐 아니라 게임 개발이라는 큰 그림을 보여줄 수 있는 형

태로 책의 내용을 설명하려고 노력했다. 이런 내부 원리를 잘 이해해야만 복잡한 게임 아이디어

를 제대로 공략할 수 있다. 이 책을 통해 독자들은 책에서 개발한 게임과 비슷한 게임뿐 아니라

웹이나 서점에서 추가로 얻은 지식을 바탕으로 새로운 게임 영역을 개발할 수 있을 만큼 충분한

기초 지식을 쌓을 수 있을 것이다.

책의 대상 독자

이 책은 우선 게임 프로그래밍 초급자를 대상으로 한다. 이 책의 독자는 게임 프로그래밍에 대한

사전 지식이 전혀 없어도 된다. 게임 프로그래밍에 대한 기본 지식은 이 책에서 모두 다루고 있다.

다만 이 책의 독자라면 자바에 대해 어느 정도 알고 있어야 한다. 자바 언어에 익숙지 않은 독자

라면 브루스 에켈이 지은 <©inking in Java(Prentice Hall, 2006)>의 온라인판을 읽어볼 것을

권한다. 이 책은 자바 언어에 대한 매우 훌륭한 입문서다. 자바 언어에 대한 기본 지식 외에 특별

히 갖춰야 할 지식은 없다. 안드로이드나 이클립스를 몰라도 상관없다.

Page 24: 시작하세요! 안드로이드 게임 프로그래밍

xxiv

또 이 책은 안드로이드에서 게임을 개발하고자 하는 중급 게임 프로그래머를 대상으로 하는

책이다. 이런 독자에게는 책의 내용 중 일부가 이미 익숙하겠지만 이 책에서는 다양한 팁과 힌트

를 소개하고 있으므로 많은 도움이 될 것이다. 안드로이드는 때때로 예상치 못한 동작을 하기도

하는데, 이때 이 책의 내용이 크게 도움될 것이다.

이 책의 구성

이 책에서는 반복적인 접근 방식을 토대로 매우 기초적인 내용부터 하드웨어 가속을 활용한 고

급 게임 프로그래밍까지 천천히, 하지만 확실히 소개한다. 이 책에서는 각 장을 통해 재사용할

코드 기반을 마련하므로 이 책을 순서대로 읽을 것을 권한다. 물론 경험이 많은 독자라면 자신이

확실히 알고 있는 장의 내용은 건너뛰어도 상관없다. 하지만 책의 내용을 건너뛰더라도 고급 주

제를 다루는 절에서 해당 클래스와 인터페이스를 어떻게 사용하는지 이해할 수 있게끔 각 절의

코드 예제는 모두 읽어볼 것을 권한다.

소스 코드 내려 받기

이 책에는 게임 예제를 실행하는 데 필요한 코드와 게임 코드 등 모든 예제 코드가 들어 있다. 하

지만 책의 예제를 이클립스로 그대로 옮겨 적으면 오타로 인해 에러가 나기 쉽고, 게임이 코드로

만 구성된 것도 아니며, 책에 나와 있지 않은 게임 자원들도 있다. (이 책의 기술 검토자인) 로버트

와 필자는 이 책의 모든 예제에 에러가 없도록 각별히 주의했지만 사소한 오류를 모두 잡아내는

작업은 항상 어렵기 마련이다.

이 작업을 좀 더 쉽게 하기 위해 필자는 다음과 같은 기능을 제공하는 구글 코드 프로젝트를

생성했다.

■ GPL 3 버전 라이선스를 적용한 전체 코드와 자원을 프로젝트의 서브버전 저장소를 통해

제공

■ 텍스트와 동영상 데모를 통해 프로젝트를 이클립스로 임포트하는 법을 보여주는 퀵스타

트 가이드

Page 25: 시작하세요! 안드로이드 게임 프로그래밍

xxv

■ 책과 책의 코드상의 에러를 보고할 수 있는 이슈 트래커. 이슈 트래커를 통해 이슈를 보고

하면 필자가 서브버전 저장소에서 관련 오류를 수정할 수 있다. 이 방식을 활용하면 독자

는 항상 최신 코드를 사용할 수 있고 다른 독자들도 에러가 없는 책의 코드를 통해 도움

을 받을 수 있다.

■ 누구든지 무료로 가입해 책의 내용에 대해 얘기할 수 있는 토론 그룹. 물론 필자도 이 그

룹에 항상 참여하고 있다.

코드가 들어 있는 각 장마다 서브버전 저장소에 관련 이클립스 프로젝트가 저장돼 있다. 이 책

에서는 책의 내용이 진행되는 동안 일부 프레임워크 클래스를 반복 작업을 통해 개선하므로 책

의 프로젝트는 서로 의존성을 갖고 있지 않다. 따라서 각 프로젝트는 서로 독립적이다. 5장과 6장

의 코드는 ch06-mrnom 프로젝트에 모두 들어 있다.

이 책의 구글 코드 프로젝트는 아래 사이트에서 확인할 수 있다.

■ http://code.google.com/p/beginning-android-games/

원서 출판사인 Apress나 위키북스 홈페이지에서 바로 소스코드를 내려 받을 수 있다. 아래 위

키북스 홈페이지에서 <시작하세요! 안드로이드 게임 프로그래밍> 표지를 클릭하면 소스코드

메뉴가 있다.

■ www.wikibook.co.kr

■ http://www.apress.com/9781430230427

아래는 위키북스에서 소스코드를 바로 내려 받을 수 있는 주소다.

■ http://wikimain.cafe24.com/wiki/data/BeginningAndroidGames/

BeginningAndroidGames_source.zip

Page 26: 시작하세요! 안드로이드 게임 프로그래밍

Beg

inni

ng

And

roid

Gam

es

Page 27: 시작하세요! 안드로이드 게임 프로그래밍

1

01안드로이드, 뉴 키즈 온 더 블록

90년대 초반에 유년 시절을 보낸 필자는 자연스럽게 닌텐도 게임 보이를 하면서 자랐다. 필자는

마리오로 공주를 구하고, 테트리스에서 최고 점수를 갱신하고, 링크 케이블을 통해 친구들과

RC Pro-Am 레이싱 게임을 하면서 수없이 많은 시간을 보냈다. 필자는 어디를 가든 항상 게임 보

이를 들고 다녔다. 게임에 대한 열정으로 인해 필자는 자신만의 공간을 만들고 그 공간을 친구들

과 나누고 싶다는 생각을 했다. 필자는 PC에서 프로그래밍을 시작했지만 이내 내가 만든 위대한

게임을 게임 보이에서 실행할 수 없다는 사실을 깨달았다. 이후로도 필자는 열정적인 프로그래

머가 되기 위해 꾸준히 노력했지만 시간이 지나면서 비디오 게임을 플레이하는 재미는 점점 줄

어들었다. 그리고 게임 보이도 결국 고장이 났다.

지금은 2011년이다. 오늘날에는 스마트폰이 새로운 모바일 게임 플랫폼이 되고 있으며 닌텐도

DS나 플레이스테이션 포터블 같은 전통적인 모바일 게임 시스템을 위협하고 있다. 이런 현실은

다시 한 번 필자의 관심을 끌었고 필자는 어떤 모바일 플랫폼이 개발 목적에 가장 적합할까 궁리

하기 시작했다. 하지만 필자는 이내 시스템이 오픈돼 있지 않거나, 개발한 내용을 다른 사람과 공

유하려면 애플의 승인이 필요하다거나, iOS용 게임을 만들려면 맥이 필요하다는 사실을 깨달았

다. 그러던 차에 안드로이드가 눈에 들어왔다.

필자는 첫눈에 안드로이드에 반했다. 안드로이드 개발 환경은 두말할 것 없이 주요 플랫폼에

서 모두 동작한다. 안드로이드는 개발자들이 부딪치는 문제를 도와주고자 하는 왕성한 커뮤니

티를 갖고 있으며 방대한 문서를 제공한다. 또 비용을 지불하지 않고도 게임을 모든 사람과 공유

할 수 있으며, 작업물을 통해 돈을 벌고 싶다면 단 몇 분 만에 수백만 명의 사용자를 지닌 세계

시장에 작품을 내놓을 수 있다.

Page 28: 시작하세요! 안드로이드 게임 프로그래밍

2 l 시작하세요! 안드로이드 게임 프로그래밍

이제 필자에게 남은 과제는 단 하나뿐이었다. 바로 안드로이드용 게임을 실제로 어떻게 개발하

고 필자의 PC 게임 지식을 안드로이드 시스템에 맞게 어떻게 변형할지만 알면 됐다. 이어지는 장

들에서 필자는 그동안 느낀 경험을 독자들과 나누고 독자들이 안드로이드 게임 개발을 시작할

수 있게 도와주려고 한다. 이건 다소 개인적인 욕심이지만 독자들을 통해 필자가 플레이할 만한

안드로이드 게임이 더 많이 나오기를 바란다!

그럼 안드로이드에 대한 소개부터 내용을 시작하자.

안드로이드에 대한 간단한 소개

안드로이드는 구글이 2005년도에 Android, Inc라는 신생 기업을 인수하면서 처음으로 주목

을 받았다. 이 인수로 인해 구글이 모바일 세계에 뛰어들 것이라는 전망이 더욱 힘을 얻게 됐다.

2008년 안드로이드 1.0 버전을 출시하면서 구글은 이런 전망에 종지부를 찍었고 안드로이드는

모바일 시장에 도전하는 새로운 플랫폼이 됐다. 이후 안드로이드는 iOS(아이폰 OS)와 블랙베리

같은 기존 플랫폼과 경쟁을 계속하고 있으며 현재 안드로이드가 이 경쟁에서 승리할 가능성은

다소 높아 보인다.

안드로이드는 오픈소스이므로 휴대기기 제조사들이 플랫폼을 사용할 때 진입 장벽이 낮다.

휴대기기 제조사들은 특정 기기의 처리 능력에 맞게 안드로이드 자체를 수정해 각기 다른 가격

대의 제품을 얼마든지 만들 수 있다. 따라서 안드로이드는 고사양의 기기뿐 아니라 저예산 기기

에도 배포할 수 있으며 그만큼 사용자층이 넓다.

안드로이드 성공의 핵심 요소 중 하나는 2007년 말에 결성된 OHA다. OHA에는 HTC, 퀄컴,

모토로라, 엔비디아 같은 기업들이 참여한다. 이들 기업은 모바일 기기에 대한 공개 표준을 개발

하기 위해 서로 협력하고 있다. 물론 안드로이드의 코어는 주로 구글에서 개발하지만 다른 OHA

회원들도 여러 형태로 안드로이드 소스에 기여하고 있다.

안드로이드 자체는 리눅스 커널 버전 2.6 기반의 모바일 운영체제이자 플랫폼으로서 상업 및

비상업적 용도로 자유롭게 사용할 수 있다. OHA에 속한 기업들은 수정된 UI를 적용해 자신들

의 기기에 맞는 커스텀 안드로이드 버전을 개발하고 있다. 이런 사례로는 HTC에서 제조한 HTC

센스와 모토로라의 모터블러 등이 있다. 안드로이드의 오픈소스 성격으로 인해 자신만의 안드로

이드 버전을 취미로 만들어 배포하는 사람들도 나오고 있다. 이런 버전은 보통 mods, 펌웨어, 롬

이라고 부른다. 이 책을 쓰고 있는 현 시점 기준으로 가장 유명한 롬은 Cyanogen이 개발한 롬으

Page 29: 시작하세요! 안드로이드 게임 프로그래밍

01 안드로이드, 뉴 키즈 온 더 블록 l 3

로, 모든 안드로이드 기기에 가장 큰 성능 개선을 가져오는 것을 목적으로 하고 있다.

2008년 출시된 이후 안드로이드는 8번의 버전 업데이트(3.0 버전은 태블릿 PC용)를 감행했으

며 매번 디저트의 이름을 따서 코드명을 지었다(안드로이드 1.1 버전은 예외다). 매 버전 업데이

트에서는 안드로이드 플랫폼에 새로운 기능을 추가했으며 이는 게임 개발자에게 어떤 식으로

든 영향을 주고 있다. 1.5 버전(컵케익)에서는 순수 자바로만 개발할 수 있었던 안드로이드 애플

리케이션에 대해 네이티브 라이브러리 지원 기능을 추가했다. 네이티브 코드는 성능이 중요한 애

플리케이션에서 큰 도움이 된다. 버전 1.6(도넛)에서는 서로 다른 화면 해상도를 지원했다. 안드

로이드에서 게임을 개발할 때는 해상도로 인한 영향이 크므로 이 문제는 이 책에서 여러 번 다시

살펴볼 것이다. 버전 2.0(이클레어)에서는 멀티터치 화면을 지원했고, 버전 2.2(프로요)에서는 안

드로이드의 자바 애플리케이션을 구동하는 달빅 가상 머신에 JIT 컴파일 기능을 추가했다. JIT

는 상황에 따라 안드로이드 애플리케이션의 실행 속도를 5배까지 향상시킨다. 이 책을 쓰고 있는

현 시점 기준으로 가장 최신 버전은 진저브레드라는 2.3 버전이다. 진저브레드에서는 달빅 VM

에 새로운 동시성 가비지 컬렉터가 추가됐다. 아직 눈치 못 챈 독자들이 있을까봐 미리 말하지만

안드로이드 애플리케이션은 자바로 작성한다.

태블릿을 대상으로 하는 안드로이드 버전 3.0 허니컴은 2011년 1월에 출시됐다. 허니컴은 아

직까지는 휴대폰에서 실행하기 위한 버전이 아니다. 하지만 허니컴의 일부 기능은 안드로이드

메인 라인으로 포팅될 수도 있다. 안드로이드 2.3은 커스텀 롬을 활용해 여러 기기에서 설치할

수 있다.

파편화

안드로이드 플랫폼의 유연성으로 인한 단점도 있다. 자체 UI를 개발하는 기업들이 새로 출시되

는 안드로이드 버전에 빠른 속도로 발맞춰 나가야 하기 때문이다. 이로 인해 출시된 지 몇 개월

안 된 휴대폰도 기기 제조사나 판매사가 새로운 안드로이드 버전 업데이트를 거부함에 따라 금

방 구식이 되곤 한다. 이런 과정을 통해 안드로이드 플랫폼은 파편화된다.

파편화의 측면은 다양하게 나타난다. 최종 사용자 입장에서 파편화란 과거 안드로이드 버전이

장착돼 있어서 특정 애플리케이션이나 기능을 사용할 수 없는 현상을 뜻한다. 개발자 입장에서

파편화란 모든 안드로이드 버전에서 동작할 수 있는 애플리케이션을 개발하기 위해 더 많은 주

의를 기울여야 함을 뜻한다. 과거 안드로이드 버전을 사용해 개발한 애플리케이션은 보통 새 버

전에서도 잘 동작하지만, 그 반대는 성립하지 않는다. 예를 들어 멀티터치 지원처럼 새로운 안드

Page 30: 시작하세요! 안드로이드 게임 프로그래밍

4 l 시작하세요! 안드로이드 게임 프로그래밍

로이드 버전에서 추가된 기능은 당연히 기존 버전에서 사용할 수 없다. 따라서 개발자들은 각기

다른 안드로이드 버전에 맞게끔 별도 코드를 작성해 코드를 분기할 수밖에 없다.

하지만 그렇다고 겁 먹을 필요는 없다. 물론 이런 말이 무섭게 들릴 수도 있지만 사실 실제로 별

도 처리해야 하는 영역은 최소한의 수준이다. 대부분의 경우 이런 문제를 신경 쓰지 않고 안드로

이드 버전이 한 개뿐인 것처럼 개발을 진행하면 된다. 게임 개발자의 경우 API의 차이점보다는

하드웨어 성능에 좀 더 신경을 써야 한다. 이는 또 다른 종류의 파편화로서, iOS 같은 플랫폼에

서도 똑같이 겪는 문제다. 이 책에서는 안드로이드 게임을 개발하는 도중 파편화 문제가 될 만한

주제들을 함께 다루고 있다.

구글의 역할

물론 안드로이드는 공식적으로 OHA의 플랫폼이지만 안드로이드 자체를 구현하고 안드로이드

가 성장하는 데 필요한 생태계를 제공하는 실질적인 리더는 구글이다.

안드로이드 오픈소스 프로젝트

구글의 노력은 안드로이드 오픈소스 프로젝트라는 이름으로 요약된다. 이 프로젝트의 코드 대

부분은 아파치 라이선스 2를 따른다. 이 라이선스는 GNU GPL 같은 다른 오픈소스 라이선스와

비교해 더욱 개방적이고 제약이 덜한 라이선스다. 누구든 이 소스를 자유롭게 사용해 자신의 시

스템을 개발할 수 있다. 하지만 안드로이드 호환 시스템으로 선전하려면 먼저 안드로이드 호환

성 프로그램을 통과해야 한다. 안드로이드 호환성 프로그램은 우리 같은 개발자가 작성한 서드

파티 애플리케이션의 기본 호환성을 담보하기 위한 검증 절차다. 호환 시스템에는 안드로이드 마

켓을 비롯해 안드로이드 생태계에 참여할 수 있는 자격이 주어진다.

안드로이드 마켓

안드로이드 마켓은 구글이 2008년 10월에 일반에 공개했다. 안드로이드 마켓은 사용자가 서드

파티 애플리케이션을 검색하고 설치할 수 있는 온라인 소프트웨어 상점이다. 이 마켓은 보통 기

기에 있는 마켓 애플리케이션을 통해서만 접근할 수 있다. 하지만 구글에 따르면 이 상황은 머지

않은 미래에 바뀔 수 있다. 구글에서는 브라우저를 통해 접근할 수 있는 데스크톱 기반의 온라인

상점을 열 계획이다.

Page 31: 시작하세요! 안드로이드 게임 프로그래밍

01 안드로이드, 뉴 키즈 온 더 블록 l 5

서드파티 개발자는 마켓에서 무료나 유료로 애플리케이션을 배포할 수 있다. 유료 애플리케이

션은 약 30개 국에서 구매할 수 있다. 개발자가 유료로 애플리케이션을 팔 수 있는 곳은 이보다

조금 적다. 표 1-1에는 애플리케이션을 사고 팔 수 있는 국가들의 목록이 나와 있다.

표 1-1 애플리케이션을 매매할 수 있는 국가별 옵션

국가 사용자의 애플리케이션 구매 가능 여부 개발자의 애플리케이션 판매 가능 여부

호주 예 예

오스트리아 예 예

벨기에 예 예

브라질 예 예

캐나다 예 예

체코 공화국 예 아니오

덴마크 예 예

핀란드 예 예

프랑스 예 예

독일 예 예

홍콩 예 예

헝가리 예 예

인도 예 예

아일랜드 예 예

이스라엘 예 예

이탈리아 예 예

일본 예 예

멕시코 예 예

네덜란드 예 예

뉴질랜드 예 예

노르웨이 예 예

파키스탄 예 아니오

폴란드 예 아니오

포르투갈 예 예

러시아 예 예

싱가포르 예 예

대한민국 예 예

스페인 예 예

Page 32: 시작하세요! 안드로이드 게임 프로그래밍

6 l 시작하세요! 안드로이드 게임 프로그래밍

국가 사용자의 애플리케이션 구매 가능 여부 개발자의 애플리케이션 판매 가능 여부

스웨덴 예 예

스위스 예 예

대만 예 예

영국 예 예

미국 예 예

사용자는 구글 계정을 설정한 후부터 마켓에 접근할 수 있다. 현재 애플리케이션은 신용카드

로만 구매할 수 있다. 사용자는 구매 후 15분 이내에 애플리케이션을 돌려주고 환불받을 수 있

다. 과거에는 환불 가능 시간이 24시간이었다. 최근 15분으로 바뀐 후 사용자들은 이를 탐탁지

않게 생각하고 있다.

개발자가 마켓에 애플리케이션을 배포하려면 25달러를 내고 한 번만 구글에 계정을 등록하면

된다. 계정 등록에 성공하고 나면 개발자는 바로 애플리케이션을 배포할 수 있다.

안드로이드 마켓은 승인 절차를 사용하지 않는 대신 퍼미션 시스템을 운영하고 있다. 사용자

는 프로그램을 설치하기에 앞서 애플리케이션에서 필요로 하는 퍼미션들을 미리 볼 수 있다. 이

런 퍼미션에는 전화 서비스, 네트워크 접근, SD 카드 접근 등이 포함된다. 사용자가 이런 퍼미션

을 승인한 경우에만 애플리케이션이 설치된다. 이런 퍼미션 시스템은 기본적으로 사용자가 올바

른 판단을 한다는 전제하에서 제대로 기능할 수 있다. 윈도우 운영체제 같은 PC에서는 이런 개념

이 잘 작동하지 않는다. 하지만 안드로이드의 경우에는 아직까지 제대로 운영되는 것 같다. 지금

까지 악의적인 행동으로 인해 마켓에서 쫓겨난 애플리케이션은 단 몇 개뿐이다.

애플리케이션을 판매하려면 개발자가 구글 체크아웃 계정을 추가로 등록해야 한다. 이 계정

등록은 무료로 할 수 있다. 모든 금융 업무는 이 계정을 통해 처리된다.

챌린지, 개발자 지원 프로그램, 구글 I/O

안드로이드 플랫폼으로 더 많은 개발자를 끌어들이기 위해 구글은 챌린지를 개최하기 시작했다.

안드로이드 개발자 챌린지(ADC)라고 불린 첫 번째 챌린지는 2008년에 열렸으며 프로젝트 우승

자에게는 비교적 많은 상금을 제공했다. ADC는 이듬해에도 열렸으며 개발자 참여 측면에서 보

자면 큰 성공을 거두었다. 2010년에는 ADC가 없었는데 이는 현재 안드로이드의 개발자 층이 그

만큼 넓기 때문에 새로운 개발자를 끌어들이기 위한 노력이 더 이상 필요 없기 때문인 것으로 보

인다.

Page 33: 시작하세요! 안드로이드 게임 프로그래밍

01 안드로이드, 뉴 키즈 온 더 블록 l 7

구글에서는 2010년 초에 개발자 지원 프로그램도 시작했다. 마켓에서 5,000회 이상 다운로드

됐고 평점 3.5 이상을 받은 애플리케이션을 하나 이상 갖고 있는 개발자는 새로 나온 모토로라

드로이드, 모토로라 마일스톤, 넥서스 원 중 하나를 선물로 받았다. 처음에는 다소 반신반의하는

분위기였지만 개발자 커뮤니티는 이런 구글의 행동을 크게 환영했다. 개발자들은 갑자기 날아

든 이메일 통보를 과장 광고라고 생각했다. 하지만 구글의 이런 프로모션은 사실로 밝혀졌고 전

세계 곳곳에 사는 개발자들에게 수천 개의 기기가 전달됐다. 구글의 과감한 결정으로 인해 수많

은 서드파티 개발자들이 보람을 느꼈고 더욱 더 플랫폼에 매력을 느끼게 됐다. 아울러 이 프로모

션이 어쩌면 새로운 개발자들을 끌어들이는 계기가 됐을 수도 있다.

구글에서는 개발자를 위한 특수 안드로이드 개발 폰(ADP)도 제공한다. 첫 번째 ADP는 T-모

바일 G1 버전(HTC 드림이라고도 부른다)이었다. 다음으로 나온 버전은 ADP 2로서, HTC 매

직의 변종이었다. 구글에서는 최종 사용자가 구매할 수 있는 넥서스 원이라는 자체 폰도 출시했

다. 넥서스 원은 본래 ADP로 출시되지는 않았지만 많은 사람들은 이를 ADP 2를 잇는 폰으로

생각했다. 구글에서는 결국 최종 사용자에 대한 넥서스 원 판매를 중단했고 넥서스 원은 현재 파

트너와 개발자에게만 공급된다. 2010년 말에는 가장 최신의 ADP가 출시됐다. 바로 안드로이드

2.3(진저브레드)을 실행하는 삼성 기기인 넥서스 S다. ADP는 안드로이드 마켓을 통해 살 수 있

는데, 이를 위해서는 개발자 계정이 필요하다. 넥서스 S는 별도 구글 사이트(www.google.com/

phone)를 통해서도 구매할 수 있다.

매년 열리는 구글 I/O 컨퍼런스는 모든 안드로이드 개발자가 기대하는 이벤트다. 구글 I/O에

서는 가장 최신의 구글 기술과 프로젝트가 공개된다. 최근 몇 년 동안은 안드로이드를 위한 별도

공간을 마련하고 있다. 구글 I/O에서는 보통 안드로이드 관련 주제에 대해 여러 세션을 할애하고

있으며, 각 세션의 내용은 유투브의 구글 개발자 채널을 통해서도 볼 수 있다.

안드로이드의 기능과 아키텍처

안드로이드는 단순히 리눅스를 모바일 기기용으로 배포한 게 아니다. 안드로이드용으로 개발을

하더라도 리눅스 커널 자체를 접할 일은 거의 없다. 안드로이드와 관련해 개발자가 주로 접하는

부분은 내부 리눅스 커널을 추상화한 플랫폼으로서 자바 프로그래밍 영역이다. 개괄적으로 살

펴보면 안드로이드는 다음과 같은 훌륭한 기능들을 제공한다.

Page 34: 시작하세요! 안드로이드 게임 프로그래밍

8 l 시작하세요! 안드로이드 게임 프로그래밍

■ 다양한 종류의 애플리케이션을 개발할 수 있는 풍부한 API로 구성된 애플리케이션 프레

임워크. 이 프레임워크를 활용하면 플랫폼에서 제공하는 컴포넌트를 재사용하고 대체할

수 있다.

■ 달빅 가상 머신. 달빅 가상 머신은 애플리케이션을 안드로이드에서 실행하는 책임을 담

당한다.

■ 2D와 3D 프로그래밍을 위한 그래픽 라이브러리

■ Ogg Vorbis, MP3, MPEG-4, H.264, PNG처럼 자주 사용하는 오디오, 동영상, 이미지 형

식에 대한 미디어 지원. 더불어 효과음을 재생할 수 있는 특수 API도 제공된다. 이런 API

는 게임 개발 등에 활용하면 무척 편리하다.

■ 카메라, GPS, 나침반, 가속도계, 터치 화면, 트랙볼, 키보드 등 주변 기기에 접근할 수 있

는 API. 이런 주변 기기들이 없는 안드로이드 기기도 있다는 사실에 주의해야 한다. 이는

하드웨어 파편화의 한 예이다.

물론 안드로이드에는 앞에서 언급한 이런 기능들 외에 수많은 기능들이 들어 있다. 하지만 여

기 언급한 기능들은 게임 개발과 관련해 주로 사용하는 기능들만 추린 것이다.

안드로이드 아키텍처는 다양한 컴포넌트 스택으로 이뤄지며, 각 컴포넌트는 하위 계층에 있는

컴포넌트 기반 위에서 구동된다. 그림 1-1에는 주요 안드로이드 컴포넌트가 나와 있다.

커널

컴포넌트 스택의 아래부터 살펴보면 리눅스 커널에서 하드웨어 요소에 대한 기본 드라이버를 제

공하는 것을 볼 수 있다. 아울러 커널은 메모리와 프로세스 관리, 네트워크 연결 같은 일상적인

작업도 처리한다.

런타임과 달빅

안드로이드 런타임은 커널 위에서 구동되며 안드로이드 애플리케이션을 설치하고 실행하는 일

을 한다. 각각의 안드로이드 애플리케이션은 자체 달빅 가상 머신을 갖고 개별 프로세스를 실행

한다.

Page 35: 시작하세요! 안드로이드 게임 프로그래밍

01 안드로이드, 뉴 키즈 온 더 블록 l 9

달빅은 DEX 바이트코드 형식으로 프로그램을 실행한다. 보통 일반 자바 .class 파일은 sdk에

서 제공하는 dx라는 특수 툴을 사용해 DEX 형식으로 변형한다. DEX 형식은 자바 .class 파일보

다 더 적은 메모리를 남기기 위해 고안됐다. 이 형식에서는 고도의 압축, 테이블, 여러 .class 파일

의 병합을 통해 메모리를 절약한다.

달빅 가상 머신은 자바 프로그램에서 접근할 수 있는 기본 기능을 제공하는 코어 라이브러리

와 연동한다. 코어 라이브러리는 아파치 하모니 자바 구현체의 서브셋을 활용해 자바 SE에서 사

용할 수 있는 클래스 중 일부를 제공한다. 이 말은 스윙이나 AWT를 사용할 수 없을 뿐 아니라

자바 ME에 포함된 클래스들도 사용할 수 없다는 뜻이다. 하지만 조금만 노력하면 달빅 기반의

자바 SE에서 사용할 수 있는 서드파티 라이브러리를 얼마든지 사용할 수 있다.

안드로이드 2.2(프로요) 이전에는 모든 바이트코드를 해석했다. 프로요에서는 JIT 컴파일러

를 도입해 실행 도중에 바이트코드를 기기 코드로 컴파일한다. 이렇게 하면 무거운 연산을 하는

애플리케이션의 성능을 크게 개선할 수 있다. JIT 컴파일러는 부동 소수점 단위(FPU) 같은 특수

연산에 최적화된 CPU 기능을 활용할 수 있다.

애플리케이션

애플리케이션 프레임워크

라이브러리 안드로이드 런타임

리눅스 커널

그림 1-1 ㅣ 안드로이드 아키텍처

Page 36: 시작하세요! 안드로이드 게임 프로그래밍

10 l 시작하세요! 안드로이드 게임 프로그래밍

달빅에는 통합 가비지 컬렉터(GC)도 들어 있다. 달빅의 GC는 마크-앤-스윕 GC로서, 이따금

씩 개발자들의 속을 끓인다. 하지만 조금만 주의하면 게임을 개발하면서 GC로 인해 스트레스를

받지 않을 수 있다. 가장 최신의 안드로이드 버전(2.3)에서는 개선된 동시성 GC를 통해 개발자들

의 고통을 조금 줄였다. GC 문제는 이 책에서 나중에 자세히 보게 될 것이다.

개별 달빅 VM 인스턴스에서 실행되는 각각의 애플리케이션은 16MB에서 24MB의 힙 메모리

를 사용할 수 있다. 이미지와 오디오 리소스를 제어할 때는 이 점을 항상 염두에 둬야 한다.

시스템 라이브러리

자바 SE 기능을 일부 제공하는 코어 라이브러리뿐 아니라 애플리케이션 프레임워크(그림 1-1에

서 다음 계층 위치에 표시)의 기본을 이루는 네이티브 C/C++ 라이브러리의 서브셋도 있다. 이런

시스템 라이브러리는 그래픽 렌더링, 오디오 재생, 데이터베이스 접근처럼 달빅 가상 머신이 하기

에 적합하지 않은 무거운 연산 작업을 주로 처리한다. 이런 API는 애플리케이션 프레임워크의 자

바 클래스로 래핑돼 있다. 이 부분은 실제 게임 개발을 시작하면서 보게 될 것이다. 다음 라이브

러리들은 한두 가지 형태로 사용하게 된다.

■ 스키아(Skia) 그래픽 라이브러리: 2D 그래픽을 위한 소프트웨어 렌더러로서 안드로이드

애플리케이션의 UI를 렌더링하는 데 사용된다. 이 라이브러리는 첫 번째 2D 게임을 그릴

때 사용할 것이다.

■ 오픈GL ES: 이 라이브러리는 하드웨어 가속 그래픽 렌더링의 산업 표준이다. 오픈GL ES

1.0과 1.1은 모든 안드로이드 버전의 자바 코드에서 접근할 수 있다. 셰이더를 추가한 오

픈GL ES 2.0은 안드로이드 2.2(프로요)부터 지원한다. 오픈GL ES 2.0의 자바 바인딩은

아직 불충분하며 핵심 메서드 몇 개가 빠져 있으므로 주의해야 한다. 아울러 에뮬레이터

와 아직까지 시장의 상당 부분을 차지하고 있는 기존 기기들은 오픈GL ES 2.0을 지원하

지 않는다. 따라서 이 책에서는 최대한 호환성을 유지하기 위해 오픈GL ES 1.0 및 1.1만을

사용한다.

■ 오픈코어: 오디오와 비디오 재생 및 기록을 위한 미디어 라이브러리다. 오픈코어는 Ogg

Vorbis, MP3, H.264, MPEG-4 등의 다양한 형식을 지원한다. 이 책에서는 주로 오디오

부분을 다룬다. 오디오는 자바 코드에서 직접 접근할 수 없고 대신 몇 개의 클래스와 서비

스로 감싸여 있다.

Page 37: 시작하세요! 안드로이드 게임 프로그래밍

01 안드로이드, 뉴 키즈 온 더 블록 l 11

■ 프리타입: 비트맵과 벡터 폰트, 특히 트루타입 형식을 로드하는 라이브러리다. 프리타입

은 아랍어처럼 오른쪽에서 왼쪽으로 쓰는 글리프 렌더링을 비롯해 유니코드 표준을 지

원한다. 하지만 아쉽게도 자바 측 코드에서는 아직까지 아랍어 글자를 지원하지 않고 있

다. 오픈코어와 마찬가지로 프리타입은 자바에서 직접 접근할 수 없고 몇 개의 편의 클래

스를 통해 접근해야 한다.

이런 시스템 라이브러리는 게임 개발자가 개발할 영역을 상당 부분 다루고 있고, 많은 어려운

작업을 대신 처리해준다. 평범한 자바 코드로 게임을 개발할 수 있는 것은 바로 이런 라이브러리

덕분이다.

알아두기

물론 대부분의 경우 달빅의 성능만으로도 충분하지만 때로는 성능을 더 개선해야 할 때가 있

다. 예를 들어 물리 시뮬레이션이나 무거운 3D 연산을 계산할 때가 이런 경우다. 이때는 네이

티브 코드를 작성하는 수밖에 없다. 이 책에서는 이런 부분까지는 다루지 않는다. 자바 코드만

을 사용해 프로그래밍을 할 수 있게 도와주는 안드로이드용 오픈소스 라이브러리들이 몇 개

나와 있다. 예를 들어 http://code.google.com/p/libgdx/를 참고하자. 또 블라디미르 실

바가 저술한 <Pro Android Games(Apress, 2010)> 1 이라는 책도 참고할 만하다. 이 책에서

는 게임 프로그래밍 관점에서 네이티브 코드와 연동하는 법을 깊이 있게 다루고 있다.

1   우리나라에는 <프로 안드로이드 게임 개발(제이펍)>이란 제목으로 번역 출판됐다.

애플리케이션 프레임워크

애플리케이션 프레임워크는 시스템 라이브러리 및 런타임과 연계해 안드로이드의 사용자 측면

을 구성한다. 프레임워크는 애플리케이션을 관리하고 애플리케이션이 활용할 수 있는 토대를 제

공한다. 개발자들은 UI 프로그래밍, 백그라운드 서비스, 알림, 리소스 관리, 주변 기기 접근 등을

다루는 자바 API를 활용해 프레임워크 기반의 애플리케이션을 개발한다. 메일 클라이언트처럼

안드로이드에서 기본으로 제공하는 핵심 애플리케이션들은 모두 이런 API로 작성했다.

애플리케이션은 UI 애플리케이션이든 백그라운드 서비스든 상관없이 다른 애플리케이션과

통신할 수 있다. 이런 통신 기능 덕분에 애플리케이션은 다른 애플리케이션의 컴포넌트를 재사

용할 수 있다. 간단한 예를 들어, 애플리케이션이 사진을 찍고 이 사진에 대해 어떤 작업을 수행

Page 38: 시작하세요! 안드로이드 게임 프로그래밍

12 l 시작하세요! 안드로이드 게임 프로그래밍

해야 한다고 가정하자. 이 경우 애플리케이션은 시스템으로 쿼리를 보내 이런 서비스를 제공하

는 다른 애플리케이션의 컴포넌트를 요청한다. 이렇게 하면 해당 애플리케이션은 컴포넌트(예를

들어 내장 카메라 애플리케이션 또는 사진 갤러리)를 재사용할 수 있다. 이런 연동 덕분에 프로

그래머의 부담은 상당히 줄어들고 안드로이드의 기능을 얼마든지 다양하게 커스터마이징할 수

있다.

게임을 개발할 때도 이런 프레임워크를 토대로 UI 애플리케이션을 생성한다. 따라서 게임 개

발자는 사용자와의 상호작용뿐 아니라 애플리케이션의 아키텍처와 생명주기도 잘 알고 있어야

한다. 보통 게임을 개발할 때는 백그라운드 서비스가 수행하는 역할이 크지 않으므로 이 책에서

는 이에 대해 자세히 언급하지 않는다.

소프트웨어 개발 킷

안드로이드용 애플리케이션을 개발할 때는 안드로이드 소프트웨어 개발 킷(SDK)을 사용한다.

SDK는 개발을 바로 시작할 수 있게 도와주는 다양한 툴, 문서, 튜토리얼, 예제로 구성된다. SDK

에는 안드로이드용 애플리케이션을 개발하는 데 필요한 자바 라이브러리도 포함된다. 주요 데스

크톱 운영체제라면 모두 개발 환경으로 사용할 수 있다.

SDK의 주요 기능은 다음과 같다.

■ 디버거는 기기 또는 에뮬레이터에서 실행 중인 애플리케이션을 디버깅할 수 있게 해준다.

■ 메모리 및 성능 프로파일은 메모리 누수와 코드 실행 성능 저하의 원인을 파악할 수 있게

도와준다.

■ QEMU(각기 다른 하드웨어 플랫폼을 시뮬레이션하기 위한 오픈소스 가상 머신) 기반의

기기 에뮬레이터는 물론 정확하기는 하지만 이따금씩 느릴 수 있다.

■ 명령행 유틸리티는 기기와의 통신에 사용할 수 있다.

■ 빌드 스크립트와 툴은 애플리케이션을 패키징하고 배포할 수 있게 해준다.

SDK는 인기 있는 오픈소스 자바 IDE인 이클립스와 연동된다. 이런 연동은 안드로이드 개발

툴(ADT) 플러그인을 통해 이뤄진다. ADT 플러그인은 안드로이드 프로젝트의 생성, 실행, 에뮬

레이터 또는 기기에서의 애플리케이션 프로파일링 및 디버깅, 안드로이드 마켓에 애플리케이션

Page 39: 시작하세요! 안드로이드 게임 프로그래밍

01 안드로이드, 뉴 키즈 온 더 블록 l 13

을 배포하기 위한 패키징 등의 새로운 기능을 이클립스에 추가해준다. SDK는 넷빈즈 같은 다른

IDE와도 연동할 수 있다. 하지만 넷빈즈에 대한 공식 지원은 없다.

알아두기

2장에서는 SDK와 이클립스를 활용한 개발 환경 설정을 다룬다.

이클립스용 SDK와 ADT 플러그인은 지속적으로 업데이트되고 있으며 매번 새로운 기능을 추

가하고 있다. 따라서 항상 최신 버전으로 업데이트해 두는 게 좋다.

좋은 SDK에는 방대한 문서가 뒤따르기 마련이다. 안드로이드 SDK도 문서 부분에서는 절대

뒤지지 않으며 문서와 더불어 수많은 예제 애플리케이션을 제공하고 있다. 또 http://developer.

android.com/guide/index.html을 참고하면 개발자 가이드와 더불어 애플리케이션 프레임워크

의 전체 모듈에 대한 전체 API 레퍼런스를 확인할 수 있다.

개발자 커뮤니티

안드로이드의 성공 요인 중 하나는 바로 개발자 커뮤니티다. 안드로이드 개발자 커뮤니티에서는

다양한 곳에서 몰려든 개발자들이 활동한다. 개발자들이 의견을 공유하기 위해 가장 자주 방문

하는 곳은 http://groups.google.com/group/android-developers에 있는 안드로이드 개발자 그

룹이다. 이 사이트는 좀처럼 해결되지 않는 문제를 만났을 때 질문을 올리거나 도움을 요청하기

위해 가장 많이 방문하는 곳이다. 이 사이트에는 시스템 프로그래머부터 애플리케이션 개발자,

게임 프로그래머에 이르기까지 다양한 안드로이드 개발자들이 방문한다. 가끔씩은 안드로이드

의 특정 부분을 담당하고 있는 구글 엔지니어가 혜안이 담긴 답변을 통해 개발자들을 도와주기

도 한다. 이 사이트는 무료로 가입할 수 있으므로 바로 가입해 그룹에 올라온 내용을 읽어볼 것

을 권장한다. 이 그룹 사이트는 질문을 올리기에도 좋지만 이미 답이 올라온 질문을 검색하고 해

결책을 찾기에도 좋다. 따라서 질문을 올리기 전에는 항상 같은 질문에 대한 답이 전에 올라오지

않았는지 미리 검색하는 게 좋다.

모든 개발자 커뮤니티는 마스코트를 하나씩 갖고 있다. 리눅스는 Tux 펭귄이 마스코트이고,

GNU는 그냥 gnu이고, 모질라 파이어폭스는 트렌디한 웹 2.0 불여우 마스코트를 갖고 있다. 안

드로이드도 예외 없이 마스코트를 갖고 있다. 안드로이드의 마스코트는 자그마한 녹색 로봇이

다. 그림 1-2에는 안드로이드의 마스코트가 나와 있다.

Page 40: 시작하세요! 안드로이드 게임 프로그래밍

14 l 시작하세요! 안드로이드 게임 프로그래밍

그림 1-2 ㅣ 안드로이드의 이름 없는 마스코트

물론 색상에 대해서는 사람들마다 기호가 다를 수 있지만, 이 로봇 마스코트는 인기 있는 안

드로이드 게임 몇 곳에서 이미 주연으로 출연한 바 있다. 이 마스코트가 등장한 게임 중 가장 눈

에 띄는 게임은 레플리카 아일랜드다. 이 게임은 구글 엔지니어인 크리스 프루엣이 20퍼센트 프

로젝트로 만든 무료 오픈소스 게임 플랫폼이다.

기기, 기기, 기기!

안드로이드는 단일 하드웨어 생태계로 제한된 플랫폼이 아니다. HTC, 모토로라, 삼성 등 주요

단말기 제조사들이 안드로이드 플랫폼에 참여했으며 안드로이드 운영체제를 실행하는 다양한

기기를 출시하고 있다. 하지만 이들 기기는 모두 핵심이 되는 주요 개념을 공유하고 있으므로, 게

임 개발자는 좀 더 쉽게 게임을 개발할 수 있다.

하드웨어

안드로이드 기기에 대한 최소한의 요구 조건은 엄격히 정해진 게 없다. 하지만 구글에서는 다음

과 같은 하드웨어 사양을 권장하고 있다. 이 사양은 사실상 모든 안드로이드 기기가 준수하고 있

으며 대부분의 기기들이 이 사양보다 높은 성능을 유지한다.

Page 41: 시작하세요! 안드로이드 게임 프로그래밍

01 안드로이드, 뉴 키즈 온 더 블록 l 15

■ ARM 기반의 CPU: 이 책을 쓰고 있는 현 시점 기준으로 이 명세에 대한 기준은 조금 완

화됐다. 지금은 안드로이드가 x86 아키텍처에서도 실행된다. 가장 최근에 출시된 ARM

기반의 기기는 듀얼 코어 CPU도 지원하고 있다.

■ 128MB 램: 이 사양은 최소 사양이다. 현재 고사양의 기기들은 이미 512MB 램을 갖고 있

으며 1GB 램을 가진 기기들도 머지않아 나올 것으로 전망된다.

■ 256MB 플래시 메모리: 시스템 이미지와 애플리케이션을 저장하는 데 필요한 최소한의

메모리 요구 사항이다. 오랫동안 서드파티 애플리케이션은 플래시 메모리에만 저장할 수

있었으므로 안드로이드 사용자들은 메모리 부족에 대한 불만을 주로 토로했다. 하지만

프로요의 출시와 더불어 이런 제약이 없어졌다.

■ 소형 또는 마이크로 SD 카드 저장소: 대부분의 기기는 몇 기가바이트에 달하는 SD 카드

저장소를 갖고 있다. 사용자는 이 SD 카드를 용량이 더 큰 SD 카드로 교체할 수 있다.

■ 16비트 HVGA TFT LCD 터치 스크린: 안드로이드 버전 1.6 이전에는 운영체제에서

HVGA 화면(480×320 픽셀)만 지원했다. 1.6 버전부터는 저해상도와 고해상도 화면을

모두 지원한다. 현재 고사양 기기는 WVGA 화면(800×480, 848×480, 852×480 픽셀)을

갖고 있으며 일부 저사양 기종에서는 QVGA(320×280 픽셀) 화면만을 지원한다. 터치 화

면은 거의 대부분 정전식이며 과거 기기에서는 싱글 터치만 지원한다.

■ 전용 하드웨어 키보드: 키는 내비게이션에 사용된다. 지금까지 출시된 대부분의 폰은 메

뉴, 검색, 홈, 백 키를 최소 하나씩은 갖고 있다. 일부 제조사에서는 이런 관행에서 벗어나

이런 키와 관련한 상세 키를 포함시키거나 아무런 키도 포함시키지 않는 방식을 선택하기

시작했다.

물론 실제 안드로이드 기기에는 이보다 훨씬 많은 하드웨어가 들어 있다. 거의 모든 기기에는

GPS, 가속도계, 나침반이 있다. 또 근거리 센서 및 광 센서가 들어 있는 기기들도 많이 있다. 게임

개발자가 이런 주변기기들을 활용하면 새로운 방식으로 사용자가 게임을 하게 만들 수 있다. 이

책에서는 나중에 이런 방법 중 몇 가지를 살펴볼 것이다. 일부 기기는 쿼티 자판과 트랙볼도 갖고

있다. 이 중 트랙볼은 대부분 HTC 기기에서 많이 등장한다.

카메라도 거의 모든 기기에서 사용할 수 있다. 일부 단말기와 태블릿에는 후면 카메라와 화상

채팅을 할 수 있는 전면 카메라에 해당하는 두 대의 카메라가 달려 있다.

Page 42: 시작하세요! 안드로이드 게임 프로그래밍

16 l 시작하세요! 안드로이드 게임 프로그래밍

게임 개발자에게 특히 중요한 하드웨어는 그래픽 프로세서(GPU)다. 안드로이드용으로 제일

처음 나온 단말기도 이미 오픈GL ES 1.0과 호환되는 GPU를 갖고 있었다. 좀 더 최근에 출시된

기기들은 성능 측면에서 볼 때 Xbox나 플레이스테이션 2에 버금가는 GPU를 갖고 있으며 오픈

GL ES 2.0을 지원한다. 그래픽 프로세서를 사용할 수 없다면 플랫폼에서 제공하는 픽셀플린저

라는 소프트웨어 렌더러를 대신 사용할 수 있다. 값싼 기기들 중에는 이런 소프트웨어 렌더러에

의존하는 기기들이 많이 있다. 이 렌더러를 사용하더라도 저해상도 화면에서는 충분한 속도가

나온다.

그래픽 프로세서와 더불어 현재 나와 있는 안드로이드 기기들은 전용 오디오 하드웨어도 갖고

있다. 많은 하드웨어 플랫폼은 H.264 같은 다양한 미디어 형식을 하드웨어에서 디코딩할 수 있

는 특수 전기회로를 갖고 있다. 모바일 전화, 와이파이, 블루투스 연결 등도 하드웨어 요소를 통

해 제공된다. 안드로이드 기기의 이런 하드웨어 모듈들은 대부분 칩으로 된 단일 시스템(SoC)으

로 통합되는데, 이런 시스템 설계는 임베디드 하드웨어에서도 사용하고 있다.

1세대, 2세대, 차세대

기능, 특히 성능상의 차이로 인해 안드로이드 개발자는 주로 기기를 1세대, 2세대, 차세대 기기로

나눈다. 이런 용어는 특히 안드로이드용 게임을 개발할 때 자주 나온다. 그럼 각 용어를 정의해

보자.

각 세대는 사용하는 안드로이드 버전(들), CPU/GPU, 기기의 화면 해상도 등으로 주로 이뤄진

세대별 고유 특징을 갖고 있다. 하드웨어 명세가 딱 정해진 데 반해 기기에 사용되는 안드로이드

버전은 차이가 있을 수 있다.

1세대 기기

1세대 기기는 현재 주로 보급된 기기로서 그림 1-3에 나온 HTC 히어로를 보면 특징을 가장 쉽게

이해할 수 있다.

이 폰은 아이폰 킬러로 불린 첫 번째 안드로이드 폰으로서 2009년 10월 출시됐다. 히어로는

2009년 당시 대부분의 안드로이드 단말기의 표준이었던 안드로이드 1.5 버전을 설치한 채 출시

됐다. 가장 마지막으로 이뤄진 히어로의 공식 업데이트는 안드로이드 2.1이었다. 더 최근 업데이

트를 설치하려면 루팅을 통해 전체 시스템 접근을 가능하게 해야 한다.

Page 43: 시작하세요! 안드로이드 게임 프로그래밍

01 안드로이드, 뉴 키즈 온 더 블록 l 17

히어로는 3.2인치 HVGA 정전식 LCD 터치 화면과 528MHz 퀄컴 MSM7201A CPU/GPU, 가

속도계, 나침반, 500메가 화소 카메라를 갖고 있다. 또 대다수 1세대 기기들이 갖고 있는 내비게

이션 하드웨어 키와 더불어 트랙볼을 갖고 있다.

히어로는 1세대 기기를 잘 보여주는 예다. 터치 화면은 핀치 줌과 같은 제한적인 멀티터치만을

지원할 뿐 진정한 멀티터치 기능을 지원하지 않는다. 이 기기에서는 멀티터치 제스처를 공식적으

로 지원하지 않으며 안드로이드 버전 1.5의 공식 API에도 멀티터치 제스처가 들어 있지 않음을

주의해야 한다. 이 점으로 인해 히어로는 아이폰과 같은 멀티터치 기능을 기대한 게임 개발자들

에게 큰 실망감을 안겨주었다.

1세대 기기의 또 다른 특징은 화면 해상도가 안드로이드 버전 1.6 이전까지의 공식 해상도인

480×320이라는 점이다.

CPU/GPU 부분에서 히어로는 흔히 볼 수 있는 퀄컴의 MSM7201A 시리즈를 사용하고 있다.

이 칩은 게임 개발자들에게 중요한 기능 중 하나인 하드웨어 부동 소수점 연산을 지원하지 않는

다. MSM7201A는 오픈GL ES 1.0 호환 칩으로, 프로그래밍 가능한 셰이더 기반의 파이프라인이

아니라 고정 함수(«xed-function) 파이프라인을 사용한다. GPU는 비교적 빠르지만 당시에 이미

그림 1-3 ㅣ HTC 히어로

Page 44: 시작하세요! 안드로이드 게임 프로그래밍

18 l 시작하세요! 안드로이드 게임 프로그래밍

출시된 아이폰 3G의 파워VR MBX 라이트 칩보다 성능이 뒤처졌다. HTC에서는 HTC 드림(T-

모바일 G1) 같은 다른 1세대 단말기 몇 개에서도 똑같은 칩을 사용했다. MSM7201A는 하드웨어

가속 3D 그래픽 측면에서는 저사양으로 간주되며 모든 세대의 안드로이드 기기를 대상으로 게

임을 개발할 때 가장 큰 걸림돌이 된다.

1세대 기기의 특징은 다음과 같이 정리할 수 있다.

■ 하드웨어 부동 소수점 연산 지원 기능이 없는 ~500MHz까지의 CPU 성능

■ 오픈GL ES 1.x을 지원하며 주로 MSM7201A 칩 형태의 GPU

■ 480×320 픽셀의 해상도

■ 제한된 멀티터치 지원

■ 초기 출시 당시 안드로이드 1.5/1.6 또는 이전 버전을 탑재

물론 이런 구분이 엄격하게 적용되는 것은 아니다. 지금 출시되고 있는 저사양의 기기 중에도

이와 유사한 특징을 갖고 있는 기기들이 있다. 물론 이들 기기는 정확히 1세대 기기는 아니지만

이런 기기들도 히어로나 유사한 기기들처럼 같은 범주로 묶을 수 있다.

1세대 기기들은 이 책을 쓰고 있는 현 시점을 기준으로 아직도 많은 시장 점유율을 갖고 있다.

가능한 한 많은 사용자를 공략하고 싶다면 이들 기기의 한계를 고려하고 이에 맞게끔 게임을 수

정해야 한다.

2세대 기기

2009년 말 새로운 안드로이드 기기 세대가 무대 위에 등장한다. 모토로라 드로이드와 넥서스 원

(2010년 1월 출시)을 선두로 한 2세대 기기들은 기존 휴대폰에서 볼 수 없었던 연산 능력을 보여

줬다.

넥서스 원은 스냅드래곤 칩셋 중 하나인 1GHz 퀄컴 QSD8250을 탑재했다. 모토로라 드로

이드는 550MHz 텍사스 인스트루먼츠 OMAP3430을 사용한다. 두 CPU 모두 VFP와 NEON

ARM 익스텐션을 통한 벡터 하드웨어 부동 소수점 연산을 지원한다. 넥서스 원은 512MB 램을

갖고 있으며 모토로라 드로이드는 256MB 램을 갖고 있다. 그림 1-4는 두 기기의 디자인을 보여

준다.

Page 45: 시작하세요! 안드로이드 게임 프로그래밍

01 안드로이드, 뉴 키즈 온 더 블록 l 19

그림 1-4 ㅣ 넥서스 원과 모토로라 드로이드

두 핸드폰은 모두 WVGA 화면에 800×480 픽셀의 아몰레드 액정(넥서스 원) 또는 854×480

픽셀의 LCD 액정(모토로라 드로이드)을 갖고 있다. 두 화면 모두 정전식 멀티터치 화면이다. 광

고에서는 두 기기가 멀티터치가 가능한 기기로 소개됐지만 실제로는 일부 상황에서 멀티터치가

원하는 대로 동작하지 않는다. 가장 자주 발생하는 문제는 화면상의 x나 y축 상에서 두 손가락

이 가까이 붙어 있을 때 잘못된 터치 위치가 보고되는 문제다.

넥서스 원은 안드로이드 버전 2.1을 탑재해 처음 출시됐으며 모토로라 드로이드는 2.0 버전으

로 처음 출시됐다. 두 폰 모두 안드로이드 버전 2.2로 이후 업데이트됐다.

두 폰에서 게임 개발자들이 특히 관심 있게 볼 부분은 내장 GPU다. PowerVR SGX530은 매

우 강력한 GPU로서 아이폰 3GS에서도 사용한다. 아이폰 3GS의 화면 크기는 실제로 모토로라

드로이드의 절반이라는 사실에 주의하자. 이로 인해 아이폰 3GS는 매 프레임당 그려야 할 화소

수가 더 적으므로 성능성의 이점이 조금 있다. 넥서스 원에서 사용 중인 아드레노 200 칩은 퀄컴

의 제품으로, PowerVR SGX530보다는 조금 느리다. 두 칩은 렌더링하는 화면에 따라 1세대 기

기에서 주로 사용된 MSM7201A보다 훨씬 빠른 성능을 보여준다.

2세대 기기의 특징은 다음과 같이 정리할 수 있다.

■ 550MHz에서 1GHz 사이의 처리 속도와 하드웨어 부동 소수점 연산을 지원하는 CPU

■ 오픈GL ES 1.x과 2.0을 지원하는 프로그래밍 가능한 GPU

Page 46: 시작하세요! 안드로이드 게임 프로그래밍

20 l 시작하세요! 안드로이드 게임 프로그래밍

■ WVGA 화면

■ 멀티 터치 지원

■ 안드로이드 버전 2.0, 2.0.1, 2.1, 또는 2.2

1세대 기기 중 일부는 안드로이드 2.1 버전까지 업데이트됐다는 사실에 주의하자. 이를 통해

이들 기기의 전반적인 시스템 성능이 개선됐지만, 그렇다고 하더라도 하드웨어 명세 자체가 2세

대 기기보다 열악하다는 사실에는 변함이 없다. 따라서 1세대와 2세대 기기를 명확히 구분하려

면 시스템 버전뿐 아니라 CPU, GPU, 화면 해상도까지 모두 고려해야 한다.

2010년에는 HTC 에보나 삼성 i9200 갤럭시 S 등 다양한 2세대 기기들이 새로 출시됐다. 물론

이들 기기는 넥서스 원이나 모토로라 드로이드보다 더 큰 화면과 더 빠른 CPU/GPU를 탑재하

는 등 일부 개선된 점이 있긴 하지만 여전히 2세대 기기로 분류된다.

차세대 기기

기기 제조사들은 자신들이 개발 중인 가장 최신의 단말기에 대한 보안을 최대한 유지하려고 노

력한다. 하지만 항상 그렇듯 어느 정도의 스펙 정보는 미리 엿볼 수 있다.

앞으로 나올 기기들의 일반적인 경향은 듀얼 코어 CPU, 더 많은 램, 더 나은 GPU, 더 높은 화

면 해상도로 압축된다. 이런 기기 중 하나가 삼성 i9200 갤럭시 S2다. 갤럭시 S2는 800×480 픽셀

의 아몰레드 2 디스플레이, 1.2GHz의 듀얼 코어 CPU, 1GB의 램을 갖고 있다. 갤럭시 S2의 GPU

는 Mali400이다. 갤럭시 S2를 비롯한 이런 차세대 기기는 가장 최신의 안드로이드 버전(2.3)을

기본 탑재하고 있다.

지금 당장은 주로 휴대폰이 안드로이드의 초점으로 되겠지만 앞으로는 새로운 형태의 기기들

도 안드로이드의 발전에 영향을 미칠 것이다. 하드웨어 제조사들은 안드로이드를 운영체제로 사

용해 태블릿 기기와 넷북을 개발 중이다. x86 같은 다른 아키텍처로의 안드로이드 포팅도 이미

진행 중이며, 이를 통해 대상 플랫폼이 크게 늘어날 것으로 전망된다. 또 안드로이드 3.0에서는

태블릿에서 사용할 수 있는 안드로이드 버전을 지원한다.

앞으로 안드로이드의 미래가 어떻게 펼쳐질지는 모르지만 안드로이드는 지금 우리 곁에 있다.

Page 47: 시작하세요! 안드로이드 게임 프로그래밍

01 안드로이드, 뉴 키즈 온 더 블록 l 21

게임 컨트롤러

다양한 안드로이드 단말기의 입력 방식상의 차이로 인해 일부 제조사들은 특수 게임 컨트롤러

를 만들었다. 안드로이드에는 이런 컨트롤러에 대한 API가 없으므로 게임 개발자들은 게임 컨트

롤러 제조사에서 제공하는 SDK를 사용해 연동 기능을 별도로 제공해야 한다.

이런 게임 컨트롤러 중 하나가 그림 1-5에 나온 Zeemote JS1이다. 이 컨트롤러는 아날로그 스

틱과 버튼으로 구성된다.

그림 1-5 ㅣ Zeemote JS1 게임 컨트롤러

이 컨트롤러는 블루투스를 통해 기기와 통신한다. 게임 개발자들은 Zeemote SDK에서 제공

하는 별도 API를 사용해 게임 컨트롤러와의 연동 기능을 제공해야 한다. 일부 안드로이드 게임

은 출시 당시부터 이 컨트롤러를 지원하고 있다.

이론적으로 사용자는 블루투스를 통해 닌텐도 위 컨트롤러를 안드로이드 기기와 연동할 수도

있다. 위 컨트롤러를 활용하는 프로토타입이 몇 개 나와 있기는 하지만 아직 공식 지원되는 SDK

는 없다. 이로 인해 연동 기능이 아직까지는 조금 어색하다.

그림 1-6에 나와 있는 게임 그리퍼(Game Gripper)는 모토로라 드로이드와 마일스톤용으로 디

자인된 획기적인 발명품이다. 게임 그리퍼는 폰의 쿼티 자판으로 밀어서 실제 하드웨어 키보드

위에 표준 게임 컨트롤러 레이아웃을 띄울 수 있게 해주는 고무 액세서리다. 이 경우 게임 개발

자들은 별도 라이브러리를 사용해 그리퍼와 통신할 필요 없이 키보드 제어 기능만 처리하면 된

다. 결국 게임 그리퍼는 그냥 고무일 뿐이기 때문이다.

Page 48: 시작하세요! 안드로이드 게임 프로그래밍

22 l 시작하세요! 안드로이드 게임 프로그래밍

그림 1-6 ㅣ 게임 그리퍼를 사용하는 모습

게임 컨트롤러는 안드로이드 분야에서는 아직 생소하다. 하지만 성공한 게임 앱 중 일부는 이

런 컨트롤러와의 연동 기능을 지원해 안드로이드 게이머들 사이에서 좋은 평가를 얻었다. 따라

서 이와 같은 액세서리에 대한 연동 기능도 함께 고려해야 한다.

모바일 게임의 차이점

게임 분야는 아이폰이나 안드로이드 같은 플랫폼이 게임 시장을 공략하기 전부터 거대한 분야

였다. 하지만 지금은 이런 새로운 하이브리드 기기로 인해 게임 분야의 지형이 달라지고 있다. 이

제 더 이상 게임은 철부지 어린 아이들의 전유물이 아니다. 점잖은 비즈니스맨들도 공공장소에

서 모바일 폰으로 최신 게임에 몰두하는가 하면, 신문에는 몇 명의 게임 개발자가 모바일 폰 애

플리케이션 시장을 공략해 대박을 낸 사연이 소개되고, 유명 게임 제작사들은 모바일 시장의 발

빠른 변화를 따라가기 위해 고군분투하고 있다. 우리는 게임 개발자로서 이런 변화를 읽고 그에

맞게 적응할 수 있어야 한다. 그럼 새로운 게임 생태계에서 제공하는 내용들을 좀 더 자세히 살

펴보자.

주머니 속으로 들어간 게임 기기

스마트폰은 도처에 있다. 이 절의 핵심 내용은 바로 이 문장으로 압축할 수 있다. 이를 잘 이해하

면 모바일 게임 분야와 관련한 다른 사실들도 쉽게 유추할 수 있다.

Page 49: 시작하세요! 안드로이드 게임 프로그래밍

01 안드로이드, 뉴 키즈 온 더 블록 l 23

하드웨어 가격은 갈수록 떨어지고 새로운 휴대폰의 연산 능력은 갈수록 좋아짐에 따라 휴대

폰은 시간이 지날수록 더욱 더 이상적인 게임 기기로 변모하고 있다. 오늘날 휴대폰은 필수 아이

템이므로 시장 보급률 또한 그만큼 높다. 기존에 갖고 있던 낡은 휴대폰을 새로운 스마트폰으로

바꾸는 사용자들은 수많은 애플리케이션을 통해 스마트폰의 위력을 실감하고 있다.

과거에 사람들은 비디오 게임을 플레이하고 싶을 때 비디오 게임 시스템을 구매할지 게임 PC

를 구매할지 의식적인 선택을 해야 했다. 하지만 지금은 휴대폰으로 인해 이런 게임 기능을 공짜

로 얻게 됐다. (데이터 요금제를 제외하면) 추가로 드는 비용도 없으며 이제 아무 때나 게임을 할

수 있게 됐다. 이제 주머니나 지갑에서 휴대폰을 꺼내면 바로 게임을 할 수 있다. 모든 것이 한 패

키지 안에 들어 있으므로 게임 전용 시스템을 따로 갖고 다닐 필요도 없다.

전화, 인터넷, 게임 기능을 한 기기에서 할 수 있다는 장점 이외에 모바일 게임의 접근성을 높

여주는 또 다른 요소가 하나 더 있다. 바로 휴대폰에서 마켓 애플리케이션을 실행해 관심 있는

게임을 골라서 그 자리에서 플레이할 수 있다는 점이다. 이제 상점에 갈 필요도 없으며 PC를 통

해 게임을 내려 받았다가 USB가 없어서 핸드폰으로 게임을 전송할 수 없다는 사실에 난감해할

필요도 없다.

오늘날 스마트폰의 강력한 처리 성능은 게임 개발자들이 만들 수 있는 게임 분야에도 영향을

주고 있다. 중간 사양 정도의 기기만 갖고 있다면 과거 Xbox와 플레이스테이션 2 시스템에서 즐

길 수 있는 게임을 그대로 즐길 수 있다. 이런 하드웨어 플랫폼 성능을 기반으로 이제 물리 시뮬

레이션을 활용한 보다 정교하고 창의적인 게임 개발도 얼마든지 시도할 수 있다.

새로운 기기와 더불어 앞에서 잠깐 얘기한 것처럼 입력 방식도 새로워지고 있다. 일부 게임에

서는 이미 대부분의 안드로이드 기기에 탑재된 GPS와 나침반을 활용하고 있다. 가속도계는 대

부분의 게임에서 이미 필수 게임 요소로 활용 중이며, 멀티터치 화면은 사용자가 게임 공간과 상

호작용할 수 있는 새로운 방법을 제공하고 있다. 과거 게임 콘솔(여기서는 위(Wii)는 잠깐 무시

한다)과 비교해 이는 게임 개발자로서는 꽤 큰 변화라 할 수 있다. 이미 많은 게임에서 다양한 시

도를 했지만 아직까지도 이런 모든 기능을 새로운 방식으로 사용하는 방법은 얼마든지 더 남아

있다.

상시 접속 상태의 유지

보통 스마트폰은 데이터 요금제를 사용한다. 데이터 요금제는 단순히 전화 용도로만 사용되지 않

고, 실제로 많은 트래픽이 주요 인터넷 사이트에 대해 일어난다. 스마트폰 사용자는 항상 웹에 접

속해 있는 경우가 많다(하드웨어 설계 결함 등으로 인한 수신 장애는 여기서 제외한다).

Page 50: 시작하세요! 안드로이드 게임 프로그래밍

24 l 시작하세요! 안드로이드 게임 프로그래밍

인터넷 상시 접속은 모바일 게임 분야에서 새로운 장을 열어주었다. 이제 사람들은 지구 반대

편에 있는 사람과 체스를 둘 수도 있고 가상 공간을 함께 탐험할 수도 있으며, 데스 매치 게임을

통해 다른 도시에 살고 있는 절친을 수류탄으로 없앨 수도 있다. 이런 게임을 모두 버스나 지하철

안 또는 좋아하는 공원 구석을 거닐며 일상적으로 할 수 있다.

멀티 플레이어 기능 외에 소셜 네트워크도 모바일 게임 분야에서 큰 역할을 하기 시작했다. 이

제 게임들은 가장 최근에 기록한 최고 점수를 트위터 계정에 바로 보내거나 레이싱 게임에서 얻

은 기록을 친구에게 알려주는 기능을 제공한다. 물론 기존 게임 공간상에서도 소셜네트워크가

성장 중이지만 (예를 들어 Xbox Live나 이와 유사한 플레이스테이션 서비스) 페이스북과 트위터

같은 서비스의 점유율이 훨씬 높으며, 이를 통해 사용자는 여러 소셜 네트워크를 한 번에 관리해

야 하는 부담을 덜고 있다.

캐주얼 게임과 하드코어 게임

스마트폰의 보급률이 높아진다는 것은 이전에 NES 컨트롤러를 만져본 적도 없는 사용자라 하더

라도 갑작스레 게임 세계에 뛰어들 수 있음을 의미한다. 이런 사람들이 생각하는 좋은 게임의 이

미지는 하드코어 게이머가 생각하는 것과는 꽤 차이가 있다.

휴대폰의 사용 패턴으로 인해 사용자들은 버스 안이나 패스트푸드점에서 줄을 기다릴 때 잠

깐씩 할 수 있는 캐주얼 게임을 더 선호하는 편이다. 이런 게임은 직장 내에서 인기척을 느낄 때

마다 Alt +탭을 눌러서 화면을 바꿔야 하는 많은 직장인들이 하고 있는 플래시 게임과 유사한

부류다. 한번 스스로에게 이런 질문을 해보자. 휴대폰에서 게임을 플레이하는 데 얼마나 많은 시

간을 보낼까? 휴대폰 같은 기기에서 문명 같은 게임을 ‘잠깐’ 플레이하는 걸 상상할 수 있을까?

물론 게이머들 중에는 ‘Advanced Dungeons & Dragons’ 같은 게임을 휴대폰에서 할 수만 있

다면 자신의 첫째 아들까지도 바칠 수 있다는 사람들이 간혹 있다. 하지만 이런 사람들은 소수일

뿐이다. 이 사실은 아이폰이나 안드로이드 마켓에서 팔리는 상위 순위의 게임들만 봐도 알 수 있

다. 상위 순위에 있는 게임들은 보통 캐주얼 게임들이며 간단한 트릭을 숨기고 있다. 즉 이런 게임

의 한 라운드를 플레이하는 데는 몇 분밖에 안 걸리지만 게임의 중독성으로 인해 계속해서 게임

을 플레이할 수밖에 없는 것이다. 이런 게임에서는 게이머가 자신의 게임 스킬을 자랑할 수 있는

온라인 순위 시스템도 제공한다. 하지만 이런 게임은 실제로는 캐주얼 게임의 가면을 쓴 하드코

어 게임이라고 볼 수도 있다. 사용자들에게 게임 기록을 저장할 수 있는 편리한 방법을 제공하면

하드코어 게임이라도 캐주얼 게임처럼 판매할 수 있다.

Page 51: 시작하세요! 안드로이드 게임 프로그래밍

01 안드로이드, 뉴 키즈 온 더 블록 l 25

큰 시장과 적은 수의 개발자

많은 취미 개발자들과 인디 개발자들을 모바일 플랫폼에 끌어들인 요소는 바로 낮은 진입 장벽

이다. 안드로이드의 경우 진입 장벽이 특히 낮다. SDK를 받아서 바로 프로그래밍을 시작하면 그

만이기 때문이다. (물론 필자는 적어도 한 대의 개발 기기를 갖고 있을 것을 권장하지만) 기기가

없더라도 애뮬레이터만으로도 개발을 진행할 수 있다. 안드로이드의 개방된 면모는 웹에서의 다

양한 활동으로도 이어진다. 안드로이드 시스템과 관련한 온갖 프로그래밍 정보는 웹상에서 무

료로 찾을 수 있다. 안드로이드의 경우 비공개 동의서에 서명을 하거나 개발 생태계에 들어가기

위해 승인을 받느라 기다릴 필요가 전혀 없다.

이 책을 쓰고 있는 현 시점 기준으로 마켓에서 가장 크게 성공한 게임은 1인 기업과 소규모 개

발 팀에서 개발한 게임들이다. 주요 게임 제작사들은 아직 마켓에서 제대로 발을 들이지 못했거

나 크게 성공을 거두지 못했다. Gamelo¯는 이를 잘 보여준다. 아이폰에서는 꽤 큰 게임 제작사

이지만 Gamelo¯는 아직 안드로이드 마켓에서 제대로 정착하지 못하고 자신의 웹사이트를 통해

게임을 판매하고 있다. 어쩌면 Gamelo¯는 안드로이드 마켓에 DRM이 없다는 사실에 불만을 품

었을 수 있다(현재는 DRM을 사용할 수 있다). 이런 움직임으로 인해 그들의 게임을 실제로 접하

게 될 사람의 수가 크게 줄어들었다.

모바일 게임 환경은 다양한 실험과 혁신을 가능하게 해준다. 마켓을 서핑하는 지루한 사용자

들은 새로운 아이디어와 게임 플레이 방식을 적용한 보석 같은 게임들을 기대하고 있다. PC나

콘솔 같은 기존 게임 플랫폼에서는 다양한 실험이 종종 실패로 이어졌다. 하지만 안드로이드 마

켓에서는 새로운 아이디어를 실험해보고 싶은 사용자들을 훨씬 더 많이 만날 수 있는 기회가 있

고, 이런 사용자들에게 다가가기도 한결 쉽다.

물론 그렇다고 해서 게임을 홍보하지 않아도 된다는 얘기는 아니다. 게임을 홍보하는 방법 중

하나는 최신 게임과 관련한 다양한 블로그와 웹사이트에 게임 정보를 제공하는 것이다. 수많은

안드로이드 사용자들은 이런 사이트를 수시로 드나들며 가장 최근에 나온 좋은 게임들을 체크

하고 있다.

폭넓은 사용자층을 공략하는 또 다른 방법으로는 안드로이드 마켓에서 추천 앱으로 선정되

는 방법이 있다. 일단 추천 앱으로 선정되고 나면 사용자들이 마켓 애플리케이션을 시작하자 마

자 여러분의 앱이 목록에 나타난다. 많은 개발자들은 마켓에서 추천 앱으로 선정된 시점부터 다

운로드 수가 크게 늘었다고 말하고 있다. 하지만 추천 앱으로 선정되는 과정 자체는 베일에 싸여

있다. 따라서 여러분이 대규모 업체에서 일하든 소규모 1인 기업이든 번뜩이는 아이디어와 세련

된 방식으로 아이디어를 구현하는 것만이 추천 앱으로 선정될 수 있는 최선의 전략이다.

Page 52: 시작하세요! 안드로이드 게임 프로그래밍

26 l 시작하세요! 안드로이드 게임 프로그래밍

정리

안드로이드는 놀라운 작은 괴물이다. 이 장에서는 안드로이드가 어떻게 구성돼 있는지 살펴봤고

안드로이드의 개발자 생태계도 들여다 봤다. 안드로이드는 개발 대상이 되는 소프트웨어와 하드

웨어 측면에서 매우 흥미로운 시스템을 제공하며 SDK를 무료로 사용할 수 있다는 점에서 진입

장벽이 매우 낮다. 안드로이드 기기는 매우 강력한 성능의 휴대용 기기로서 사용자들에게 시각

적으로 풍부한 게임 공간을 제공할 수 있다. 가속도계 같은 센서는 혁신적인 게임 아이디어를 촉

진시켜주고, 이를 통해 새로운 방식의 사용자 상호작용을 가능하게 해준다. 게임 개발을 모두 마

치고 나면 단 몇 분 만에 수백만 명의 잠재 게이머들에게 게임을 배포할 수 있다. 이런 얘기에 가

슴이 설렌다면 이제 본격적으로 손에 코드를 조금씩 묻혀보자!

Page 53: 시작하세요! 안드로이드 게임 프로그래밍

01 안드로이드, 뉴 키즈 온 더 블록 l 27

Page 54: 시작하세요! 안드로이드 게임 프로그래밍

Beg

inni

ng

And

roid

Gam

es

Page 55: 시작하세요! 안드로이드 게임 프로그래밍

29

02안드로이드 SDK 첫 걸음

안드로이드 SDK는 애플리케이션을 바로 개발할 수 있게 해주는 다양한 도구를 제공한다. 이 장

에서는 이런 SDK 도구를 활용해 간단한 안드로이드 애플리케이션을 개발하는 과정을 살펴본

다. 이를 위한 절차는 다음과 같다.

1. 개발 환경의 설정

2. 이클립스에서의 새 프로젝트 생성과 코드 작성

3. 에뮬레이터 또는 기기에서의 애플리케이션 실행

4. 애플리케이션 디버깅과 프로파일링

그럼 먼저 개발 환경 설정부터 시작하자.

개발 환경의 설정

안드로이드 SDK는 매우 유연하며 다양한 개발 환경과 잘 연동된다. 순수주의자들은 명령행 도

구를 사용하는 방법을 선택할 수도 있겠지만 우리 같은 평범한 개발자는 더 편한 게 좋기 때문

에, 더 간편하고 보다 시각적인 IDE(통합 개발 환경) 활용 방식을 사용하기로 한다.

다음은 내려 받아 설치할 소프트웨어 목록을 순서대로 정리한 것이다.

Page 56: 시작하세요! 안드로이드 게임 프로그래밍

30 l 시작하세요! 안드로이드 게임 프로그래밍

■ 자바 개발 킷(JDK) 버전 5 또는 6. 버전 6을 권장한다.

■ 안드로이드 소프트웨어 개발 킷(안드로이드 SDK).

■ 자바 개발자를 위한 이클립스 버전 3.4 또는 3.5.

■ 이클립스용 안드로이드 개발 툴(ADT) 플러그인

그럼 설정에 필요한 과정을 하나씩 살펴보자.

알아두기

웹은 끊임 없이 변하므로 여기서는 URL을 수록하지 않았다. 앞에 있는 항목들을 내려 받으려

면 검색 엔진에서 검색해 적절한 위치를 찾으면 된다.

JDK의 설정

앞에서 얘기한 JDK 버전 중 운영체제에 맞는 버전을 내려 받는다. 대부분의 운영체제용 JDK는

설치파일 또는 패키지 형태로 제공되므로 설치의 어려움은 거의 없다. JDK를 설치했다면 JDK

설치 루트 디렉터리를 가리키는 JDK_HOME 환경 변수를 추가하는 게 좋다. 아울러 PATH 환

경 변수에 $JDK_HOME/bin(윈도우 운영체제에서는 %JDK_HOME%\bin)도 추가해야 한다.

안드로이드 SDK의 설정

안드로이드 SDK는 세 가지 주요 운영체제용으로 배포된다. 자신의 운영체제에 맞는 버전을 선

택해 내려 받는다. SDK는 ZIP 또는 tar gzip 파일 형태로 제공된다. 이 파일을 원하는 폴더에 압

축 해제한다(예를 들어 윈도우 운영체제에서는 c:\android-sdk, 리눅스 운영체제에서는 /opt/

android-sdk). SDK 설치 루트 디렉터리를 가리키는 ANDROID_HOME 환경 변수를 생성하

고 PATH 환경 변수에 $ANDROID_HOME/tools (윈도우 운영체제의 경우 %ANDROID_

HOME%\tools)를 추가한다. 이렇게 해 놓으면 나중에 필요할 때마다 명령행 도구를 쉽게 실행

할 수 있다.

앞의 절차를 모두 따라 하고 나면 안드로이드 프로젝트를 생성, 컴파일, 배포할 수 있는 기본

명령행 도구와 더불어 SDK 및 SDK 컴포넌트를 설치하고 에뮬레이터에서 사용하는 가상 기기

Page 57: 시작하세요! 안드로이드 게임 프로그래밍

02 안드로이드 SDK 첫 걸음 l 31

를 생성할 수 있는 AVD 매니저까지 모두 갖추게 된다. 개발 도구만으로는 개발을 시작하기에 충

분치 않으므로 추가 컴포넌트를 설치해야 한다. 바로 SDK와 AVD 매니저를 설치해야 하는 것이

다. AVD 매니저는 패키지 매니저로서 리눅스의 패키지 관리 도구와 비슷한 기능을 한다. AVD

매니저는 다음과 같은 컴포넌트들을 설치할 수 있게 해준다.

■ 안드로이드 플랫폼: 개별 안드로이드 출시 버전에는 런타임 라이브러리, 에뮬레이터에서

사용하는 시스템 이미지, 버전 관련 도구들을 포함하는 SDK용 플랫폼 컴포넌트가 들어

있다.

■ SDK 애드온: 애드온은 보통 외부 라이브러리 및 도구로서 플랫폼에 종속되지 않는다. 애

드온의 예로는 애플리케이션에서 구글 맵과 연동할 수 있는 구글 API가 있다.

■ 윈도우용 USB 드라이버: 윈도우 운영체제에서는 애플리케이션을 실제 기기에서 실행하

고 디버깅하기 위해 이 드라이버가 필요하다. 맥 OS X나 리눅스에서는 이런 특수 드라이

버가 필요 없다.

■ 예제: 각 플랫폼에서는 플랫폼 관련 예제도 제공한다. 이런 예제는 안드로이드 런타임 라

이브러리를 활용해 특정 목적을 달성하는 법을 파악하려 할 때 큰 도움이 된다.

■ 문서: 문서는 가장 최신의 안드로이드 프레임워크 API 문서에 대한 로컬 복사본이다.

우리는 욕심이 많은 개발자이므로 이들 컴포넌트를 모두 설치해 모든 기능을 마음껏 사용하

고자 한다. 이를 위해서는 먼저 SDK와 AVD 매니저를 시작해야 한다. 윈도우 운영체제에서는

SDK의 루트 디렉터리에 SDK manager.exe라는 실행 파일이 들어 있다. 리눅스와 맥 OS X에서

는 SDK의 tools 디렉터리에서 android 스크립트를 실행하면 된다.

일단 실행되고 나면 SDK와 AVD 매니저는 패키지 서버에 연결해 사용 가능한 패키지 목록을

가져온다. 그런 다음 그림 2-1처럼 개별 패키지를 선택해 설치할 수 있는 대화상자를 보여준다.

이때는 Accept All을 체크하고 Install 버튼을 클릭해 모두 내려 받고, 다운로드가 진행되는 동안

커피나 차를 마시며 느긋하게 기다리면 된다. 매니저에서 전체 패키지를 모두 내려 받기까지는

다소 시간이 걸린다.

Page 58: 시작하세요! 안드로이드 게임 프로그래밍

32 l 시작하세요! 안드로이드 게임 프로그래밍

그림 2-1 ㅣ SDK와 AVD 매니저와의 첫 만남

SDK와 AVD 매니저를 활용하면 아무 때나 컴포넌트를 업데이트하고 새로운 컴포넌트를 설치

할 수 있다. AVD 매니저는 새로운 AVD를 생성할 때도 사용한다. 이 부분은 나중에 애플리케이

션을 에뮬레이터에서 실행하고 디버깅할 때 살펴볼 것이다.

설치 과정이 모두 끝나면 개발 환경을 설정하는 다음 단계를 진행한다.

이클립스의 설치

이클립스 설치 버전은 다양한 형태로 제공된다. 안드로이드 개발자라면 자바 개발자를 위한 이

클립스 3.6 버전을 권장한다. 안드로이드 SDK와 마찬가지로 이클립스도 ZIP 또는 tar gzip 패키

지 형태로 제공된다. 이 파일은 원하는 폴더에 압축을 바로 풀면 된다. 압축이 풀리고 나면 이클

립스 설치 경로의 eclipse 실행 파일 바로가기를 바탕화면에 추가하는 게 좋다.

이클립스를 처음 실행하면 작업공간 디렉터리를 지정할 수 있는 대화상자가 나타난다. 그림

2-2는 이 대화상자를 보여준다.

Page 59: 시작하세요! 안드로이드 게임 프로그래밍

02 안드로이드 SDK 첫 걸음 l 33

그림 2-2 ㅣ 작업 공간의 선택

작업 공간은 이클립스에서 프로젝트들을 저장할 폴더를 가리킨다. 전체 프로젝트에 대해 하나

의 작업 공간을 사용하든, 몇 개의 프로젝트마다 새로운 작업 공간을 만들든 전적으로 개발자

마음이다. 이 책과 함께 제공되는 예제 프로젝트들은 모두 이 대화상자에서 지정할 수 있는 하나

의 작업 공간 내에 들어 있다. 지금은 일단 빈 작업 공간을 생성해 둔다.

이렇게 하고 나면 이클립스가 환영 화면을 보여주면서 여러분을 반길 것이다. 이 화면은 그냥

무시하고 닫아도 된다. 환영 화면을 닫으면 기본 이클립스 자바 퍼스펙티브가 보인다. 이클립스

에 대한 내용은 나중에 다른 절에서 자세히 다룰 것이다. 지금은 일단 이클립스를 실행한 것만으

로도 충분하다.

ADT 이클립스 플러그인의 설치

설정 퍼즐의 마지막 조각은 바로 ADT 이클립스 플러그인이다. 이클립스는 플러그인 아키텍처를

기반으로 한다. 이런 아키텍처 덕분에 이클립스는 서드파티 플러그인을 통해 기능을 확장할 수

있다. ADT 플러그인은 안드로이드 SDK의 개발 도구와 이클립스의 힘을 서로 연결해주는 역할

을 한다. 이와 같은 연동을 통해 개발자는 명령행 안드로이드 SDK 툴을 호출하는 불편함을 겪

지 않아도 된다. ADT 플러그인이 이클립스의 작업 흐름에 맞게끔 이런 연동 과정을 모두 처리해

주기 때문이다.

이클립스용 플러그인 설치는 플러그인 ZIP 파일을 이클립스의 plug-ins 폴더에 직접 드롭해

수동으로 설치할 수도 있고 이클립스에 들어 있는 이클립스 플러그인 매니저를 활용해 설치할

수도 있다. 여기서는 후자의 방법을 택한다.

Page 60: 시작하세요! 안드로이드 게임 프로그래밍

34 l 시작하세요! 안드로이드 게임 프로그래밍

1. 새 플러그인을 설치하려면 Help Install New Software...로 간다. 그럼 설치 대화상자

가 열릴 것이다. 이 대화상자에서는 어떤 소스로부터 어떤 플러그인을 설치할지 지정할

수 있다. 먼저 어느 곳에서 ADT 플러그인을 가져올지 지정하기 위해 플러그인 저장소를

추가해야 한다. Add 버튼을 클릭한다. 그럼 그림 2-3 같은 대화상자가 나타날 것이다.

2. 첫 번째 텍스트 필드에는 저장소의 이름을 입력하면 된다. 저장소의 이름은 ‘ADT

repository’ 정도로 입력하면 된다. 두 번째 텍스트 필드에는 저장소의 URL을 지정해야

한다. ADT 플러그인의 경우 이 필드는 https://dl-ssl.google.com/android/eclipse/로 지

정하면 된다. 이 URL은 새 버전에서는 달라질 수 있으므로 최신 링크는 항상 ADT 플러

그인 사이트에서 확인하는 게 좋다.

그림 2-3 ㅣ 저장소의 추가

3. 대화상자 내용을 확인하고 나면 다시 설치 대화상자로 돌아오게 될 것이다. 이번에는 저

장소에서 내려 받을 수 있는 플러그인 목록이 보일 것이다. Developer Tools 체크박스를

선택하고 Next 버튼을 클릭한다.

4. 이번에는 이클립스가 필요한 의존성을 계산하고 새 대화상자를 통해 설치될 플러그인과

의존성 목록을 보여줄 것이다. 대화상자의 내용을 확인한 후 Next 버튼을 클릭한다.

5. 그럼 설치될 플러그인 각각에 대한 라이선스에 동의하는지 묻는 또 다른 대화상자가 나

타날 것이다. 당연히 이런 라이선스에는 동의해야 하므로 동의를 체크하고 Finish 버튼을

클릭해 설치를 시작한다.

Page 61: 시작하세요! 안드로이드 게임 프로그래밍

02 안드로이드 SDK 첫 걸음 l 35

알아두기

설치 과정에서 서명되지 않은 소프트웨어를 설치할 것인지 묻는 대화상자가 나타날 것이다.

하지만 플러그인의 경우 인증된 서명이 따로 없기 때문에 이런 대화상자가 나타나는 것이므로

이 부분은 걱정하지 않아도 된다. 설치에 그냥 동의하고 설치 과정을 계속하면 된다.

6. 끝으로 이클립스가 변경 사항을 적용하기 위해 이클립스를 재시작할지 물을 것이다. 이때

는 재시작을 통해 변경 사항을 적용할 수도 있고 재시작 없이 변경 사항을 적용할 수도 있

다. 하지만 안전하게 하기 위해 Restart Now를 선택해 이클립스를 재시작한다.

수없이 많은 대화상자를 통해 설치를 완료하고 나면 기존과 동일한 이클립스 창이 보일 것이

다. 하지만 이제 툴바를 보면 SDK와 AVD 매니저를 이클립스에서 바로 실행할 수 있는 버튼과

새로운 안드로이드 프로젝트를 생성할 수 있는 버튼이 추가된 것을 볼 수 있다. 그림 2-4에는 새

로 추가된 툴바 버튼이 나와 있다.

그림 2-4 ㅣ ADT 툴바 버튼

그림 2-4에서 왼쪽에 있는 첫 번째 버튼은 AVD와 SDK 매니저를 실행하는 버튼이다. 옆에 있

는 다음 버튼은 새로운 안드로이드 프로젝트를 생성하는 단축 버튼이다. 나머지 두 버튼은 새로

운 단위 테스트 프로젝트를 생성하고 안드로이드 매니페스트 파일을 생성하는 버튼이다(이 책

에서는 이 기능을 사용하지 않는다).

끝으로 ADT 플러그인의 설치를 마무리하려면 플러그인에게 안드로이드 SDK가 있는 위치를

알려줘야 한다.

1. Window Preferences를 선택하고 대화상자의 트리 뷰에서 Android를 선택한다.

2. 우측에서 Browse 버튼을 클릭해 안드로이드 SDK 설치 경로의 루트 디렉터리를 찾는다.

3. OK 버튼을 클릭해 대화상자를 닫고 나면 이제 첫 번째 안드로이드 애플리케이션 개발을

위한 모든 준비가 끝난다.

Page 62: 시작하세요! 안드로이드 게임 프로그래밍

36 l 시작하세요! 안드로이드 게임 프로그래밍

이클립스 간단히 살펴보기

이클립스는 다양한 언어로 작성된 애플리케이션을 개발하는 데 사용할 수 있는 오픈소스 IDE

다. 보통 이클립스는 자바 개발에 주로 사용한다. 이클립스의 플러그인 아키텍처 덕분에 다양한

확장 플러그인이 나왔으며 이들 플러그인을 활용하면 순수 C/C++, 스칼라, 파이썬 프로젝트 등

도 개발할 수 있다. 이런 가능성은 무궁무진하다. 예를 들어 일상적인 코드 개발 작업을 도와주

는 LaTeX 프로젝트를 개발할 수 있는 플러그인도 나와 있다.

이클립스는 하나 이상의 프로젝트를 포함하는 작업 공간을 갖고 있다. 이 장에서는 앞서 작업

공간을 한 개 정의했다. 앞으로 생성할 프로젝트들은 모두 이 작업 공간에 저장할 것이다. 더불어

작업 공간을 사용할 때 이클립스의 형태를 정의하는 설정 또한 이 작업 공간에 저장된다.

이클립스의 UI는 다음 두 가지 개념을 중심으로 구성된다.

■ 뷰는 소스 코드 편집기, 결과 콘솔, 프로젝트 익스플로러 같은 단일 UI 컴포넌트를 말한다.

■ 퍼스펙티브는 이를테면 편집, 소스 코드 검색, 디버깅, 프로파일링, 버전 제어 저장소와의

동기화 같은 특정 개발 작업에 필요한 뷰들을 한데 모아놓은 것을 말한다.

자바 개발자를 위한 이클립스에는 미리 정의된 퍼스펙티브가 몇 개 들어 있다. 개발 시에 주로

사용하는 퍼스펙티브는 자바 퍼스펙티브와 디버그 퍼스펙티브다. 자바 퍼스펙티브는 그림 2-5에

나와 있다. 이 퍼스펙티브에서는 왼쪽에 패키지 익스플로러가 나오고 소스 편집 뷰가 가운데(아

직 소스 파일을 열지 않아서 지금은 비어 있다) 나오며, 작업 목록 뷰 및 문제 뷰, 자바 문서 뷰, 선

언 뷰의 하위 뷰를 포함하는 아웃라인 뷰가 오른쪽에 나온다.

한 퍼스펙티브 내에 속한 뷰는 드래그앤드롭을 통해 얼마든지 자유롭게 위치를 조절할 수 있

다. 또 뷰 크기를 조절할 수도 있다. 아울러 퍼스펙티브에 뷰를 추가하거나 제거할 수도 있다. 뷰

를 추가하려면 Window Show View를 선택하거나 Other...를 선택해 사용할 수 있는 뷰 목록

을 모두 불러와 그 가운데 하나를 선택하면 된다.

다른 퍼스펙티브로 전환하려면 Window Open Perspective를 선택해 원하는 퍼스펙티브

를 고르면 된다. 이클립스의 우측 상단 구석을 활용하면 이미 열려 있는 퍼스펙티브 사이에서 빠

르게 전환할 수 있다. 이곳에서는 열려 있는 퍼스펙티브를 볼 수 있고 어떤 퍼스펙티브가 현재 활

성화돼 있는지 볼 수 있다. 그림 2-5를 살펴보면 자바 퍼스펙티브가 이미 열려 있고 활성화돼 있

음을 알 수 있다. 지금은 자바 퍼스펙티브만 열려 있는 상태다. 이후 추가 퍼스펙티브를 열면 추

가 퍼스펙티브도 이 UI 영역에 표시된다.

Page 63: 시작하세요! 안드로이드 게임 프로그래밍

02 안드로이드 SDK 첫 걸음 l 37

그림 2-5 ㅣ 이클립스의 자바 퍼스펙티브를 사용하는 모습

그림 2-5에 나와 있는 툴바 또한 뷰에 포함된다. 사용하는 퍼스펙티브에 따라 툴바도 바뀔 수

있다. ADT 플러그인을 설치한 후 툴바가 몇 개 추가된 사실을 기억하자. 이는 플러그인의 일반적

인 기능에 속한다. 플러그인은 새로운 뷰와 퍼스펙티브를 추가해준다. ADT 플러그인을 추가하고

나면 표준 자바 디버그 퍼스펙티브 말고도 DDMS라는 퍼스펙티브(안드로이드 애플리케이션을

디버깅하고 프로파일링하기 위한 전용 퍼스펙티브)에 접근할 수 있다. ADT 플러그인은 연결된

기기나 에뮬레이터의 로깅 정보를 보여주는 로그캣 뷰를 비롯해 새로운 뷰도 몇 개 추가해준다.

퍼스펙티브와 뷰 개념에 익숙해지면 이클립스가 훨씬 편하게 느껴질 것이다. 이어지는 절에서

는 안드로이드 게임을 작성할 때 사용할 몇 가지 퍼스펙티브와 뷰를 살펴볼 것이다. 이 책에서는

이클립스를 활용해 개발을 진행하는 상세 내용을 모두 다룰 수 없으므로, 필요할 때마다 이클립

스의 도움말 시스템을 잘 활용해 이클립스를 더 배울 것을 권장한다.

안드로이드 방식의 Hello World

개발 환경을 설정하고 나면 이제 이클립스를 사용해 첫 번째 안드로이드 프로젝트를 생성할 수

있다. ADT 플러그인은 새 안드로이드 프로젝트를 쉽게 만들 수 있는 몇 가지 마법사를 함께 설

치해준다.

Page 64: 시작하세요! 안드로이드 게임 프로그래밍

38 l 시작하세요! 안드로이드 게임 프로그래밍

프로젝트의 생성

새 안드로이드 프로젝트를 생성하는 방법은 두 가지가 있다. 먼저 패키지 익스플로러 뷰를 마

우스 오른쪽 클릭(그림 2-4)하고 팝업 메뉴에서 New Project...를 누른다. 새 대화상자에서

Android 카테고리 아래 있는 Android Project를 선택한다. 그럼 프로젝트 생성과 관련한 다양

한 옵션이 대화상자에 보일 것이다. 이 방식은 이클립스에서 새 프로젝트를 생성할 때 사용하는

표준 방식이다. 대화상자의 내용을 확인하고 나면 안드로이드 프로젝트 마법사가 열릴 것이다.

두 번째 방법은 훨씬 더 쉽다. 새 안드로이드 프로젝트를 생성하는 버튼을 그냥 클릭하면 된다

(그림 2-4 참고).

안드로이드 프로젝트 마법사가 열려 있다면 다음 항목들을 선택할 수 있다.

1. 먼저 프로젝트명을 정의해야 한다. 보통 프로젝트명은 소문자로 지정하는 게 관례다. 이

예제의 경우 프로젝트명을 "hello world"로 지정한다.

2. 다음으로 빌드 대상을 지정해야 한다. 지금은 Android 1.5를 빌드 대상으로 지정한다. 이

버전은 모든 안드로이드 기기에 사용할 수 있는 공통 버전이고 이 예제에서는 멀티터치 등

의 기능이 아직 필요 없기 때문이다.

알아두기

1장에서는 안드로이드 버전이 새로 출시될 때마다 안드로이드 프레임워크 API에 새 클래스들

이 추가됐다는 사실을 배웠다. 빌드 대상을 지정하면 애플리케이션에서 사용할 API 버전을 지

정하게 된다. 예를 들어 Android 2.3을 빌드 대상으로 선택하면 가장 최근에 나온 API 기능

들을 사용할 수 있다. 하지만 그만큼 위험 요소도 크다. 이 경우 애플리케이션이 하위 API 버

전을 사용하는 기기에서 실행될 때 (예를 들어 안드로이드 1.5 버전을 실행하는 기기) 애플리

케이션이 2.3 버전에서만 사용할 수 있는 API에 접근할 경우 충돌하게 된다. 따라서 이때는

런타임 시점에 SDK 버전을 판단해 기기에서 안드로이드 버전을 지원하는 경우에만 2.3 버전

의 기능에 접근해야 한다. 이렇게 설명하면 꽤 지저분하게 들릴 수 있다. 하지만 5장에서 살펴

보겠지만 좋은 애플리케이션 아키텍처를 적용하면 충돌 위험을 초래하지 않고도 특정 버전과

관련한 기능을 쉽게 활성화 또는 비활성화할 수 있다.

3. 다음으로 애플리케이션의 이름(예를 들어 Hello World), 소스 코드를 지정할 위치(예를

들어 com.helloworld), 액티비티 이름을 지정해야 한다. 액티비티는 데스크톱 운영체제의

창 또는 대화상자와 비슷한 개념이다. 액티비티 이름은 HelloWorldActivity로 정한다.

Page 65: 시작하세요! 안드로이드 게임 프로그래밍

02 안드로이드 SDK 첫 걸음 l 39

4. Min SDK Version 필드는 애플리케이션에서 필요로 하는 최소 안드로이드 버전을 나타

낸다. 이 필드는 필수 값은 아니지만 지정하는 게 좋다. SDK 버전은 1(1.0)부터 시작해 새

로 나올 때마다 값이 올라간다. 1.5 버전은 세 번째 출시 버전이었으므로 여기서는 3을 지

정한다. 이때 최소 SDK 버전을 지정하기 앞서 빌드 대상을 먼저 지정해야 한다는 사실에

주의한다. 보통 빌드 대상은 최소 SDK 버전보다 새 버전으로 지정한다. 이렇게 하면 더

높은 버전의 API를 사용하는 동시에 과거 안드로이드 버전으로 애플리케이션을 배포할

수 있다(물론 해당 버전에서 지원하는 API 메서드만 호출한다는 전제가 있어야 한다).

5. Finish를 클릭해 첫 번째 안드로이드 프로젝트의 생성을 마친다.

알아두기

최소 SDK 버전 설정에는 몇 가지 암시적인 의미가 들어 있다. 애플리케이션은 최소 SDK 버

전에 해당하는 안드로이드 버전 이상의 기기에서만 실행될 수 있다. 사용자가 마켓 애플리케

이션을 사용해 안드로이드 마켓을 검색할 때는 최소 SDK 버전에 부합하는 애플리케이션들만

보이게 된다.

프로젝트 내용 살펴보기

이제 패키지 익스플로러를 보면 'hello world'라는 프로젝트를 볼 수 있을 것이다. 이 프로젝트의

내용을 모두 펼쳐보면 그림 2-6과 같은 모습이 될 것이다. 대부분의 안드로이드 프로젝트의 구조

가 바로 이렇게 돼 있다. 이제 이 구조를 좀 더 자세히 살펴보자.

■ AndroidManifest.xml은 애플리케이션에 대해 설명하는 파일이다. 이 파일에서는 애플

리케이션이 어떤 액티비티와 서비스로 구성되고, 최소 버전과 대상 버전이 어떻게 되는

지, 또 어떤 퍼미션(예를 들어 SD 카드 접근 또는 네트워크 접근 퍼미션 등)이 필요한지 정

의한다.

■ default.properties는 빌드 시스템에 대한 다양한 설정을 포함한다. 필요할 경우 ADT 플

러그인이 이런 설정을 알아서 수정하므로 이 파일은 따로 건드리지 않아도 된다.

■ src/에는 모든 자바 소스 파일들이 들어간다. 이때 패키지명이 안드로이드 프로젝트 마법

사에서 지정한 이름과 동일한 것을 확인할 수 있다.

Page 66: 시작하세요! 안드로이드 게임 프로그래밍

40 l 시작하세요! 안드로이드 게임 프로그래밍

■ gen/에는 안드로이드 빌드 시스템에서 생성한 자바 소스 파일들이 들어간다. 이 파일들

은 자동으로 생성되므로 건드리지 말아야 한다.

■ assets/는 애플리케이션에서 필요로 하는 파일들(설정 파일 또는 오디오 파일 등)을 저장

하는 공간이다. 이 파일들은 안드로이드 애플리케이션과 함께 패키징된다.

■ res/에는 애플리케이션에서 필요로 하는 아이콘, 국제화에 사용할 문자열, UI 레이아웃

을 정의한 XML 등의 자원이 들어간다. assets와 마찬가지로 이들 자원도 애플리케이션

과 함께 패키징된다.

■ Android 1.5는 현재 안드로이드 1.5 버전을 대상으로 빌드하고 있음을 알려준다. 이 폴더

는 사실 안드로이드 1.5 API의 클래스들을 포함하는 표준 JAR 파일 형태의 의존성이다.

패키지 익스플로러 뷰에서는 기기나 에뮬레이터로 배포할 컴파일된 소스 파일이 들어 있는

bin/ 디렉터리를 보여주지 않는다. gen/ 폴더와 마찬가지로 이 폴더도 보통은 따로 신경 쓰지 않

아도 된다.

그림 2-6 ㅣ Hello World 프로젝트의 구조

패키지 익스플로러에서 폴더를 마우스 오른쪽 클릭해 생성하려는 리소스 타입과 관련한 New

항목을 선택하면 소스 파일, 폴더, 기타 자원을 쉽게 추가할 수 있다. 하지만 지금은 모든 내용을

그대로 둔다. 다음으로 소스 코드를 조금 수정해 보자.

Page 67: 시작하세요! 안드로이드 게임 프로그래밍

02 안드로이드 SDK 첫 걸음 l 41

애플리케이션 코드의 작성

아직까지 소스를 한 줄도 작성하지 않았으므로 이제 조금 작성해 보기로 하자. 안드로이드 프로

젝트 마법사는 HelloWorldActivity라는 템플릿 액티비티 클래스를 자동으로 생성해주는데, 에

뮬레이터나 기기에서 애플리케이션을 실행하면 바로 이 액티비티가 보이게 된다. 패키지 익스플

로러 뷰에서 이 파일을 더블클릭해 클래스를 연다. 그런 다음 템플릿 코드를 예제 2-1과 같이 수

정한다.

예제 2-1 ㅣ HelloWorldActivity.java

package com.helloworld;

import android.app.Activity;

import android.os.Bundle;

import android.view.View;

import android.widget.Button;

public class HelloWorldActivity extends Activity

implements View.OnClickListener {

Button button;

int touchCount;

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

button = new Button(this);

button.setText( "Touch me!" );

button.setOnClickListener(this);

setContentView(button);

}

public void onClick(View v) {

touchCount++;

button.setText("Touched me " + touchCount + " time(s)");

}

}

예제 2-1의 내용을 하나씩 살펴보자. 여기서는 지나치게 상세한 설명은 이어질 장으로 미루고,

일단 전체적으로 어떤 일이 일어나는지만 살펴보겠다.

Page 68: 시작하세요! 안드로이드 게임 프로그래밍

42 l 시작하세요! 안드로이드 게임 프로그래밍

소스 코드 파일의 시작 부분은 표준 자바 패키지 선언과 몇 개의 임포트로 이뤄진다. 대부분의

안드로이드 프레임워크 클래스는 android 패키지 안에 들어 있다.

package com.helloworld;

import android.app.Activity;

import android.os.Bundle;

import android.view.View;

import android.widget.Button;

다음으로 HelloWorldActivity를 정의하고 이 클래스가 안드로이드 프레임워크 API에서 제공

하는 Activity 기저 클래스를 상속하게 했다. Activity는 데스크톱 UI의 창과 같은 것인데, 다만

(안드로이드 UI 상단에 있는 알림 바를 제외하고) 항상 전체 화면을 채워야 한다는 제약이 있다.

여기서는 추가로 액티비티가 OnClickListener 인터페이스를 구현하게 했다. 다른 UI 툴킷을 사

용해 본 적이 있다면 아마 다음 번에 나올 내용이 무엇인지 예상이 될 것이다. 이 부분은 잠시 후

에 바로 나온다.

public class HelloWorldActivity extends Activity

implements View.OnClickListener {

이어서 Activity에 두 개의 멤버를 추가했다. 하나는 Button이고 다른 하나는 Button의 클릭

횟수를 계산하는 정수다.

Button button;

int touchCount;

모든 Activity는 항상 추상 메서드인 Activity.onCreate()를 구현해야 한다. 이 메서드는 액

티비티가 처음 시작할 때 안드로이드 시스템에서 한 번 호출한다. 이 메서드는 마치 클래스

의 생성자와 비슷한 역할을 한다. 이 메서드 바디의 첫 번째 명령문에서는 항상 기저 클래스의

onCreate() 메서드를 호출해야 한다.

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

다음으로 Button을 생성하고 초기 텍스트를 설정한다. Button은 안드로이드 프레임워크 API

에서 제공하는 여러 위젯 중 하나다. 위젯은 안드로이드에서 View와 같은 개념으로 사용한다.

여기서는 button이 HelloWorldActivity 클래스의 멤버라는 사실에 주의해야 한다. 이 버튼은

나중에 따로 참조할 것이다.

Page 69: 시작하세요! 안드로이드 게임 프로그래밍

02 안드로이드 SDK 첫 걸음 l 43

button = new Button(this);

button.setText( "Touch me!" );

onCreate()의 다음 줄에서는 Button의 OnClickListener를 설정한다. OnClickListener는

OnClickListener.onClick()에 해당하는 단일 메서드를 정의한 콜백 인터페이스로서 Button을

클릭할 때 호출된다. 여기서는 버튼 클릭 횟수를 알아야 하므로 HelloWorldActivity가 이 인터

페이스를 구현하게 하고 HelloWorldActivity 자체를 Button의 OnClickListener로 등록한다.

button.setOnClickListener(this);

onCreate() 메서드의 마지막 줄에서는 Button을 Activity의 콘텐츠 View로 설정한다. View

는 계층 구조를 가질 수 있으며 Activity의 콘텐츠 View는 이런 계층 구조의 루트가 된다. 이 예

제에서는 Activity에서 보여줄 View로 Button만을 지정했다. 예제를 단순화하기 위해 여기서는

복잡한 콘텐츠 View를 지정해 Activity가 어떤 식으로 레이아웃을 잡는지는 살펴보지 않았다.

setContentView(button);

}

다음으로 OnClickListener.onClick() 메서드를 구현해야 한다. 이 메서드는 Activity에서 구

현하는 인터페이스가 필요로 하는 메서드다. 이 메서드는 Button을 클릭할 때마다 호출된다. 이

메서드 내에서는 touchCount 카운터 값을 증가시키고 Button의 텍스트를 새로운 문자열로 설

정한다.

public void onClick(View v) {

touchCount++;

button.setText("Touched me" + touchCount + "times");

}

간단히 Hello World 애플리케이션을 정리하면 이 애플리케이션은 Button이 들어 있는

Activity일 뿐이다. 매번 Button을 클릭하면 사용자의 클릭을 반영하기 위해 텍스트를 수정한다

(물론 이 애플리케이션은 그다지 재미있는 애플리케이션은 아니지만 예제 설명에 활용하기에는

충분하다).

앞에서 아무것도 직접 컴파일하지 않았다는 사실에 주의하자. 소스 파일이나 리소스를 추가,

수정, 삭제하면 이클립스와 더불어 ADT 플러그인이 알아서 프로젝트를 재컴파일해 준다. 이런

컴파일 과정을 거치면 에뮬레이터나 안드로이드 기기에 배포할 수 있는 APK 파일이 생성된다.

이 APK 파일은 프로젝트의 bin/ 폴더에 생성된다.

Page 70: 시작하세요! 안드로이드 게임 프로그래밍

44 l 시작하세요! 안드로이드 게임 프로그래밍

이 애플리케이션은 이어지는 절에서 사용할 것이다. 이어지는 절에서는 에뮬레이터와 더불어

기기에서 안드로이드 애플리케이션을 실행하고 디버그하는 법을 살펴본다.

안드로이드 애플리케이션의 실행과 디버깅

애플리케이션 코드의 첫 번째 반복 과정을 마쳤으므로 이번에는 애플리케이션을 실행하고 테

스트해 문제가 있는지 파악하고 결과를 확인할 차례다. 이때는 다음 두 가지 방법을 사용할 수

있다.

■ 애플리케이션은 USB를 통해 개발 PC와 연결된 실제 기기에서 테스트할 수 있다.

■ SDK에 포함된 에뮬레이터를 실행해 에뮬레이터에서 테스트할 수 있다.

두 경우 모두 실제 애플리케이션이 동작하는 것을 보기까지는 약간의 설정이 필요하다.

기기 연결

테스트를 위해 기기를 연결하려면 먼저 기기를 운영체제에서 인식할 수 있게 해야 한다. 윈도우

운영체제에서는 이 과정에서 적절한 드라이버를 설치해줘야 한다. 이 드라이버는 앞서 설치한

SDK 설치 폴더에 들어 있다. 기기를 PC와 연결한 후 윈도우의 표준 드라이버 설치 과정을 따르

고, SDK가 설치된 루트 디렉터리의 driver/ 폴더를 지정한다. 일부 기기의 경우 기기 제조사의 웹

사이트에서 드라이버를 직접 내려 받아야 한다.

리눅스나 맥 OS X에서는 보통 운영체제에 드라이버가 포함돼 있으므로 별도 드라이버를 설치

하지 않아도 된다. 리눅스 종류에 따라서는 udev에 대한 새 규칙 파일을 생성하는 등 USB 기기

를 검색하는 데 다소 작업이 필요할 수 있다. 하지만 웹 검색만으로도 기기에 대한 해결책을 쉽게

찾을 수 있을 것이다.

안드로이드 가상 기기의 생성

SDK에서는 안드로이드 가상 기기(AVD)라는 에뮬레이터를 제공한다. 가상 기기는 특정 안드로

이드 버전의 시스템 이미지, 스킨, 화면 해상도, SD 카드 크기 등을 비롯한 어트리뷰트로 구성

된다.

Page 71: 시작하세요! 안드로이드 게임 프로그래밍

02 안드로이드 SDK 첫 걸음 l 45

AVD를 생성하려면 먼저 SDK와 AVD 매니저를 실행해야 한다. 이를 실행하려면 앞서 SDK 설

치 과정에서 설명한 대로 할 수도 있고 이클립스의 툴바에서 SDK 매니저 버튼을 클릭해 실행할

수도 있다.

1. 왼쪽에 있는 가상 기기 목록에서 하나를 선택한다. 그럼 현재 사용 가능한 AVD 목록이

나타날 것이다. SDK 매니저를 전에 사용해 본 적이 없다면 이 목록이 비어 있을 것이다.

이 목록이 비어 있다면 다음과 같이 새로 추가한다.

2. 새 AVD를 생성하려면 오른쪽에 있는 New... 버튼을 클릭한다. 그럼 그림 2-7 같은 대화

상자가 나타난다.

그림 2-7 ㅣ SDK 매니저의 AVD 생성 대화상자

3. 각 AVD는 나중에 참조할 수 있는 이름을 갖고 있다. Target은 AVD에서 사용할 안드로이

드 버전을 지정하는 필드다. 추가로 AVD의 SD 카드 크기와 화면 크기도 지정할 수 있다.

Hello World 프로젝트에서는 Target을 Android 1.5로 지정하고 나머지는 그냥 원래대로

둔다. 실제 테스트 시에는 애플리케이션에서 지원하는 모든 안드로이드 버전과 화면 크기

를 포함하는 다양한 AVD를 생성해 애플리케이션을 테스트해야 한다.

Page 72: 시작하세요! 안드로이드 게임 프로그래밍

46 l 시작하세요! 안드로이드 게임 프로그래밍

알아두기

서로 다른 안드로이드 버전과 화면 크기를 갖춘 기기를 수십 개씩 갖고 있지 않다면 추가적인

안드로이드 버전/화면 크기 조합에 대해서는 에뮬레이터를 사용해 테스트할 것을 권장한다.

애플리케이션의 실행

이제 기기와 AVD 설정을 마쳤으므로 드디어 Hello World 애플리케이션을 실행할 수 있다. 이

클립스의 패키지 익스플로러에서 'hello world' 프로젝트를 마우스 오른쪽 클릭하고 Run As

Android Application를 선택하면(또는 툴바의 Run 버튼을 눌러도 된다) 애플리케이션을 바로

실행할 수 있다. 이렇게 하고 나면 이클립스는 내부적으로 다음 작업들을 수행한다.

1. 마지막 컴파일 시점 이후 수정된 파일이 있다면 프로젝트를 컴파일해 APK 파일을 만든다.

2. 안드로이드 프로젝트에 대해 기존에 존재하는 실행 설정이 없다면 새 실행 설정을 생성

한다(실행 설정은 잠시 후 보게 될 것이다).

3. 안드로이드 버전에 맞는 에뮬레이터를 시작하거나 이미 구동 중인 에뮬레이터를 재사용해

애플리케이션을 설치하고 실행한다. 또는 연결된 기기에 애플리케이션을 배포하고 실행한

다(이 경우 기기가 프로젝트 생성 시 Min SDK Level에 지정한 최소 안드로이드 버전 이상

의 버전에서 구동돼야 한다).

앞 절에서 설명한 대로 Android 1.5 AVD를 생성하면 ADT 이클립스 플러그인이 AVD를 실

행하는 새 에뮬레이터를 실행해 Hello World APK 파일을 배포하고 애플리케이션을 시작할 것

이다. 결과 화면은 그림 2-8과 같다.

Page 73: 시작하세요! 안드로이드 게임 프로그래밍

02 안드로이드 SDK 첫 걸음 l 47

그림 2-8 ㅣ Hello World 애플리케이션을 실행한 모습

에뮬레이터는 실제 기기와 거의 똑같이 동작하며 기기를 손가락으로 터치하는 것처럼 마우스

를 통해 상호작용할 수 있다. 실제 기기와 에뮬레이터의 차이점을 정리하면 다음과 같다.

■ 에뮬레이터는 싱글터치 입력만 지원한다. 마치 손가락을 사용하는 것처럼 마우스 커서를

사용한다.

■ 에뮬레이터에는 안드로이드 마켓 같은 일부 애플리케이션이 빠져 있다.

■ 화면상에서 기기 방향을 바꾸려고 할 때 모니터를 기울여서는 안 된다. 대신 숫자 키패드

의 7 키를 사용하면 된다. 이 기능을 사용하려면 먼저 Num Lock 키를 사용해 숫자 기능

을 비활성화해야 한다.

■ 에뮬레이터는 정말, 정말 느리다. 에뮬레이터에서의 실행 결과를 기준으로 애플리케이션

의 성능을 판단해서는 안 된다.

■ 현재 에뮬레이터는 오픈GL ES 1.0 및 몇 개의 확장 기능만을 지원한다. 오픈GL ES는 7

장에서 자세히 설명할 것이다. 에뮬레이터의 오픈GL ES 구현체는 버그가 있고 실제 기기

에서 테스트할 때와 다른 결과를 종종 보여준다는 점을 제외하고는 쓸 만하다. 지금은 오

픈GL ES 애플리케이션은 에뮬레이터에서 테스트하지 말아야 한다는 사실만 알아 두자.

에뮬레이터가 익숙해질 때까지 에뮬레이터를 이리 저리 사용해 보자.

Page 74: 시작하세요! 안드로이드 게임 프로그래밍

48 l 시작하세요! 안드로이드 게임 프로그래밍

알아두기

에뮬레이터를 새로 시작하려면 꽤 많은 시간이 소요된다(하드웨어에 따라 몇 분이 걸릴 수도

있다). 에뮬레이터를 개발 세션 내내 열어 둔 채로 두면 매번 닫고 재시작하지 않아도 되므로

편리하다.

때로는 안드로이드 애플리케이션을 실행할 때 ADT 플러그인이 자동으로 에뮬레이터/기기를

선택하는 게 방해가 될 수도 있다. 예를 들어 여러 개의 기기/에뮬레이터가 연결된 상태에서 특

정 기기/에뮬레이터에서 애플리케이션을 테스트하려는 경우가 있을 수 있다. 이때는 안드로이드

프로젝트의 실행 설정에서 자동 기기/에뮬레이터 선택 옵션을 비활성화하면 된다. 그럼 실행 설

정이란 무엇일까?

실행 설정은 애플리케이션을 실행할 때 이클립스에게 어떻게 실행해야 할지 알려주는 설정을

말한다. 실행 설정에서는 보통 애플리케이션에 전달되는 명령행 인자, VM 인자(자바 SE 데스크

톱 애플리케이션의 경우) 등을 설정한다. 이클립스와 서드파티 플러그인은 특정 프로젝트 타입

에 대해 서로 다른 설정을 제공한다. ADT 플러그인은 사용 가능한 실행 설정에 안드로이드 애

플리케이션 실행 설정을 추가한다. 이 장에서 앞서 애플리케이션을 처음 실행했을 때 이클립스

와 ADT는 기본 매개변수를 사용해 안드로이드 애플리케이션에 대한 새로운 설정을 내부적으

로 생성했다.

안드로이드 프로젝트의 실행 설정을 제어하려면 다음과 같이 하면 된다.

1. 패키지 익스플로러 뷰에서 프로젝트를 마우스 오른쪽 클릭하고 Run  As Run 

Configurations를 선택한다.

2. 왼쪽 목록에서 'hello world' 프로젝트를 선택한다.

3. 이제 대화상자 오른쪽에서 실행 설정의 이름을 바꾸고 Android, Target, Commons 탭

에 대한 다른 설정도 바꿀 수 있을 것이다.

4. 자동 배포를 수동 배포로 바꾸려면 Target 탭을 클릭하고 Manual을 선택한다.

이제 애플리케이션을 다시 실행하면 애플리케이션을 실행할 수 있는 호환 에뮬레이터와 기기

를 선택할 수 있는 대화상자가 보일 것이다. 그림 2-9에서는 이 대화상자를 보여준다. 이 그림에

서는 다른 배포 대상을 적용한 AVD 몇 개를 추가하고 기기도 두 대 연결했다.

Page 75: 시작하세요! 안드로이드 게임 프로그래밍

02 안드로이드 SDK 첫 걸음 l 49

그림 2-9 ㅣ 애플리케이션을 실행할 에뮬레이터/기기를 선택하는 대화상자

이 대화상자에서는 실행 중인 에뮬레이터와 현재 연결된 기기뿐 아니라 지금 실행하고 있지

않은 AVD들도 모두 보여준다. 여기서는 애플리케이션을 실행할 에뮬레이터나 기기를 마음대로

선택할 수 있다.

애플리케이션 디버깅

때로는 애플리케이션이 예상치 못한 행동을 하거나 강제 종료될 때가 있다. 이때 무엇이 잘못됐

는지 정확히 알려면 애플리케이션을 디버깅해야 한다.

이클립스와 ADT는 안드로이드 애플리케이션을 디버깅할 수 있는 강력한 기능을 제공한다.

소스 코드에는 브레이크포인트를 설정할 수도 있고 변수 값과 현재 스택 트레이스도 확인할 수

있다.

애플리케이션을 디버깅하려면 먼저 AndroidManifest.xml 파일을 수정해 디버깅을 활성화해

야 한다. 이 책에서는 아직 매니페스트 파일을 자세히 살펴보진 않았으므로 지금은 메니페스트

파일 안에 애플리케이션의 속성을 정의한 내용들이 들어 있다는 사실만 알아두면 된다. 이들 속

성 중 하나는 애플리케이션을 디버깅할 수 있는지 여부(debuggable)다. 이 속성은 메니페스트 파

일에서 <application> 태그의 xml 어트리뷰트로 들어 있다. 디버깅을 활성화하려면 메니페스트

파일의 <application>에서 다음 어트리뷰트를 추가하면 된다.

android:debuggable="true"

Page 76: 시작하세요! 안드로이드 게임 프로그래밍

50 l 시작하세요! 안드로이드 게임 프로그래밍

애플리케이션을 개발할 때는 이 어트리뷰트를 메니페스트 파일에 그대로 두어도 된다. 하지만

애플리케이션을 마켓에 배포할 때는 이 어트리뷰트를 지워야 한다.

이제 애플리케이션을 디버그할 수 있게 설정했으므로 에뮬레이터나 기기에서 디버그를 진행

할 수 있다. 보통 디버깅을 할 때는 프로그램의 특정 위치에서 프로그램의 상태를 확인하기 위해

브레이크포인트를 설정한다.

브레이크포인트를 설정하려면 이클립스에서 소스 파일을 열어서 브레이크포인트를 설정할 코

드 줄 앞에 있는 회색 영역을 더블클릭하면 된다. 테스트를 위해 HelloWorldActivity 클래스의

23번째 줄에 브레이크포인트를 설정해 보자. 이렇게 브레이크포인트를 설정하면 버튼을 클릭할

때마다 디버거가 해당 위치에서 애플리케이션의 실행을 멈춘다. 그림 2-10에서 보는 것처럼 소스

코드 뷰에서는 브레이크포인트가 설정된 코드 줄 앞에 작은 원을 보여준다. 브레이크포인트를

제거하려면 소스 코드 뷰에서 브레이크포인트를 다시 한 번 더블클릭하면 된다

그림 2-10 ㅣ 브레이크포인트의 설정

디버깅 실행은 앞 절에서 설명한 애플리케이션 실행과 거의 비슷하다. 패키지 익스플로러 뷰에

서 프로젝트를 마우스 오른쪽 클릭하고 Debug As Android Application을 누른다. 그럼 애

플리케이션을 실행할 때와 비슷하게 프로젝트의 새로운 디버그 설정이 생성된다. 디버그 설정의

기본값은 컨텍스트 메뉴의 Debug As Debug Configurations에서 바꿀 수 있다.

알아두기

패키지 익스플로러 뷰의 프로젝트 컨텍스트 메뉴를 사용하는 대신 Run 메뉴를 사용해 애플리

케이션을 실행, 디버그할 수도 있고 설정에 접근할 수도 있다.

디버그 세션을 처음 시작했다면 이클립스가 디버그 퍼스펙티브로 전환할지 물을 것이다. 이때

는 그냥 확인을 누르면 된다. 그럼 디버그 퍼스펙티브를 살펴보자. 그림 2-11에는 Hello World 애

플리케이션의 디버깅을 처음 시작했을 때의 모습이 나와 있다.

Page 77: 시작하세요! 안드로이드 게임 프로그래밍

02 안드로이드 SDK 첫 걸음 l 51

그림 2-11 ㅣ 디버그 퍼스펙티브

앞에서 다룬 이클립스 살펴보기 절의 내용을 기억한다면 이클립스에는 특정 작업을 위한 뷰

로 구성된 퍼스펙티브가 여러 개 있다는 사실을 기억할 것이다. 디버그 퍼스펙티브는 다음과 같

은 특징으로 인해 자바 퍼스펙티브와 다르다.

■ 첫 번째로 보이는 새로운 뷰는 좌측 상단에 있는 디버그 뷰다. 디버그 뷰는 현재 실행 중

인 애플리케이션과 디버그 모드에서 실행 중인 모든 스레드의 스택 트레이스를 보여준다.

■ 디버그 뷰 아래에는 자바 퍼스펙티브에서도 사용한 바 있는 소스 편집 뷰가 있다.

■ 콘솔 뷰는 ADT 플러그인의 메시지를 출력해 줌으로써 현재 일어나고 있는 일을 알려준다.

■ 로그캣 뷰는 개발 과정에서 가장 큰 도움이 되는 뷰 중 하나다. 로그캣 뷰는 애플리케이

션이 실행되는 에뮬레이터/기기의 로깅 결과를 보여준다. 로깅 결과는 시스템 컴포넌트,

다른 애플리케이션, 우리가 개발한 애플리케이션으로부터 출력된다. 로깅 결과는 애플리

케이션이 강제 종료될 경우 스택 트레이스를 보여주고, 런타임 시에 로깅 메시지를 출력할

수도 있게 해준다. 로그캣은 다음 절에서 자세히 살펴볼 것이다.

■ 아웃라인 뷰는 디버그 퍼스펙티브에서는 큰 도움이 안 된다. 디버깅 과정에서는 주로 브

레이크포인트와 변수 뷰를 사용해 프로그램이 현재 실행 중단된 코드 줄을 살펴보기 때

문이다. 필자는 다른 뷰에 사용할 공간을 더 벌기 위해 디버그 퍼스펙티브에서 아웃라인

뷰를 종종 제거하곤 한다.

Page 78: 시작하세요! 안드로이드 게임 프로그래밍

52 l 시작하세요! 안드로이드 게임 프로그래밍

■ 변수 뷰는 디버깅 시에 특히 유용하다. 디버거가 브레이크포인트를 만나면 프로그램의 현

재 스코프에 있는 변수 값을 확인하고 수정할 수 있다.

■ 끝으로 브레이크포인트 뷰는 지금까지 설정한 브레이크포인트 목록을 모두 보여준다.

호기심이 많은 독자라면 디버거가 어떻게 반응하는지 살펴보기 위해 실행 중인 애플리케이션

에서 버튼을 이미 클릭해 봤을 것이다. 그럼 애플리케이션은 브레이크포인트를 설정한 23줄에서

실행을 멈춘다. 이때 현재 스코프에 있는 변수를 변수 뷰에서 보여주는 것을 볼 수 있다. 현재 스

코프에 해당하는 변수에는 액티비티 자체(this)와 메서드 매개변수(v)가 들어 있다. 변수를 펼치

면 변수를 드릴다운해 내려갈 수 있다.

디버그 뷰는 현재 위치의 메서드까지의 스택 트레이스를 보여준다. 디버그 뷰에서는 여러 스레

드가 실행 중이더라도 아무 때나 실행을 멈출 수 있다.

끝으로 브레이크포인트를 설정한 코드 줄이 강조되는 것을 볼 수 있다. 이런 강조 표시는 프로

그램이 현재 멈춰 있는 코드 위치를 알려주기 위해 사용된다.

디버거가 현재 명령문을 실행하게 할 수도 있고(F6), 현재 메서드에서 호출한 메서드로 단계 진

입할 수도 있고(F5), 프로그램을 정상적으로 계속 실행할 수도 있다(F8). 또는 Run 메뉴에 있는

항목을 선택하더라도 이와 동일한 작업을 수행할 수 있다. 아울러 여기 설명한 것 외에 더 많은

단계 옵션이 있음을 기억하자. 다른 내용과 마찬가지로 이 부분 또한 직접 실험해 보면서 내용을

익힐 것을 권장한다.

알아두기

호기심이야 말로 안드로이드 게임 개발을 성공으로 이끄는 원동력이다. 개발 환경을 잘 활용

하려면 개발 환경과 가능한 한 친해져야 한다. 이 책에서는 이클립스 개발 환경에 대한 상세

내용을 모두 다루지 못하므로 이 부분은 독자들이 직접 여러 가지로 실험해보기를 권장한다.

로그캣과 DDMS

ADT 이클립스 플러그인은 이클립스에 새로운 뷰와 퍼스펙티브를 여러 개 설치해준다. 이 중 가

장 유용한 뷰는 (앞 절에서 잠깐 언급한 것처럼) 로그캣 뷰다.

Page 79: 시작하세요! 안드로이드 게임 프로그래밍

02 안드로이드 SDK 첫 걸음 l 53

로그캣은 안드로이드의 이벤트 로깅 시스템으로서 시스템 컴포넌트와 애플리케이션이 다양

한 로깅 레벨의 로깅 정보를 출력할 수 있게 해준다. 각 로그 항목은 타임 스탬프, 로깅 레벨, 로

그의 출처가 된 프로세스 ID, 로깅 애플리케이션 자체에서 정의한 태그, 실제 로깅 메시지로 구성

된다.

로그캣 뷰는 연결된 에뮬레이터 또는 기기로부터 정보를 수집해 보여준다. 그림 2-12는 로그

캣 뷰의 출력 결과 예시를 보여준다.

그림 2-12 ㅣ 로그캣 뷰

로그캣 뷰의 우측 상단에서는 여러 개의 버튼을 볼 수 있다.

■ 처음 다섯 개의 버튼은 표시하고자 하는 로깅 레벨을 선택하는 데 사용한다.

■ 녹색 더하기 버튼은 태그, 프로세스 ID, 로그 레벨을 기반으로 필터를 정의할 수 있게 해

준다. 이런 필터는 애플리케이션의 로그 결과만 보려고 할 때 편하게 활용할 수 있다(보통

애플리케이션은 로깅 시에 특정 태그를 사용하기 마련이다).

■ 나머지 버튼들은 필터를 편집, 삭제하거나 현재 출력 결과를 지우는 데 사용한다.

현재 여러 개의 기기와 에뮬레이터가 연결돼 있다면 로그캣 뷰는 이들 중 하나의 로깅 데이터

만 출력한다. 좀 더 미세한 제어가 필요하고 검색 옵션이 더 필요하다면 DDMS 퍼스펙티브로 전

환하면 된다.

DDMS(달빅 디버깅 모니터 서버)는 프로세스 및 연결된 모든 기기에서 실행 중인 달빅 VM에

대한 상세 정보를 제공한다. DDMS 퍼스펙티브로 전환하려면 Window Open Perspective

Other DDMS를 선택하면 된다. 그림 2-13에는 DDMS 퍼스펙티브의 일반적인 모습이 나

와 있다.

Page 80: 시작하세요! 안드로이드 게임 프로그래밍

54 l 시작하세요! 안드로이드 게임 프로그래밍

항상 그렇듯이 작업 종류에 따라 이를 처리하는 특수 뷰들이 있기 마련이다. DDMS 퍼스펙티

브에서는 전체 프로세스, VM과 스레드, 힙의 현재 상태, 특정 연결 기기에 대한 로그캣 정보 등

에 대한 정보를 모아서 보여준다.

■ 기기 뷰는 현재 연결된 에뮬레이터와 기기 및 그 안에서 실행 중인 모든 프로세스를 보여

준다. 이 뷰의 툴바 버튼에서는 선택한 프로세스를 디버깅하거나 힙과 스레드 정보를 기

록하고 화면을 캡처하는 등의 다양한 작업을 수행할 수 있다.

■ 로그캣 뷰는 앞의 퍼스펙티브에서와 같다. 다만 이 퍼스펙티브에서는 기기 뷰에서 현재

선택된 기기에 대한 출력 결과만을 보여준다는 점이 다르다.

■ 에뮬레이터 제어 뷰는 실행 중인 에뮬레이터의 행동을 변경할 수 있게 해준다. 이 뷰에서

는 예컨대 테스트용으로 에뮬레이터의 GPS 좌표를 강제 지정할 수 있다.

그림 2-13 ㅣ DDMS 퍼스펙티브

■ 스레드 뷰는 기기 뷰에서 선택한 프로세스에서 실행 중인 스레드에 대한 정보를 보여준

다. 스레드 뷰는 스레드 트래킹을 활성화한 경우에만 이 정보를 보여준다. 스레드 트래킹

을 활성화하려면 기기 뷰의 왼쪽에서 다섯 번째 있는 버튼을 클릭하면 된다.

Page 81: 시작하세요! 안드로이드 게임 프로그래밍

02 안드로이드 SDK 첫 걸음 l 55

■ 그림 2-13에는 나오지 않은 힙 뷰는 기기의 힙 상태에 대한 정보를 제공한다. 스레드 정보

와 마찬가지로 기기 뷰의 왼쪽에서 두 번째 있는 버튼을 클릭해 힙 트래킹을 활성화해야

이 정보를 볼 수 있다.

■ 할당 트래커 뷰는 최근에 가장 많이 메모리가 할당된 클래스들을 보여준다. 이 뷰는 메모

리 누수를 추적할 때 큰 도움이 된다.

■ 끝으로 파일 익스플로러 뷰는 연결된 안드로이드 기기 또는 에뮬레이터에서 파일을 수정

할 수 있게 해준다. 이 뷰에서는 표준 운영체제의 탐색기처럼 파일을 드래그앤드롭할 수

있다.

사실 DDMS는 ADT 플러그인을 통해 이클립스로 통합된 단독 실행 툴이다. DDMS는

$ANDROID_HOME/tools 디렉터리(윈도우에서는 %ANDROID_HOME%/tools)에서 단독

실행 애플리케이션 형태로 실행할 수도 있다. DDMS는 직접 기기를 연결하지 않고 SDK에 포함

된 또 다른 툴인 안드로이드 디버그 브릿지(ADB)를 사용해 연결한다. 그럼 안드로이드 개발 환

경에 대한 지식을 마무리하는 차원에서 끝으로 ADB에 대해 알아보자.

ADB의 활용

ADB는 연결된 기기와 에뮬레이터를 관리할 수 있게 해준다. ADB는 실제로는 세 개의 각기 다

른 컴포넌트로 구성된다.

■ 개발 장비에서 실행되는 클라이언트. 이 클라이언트는 명령형에서 adb 명령을 통해 실행

할 수 있다(앞에서 설명한 대로 환경 변수를 설정했다면 바로 실행할 수 있다). 보통 ADB

라고 하면 바로 이 명령행 프로그램을 가리킨다.

■ 마찬가지로 개발 장비에서 실행 중인 서버. 이 서버는 백그라운드 서비스로 설치되며

ADB 프로그램과 연결된 기기 또는 에뮬레이터 사이의 통신을 책임진다.

■ 마찬가지로 모든 에뮬레이터와 기기에 대해 백그라운드 프로세스로 실행되는 ADE 데몬.

ADB 서버는 통신을 위해 이 데몬과 연결을 맺는다.

보통 ADB는 DDMS를 통해 사용하며 별도 명령행 도구로 사용하는 일은 거의 없다. 하지만 때

로는 작업 규모가 작을 경우 명령행이 편할 수 있으므로 간단히 ADB의 기능을 살펴보기로 하자.

Page 82: 시작하세요! 안드로이드 게임 프로그래밍

56 l 시작하세요! 안드로이드 게임 프로그래밍

알아두기

사용 가능한 전체 명령에 대한 레퍼런스가 궁금하다면 안드로이드 개발자 사이트인 http://

developer.android.com에서 ADB 문서를 참고하자.

ADB로 할 수 있는 유용한 작업 중 하나는 현재 ADB 서버(즉 개발 장비)에 연결된 전체 기기

와 에뮬레이터의 목록을 조회하는 것이다. 이를 위해서는 명령행에서 다음 명령을 실행하면 된

다(>는 명령에 포함되지 않는다).

> adb devices

이렇게 하고 나면 연결된 기기 및 에뮬레이터의 목록이 일련 번호 형태로 출력될 것이다. 그 형

태는 대략 다음과 같다.

List of devices attached

HT97JL901589 device

HT019P803783 device

기기나 에뮬레이터의 일련 번호는 해당 기기 또는 에뮬레이터를 대상으로 특정 명령을 실행

할 때 사용한다. 다음 명령은 개발 장비에 들어 있는 myapp.apk라는 APK 파일을 일련 번호가

HT019P803783인 기기에 설치하는 명령이다.

> adb –s HT019P803783 install myapp.apk

–s 인자는 특정 기기를 대상으로 작업을 수행하는 ADB 명령에 사용할 수 있다.

기기 및 에뮬레이터와 관련해 파일을 복사하는 명령도 있다. 다음 명령은 my«le.txt라는 로컬

파일을 일련 번호가 HT019P803783인 기기의 SD 카드에 복사하는 명령이다.

> adb –s HT019P803783 push myfile.txt /sdcard/myfile.txt

SD 카드에서 my«le.txt라는 파일을 가져오려면 다음 명령을 실행하면 된다

> abd pull /sdcard/myfile.txt myfile.txt

ADB 서버와 연결된 기기 또는 에뮬레이터가 한 개뿐이라면 일련 번호를 생략해도 된다. 이 경

우 adb 툴은 연결된 기기나 에뮬레이터를 자동으로 지목해 명령을 실행한다.

Page 83: 시작하세요! 안드로이드 게임 프로그래밍

02 안드로이드 SDK 첫 걸음 l 57

물론 ADB 툴에서 제공하는 기능은 이보다 훨씬 많다. 이들 기능 중 대부분은 DDMS를 통해

서 사용할 수 있으므로 이 책에서는 명령행을 사용하는 대신 DDMS를 사용할 것이다. 하지만

작업을 빨리 해야 할 때는 명령행 도구가 더 적합할 수 있다.

정리

안드로이드 개발 환경은 때로 어렵게 느껴질 수도 있다. 하지만 처음 개발을 시작할 때는 사용할

수 있는 전체 옵션 중 일부만을 사용해도 충분하며, 이 장에서는 기본 코딩을 시작하는 데 필요

한 기초 지식을 충분히 다뤘다.

이 장에서는 각 부분이 어떻게 연동되는지 꼭 이해해야 한다. JDK와 안드로이드 SDK는 모든

안드로이드 개발의 기초가 된다. 이들 SDK는 에뮬레이터나 기기에서 애플리케이션을 컴파일, 배

포, 실행하는 데 필요한 도구를 제공한다. 개발 생산성을 높이려면 이클립스와 더불어 ADT 플

러그인을 사용하는 게 좋다. ADT 플러그인은 JDK와 SDK를 사용해 명령행에서 일일이 수행해

야 하는 복잡한 작업들을 추상화해 간편하게 만들어준다. 이클립스는 몇 가지 핵심 개념을 기반

으로 구축됐다. 이런 핵심 개념에는 프로젝트를 관리하는 작업 공간, 소스 편집이나 로그캣 결과

처럼 특정 기능을 제공하는 뷰, 디버깅 등의 특정 작업을 수행하는 데 필요한 뷰들을 연결해 놓

은 퍼스펙티브, 애플리케이션을 실행하거나 디버그할 때 시작 설정을 지정할 수 있는 실행 설정

과 디버그 설정 등이 있다.

고리타분한 얘기처럼 들리겠지만 이런 내용을 모두 마스터하려면 부단히 연습해야 한다. 이 책

에서는 다양한 프로젝트를 구현하면서 독자들이 안드로이드 개발 환경을 보다 편하게 느낄 수

있게 해준다. 하지만 결국 이를 한 단계 더 발전시키는 것은 독자들의 몫이다.

이제 이런 내용을 모두 익혔다면 처음 이 책의 진짜 주제를 살펴볼 준비가 된 것이다. 이제 게

임을 개발할 차례다.

Page 84: 시작하세요! 안드로이드 게임 프로그래밍

Beg

inni

ng

And

roid

Gam

es

Page 85: 시작하세요! 안드로이드 게임 프로그래밍

59

03게임 개발 101

게임 개발은 어렵다. 게임 개발이 어려운 이유는 게임 개발이 로켓 과학처럼 고도의 기술이 필요

해서가 아니라 원하는 게임 코드를 작성하기에 앞서 익혀야 할 정보의 양이 그만큼 방대하기 때

문이다. 프로그래밍 측면에서는 파일 입/출력(I/O), 사용자 입력 처리, 오디오 및 그래픽 프로그

래밍, 네트워크 코드를 처리할 줄 알아야 한다. 하지만 이 정도는 그저 기초 지식일 뿐이다. 그 외

에 실제 게임 방식을 구현할 수 있어야 한다. 또 이런 코드를 잘 구조화해야 하는데 게임의 아키

텍처를 구축하는 방법이 딱 정해진 것도 아니다. 게임을 만들 때는 게임 공간을 어떻게 움직일지

결정해야 한다. ‘물리 엔진을 사용하지 않으면서 간단한 시뮬레이션 코드를 돌릴 수 있을까?’, ‘게

임 공간에서 사용할 단위와 크기는 어떻게 설정해야 할까?’, ‘화면의 좌표 전환은 어떻게 해야 할

까?’ 등의 고민을 해결해야 한다.

이런 문제들 외에 초보자들이 간과하는 또 다른 문제점이 있다. 즉 코드를 작성하기에 앞서 게

임 설계부터 해야 한다는 사실을 간과하는 것이다. 수없이 많은 게임 프로젝트가 명확한 게임 설

계 없이 개발돼 끝내 빛을 못 보고 데모 수준에서 끝나고 만다. 여기서 필자는 1인칭 슈팅 게임

같은 기본 게임 방식의 설계를 얘기하는 게 아니다. 이런 게임이라면 상당히 쉽게 설계할 수 있다.

WASD 키와 마우스만 가지고 있으면 게임 설계가 끝난다. 게임을 설계할 때는 다음과 같은 질문

을 해야 한다. 로고 화면이 있나? 로고 화면은 어떤 화면으로 전환되나? 메인 메뉴에는 어떤 내용

이 들어 있나? 실제 게임 화면의 상단에는 어떤 요소들을 배치하나? 일시 정지 버튼을 누르면 어

떤 일이 일어나나? 설정 화면에서는 어떤 옵션을 제공하나? 화면 크기와 비율이 달라질 경우 UI

디자인에 어떤 변화가 생기나?

Page 86: 시작하세요! 안드로이드 게임 프로그래밍

60 l 시작하세요! 안드로이드 게임 프로그래밍

재미있는 것은 이에 대한 명확한 해결책이 없다는 점이다. 즉 이런 질문들을 접근하는 표준 방

식이 없는 것이다. 필자는 게임을 개발할 때 독자들에게 획일적인 해결책을 강요하지 않을 것이

다. 대신 게임을 설계할 때 필자가 주로 사용하는 접근 방식을 보여줄 것이다. 독자들은 필자의

방식을 그대로 따를 수도 있고 자신의 목적에 맞게끔 얼마든지 수정해 사용할 수도 있다. 정해진

규칙은 없다. 여러분에게 잘 맞는 해결책이 바로 좋은 해결책이다. 하지만 더 쉬운 해결책을 찾기

위한 코드나 문서화 노력을 게을리해서는 안 된다.

장르 - 각인각색

게임 프로젝트를 시작할 때는 보통 게임이 속할 장르부터 결정한다. 이전에 볼 수 없었던 전혀 새

로운 게임을 개발하는 게 아니라면 여러분의 게임 아이디어는 보통 현재 인기 있는 장르 중 하

나에 속하게 된다. 대다수 장르는 표준 게임 방식을 갖고 있다(예를 들어 제어 방식, 게임의 목적

등). 게이머들은 항상 뭔가 새로운 것을 찾고 있으므로 이런 표준을 살짝 벗어나면 히트하는 게

임을 만들 수 있다. 하지만 동시에 큰 위험이 따를 수도 있으므로 새로운 플랫폼 게임/1인칭 슈팅

게임/실시간 전략 게임을 즐길 실제 사용자층이 있을지 신중하게 고려해야 한다.

그럼 안드로이드 마켓에서 인기 있는 게임 장르부터 몇 개 살펴보자.

캐주얼 게임

안드로이드 마켓의 게임 분야에서 가장 큰 비중을 차지하는 게임은 소위 캐주얼 게임이라고 부

르는 게임들이다. 그럼 캐주얼 게임이 정확히 무엇일까? 이 질문에 대한 명확한 답은 없지만 캐주

얼 게임에는 몇 가지 공통된 특징이 있다. 보통 캐주얼 게임은 쉽게 접근할 수 있다. 따라서 게임

을 잘 즐기지 않는 사람들도 게임을 쉽게 할 수 있고, 이로 인해 잠재적인 플레이어층이 두텁다.

한 게임 세션은 최대 몇 분을 넘기지 않는다. 하지만 캐주얼 게임의 단순함으로 인한 중독성 때문

에 게이머들은 몇 시간씩 게임에 빠져들기도 한다. 캐주얼 게임의 실제 게임 방식은 간단한 퍼즐

게임부터 버튼 하나로 구성된 플랫폼 게임, 종이 공을 던지는 간단한 게임부터 농구 게임에 이르

기까지 다양하다. 캐주얼 게임 장르의 정의는 명확히 정해진 게 없으므로 캐주얼 게임의 가능성

또한 무궁무진하다.

Psym Mobile에서 출시한 Abduction과 Abduction 2(그림 3-1)는 캐주얼 게임을 잘 보여주는

예다. 이 게임은 점프업 게임의 하위 장르에 속한다(적어도 필자가 보는 기준은 이렇다). 이 게임

Page 87: 시작하세요! 안드로이드 게임 프로그래밍

03 게임 개발 101 l 61

의 목적은 쉴새 없이 점프하는 소를 한 곳에서 다른 곳으로 이끌어 레벨 꼭대기까지 올라가는 것

이다. 화면 위에는 깨지는 발판과 스파이크, 날아다니는 적들이 있다. 파워업 아이템을 먹으면 위

로 좀 더 쉽게 올라갈 수 있다. 폰을 기울이면 소를 조종해 소가 점프하고 떨어지는 방향을 조절

할 수 있다. 쉽게 이해할 수 있는 게임 조작 방식과 명확한 게임 목적, 귀여운 그래픽으로 인해 이

게임은 안드로이드 마켓의 게임 분야에서 첫 번째 성공작 중 하나가 됐다.

그림 3-1 ㅣ Psym Mobile의 Abduction(왼쪽)과 Abduction 2(오른쪽)

Battery Powered Games의 Antigen(그림 3-2)에서는 전혀 다른 동물이 등장한다. 이 게임에

서는 여러 종류의 바이러스와 싸우는 항체를 플레이한다. 이 게임은 사실 변종 액션 퍼즐 게임이

다. 항체는 화면상의 D-패드를 사용해 조종하고 회전시키려면 우측 상단의 버튼을 사용한다. 항

체에는 바이러스에 붙어서 바이러스를 죽일 수 있는 연결기가 있다. 이 게임은 간단하면서 매우

중독성 있는 게임이다. Abduction에서는 입력 방식이 가속도계를 사용하는 방식 하나뿐이었지

만 Antigen에서는 조작 방식이 조금 더 많아졌다. 일부 기기는 멀티터치를 지원하지 않으므로 개

발자들은 모든 기기에서 사용할 수 있는 입력 방식을 고안해 냈는데, Zeemote 컨트롤도 그중 하

나다. 가능한 한 많은 사용자층을 공략하기 위해 이 게임 개발자는 320×240 픽셀의 낮은 해상

도를 사용하는 저사양 기기에서도 게임이 동작하게끔 특별히 신경 썼다.

Page 88: 시작하세요! 안드로이드 게임 프로그래밍

62 l 시작하세요! 안드로이드 게임 프로그래밍

그림 3-2 ㅣ Battery Powered Games의 Antigen

캐주얼 게임 장르의 하위 장르에 속하는 게임을 다 나열하려면 이 책의 거의 모든 페이지를 할

애해야 할 것이다. 이 게임 장르에서는 혁신적인 게임 개념을 적용한 게임들이 많으므로 게임에

대한 영감을 얻고 싶다면 마켓에서 관련 카테고리를 수시로 확인하는 게 좋다.

퍼즐 게임

퍼즐 게임은 따로 설명하지 않아도 알 것이다. 테트리스나 비주웰드 같은 게임은 누구나 알고 있

다. 안드로이드 게임 마켓에서도 퍼즐 게임은 큰 영역을 차지하고 있으며 게임 사용자층을 비교

해 보더라도 매우 인기가 높다. PC 기반의 퍼즐 게임과 달리 안드로이드의 퍼즐 게임은 전통적인

3색 맞추기 공식에서 벗어나 더욱 정교한 물리 기반의 퍼즐 방식을 사용하고 있다.

그림 3-3 ㅣ Camel Games의 Super Tumble

Page 89: 시작하세요! 안드로이드 게임 프로그래밍

03 게임 개발 101 l 63

Super Tumble(그림 3-3)은 물리 퍼즐 게임을 잘 보여주는 예다. 이 게임의 목적은 블록을 터

치해 제거한 후 블록 상단에 있는 별을 아래로 안전하게 옮기는 곳이다. 이렇게 얘기하면 게임이

쉬워 보이지만 레벨이 올라갈수록 게임 내용이 어려워진다. 이 게임은 2D 물리 엔진인 Box2D를

사용하고 있다.

BitLogik의 U Connect(그림 3-4)는 매우 단순하면서도 머리를 쓰게 하는 게임이다. 이 게임의

목적은 화면에 보이는 점을 선 하나로 한 번에 연결하는 것이다. 컴퓨터 공학을 전공하는 학생이

라면 이와 비슷한 문제를 접한 적이 있을 것이다.

그림 3-4 ㅣ BitLogik의 U Connect

물론 테트리스 아류작, 블록 3개 맞추기, 기타 표준 공식을 사용한 게임들은 수없이 많이 나와

있다. 앞에서 예로 든 게임들은 이미 20년도 지난 낡은 게임 개념을 그대로 복사하는 것만이 퍼

즐 게임의 전부는 아니라는 사실을 강조하기 위한 예일 뿐이다.

액션 및 아케이드 게임

액션 및 아케이드 게임은 보통 안드로이드 플랫폼의 모든 가능성을 최대한 활용한다. 이들 게임

중에는 멋진 3D 화면을 통해 현재 세대의 하드웨어에서 최대한으로 표현할 수 있는 그래픽 성능

을 유감 없이 보여준다. 이 장르에는 레이싱 게임, 슈팅 게임, 1인칭 및 3인칭 슈팅 게임, 플랫폼 게

임 등 다양한 하위 장르가 포함된다. 안드로이드 마켓에서 아직 이 장르 분야는 큰 발전을 이루

지 못하고 있다. 이런 게임을 개발할 수 있는 자본이 있는 거대 기업들이 안드로이드 게임 분야에

뛰어들기를 주저하고 있기 때문이다. 하지만 대신 일부 인디 개발자들이 이런 게임 분야를 공략

하고 있다.

Page 90: 시작하세요! 안드로이드 게임 프로그래밍

64 l 시작하세요! 안드로이드 게임 프로그래밍

Replica Island(그림 3-5)는 아마 지금껏 안드로이드 게임 마켓에서 가장 큰 성공을 거둔 플랫

폼 게임일 것이다. 이 게임은 구글 엔지니어이자 게임 개발 예찬론자인 크리스 프루엣이 순수 자

바 코드만으로도 안드로이드 플랫폼에서 고성능의 게임을 개발할 수 있음을 보여주기 위해 만

들었다. 이 게임에서는 다양한 입력 방식을 제공해 온갖 기기 설정을 최대한 수용하고 있다. 이

게임에서도 저사양 기기에서 게임을 제대로 즐길 수 있게 하기 위해 별도로 신경을 썼다. 게임 자

체는 신비로운 보물을 찾으라는 명령을 받은 로봇의 이야기를 다룬다. 게임 방식은 SNES 16비트

플랫폼 게임과 유사하다. 표준 설정에서는 가속도계와 두 개의 버튼을 사용해 로봇을 움직인다.

이 중 한 버튼은 장애물을 만났을 때 로봇이 점프하게 하는 데 사용하고, 다른 버튼은 위에서부

터 내려와 적들을 깔고 뭉갤 때 사용된다. 이 게임의 또 다른 장점은 오픈소스라는 점이다.

그림 3-5 ㅣ 크리스 프루엣의 Replica Island

HyperDevBox의 Exzeus(그림 3-6)는 고품질의 3D 그래픽을 사용한 SNES용 Starfox의 정신

을 이어받은 전통적인 레일 슈팅 게임이다. 이 게임에서는 슈팅 게임의 모든 기능을 제공한다. 다

양한 무기, 파워업 아이템, 거대한 보스와의 싸움, 수없이 많은 슈팅 대상이 모두 등장한다. 대다

수 3D 게임과 마찬가지로 이 게임은 고사양의 기기에서만 즐길 수 있게 설계됐다. 이 게임의 메인

캐릭터는 기기를 기울이고 화면의 버튼을 사용해 조종할 수 있다. 이런 게임에서는 이런 조종 방

식이 매우 직관적이라 할 수 있다.

Page 91: 시작하세요! 안드로이드 게임 프로그래밍

03 게임 개발 101 l 65

그림 3-6 ㅣ HyperDevBox의 Exzeus

Battery Powered Games의 Deadly Chambers(그림 3–7)는 둠과 퀘이크 같은 전통적인 형태의

3차원 슈팅 게임이다. 메인 캐릭터인 Dr. Chambers는 성에 있는 악한 마법사의 던전(지하 감옥)

에서 빠져나가려고 한다. Battery Powered Games는 슈팅 게임의 배경 이야기를 화려하게 꾸미지

않는 전통을 지키고 있다. 하긴 강력한 무기로 앞을 가로막는 적들을 무심하게 죽일 수만 있다면

주인공의 사연 이야기는 그다지 중요하지 않다. 이 게임에서 메인 캐릭터는 화면상의 아날로그 스

틱을 통해 조정할 수 있다. 추가 버튼을 사용하면 1인칭 시점으로 전환해 좀 더 정확한 조준을 하

고 무기를 바꾸는 등의 일을 할 수 있다. Exzeus와 달리 이 게임의 개발자는 저사양의 기기에서도

게임이 실행될 수 있게끔 별도로 신경을 썼다. 이 게임에서는 다양한 입력 방식을 제공하므로 싱

글 터치 화면의 기기에서도 게임을 즐기는 데 문제가 없다. 기술적으로 살펴보자면 이 게임은 대

략 6개월이라는 시간 동안 한 사람이 프로그래밍한 점을 감안할 때 걸작이라고 할 수 있다.

그림 3-7 ㅣ Battery Powered Games의 Deadly Chambers

Page 92: 시작하세요! 안드로이드 게임 프로그래밍

66 l 시작하세요! 안드로이드 게임 프로그래밍

Hexage의 Radiant(그림 3-8)는 기존 스페이스 인베이더 개념에서 한 단계 진보한 게임이다. 이

게임에서는 정적인 플레이 공간 대신 양측으로 스크롤되는 게임 레벨을 제공해 레벨과 적 캐릭

터를 다양화했다. 이 게임에서는 폰을 기울여 우주선을 조정할 수 있고 적 우주선을 폭파시켜 얻

은 점수를 가지고 새 무기를 살 수도 있다. 다소 픽셀화된 형태의 그래픽을 사용함에 따라 이 게

임은 고유의 룩앤필을 갖게 됐고 과거 시절의 향수를 불러일으키고 있다.

그림 3-8 ㅣ Hexage의 Radiant

액션 및 아케이드 장르의 게임은 아직까지는 마켓에서 잘 보이지 않는다. 하지만 플레이어들은

훌륭한 액션 게임들을 찾고 있으므로 이 분야가 여러분의 틈새 시장이 될 수도 있다.

타워 디펜스 게임

안드로이드 플랫폼에서 큰 성공을 거둔 만큼 타워 디펜스 게임은 별도 장르로 설명해야 할 것 같

다. 타워 디펜스 게임은 모딩 커뮤니티에서 개발한 PC 실시간 전략 게임의 변종 게임 형태로 인기

를 얻었다. 이 게임의 개념은 곧 독립 게임 형태로 발전했다. 타워 디펜스 게임은 현재 안드로이드

에서 가장 잘 팔리는 게임 장르에 속한다.

전형적인 타워 디펜스 게임에서는 어떤 악의 세력이 생물을 내보내 성/기지/크리스탈 등을 공

격한다. 게이머의 임무는 공격하는 적을 격추할 터렛을 구축해 게임 지도상에서의 특수 공간을

지켜내는 것이다. 적 캐릭터를 하나씩 죽일 때마다 새로운 터렛을 짓거나 업그레이드할 수 있는

돈이나 점수를 얻게 된다.

Page 93: 시작하세요! 안드로이드 게임 프로그래밍

03 게임 개발 101 l 67

개념 자체는 상당히 간단하지만 이런 게임에서 난이도 균형을 제대로 유지하기란 매우 어렵다.

Lupis Labs So¯ware의 Robo Defense(그림 3-9)는 안드로이드의 모든 타워 디펜스 게임의 모

태가 됐다. 이 게임은 안드로이드가 출시된 이후로 줄곧 안드로이드 마켓의 유료 게임 1등 자리

를 지키고 있다. 이 게임에서는 표준 타워 디펜스 게임의 공식을 가감 없이 그대로 따르고 있다.

이 게임은 매우 간단하면서 중독성이 강한 게임이며 다양한 지도와 게임 성을 사용하고, 하이스

코어를 적용한다. 이 게임의 내용은 게임 개념을 이해하기에는 충분하지만 그다지 완성도가 높

진 않다. 이런 점을 고려하면 잘 팔리는 게임이 꼭 최고의 그래픽과 오디오를 갖출 필요는 없다는

사실을 알 수 있다.

그림 3-9 ㅣ Lupis Labs Software의 Robo Defense

혁신 게임

특정 범주에 넣을 수 없는 게임들도 있다. 이런 게임들은 카메라와 GPS 같은 안드로이드 기기의

새 기능들을 활용해 전혀 다른 사용자 경험을 전달한다. 이런 혁신적인 게임들은 소셜 및 위치

기반 성격을 갖고 있으며 증강 현실 요소를 가미하기도 한다.

SpecTrek(그림 3-10)은 두 번째로 열린 안드로이드 개발자 챌린지의 우승작 중 하나다. 이 게

임의 목적은 GPS를 켜고 돌아다니다가 유령을 찾아 카메라로 찍는 것이다. 유령은 카메라 뷰 위

에 올라오는데 플레이어는 이런 유령에 포커스를 맞추고 유령 사진을 찍어 점수를 올려야 한다.

Page 94: 시작하세요! 안드로이드 게임 프로그래밍

68 l 시작하세요! 안드로이드 게임 프로그래밍

그림 3-10 ㅣ SpecTrekking.com의 SpecTrek

지금까지 안드로이드 마켓에 이미 나와 있는 게임 장르들을 살펴봤으니 이쯤에서 한번 마켓

애플리케이션을 실행해 앞에서 소개한 게임들을 직접 확인해 보자. 이때 게임의 구조(예를 들어

어떤 화면이 어떤 화면으로 이어지고 어떤 버튼이 무슨 일을 하고, 게임 요소들이 어떻게 서로 상

호작용하는지 등)를 특별히 주의해서 살펴보자. 이런 게임 요소들에 대한 감을 키우려면 실제로

분석적인 생각을 가지고 게임을 플레이해봐야 한다. 잠시 재미 요소는 접어두고 게임 요소를 하

나씩 분해해보자. 게임 분석을 모두 마쳤다면 책으로 돌아와 다음 내용을 계속 읽는다. 이번에는

종이 위에 아주 간단한 게임 설계를 그려볼 것이다.

게임 설계 - 펜은 코드보다 강하다.

앞서 얘기한 것처럼 IDE를 바로 실행해 멋진 기술 데모를 바로 만들고 싶은 유혹에 빠질 수 있

다. 물론 실험적인 게임 방식의 프로토타입을 만들어서 실제 원하는 대로 동작하는지 확인하고

싶다면 그렇게 해도 된다. 하지만 이렇게 프로토타입을 만들고 난 후에는 프로토타입을 내려놓

고 펜과 종이를 들고 편안한 의자에 앉아서 게임의 개괄적인 특성을 잘 정리해야 한다. 이때 기술

적인 세부 내용은 아직 신경 쓰지 않아도 된다. 이 부분은 나중에도 얼마든지 할 수 있다. 지금은

게임의 사용자 경험을 설계하는 데 집중하는 게 좋다. 필자의 경우 다음과 같은 내용을 스케치로

정리할 때 게임 설계가 가장 잘 된다.

Page 95: 시작하세요! 안드로이드 게임 프로그래밍

03 게임 개발 101 l 69

■ 게임의 핵심 플레이 방식

■ 메인 캐릭터에 대한 대충의 소개 이야기

■ 소개 이야기와 캐릭터에 기반한 대략적인 그래픽

■ 게임에 들어 있는 각 화면, 화면 사이의 전환 다이어그램, 화면 전환을 이끌어내는 요소

(예를 들어 게임 오버 상태 등)에 대한 스케치.

이 책의 목차를 살펴봤다면 안드로이드에서 Snake 게임을 구현한다는 사실을 알고 있을 것이

다. Snake는 모바일 시장에서 가장 큰 성공을 거둔 게임 중 하나다. Snake 게임을 아직 모른다면

책의 내용을 계속 읽기 전에 웹에서 이 게임을 찾아보자. 필자는 여기서 독자들이 다시 돌아올

때까지 가만히 기다리겠다.

다시 돌아온 것을 환영한다. 이제 Snake 게임에 대해 알았으니 이제부터는 마치 이 게임이 우

리 아이디어에서 나온 것처럼 생각하고 이 게임에 대한 설계를 시작해 보겠다. 먼저 게임 방식부

터 설계해보자.

핵심 게임 방식

시작에 앞서 작업에 필요한 목록을 다음과 같이 정리했다.

■ 가위

■ 필기 도구

■ 수많은 종이

게임 설계를 할 때 이 단계에서는 모든 내용이 가변적이다. 따라서 페인트나 Gimp, 포토샵 같

은 프로그램에서 정교한 이미지를 그리기보다는 종이 위에 기본 구성 요소를 그린 후 각 요소들

이 서로 들어맞을 때까지 테이블 위에서 재배치하는 게 좋다. 이렇게 하면 마우스를 사용하지 않

고도 많은 내용을 물리적으로 수정할 수 있다. 종이에서의 설계가 모두 끝나면 나중에 참고할 수

있게끔 사진을 찍거나 디자인을 스캔한다. 그럼 핵심 게임 화면의 구성 요소부터 만들어보자. 그

림 3-11에는 필자가 이 게임의 핵심 요소라고 판단하는 내용들이 나와 있다.

Page 96: 시작하세요! 안드로이드 게임 프로그래밍

70 l 시작하세요! 안드로이드 게임 프로그래밍

그림 3-11 ㅣ 게임의 핵심 구성 요소의 설계

왼쪽 사각형은 화면으로, 대략 넥서스 원의 화면 크기를 갖고 있다. 바로 이 공간에 다른 게임

요소들을 배치할 것이다. 다음으로 볼 게임 구성 요소는 뱀을 제어하는 데 사용할 두 개의 버튼

이다. 끝으로 뱀의 머리와 뱀의 꼬리 부분 몇 개, 그리고 뱀이 먹을 수 있는 아이템이 나와 있다.

필자는 여기서 몇 개의 숫자를 쓰고 별도로 구분했다. 이런 숫자는 점수를 표시하는 데 사용할

것이다. 그림 3-12에는 필자가 생각한 초기 게임 플레이 공간이 나와 있다.

그림 3-12 ㅣ 초기 게임 공간

Page 97: 시작하세요! 안드로이드 게임 프로그래밍

03 게임 개발 101 l 71

이어서 게임 방식을 정의해 보자.

■ 뱀은 꼬리를 끌면서 머리가 가리키는 방향으로 전진한다. 머리와 꼬리는 시각적인 형태가

약간 다른 동일 크기의 영역으로 구성된다.

■ 뱀이 화면 경계를 벗어나면 반대쪽을 통해 다시 화면에 들어온다.

■ 우측 또는 좌측 버튼을 누르면 뱀이 시계(오른쪽) 또는 반시계(왼쪽) 방향으로 90도 회전

한다.

■ 뱀이 자기 자신과 부딪치면(예를 들어 꼬리 일부분과 부딪치면) 게임이 끝난다.

■ 뱀의 머리 부분이 아이템과 부딪치면 아이템이 사라지고 점수가 10점 오른다. 아울러 현

재 뱀이 차지하고 있지 않은 게임 공간상의 다른 위치에 새 아이템이 나타나고, 뱀은 꼬리

한 단위만큼 키가 자란다. 새로운 꼬리 영역은 뱀의 꼬리 끝에 추가된다.

게임이 단순한 데 비해 게임 설명은 꽤 자세하다. 여기서는 간단한 것부터 복잡한 순서대로 게

임 설명을 나열한 것을 볼 수 있다. 이 게임에서는 아마도 뱀이 아이템을 먹는 부분이 가장 복잡

할 것이다. 물론 이보다 정교한 게임에서는 이런 식으로 간단히 게임 내용을 기술하지는 않는다.

보통은 각 영역을 개별적으로 떼어내 설계하고 이 과정을 모두 마친 후 각 설계 내용을 한데 합치

는 방식을 사용한다.

게임 방식에 대한 마지막 설명을 자세히 생각해 보면 안에 내포된 의미를 파악할 수 있다. 즉 뱀

이 전체 화면을 차지하는 순간 이 게임은 끝날 수밖에 없다.

이제 게임 방식을 잘 정의했으므로 이 게임의 배경 이야기를 만들어 보자.

게임 스토리와 아트 스타일

좀비나 우주선, 난쟁이, 다양한 무기들이 나오는 서사적인 이야기도 물론 재미있겠지만 우리가

가진 자원은 제한적이다. 그림 3-12에서 볼 수 있듯이 필자의 그림 실력도 그다지 좋지는 않다. 필

자는 아무리 노력해도 좀비 같은 것은 그릴 수 없다. 따라서 필자도 자기 자신을 잘 알고 있는 인

디 개발자들이 하는 행동과 동일한 선택을 했다. 즉 낙서 스타일을 사용하고 설정을 적당히 수정

한 것이다.

Page 98: 시작하세요! 안드로이드 게임 프로그래밍

72 l 시작하세요! 안드로이드 게임 프로그래밍

Mr. Nom의 세계에 온 것을 환영한다. Mr. Nom은 종이 왕국에서 떨어진 잉크를 먹고 다니는

종이 뱀이다. Mr. Nom은 매우 이기적이며 그의 목적은 하나뿐이다. 바로 이 세상에서 가장 많은

잉크가 묻은 종이 뱀이 되는 것이다.

이렇게 배경 스토리를 정하고 나면 몇 가지 더 정의해야 할 게 생긴다.

■ 아트 스타일은 낙서 스타일이다. 여기서는 실제로 게임 구성 요소를 나중에 스캔한 후 게

임의 그래픽 자원으로 사용할 것이다.

■ Mr. Nom은 이기주의자이므로 앞에서 각진 형태의 얼굴을 모자를 쓴 뱀의 형태로 변경

한다.

■ 먹을 수 있는 아이템은 잉크 얼룩으로 표현한다.

■ Mr. Nom이 잉크 얼룩을 먹을 때마다 꿀꿀대는 소리를 내 게임의 음향 효과를 만든다.

■ ‘Doodle Snake’ 같은 평범한 제목보다는 더 흥미를 끌 수 있는 ‘Mr. Nom’ 같은 게임 제목

을 사용한다.

그림 3-13에는 초기 설계 당시의 게임 요소를 대체할 잉크 얼룩과 더불어 Mr. Nom의 전체 게

임 화면이 나와 있다. 필자는 이 게임에서 재사용할 수 있게끔 Mr. Nom 로고도 직접 그렸다.

그림 3-13 ㅣ Mr. Nom, 모자, 잉크 얼룩, 로고의 모습

Page 99: 시작하세요! 안드로이드 게임 프로그래밍

03 게임 개발 101 l 73

화면과 화면 전환

이제 게임 방식, 배경 이야기, 캐릭터, 아트 스타일까지 정해졌으니 화면과 화면 사이의 전환 방식

을 설계할 차례다. 하지만 먼저 화면을 구성하는 요소를 정확히 이해해야 한다.

■ 화면은 전체 디스플레이를 채우는 원자 단위로서 게임의 한 영역을 정확히 책임진다(예

를 들어 메인 메뉴, 설정 메뉴, 액션이 일어나는 게임 화면 등)

■ 화면은 다양한 구성 요소로 이뤄질 수 있다(예를 들어 버튼, 컨트롤러, 상단 디스플레이,

게임 공간의 렌더링 등).

■ 사용자는 화면상에서 화면의 구성 요소와 상호작용할 수 있어야 한다. 이런 상호작용은

화면 전환을 일으킬 수도 있다(예를 들어 메인 메뉴에서 New Game 버튼을 누르면 현재

활성화된 메인 메뉴가 게임 화면 또는 레벨 선택 화면으로 바뀐다).

이제 이런 기본 개념을 바탕으로 Mr. Nom 게임의 각 화면을 설계해보자.

이 게임에서 플레이어에게 처음으로 보여주는 내용은 메인 메뉴 화면이다. 그럼 좋은 메인 메

뉴 화면을 만들려면 어떻게 해야 할까?

■ 원칙상 게임의 이름을 표시하는 게 좋다. 따라서 여기서는 Mr. Nom 로고를 표시할 것

이다.

■ 게임 화면을 일관된 형태로 보여주려면 배경이 있는 게 좋다. 여기서는 게임 공간의 배경

을 재사용한다.

■ 플레이어는 보통 게임을 바로 플레이하기를 원하므로 Play 버튼을 둔다. 이 버튼은 이 게

임에서 상호작용을 사용하는 첫 번째 컴포넌트다.

■ 사람들 중에는 Snake 게임을 모르는 사용자도 있기 마련이다. 도움말 화면으로 전환할

수 있게 Help 버튼을 두어서 사람들이 게임의 내용을 이해할 수 있게 도와준다.

■ 물론 이 게임의 사운드는 듣기 편하지만 일부 플레이어는 조용히 게임을 즐기고자 할 수

있다. 이런 사용자들을 배려해 사운드를 켜고 끌 수 있는 토글 버튼을 제공한다.

Page 100: 시작하세요! 안드로이드 게임 프로그래밍

74 l 시작하세요! 안드로이드 게임 프로그래밍

이런 구성 요소들을 실제로 어떻게 배치할지는 다분히 취향의 문제다. 이때 필요하다면 컴퓨

터 사이언스의 하위 분야인 휴먼 컴퓨터 인터페이스(HCI)를 공부해 사용자에게 애플리케이션

을 보여주는 것과 관련한 가장 최신의 학계 의견을 반영할 수도 있을 것이다. 하지만 Mr. Nom에

서는 이런 전문적인 지식까지는 필요 없다. 필자는 그림 3-14처럼 간단히 디자인을 구성했다.

그림 3-14 ㅣ 메인 메뉴 화면

여기서는 모든 화면 요소(로고, 메뉴 버튼 등)가 개별 이미지로 돼 있음을 주의해야 한다.

메인 메뉴 화면부터 설계를 시작하면 인터랙티브 컴포넌트 1 를 통해 나머지 화면들로 전환할

수 있다는 장점이 있다. Mr. Nom 게임에서는 게임 화면과 하이스코어 화면, 도움말 화면이 필요

하다. 이 게임에서는 설정이 하나뿐(사운드)이고 메인 화면에 이미 보이므로 설정 화면이 별도로

필요 없다.

게임 화면은 잠시 잊고 이번에는 하이스코어 화면을 살펴보자. 필자는 하이스코어를 Mr. Nom

게임 내부에서만 저장해 한 플레이어의 점수 결과만 기록하기로 결정했다. 또 다섯 개의 하이스

코어만 저장하기로 했다. 하이스코어 화면은 그림 3-15처럼 ‘HIGHSCORES’ 텍스트를 상단에

보여주고 그 아래에 다섯 개의 최고 점수와 뒤로 갈 수 있는 화살표 버튼을 보여준다. 여기서도

게임 공간의 배경을 재사용한다.

1   (옮긴이) 여기서 말한 인터랙티브 컴포넌트는 이를테면 화면을 구성하는 버튼 등을 말한다. 이런 버튼 등은 사용자와의 상호

작용(사용자의 탭)을 통해 다른 화면으로의 화면 전환을 이끌어 낸다.

Page 101: 시작하세요! 안드로이드 게임 프로그래밍

03 게임 개발 101 l 75

그림 3-15 ㅣ 하이스코어 화면

다음으로 도움말 화면을 설계해야 한다. 도움말 화면에서는 플레이어에게 게임 배경 이야기와

게임 방식을 알려준다. 이런 정보를 한 화면에 담기에는 정보의 양이 많기 때문에 여기서는 도움

말 화면을 여러 화면으로 나누는 방식을 사용한다. 이들 각 화면은 사용자에게 핵심 정보를 전

달해준다. Mr. Nom이 누구이고 그가 원하는 것이 무엇인지, Mr. Nom을 움직여 잉크 얼룩을 먹

게 하려면 어떻게 해야 하는지, 또 Mr. Nom이 싫어하는 게 무엇인지(자기 자신을 먹는 것을 싫

어한다)가 그 내용이다. 이런 내용을 모두 채우려면 그림 3-16처럼 세 개의 화면이 필요하다. 여기

서는 더 많은 정보가 뒤에 있음을 보여주기 위해 각 화면에 버튼을 추가한 것을 볼 수 있다. 이런

화면들은 잠시 후 연결할 것이다.

그림 3-16 ㅣ 도움말 화면

Page 102: 시작하세요! 안드로이드 게임 프로그래밍

76 l 시작하세요! 안드로이드 게임 프로그래밍

끝으로 게임 화면이 남았다. 게임 화면이 동작하는 방식은 앞에서 이미 살펴본 바 있다. 하지만

아직 세부 내용 몇 가지가 남아 있다. 먼저 게임이 바로 시작돼서는 안 된다. 플레이어에게 준비할

시간을 줘야 하기 때문이다. 따라서 게임 화면에서 처음 보이는 내용은 ‘게임을 시작하려면 화면

을 터치하라’는 안내 문구다. 이 과정에서는 별도 화면이 필요 없다. 이 게임에서는 처음 시작 시

게임 일시 정지 기능을 게임 화면에서 직접 구현할 것이다.

일시 정지 얘기가 나온 김에 얘기하자면 이 게임에서는 게임을 일시 정지할 수 있는 버튼도 추

가해야 한다. 또 게임을 일시 정지하고 나면 게임을 재개할 방법도 사용자에게 제공해야 한다. 이

때는 커다란 Resume 버튼을 보여줄 것이다. 일시 정지 상태에서는 사용자가 메인 메뉴 화면으

로 돌아갈 수 있는 또 다른 버튼을 보여줄 것이다.

Mr. Nom이 자신의 꼬리를 깨무는 경우에는 플레이어에게 게임이 끝났음을 알려줘야 한다. 이

때는 별도 게임 오버 화면을 구현할 수도 있고 게임 화면 내에 머물면서 ‘Game Over’ 메시지를

크게 띄워 보여줄 수도 있다. 여기서는 후자의 방식을 택하기로 한다. 아울러 게임을 마무리하기

위해 플레이어가 지금까지 얻은 점수를 보여주고 메인 메뉴로 돌아갈 수 있는 버튼도 함께 보여

준다.

이와 같은 다양한 상태는 게임 화면의 하위 화면처럼 생각하면 된다. 게임 화면에는 네 개의 하

위 화면이 들어 있다. 초기 준비 상태, 일반적인 게임 플레이 상태, 일시 정지 상태, 게임 오버 상

태가 있는 것이다. 그림 3-17은 이런 상태들을 보여준다.

그림 3-17 ㅣ 게임 화면과 게임 화면 내의 네 가지 각기 다른 상태

Page 103: 시작하세요! 안드로이드 게임 프로그래밍

03 게임 개발 101 l 77

이제 지금껏 정리한 화면들을 서로 연결할 차례다. 각 화면에는 다른 화면으로 전환할 수 있는

인터랙티브 컴포넌트들이 들어 있다.

■ 메인 메뉴 화면에서는 각각의 버튼을 통해 게임 화면, 하이스코어 화면, 도움말 화면으로

갈 수 있다.

■ 게임 화면에서는 일시 정지 상태에서 버튼을 사용하거나 게임 오버 상태에서 버튼을 사

용해 메인 화면으로 돌아갈 수 있다.

■ 하이스코어 화면에서는 뒤로가기 버튼을 통해 메인 화면으로 돌아갈 수 있다.

■ 첫 번째 도움말 화면에서는 두 번째 도움말 화면으로, 두 번째 도움말 화면에서는 세 번

째 도움말 화면으로, 세 번째 도움말 화면에서는 메인 화면으로 갈 수 있다.

화면 전환은 이것으로 끝이다. 지금까지의 내용이 그리 어렵지는 않았을 것이다. 그림 3-18에

서는 개별 인터랙티브 컴포넌트와 해당 컴포넌트와 연계된 대상 화면을 화살표를 통해 시각적으

로 보여주고 있다. 필자는 이 그림을 통해 각 화면을 구성하는 요소들도 함께 볼 수 있게 했다.

Page 104: 시작하세요! 안드로이드 게임 프로그래밍

78 l 시작하세요! 안드로이드 게임 프로그래밍

그림 3-18 ㅣ 전체 디자인 요소와 화면 전환

이로써 첫 번째 게임에 대한 전체 설계가 완전히 끝났다. 이제 남은 내용은 구현뿐이다. 그런데

이렇게 설계한 내용을 실제 실행할 수 있는 게임으로 만들려면 어떻게 해야 할까?

Page 105: 시작하세요! 안드로이드 게임 프로그래밍

03 게임 개발 101 l 79

알아두기

여기서 방금 전에 게임 설계에 사용한 방식은 작은 규모의 게임에 적합하다. 이 책 제목이 ‘시

작하세요! 안드로이드 게임 프로그래밍’이므로 이런 설계 방식은 책의 내용과도 딱 들어맞는

다. 하지만 대규모 프로젝트에서는 주로 팀별로 일을 하고 각 팀의 멤버가 특정 영역만을 전문

으로 담당한다. 물론 이런 상황에서도 앞에서와 같은 접근 방식을 사용할 수 있지만 각기 다른

상황에 맞춰 조금씩 수정하고 손을 봐야 할 것이다. 아울러 이런 프로젝트에서 일할 때는 조금

더 반복*적으로 일을 하게 되며 설계를 끊임없이 가다듬어야 한다.

* (옮긴이) 여기서 말한 ‘반복’은 iteration을 가리킨다. 즉 설계-구현-테스트를 하나의 반복 과정이라고 볼 수 있는데, 이렇게 팀을 통해 협업할 때는 이런 반복 과정을 여러 번 되풀이하면서 프로젝트를 조금씩 완성한다.

코드 - 핵심적인 세부 내용

그런데 한 가지 문제가 있다. 게임 프로그래밍과 관련한 안드로이드 API만 알고 싶은데 정작 게

임을 실제 프로그래밍하는 방법조차 모르고 있는 것이다. 이제 게임을 설계한 아이디어는 갖고

있지만 아직까지는 이를 실행 가능한 게임으로 바꾸는 과정이 신비스럽고 어렵게만 느껴질 것이

다. 따라서 이어지는 절을 통해 필자는 게임이 보통 어떤 요소들로 구성되는지 개략적으로 설명

하고자 한다. 이 과정에서 우리는 나중에 안드로이드에서 제공하는 API를 통해 구현할 인터페이

스에 대한 의사 코드를 살펴볼 것이다. 인터페이스는 두 가지 이유에서 장점이 있다. 첫 번째 장점

은 실제 구현에 대한 세부 내용을 모르더라도 의미 자체에만 집중할 수 있게 해준다는 점이다. 또

다른 장점은 나중에 구현체를 바꾸더라도 전혀 문제가 생기지 않는다(예를 들어 2D CPU 렌더

링 대신 오픈GL ES를 사용해 화면상에서 Mr. Nom을 보여주더라도 문제될 게 없다)는 점이다.

모든 게임에는 내부 운영체제와의 통신을 추상화하고 쉽게 해주는 기본 프레임워크가 꼭 필요

하다. 보통 이런 기본 프레임워크는 다음과 같은 모듈로 나뉜다.

■ 창 관리: 창을 생성하고 창을 닫거나 안드로이드에서 애플리케이션을 일시 정지/실행 재

개 하는 등의 작업을 책임진다.

■ 입력: 창 관리 모듈과 연계해 사용자 입력을 추적한다(예를 들어 터치 이벤트, 키 입력, 가

속도계 값 입력 등)

■ 파일 I/O: 디스크에서 바이트를 읽어서 자원을 프로그램에 공급해준다.

Page 106: 시작하세요! 안드로이드 게임 프로그래밍

80 l 시작하세요! 안드로이드 게임 프로그래밍

■ 그래픽: 실제 게임 내용 자체를 제외하면 아마도 가장 복잡한 모듈일 것이다. 그래픽 모듈

은 그래픽을 로드해 화면상에 그리는 일을 책임진다.

■ 오디오: 이 모듈은 사운드를 로드해 재생하는 것과 관련한 모든 작업을 책임진다.

■ 게임 프레임워크: 이 모듈은 앞의 모듈들을 모두 연결해줌으로써 손쉽게 게임을 작성할

수 있게 해준다.

이들 각 모듈은 하나 이상의 인터페이스로 구성된다. 각 인터페이스는 제공되는 내부 플랫폼(여

기서는 안드로이드)에 기반한 인터페이스의 의도에 맞게 구현된 구현체를 하나 이상 갖고 있다.

알아두기

여기서는 의도적으로 네트워크 모듈을 앞의 목록에서 뺐다. 이 책에서는 멀티플레이어 게임을

구현하지 않는다. 게임 종류에 따라 다를 수도 있지만 이 분야는 다소 고급 주제에 속한다. 이

런 주제에 관심이 있는 독자라면 웹상에서 다양한 튜토리얼을 찾아볼 수 있다(처음 시작하기

에는 www.gamedev.net 사이트가 좋다).

이어지는 설명에서는 최대한 플랫폼을 배제한 채 설명하겠다. 이런 설명은 모든 플랫폼에서

공통으로 적용되기 때문이다.

애플리케이션과 창 관리

게임도 다른 컴퓨터 프로그램과 마찬가지로 UI를 갖고 있다. (주요 운영체제가 대부분 그렇듯이

내부 운영체제가 창 기반일 경우) 게임은 창 안으로 들어간다. 창은 컨테이너 역할을 하며 보통

게임 콘텐츠를 그릴 수 있는 캔버스 정도로 생각할 수 있다.

대다수 운영체제에서는 클라이언트 영역을 터치하거나 키를 누르는 방식 외에 특수한 방식으

로 사용자가 창을 사용할 수 있게 해준다. 데스크톱 운영체제에서는 창을 드래그하고 크기를 조

절하거나 작업바 같은 것으로 최소화할 수 있다. 안드로이드에서는 크기를 조절하는 대신 방향

을 조절할 수 있고, 홈 버튼을 눌렀을 때나 걸려온 전화를 받을 때 애플리케이션을 백그라운드로

보냄으로써 최소화와 비슷한 효과를 사용한다.

애플리케이션과 창 관리 모듈은 실제 창을 설정하고 사용자의 터치나 키 입력 등을 수신할 수

있는 단일 컴포넌트로 창을 채우는 일을 책임진다. 이 단일 컴포넌트는 나중에 렌더링한 내용을

Page 107: 시작하세요! 안드로이드 게임 프로그래밍

03 게임 개발 101 l 81

채우는 공간이 된다. 이런 UI 컴포넌트는 CPU를 통해 렌더링할 수도 있고 오픈GL ES처럼 하드

웨어 가속을 사용할 수도 있다.

애플리케이션과 창 관리 모듈은 구체적인 인터페이스를 따로 갖고 있지 않다. 이 책에서는 나

중에 이 모듈을 게임 프레임워크와 합칠 것이다. 다만 관리해야 할 애플리케이션 상태와 윈도우

이벤트에 대해서는 기억해야 한다.

■ 생성: 창이 처음 시작될 때(즉 애플리케이션이 처음 시작할 때) 호출된다.

■ 일시 정지: 어떤 메커니즘에 의해 애플리케이션을 일시 정지할 때 호출된다.

■ 재개: 애플리케이션 실행이 재개되고 창이 다시 전방으로 나올 때 호출된다.

알아두기

일부 안드로이드 매니아들은 이 시점에서 고개를 갸우뚱할 것이다. 왜 창을 하나만 사용할까(

안드로이드식으로 말하자면 액티비티를 왜 하나만 사용할까)? 왜 게임에 여러 개의 UI 위젯을

사용하지 않을까? 다시 말해 게임에서 복잡한 UI를 구현하지 않는 이유가 뭘까? 그 이유는 게

임의 룩앤필을 완전히 제어하기 위해서다. 아울러 이렇게 단일 UI를 사용하면 안드로이드 UI

프로그래밍이 아니라 안드로이드 게임 프로그래밍에 좀 더 초점을 맞출 수 있다. 이런 주제와

관련한 책은 마크 머피가 저술한 <Beginning Android 2(Apress, 2010)> 등이 있으니 따로

참고하자. 1 

1   우리나라에는 '알짜만 골라 배우는 안드로이드 프로그래밍 2(에이콘)'로 번역 출간됐다.

입력

사용자는 어떤 식으로든 게임과 상호작용하길 원한다. 바로 이때 입력 모듈을 사용한다. 대부분

의 운영체제에서는 화면 터치와 키 입력 등의 입력 이벤트가 현재 포커스가 위치한 창으로 전달

된다. 이 창은 이런 이벤트를 다시 포커스를 갖고 있는 UI 컴포넌트로 전달한다. 이런 전달 과정

은 대부분 투명하게 처리된다. 따라서 개발자가 할 일은 포커스가 위치한 UI 컴포넌트로부터 이

벤트를 제대로 가져오는 것뿐이다. 운영체제의 UI API는 이런 이벤트 전달 시스템에 접근해 이

벤트를 쉽게 등록하고 기록할 수 있게 해준다. 이와 같은 이벤트 연결과 기록이 입력 모듈의 주된

역할이다.

Page 108: 시작하세요! 안드로이드 게임 프로그래밍

82 l 시작하세요! 안드로이드 게임 프로그래밍

그럼 기록한 정보를 가지고 어떤 일을 할 수 있을까? 이때는 두 가지 작업 방식을 활용할 수

있다.

■ 폴링: 폴링을 사용하면 입력 기기의 현재 상태만을 확인한다. 현재 확인 시점과 이전 확인

시점 사이의 상태 정보는 모두 잃게 된다. 이런 입력 처리는 사용자가 특정 버튼을 터치했

는지 여부 등을 확인할 때 적절하다. 하지만 키 이벤트의 순서 정보가 사라지므로 텍스트

입력을 추적하려고 하는 경우에는 적절치 않다.

■ 이벤트 기반의 처리: 이 방식을 사용하면 마지막으로 확인한 시점 이후 발생한 모든 이벤

트를 시간 순서대로 확인할 수 있다. 이 방식은 텍스트 입력 또는 이벤트 순서에 의존하는

작업을 처리할 때 적합하다. 이 방식은 손가락이 화면을 처음 터치하거나 손가락이 화면

에서 떨어지는 시점을 파악할 때도 유용하다.

그럼 어떤 입력 기기를 처리해야 할까? 안드로이드에는 세 가지 주요 입력 방식이 있다. 터치 화

면과 키보드/트랙볼, 가속도계가 이에 해당한다. 처음 두 입력 방식은 폴링과 이벤트 기반 처리에

모두 적합하다. 가속도계는 주로 폴링만을 사용한다. 터치화면은 다음 세 개의 이벤트를 발생시

킨다.

■ 터치 다운: 손가락이 화면을 터치할 때 발생한다.

■ 터치 드래그: 손가락이 화면을 드래그할 때 발생한다. 드래그 이벤트가 일어나기 전에는

항상 터치 다운 이벤트가 일어난다.

■ 터치 업: 손가락이 화면에서 떨어질 때 발생한다.

각각의 터치 이벤트는 부가 정보를 갖고 있다. UI 컴포넌트의 중점에 대한 상대 위치, 각각의 손

가락을 식별하고 추적하기 위한 멀티터치 환경에서의 포인터 인덱스가 이런 정보에 해당한다.

키보드는 다음 두 종류의 이벤트를 발생시킨다.

■ 키 다운: 키를 누를 때 발생한다.

■ 키 업: 키에서 손을 뗄 때 발생한다. 이 이벤트 전에는 항상 키 다운 이벤트가 발생한다.

Page 109: 시작하세요! 안드로이드 게임 프로그래밍

03 게임 개발 101 l 83

키 이벤트에도 추가 정보가 들어 있다. 키 다운 이벤트는 처리된 키의 코드를 담고 있다. 키 업

이벤트는 키의 코드와 실제 유니코드 문자열을 보관한다. 키 코드와 키 업 이벤트를 통해 발생한

유니코드 문자 사이에는 차이점이 있다. 후자의 경우 시프트 키 같은 다른 키의 상태까지도 고려

한다. 따라서 키 업 이벤트에서는 이를테면 대문자와 소문자를 구분할 수 있다. 하지만 키 다운

이벤트에서는 특정 키가 눌렸다는 사실만을 알 수 있다. 따라서 이 키를 눌러서 어떤 문자를 썼

는지에 대한 정보는 전혀 갖고 있지 않다.

끝으로 가속도계가 있다. 가속도계의 상태는 항상 폴링을 통해 확인한다. 가속도계는 가속도

계의 세 축 중 한 축에 대해 지구 중력이 가한 가속도를 측정해 보고한다. 이런 축은 x, y, z 축으

로 부른다. 그림 3-19에는 각 축의 방향이 나와 있다. 각 축에 대한 가속도는 제곱초당 미터(m/s2)

로 표현한다. 지구 과학 수업에서 지구에서 자유 낙하할 때 객체가 9.8m/s2의 가속도를 받는다는

사실을 배운 적이 있을 것이다. 다른 행성에서는 다른 중력이 적용되므로 가속도 상수 또한 달라

진다. 여기서는 예제를 단순히 하기 위해 지구의 가속도만을 다루겠다. 축이 지구 중심으로부터

멀어지면 최대 가속도가 해당 축에 적용된다. 축이 지구 중심 쪽을 가리키면 음의 최대 가속도가

적용된다. 폰을 세로 모드에서 수직 방향으로 똑바로 들고 있으면 y축의 가속도는 9.8m/s2가 된

다. 그림 3-19에서는 z축이 9.8m/s2를 나타내고, x와 y축은 가속도 값이 0을 나타낸다.

그림 3-19 ㅣ 안드로이드 폰의 가속도계 축. z 축이 폰의 중력 방향과 반대 방향을 가리킨다.

이번에는 터치 화면, 키보드, 가속도계 값을 폴링하고 아울러 터치 화면과 키보드에 대한 이벤

트 기반 접근을 할 수 있는 인터페이스를 정의해 보자(예제 3-1).

Page 110: 시작하세요! 안드로이드 게임 프로그래밍

84 l 시작하세요! 안드로이드 게임 프로그래밍

예제 3-1 ㅣ 입력 인터페이스와 KeyEvent 및 TouchEvent 클래스

package com.badlogic.androidgames.framework;

import java.util.List;

public interface Input {

public static class KeyEvent {

public static final int KEY_DOWN = 0;

public static final int KEY_UP = 1;

public int type;

public int keyCode;

public char keyChar;

}

public static class TouchEvent {

public static final int TOUCH_DOWN = 0;

public static final int TOUCH_UP = 1;

public static final int TOUCH_DRAGGED = 2;

public int type;

public int x, y;

public int pointer;

}

public boolean isKeyPressed(int keyCode);

public boolean isTouchDown(int pointer);

public int getTouchX(int pointer);

public int getTouchY(int pointer);

public float getAccelX();

public float getAccelY();

public float getAccelZ();

public List<KeyEvent> getKeyEvents();

public List<TouchEvent> getTouchEvents();

}

여기서는 먼저 두 클래스인 KeyEvent와 TouchEvent부터 정의한다. KeyEvent 클래스

는 KeyEvent의 타입을 인코딩하는 상수를 정의한다. TouchEvent 클래스도 같은 일을 한다.

Page 111: 시작하세요! 안드로이드 게임 프로그래밍

03 게임 개발 101 l 85

KeyEvent 인스턴스는 타입, 키 코드, 이벤트의 타입이 KEY_UP인 경우 유니코드 문자열을 기록

한다.

TouchEvent 코드도 이와 유사하며 TouchEvent의 타입, UI 컴포넌트의 중심점을 기준으로

한 손가락의 상대 위치, 터치 화면 드라이버에 의해 부여된 포인터 ID를 기록한다. 손가락에 대

한 포인터 ID는 손가락이 화면에 머무는 동안 동일한 값을 유지한다. 첫 번째 터치한 손가락은

ID 0을 부여받고 다음 손가락은 ID 1 등을 부여 받는다. 두 손가락이 터치한 상태에서 손가락 0

이 화면에서 떨어지더라도, 터치 상태를 계속 유지하는 한 손가락 1은 계속 같은 ID를 유지한다.

이때 새로운 손가락이 화면을 터치하면 자유로운 ID 중 첫 번째 ID를 부여받는데 이 경우 이 ID

는 0이다.

다음으로 Input 인터페이스의 폴링 메서드를 볼 수 있다. 이들 메서드는 그 자체로 쉽게 이해

할 수 있다. Input.isKeyPressed() 메서드는 keyCode를 인자로 받아서 해당 키가 눌렸는지 여부

를 반환한다. Input.isTouchDown(), Input.getTouchX(), Input.getTouchY()는 특정 포인터가

터치 다운됐는지 여부와 현재 터치한 x, y 좌표를 반환한다. 이때 주의할 점은 해당 포인터가 실

제로 화면을 터치하지 않을 경우 모든 좌표가 정의되지 않는다는 점이다.

Input.getAccelX(), Input.getAccelY(), Input.getAccelZ()는 각 가속도계 축에 대한 가속도

계 값을 반환한다.

마지막 두 메서드 getKeyEvents(), getTouchEvents()는 이벤트 기반 처리에 사용된다. 이 메서

드들은 마지막으로 이들 메서드를 호출한 후 기록된 KeyEvent와 TouchEvent 인스턴스를 반환

한다. 이벤트의 순서는 이벤트 발생 순서를 따르며 가장 최근에 발생한 이벤트가 이벤트 목록의

끝에 오게 된다.

이처럼 간단한 인터페이스와 헬퍼 클래스만 가지고도 필요한 입력 처리를 모두 할 수 있다. 이

제 파일 처리로 넘어가 보자.

알아두기

보통 수정 가능한 클래스의 멤버를 public으로 선언하는 방식은 지양하지만 여기서는 두 가지

이유로 인해 이 방식을 사용하고 있다. 첫 번째 이유는 달빅이 메서드(이 경우 게터)를 호출하

기에는 여전히 느리다는 것이며, 두 번째 이유는 이벤트 클래스의 수정 가능성이 Input 구현

체의 내부 동작에 영향을 주지 않는다는 점이다. 하지만 이런 코딩 방식은 나쁜 방식이라는 점

을 참고하자. 그렇지만 이 책에서는 가끔씩 성능이 문제가 될 때마다 이 방식을 사용한다.

Page 112: 시작하세요! 안드로이드 게임 프로그래밍

86 l 시작하세요! 안드로이드 게임 프로그래밍

파일 I/O

파일을 읽고 쓰는 기능은 게임을 개발할 때 꼭 필요한 기능이다. 안드로이드에서는 자바를 사용

해 개발하므로 파일 I/O를 처리할 때는 특정 파일로(부터) 데이터를 읽고 쓰는 표준 자바 방식인

InputStream과 OutputStream 인스턴스를 주로 생성해 사용한다. 파일 I/O 모듈에서는 게임과

함께 패키징한 레벨 파일, 이미지, 오디오 파일 등을 주로 읽는 것을 처리한다. 파일을 쓰는 경우

는 많지 않다. 보통은 하이스코어를 저장하거나 게임 설정 또는 사용자들이 마지막에 게임을 한

상태로 바로 돌아갈 수 있게끔 게임 상태를 저장할 때 주로 파일을 쓴다.

여기서는 가장 손쉬운 파일 접근 방식을 사용한다. 예제 3-2에는 필자가 제안하는 간단한 인터

페이스가 나와 있다.

예제 3-2 ㅣ FileIO 인터페이스

package com.badlogic.androidgames.framework;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

public interface FileIO {

public InputStream readAsset(String fileName) throws IOException;

public InputStream readFile(String fileName) throws IOException;

public OutputStream writeFile(String fileName) throws IOException;

}

이 인터페이스는 아주 간단하다. 여기서는 파일명을 지정하고 반환값으로 스트림을 받는다.

자바에서 보통 하는 것처럼 여기서도 뭔가가 잘못되면 IOException을 던진다. 물론 어느 곳에서

파일을 읽고 쓸지는 구현체에서 정한다. 예를 들어 자원은 애플리케이션의 APK 파일에서 읽을

수 있을 것이고 파일 등은 (외부 저장소라고 부르는) SD 카드에서 읽고 쓸 것이다.

반환된 InputStream과 OutputStream은 일반 자바 스트림이다. 물론 이런 스트림을 다 사용

했다면 꼭 닫아줘야 한다.

Page 113: 시작하세요! 안드로이드 게임 프로그래밍

03 게임 개발 101 l 87

오디오

오디오 프로그래밍은 다소 복잡한 주제이기는 하지만 간단한 추상화를 적용하면 이런 복잡성에

서 벗어날 수 있다. 여기서는 복잡한 오디오 처리를 하지는 않는다. 다만 그래픽 모듈에서 비트맵

을 로드하는 것처럼 파일로부터 효과음과 음악을 로드해 재생할 뿐이다.

인터페이스를 살펴보기 전에 잠시 시간을 내서 소리가 실제로 무엇이고 어떻게 디지털적으로

표현되는지 살펴보자.

소리의 물리학

소리는 보통 공기 또는 물 같은 매체를 통과하는 파장으로 설명한다. 이런 파장은 실제 물리 객체

는 아니고 매체 내에서의 분자 운동에 더 가깝다. 조약돌을 던질 수 있는 작은 연못을 생각해보

자. 이 연못의 표면에 조약돌을 던지면 이 조약돌은 연못 내의 수많은 물 분자들을 밀어내고, 이

렇게 밀려난 분자들은 이웃한 분자로 에너지를 전달해 옆에 있는 분자들 또한 움직여 밀어낸다.

이로 인해 조약돌이 빠진 연못에는 원형 파장이 생기게 된다. 소리가 생성될 때도 이와 비슷한 일

이 생긴다. 이때는 원형 운동 대신 구형 운동이 일어난다. 어렸을 적에 연못에 조약돌을 던져본

적이 있다면 물의 파장이 서로 간섭해 한쪽이 더 약해지거나 더 강해지는 것을 본 적이 있을 것

이다. 소리의 파장에서도 같은 효과가 적용된다. 한 환경에 있는 모든 소리의 파장은 서로 결합해

음악을 들을 때 느끼는 톤과 멜로디를 형성한다. 소리의 볼륨은 얼마나 많은 에너지가 움직이고

얼마나 많은 분자가 이웃한 분자에 영향을 미치는지를 통해 결정되며 여러분의 귀를 통해 전달

된다.

녹음과 재생

오디오의 녹음과 재생 원리는 이론적으로는 아주 간단하다. 녹음의 경우 소리의 파장을 형성하

는 분자들이 특정 시점에 공간상에서 얼마만큼의 압력을 가했는지 측정하면 된다. 이 데이터를

재생하려면 녹음 시점과 똑같이 스피커 주변의 공기 분자를 움직이게 하면 된다.

하지만 실제로는 이보다 좀 더 복잡하다. 오디오는 보통 두 가지 방식 중 하나를 사용해 녹음

한다. 바로 아날로그와 디지털이다. 두 방식 모두 특정 마이크를 통해 소리의 파장을 녹음한다.

이런 마이크는 공기 분자의 움직임을 신호로 변환할 수 있는 막(membrane)을 갖고 있다. 이 신호

를 처리하고 저장하는 방식의 차이가 아날로그 녹음과 디지털 녹음의 차이다. 여기서는 디지털

녹음을 할 것이므로 디지털 방식만 살펴보자.

Page 114: 시작하세요! 안드로이드 게임 프로그래밍

88 l 시작하세요! 안드로이드 게임 프로그래밍

오디오를 디지털로 녹음한다는 말은 마이크 막의 상태를 개별 시간 단계를 통해 측정하고 저

장한다는 뜻이다. 주위 분자의 압력에 따라 막은 중성 상태를 기준으로 안쪽으로 또는 바깥쪽으

로 밀릴 수 있다. 이 과정을 샘플링이라고 하는데, 이렇게 부르는 이유는 개별 시점에 막의 상태

샘플을 가져오기 때문이다. 시간 단위 당 가져오는 샘플의 수는 샘플링 레이트라고 부른다. 보통

시간 단위는 초로 계산하며 이런 단위를 헤르쯔(Hz)라고 부른다. 초당 샘플 개수가 많을수록 오

디오의 품질도 높아진다. CD는 샘플링 레이트가 44,100Hz, 즉 44.1KHz다. 낮은 샘플링 레이트

는 전화선을 통해 음성을 전달할 때 등에 사용한다(보통 이 경우 8KHz를 사용한다).

샘플링 레이트는 녹음 품질에 영향을 주는 여러 속성 중 하나일 뿐이다. 막의 상태 샘플을 기

록하는 방법 또한 녹음 품질에 영향을 줄 수 있으며 디지털화로 인한 영향도 받는다. 막 상태가

정확이 어떤 것인지 생각해 보자. 막 상태는 중성 상태로부터의 막의 거리를 나타낸다. 막이 안쪽

으로 또는 바깥쪽으로 밀려남에 따라 차이가 있으므로 녹음 시에는 부호를 사용해 거리를 계산

한다. 따라서 특정 시점의 막의 상태는 음수 또는 양수의 숫자가 된다. 이런 부호 숫자 값은 다양

한 방식으로 저장할 수 있다. 부호가 적용된 8, 16, 32비트 정수, 32비트 ¶oat, 64비트 ¶oat 등으

로 저장할 수 있는 것이다. 모든 데이터 타입에는 제한된 정확도가 있다. 8비트 부호 정수는 127

자리의 양수 및 128자리의 음수 거리 값까지 저장할 수 있다. 32비트 정수는 더 높은 해상도를

저장할 수 있다. ¶oat으로 저장할 때는 막의 상태가 보통 -1과 1 사이의 값으로 정규화된다. 최대

양수와 최소 음수 값은 막이 중성 상태로부터 가질 수 있는 최대 거리를 나타낸다. 막의 상태는

진폭이라고도 부른다. 진폭은 사운드가 부딪치는 시끄러움의 크기를 나타낸다.

하나의 마이크로는 모노 사운드만 녹음할 수 있으며 이 경우 전체 공간에 대한 정보는 사라진

다. 두 개의 마이크를 사용하면 공간상의 다른 위치에서 사운드를 측정해 스테레오 사운드를 얻

을 수 있다. 예를 들어 소리를 내는 대상의 왼쪽에 마이크를 하나 두고 오른쪽에도 마이크를 하

나 두면 스테레오 사운드를 얻을 수 있다. 사운드를 두 개의 스피커를 통해 동시 재생하면 오디오

의 공간 요소를 만들 수 있다. 하지만 이는 스테레오 오디오를 저장할 때 샘플을 두 번 녹음해야

한다는 뜻도 된다.

재생은 결국 간단한 문제다. 특정 샘플링 레이트와 데이터 타입을 갖는 오디오 샘플을 디지털

형태로 얻었다면 이 데이터를 오디오 처리 유닛에 넘겨주면 오디오 처리 유닛은 스피커가 재생할

수 있게끔 이 정보를 신호로 변형해준다. 스피커는 이 신호를 해석해 이를 막의 떨림으로 변형하

고 이를 통해 주변 공기 분자들이 움직이며 소리의 파장 효과를 만들어낸다. 이 과정은 녹음 과

정을 정확히 반대로 한 것이다.

Page 115: 시작하세요! 안드로이드 게임 프로그래밍

03 게임 개발 101 l 89

오디오 품질과 압축

참 많은 이론을 다뤘다. 그런데 왜 이런 이론이 중요할까? 앞의 이론을 주의 깊게 살펴봤다면 오

디오 파일의 품질은 샘플링 레이트와 각 샘플을 저장하는 데 사용한 데이터 타입에 달려 있다는

사실을 알 수 있을 것이다. 샘플링 레이트가 높고 데이터 타입의 정확도가 크면 클수록 오디오 품

질 또한 좋아진다. 하지만 이 말은 오디오 신호를 저장하기 위해 그만큼 더 많은 저장 공간이 필

요하다는 뜻도 된다.

예를 들어 60초 길이의 동일 사운드를 두 번 녹음한다고 가정하자. 이때 한 번은 8KHz 샘플링

레이트에 샘플당 8비트를 사용하고 한 번은 44KHz 샘플링 레이트에 16비트 정확도를 사용한다.

그럼 각 사운드를 저장할 때 필요한 메모리의 양은 어떻게 될까? 첫 번째 사례의 경우 샘플당 1바

이트가 필요하다. 이 값을 8,000Hz의 샘플링 레이트에 곱하면 초당 8,000바이트가 필요하다. 60

초간 오디오를 저장하려면 결국 480,000바이트 또는 0.5 메가 바이트 정도가 필요하다. 고품질

로 녹음할 때는 훨씬 더 많은 메모리가 필요하다. 이때는 샘플당 2바이트가 필요하고 2에 44,000

바이트를 곱하면 초당 88,000바이트가 된다. 이 값에 다시 60초를 곱하면 5,280,000바이트 또는

5MB 정도가 나온다. 이 품질을 적용할 경우 보통 3분짜리 팝송 한 곡을 녹음하는 데 15MB가

소요되는데 이마저도 모노 녹음일 뿐이다. 스테레오 녹음을 할 경우에는 이 용량의 두 배만큼이

든다. 노래 하나 녹음하는 데 참으로 많은 메모리가 필요하다는 것을 새삼 느낄 것이다.

많은 사람들은 이런 오디오 녹음에 필요한 바이트 수를 줄이기 위한 방법들을 내놓았다. 사람

들은 압축되지 않은 오디오 녹음을 분석하는 음향심리학적 압축 알고리즘을 통해 더 용량이 작

은 압축 버전을 만들어냈다. 이런 압축 파일은 보통 손실을 동반하므로 원본 오디오에서 사소한

부분이 빠져 있곤 하다. MP3나 OGG를 재생할 때는 이렇게 압축된 오디오를 듣는 것이다. MP3

나 OGG 같은 형식을 사용하면 디스크상에 오디오를 저장하는 데 필요한 공간을 줄일 수 있다.

그럼 압축된 파일로부터 오디오를 어떻게 재생할 수 있을까? 물론 다양한 오디오 압축 형식을

디코딩하는 전용 하드웨어도 있지만 일반 하드웨어는 압축되지 않은 샘플만을 처리할 수 있다.

따라서 오디오 카드에 샘플을 실제로 제공하기 전에 먼저 이를 읽고 압축을 풀어줘야 한다. 이 작

업은 한 번만 한 후 압축되지 않은 오디오를 메모리에 저장하거나 필요에 따라 오디오 파일로부

터 파티션을 스트림한다.

실제 적용

앞에서는 3분 정도의 노래를 녹음하는 데도 많은 메모리가 필요하다는 사실을 배웠다. 따라서

게임의 음악을 재생할 때는 전체 오디오 샘플을 메모리에 미리 로딩하는 대신 필요할 때마다 오

Page 116: 시작하세요! 안드로이드 게임 프로그래밍

90 l 시작하세요! 안드로이드 게임 프로그래밍

디오 샘플을 스트리밍할 것이다. 보통은 하나의 음악만 스트리밍으로 재생하므로 디스크에는

한 번만 접근하면 된다.

폭발음이나 총소리 같은 짧은 효과음의 경우 상황이 조금 다르다. 효과음은 동시에 여러 개를

재생하는 경우도 많기 때문이다. 오디오 샘플을 디스크에서 스트리밍해 효과음을 재생하는 방

식은 좋지 못하다. 하지만 다행히 짧은 효과음은 많은 메모리를 차지하지 않는다. 따라서 효과음

은 모두 메모리에 저장하고 메모리에서 직접 재생하기로 한다.

따라서 다음과 같은 사항을 준비해야 한다.

■ 스트리밍 재생과 메모리에서의 직접 재생을 위해 오디오 파일을 로드하는 방법이 필요

하다.

■ 스트리밍 오디오의 재생을 제어할 수 있는 방법이 필요하다.

■ 완전히 로드된 오디오의 재생을 제어할 수 있는 방법이 필요하다.

이는 Audio, Music, Sound 인터페이스로 바로 연결된다(예제 3-3부터 3-5에 각각 나와 있다).

예제 3-3 ㅣ Audio 인터페이스

package com.badlogic.androidgames.framework;

public interface Audio {

public Music newMusic(String filename);

public Sound newSound(String filename);

}

Audio 인터페이스는 새로운 Music과 Sound 인스턴스를 생성하는 법을 제공하는 인터페이

스다. Music 인스턴스는 스트리밍 오디오 파일을 나타낸다. Sound 인스턴스는 메모리에 모두 보

관하는 짧은 효과음을 나타낸다. Audio.newMusic()과 Audio.newSound()는 모두 파일명을

인자로 받고 로딩 과정이 실패할 경우(예를 들어 지정한 파일이 존재하지 않거나 훼손된 경우)

IOException을 던진다. 파일명은 애플리케이션의 APK 파일 내의 자원 파일을 나타낸다.

Page 117: 시작하세요! 안드로이드 게임 프로그래밍

03 게임 개발 101 l 91

예제 3-4 ㅣ Music 인터페이스

package com.badlogic.androidgames.framework;

public interface Music {

public void play();

public void stop();

public void pause();

public void setLooping(boolean looping);

public void setVolume(float volume);

public boolean isPlaying();

public boolean isStopped();

public boolean isLooping();

public void dispose();

}

Music 인터페이스는 좀 더 내용이 많다. 이 인터페이스에는 음악 스트림의 재생을 시작, 일시

정지, 멈춤, 반복 재생으로 설정(다시 말해 오디오 파일 끝으로 가면 자동으로 처음부터 다시 재

생)하는 메서드가 들어 있다. 아울러 볼륨은 0(무음)부터 1(최대 볼륨) 사이의 ¶oat으로 설정할

수 있다. 또한 이 인터페이스에는 Music 인스턴스의 현재 상태를 가져오는 게터 메서드도 몇 개

있다. Music 인스턴스가 더 이상 필요 없는 경우에는 이를 제거할 수도 있다. 이렇게 하면 스트리

밍 대상이 되는 오디오 파일 등의 시스템 자원을 완전히 닫을 수 있다.

예제 3-5 ㅣ Sound 인터페이스

package com.badlogic.androidgames.framework;

public interface Sound {

public void play(float volume);

public void dispose();

}

Sound 인터페이스는 좀 더 간단하다. 여기서는 마찬가지로 볼륨을 지정할 수 있는 ¶oat 매개변

수를 받는 play() 메서드만 호출하면 된다. play() 메서드는 아무 때나 호출할 수 있다(예를 들어

Page 118: 시작하세요! 안드로이드 게임 프로그래밍

92 l 시작하세요! 안드로이드 게임 프로그래밍

총을 쏘거나 플레이어가 점프할 때 등). Sound 인스턴스가 필요 없을 때는 이를 제거해 샘플에서

사용하는 메모리뿐 아니라 이와 관련한 다른 시스템 자원을 모두 메모리에서 해제할 수 있다.

알아두기

물론 이 장에서 많은 내용을 다루기는 했지만 아직 오디오 프로그래밍에 대해 배울 내용이 많

이 남아 있다. 여기서는 최대한 내용을 짧고 이해하기 쉽게 꾸몄다. 예를 들어 보통 오디오 볼

륨은 선형적으로 지정하지 않는다. 하지만 이 책에서는 이런 사소한 부분은 무시해도 괜찮다.

다만 이와 관련한 내용이 더 많다는 것만 염두에 두자.

그래픽

마지막으로 살펴볼 모듈은 그래픽 모듈이다. 짐작한 독자도 있겠지만 그래픽 모듈은 화면상에 이

미지를 드로잉(비트맵)하는 일을 책임진다. 이렇게 얘기하면 쉬워 보일 수 있지만 고성능 그래픽

을 사용하려면 최소한의 그래픽 프로그래밍에 대한 배경 지식을 알고 있어야 한다. 이번에는 2D

그래픽의 기본 지식을 배워보자.

첫 번째로 풀어야 할 질문은 ‘대체 어떻게 이미지가 디스플레이상에 표현되는가?’다. 이에 대한

대답은 조금 복잡하며 실제로 이와 관련한 상세 내용을 모두 이해할 필요도 없다. 따라서 여기서

는 컴퓨터 내부에서 일어나는 일들과 디스플레이에 대해 간단히 살펴보기만 하겠다.

래스터, 픽셀, 프레임버퍼

오늘날의 디스플레이는 래스터 기반이다. 래스터는 소위 그림 요소(picture element)로 구성된 2

차원 그리드다. 독자들은 래스터를 픽셀로 알고 있을 것이므로 여기서도 래스터라는 용어 대신

픽셀이라는 용어를 사용하겠다. 래스터 그리드는 제한된 너비와 높이를 갖고 있으며, 이런 너비

와 높이는 보통 행 또는 열당 픽셀 수로 표현한다. 궁금한 독자라면 컴퓨터를 켜고 디스플레이의

각 픽셀 수를 직접 세 보는 것도 좋을 것이다. 하지만 이렇게 하다가 눈을 버렸다고 하더라도 필자

의 책임은 아니다.

픽셀에는 두 가지 속성이 있다. 그리드 내의 위치와 색상이 이에 해당한다. 픽셀의 위치는 개별

좌표계 내에서 2차원 좌표로 주어진다. ‘개별’이란 말은 좌표가 항상 정수 위치를 가짐을 뜻한다.

좌표는 그리드상에 부여된 유클리드 좌표계 내에서 정의된다. 좌표계의 중점은 그리드의 좌측

Page 119: 시작하세요! 안드로이드 게임 프로그래밍

03 게임 개발 101 l 93

상단 구석이다. x좌표 값이 증가하면 좌표가 오른쪽으로 움직이고 y좌표 값이 증가하면 좌표가

아래쪽으로 움직인다. 사람들이 헷갈리는 부분도 바로 이 부분이다. 이에 대해서는 잠시 후에 좀

더 자세히 살펴보면서 왜 이런 좌표계를 사용하는지 이유를 알아볼 것이다.

y축을 무시하고 나면 좌표계의 개별적인 성격으로 인해 원점이 (0, 0)에 있는 그리드상의 좌측

상단 픽셀과 일치하는 것을 볼 수 있다. 원점에서 오른쪽에 있는 픽셀은 (1, 0)이고 원점의 바로

아래 있는 픽셀은 (0, 1) 등이다(그림 3-20의 왼쪽 면 참고). 디스플레이의 래스터 그리드는 유한

하므로 의미 있는 좌표 또한 그 수가 제한된다. 음의 좌표는 화면 밖에 있다. 래스터의 너비 또는

높이 값보다 크거나 같은 좌표도 화면 밖에 있다. 이때 가장 큰 x좌표는 래스터의 너비보다 1만

큼 작은 값이며 가장 큰 y좌표는 래스터의 높이보다 1만큼 작은 값이라는 사실에 주의하자. 이는

좌측 상단에 픽셀이 원점이 되기 때문이다. 1만큼 벗어난 값으로 인한 범위 에러는 그래픽 프로

그래밍을 할 때 자주 실수하는 대목 중 하나다.

디스플레이는 그래픽 프로세서로부터 지속적인 정보 스트림을 받는다. 디스플레이는 프로그

램 또는 화면상의 드로잉을 책임지는 운영체제에서 지정한 대로 디스플레이의 래스터에 있는 각

픽셀의 색상을 인코딩한다. 디스플레이는 초당 수십 번씩 자신의 상태를 리프레시한다. 이 비율

을 리프레시 비율이라고 부르며, 값은 헤르쯔로 표현한다. LCD 디스플레이는 보통 초당 60Hz를

갖고 있으며 CRT 모니터나 플라즈마 모니터는 이보다 헤르쯔가 더 높은 경우도 있다.

그래픽 프로세서는 비디오 메모리 또는 VRAM이라고 하는 특수 메모리 영역에 접근할 수 있

다. VRAM 내에는 화면에 표시할 각 픽셀을 저장하기 위한 예약 공간이 들어 있다. 이 공간은

프레임버퍼라고 부른다. 전체 화면 이미지는 프레임이라고 부른다. 디스플레이의 래스터 그리드

내의 각 픽셀은 픽셀의 색상을 보관하는 프레임버퍼 내의 메모리 주소를 갖고 있다. 화면상에 표

시되는 내용을 바꾸려고 할 때는 VRAM 내의 메모리 영역에서 해당 픽셀의 색상값을 바꿔주면

된다.

그림 3-20 ㅣ 간단히 도식화한 디스플레이 래스터 그리드와 VRAM

Page 120: 시작하세요! 안드로이드 게임 프로그래밍

94 l 시작하세요! 안드로이드 게임 프로그래밍

이제 디스플레이 좌표계의 y축이 왜 아래 방향을 향하는지 설명할 차례다. 메모리는 VRAM

이 됐든 일반 RAM이 됐든 항상 선형적이며 1차원을 갖고 있다. 이는 마치 1차원 배열처럼 생각

할 수 있다. 그럼 2차원 픽셀 좌표를 1차원 메모리 주소에 매핑하려면 어떻게 해야 할까? 그림

3-20에서는 3×2 픽셀의 간단한 디스플레이 래스터 그리드를 VRAM으로 표현한 결과를 보여준

다(여기서는 VRAM이 프레임버퍼 메모리로만 구성된다고 가정한다). 이 그림을 보면 (x, y) 위치

의 픽셀에 대한 메모리 주소를 계산하는 다음과 같은 공식을 도출할 수 있다.

int address = x + y * rasterWidth;

이 주소를 바탕으로 픽셀의 x, y 좌표를 구할 수도 있다.

int x = address % rasterWidth;

int y = address / rasterWidth;

따라서 y축이 아래를 향하는 이유는 VRAM의 픽셀 색상에 대한 메모리 레이아웃 때문이라

고 할 수 있다. 사실 이는 컴퓨터 그래픽의 초창기 시절로부터 물려받은 유산에 가깝다. 모니터는

좌측 상단 구석에서부터 시작해 오른쪽으로 움직이면서 화면상의 각 픽셀 색상을 업데이트하고

다음 줄에서는 다시 왼쪽 끝으로 가 진행하는 식으로 화면 끝에 이를 때까지 업데이트를 계속한

다. VRAM의 내용을 이런 식으로 배치하고 나면 색상 정보를 모니터에 전달하기까지의 과정을

쉽게 살펴볼 수 있다.

알아두기

프레임버퍼에 완전히 접근할 수 있다면 앞의 공식을 사용해 픽셀, 선, 사각형, 메모리에 로

드된 이미지를 그릴 수 있는 완전한 기능의 그래픽 라이브러리를 만들 수 있을 것이다. 하지

만 현대 운영체제는 다양한 이유로 인해 프레임버퍼에 대한 직접 접근을 허용하지 않는다. 대

신 운영체제에서 실제 프레임버퍼로 복사할 메모리 영역 위에 그림을 그린다. 하지만 이 경

우에도 일반적인 개념은 그대로 동작한다. 저수준의 작업을 하는 데 관심이 있다면 웹에서

Bresenham을 찾아보고 그가 만든 선과 원 드로잉 알고리즘을 살펴보자.

Vsync와 이중 버퍼링

리프레시 레이트에 대해서 앞에서 설명한 내용을 기억한다면 이 비율이 다소 낮다는 것과 디스

플레이의 리프레시 레이트보다 더 빠른 속도로 프레임 레이트에 쓰는 일이 생길 수도 있다는 생

각이 들 것이다. 실제로 이런 경우가 종종 있다. 한 가지 문제를 더 얘기하자면 디스플레이가 언제

Page 121: 시작하세요! 안드로이드 게임 프로그래밍

03 게임 개발 101 l 95

VRAM으로부터 가장 최신의 프레임 복사본을 가져올지 알 수 없다는 것이다. 이런 문제로 인해

드로잉 도중 디스플레이가 과거 프레임버퍼 내용 중 일부와 새 상태의 일부를 함께 보여주게 되

는 현상이 생길 수 있다. 이런 효과는 많은 PC 게임에서 티어링이라는 효과로도 나타난다(화면

에서 마지막 프레임의 영역 일부와 새 프레임의 영역을 동시에 보여주는 현상).

이 문제는 이중 버퍼링(dubble-bu·ering)이라고 하는 것이 하나의 해결책이 될 수 있다. 한 개의

프레임버퍼만 사용하는 대신 그래픽 프로세서(GPU)가 실제로 앞 버퍼와 뒷 버퍼에 해당하는 버

퍼 두 개를 관리하는 것이다. 앞 버퍼는 픽셀 색상을 가져오는 용도로 디스플레이가 사용하고 디

스플레이가 앞 버퍼로 내용을 채우는 동안 뒷 버퍼는 다음 프레임을 그리는 용도로 사용된다. 현

재 프레임을 다 그리면 GPU가 두 버퍼를 서로 교체하게 해야 한다. 이 과정은 주로 앞 버퍼와 뒷

버퍼의 주소를 교체하는 식으로 이뤄진다. 그래픽 프로그래밍 문서 또는 API 문서에서는 이를

페이지 플립 또는 버퍼 스왑 등의 용어로 부른다.

하지만 이중 버퍼링만으로는 문제를 완전히 해결할 수 없다. 스왑은 콘텐츠를 리프레시하는 도

중에도 일어날 수 있기 때문이다. 이때는 수직 동기화(또는 vsync)를 사용한다. 버퍼 스왑 메서드

를 호출할 때 GPU는 디스플레이가 현재 리프레시를 모두 끝냈다고 신호를 보낼 때까지는 블록

상태를 유지한다. 이렇게 하면 GPU가 버퍼 주소를 안전하게 스왑할 수 있고 모든 게 정상 동작

한다.

다행히 요즘에는 이런 내부 내용은 다 신경 쓰지 않아도 된다. VRAM과 이중 버퍼링에 대한

세부 내용 및 vsync는 개발자들이 해를 끼칠 수 없게끔 안전하게 은닉돼 있다. 대신 개발자들에

게는 애플리케이션 창의 콘텐츠로 제어 영역을 제한한 API가 주어진다. 오픈GL ES 같은 이런

API 중 일부는 하드웨어 가속 같은 기능도 노출한다. 하드웨어 가속은 기본적으로 그래픽 칩상

의 특수 회로를 갖춘 VRAM을 제어하는 것일 뿐이다. 이처럼 이론을 알고 보면 어느 것도 마술

이 아니다. 적어도 이런 내부 동작 원리를 고수준에서라도 이해해야 하는 이유는 이를 통해 애플

리케이션의 성능 측면을 더 잘 이해할 수 있기 때문이다. vsync를 활성화하면 화면의 리프레시

레이트를 초과할 일이 전혀 없다.

하드웨어 가속을 사용하지 않는 API로 렌더링할 때는 디스플레이 자체를 직접 처리하지 않는

다. 대신 이때는 창의 UI 컴포넌트 중 하나에 드로잉을 한다. 이 경우 전체 창 크기만큼 확장된 단

일 UI 컴포넌트를 처리한다. 따라서 좌표계가 전체 화면을 덮지는 않지만 UI 컴포넌트 한 개는

전체 화면을 모두 덮는다. UI 컴포넌트는 자신의 가상 프레임버퍼를 갖고 있는 실질적인 디스플

레이가 된다. 운영체제에서는 보이는 전체 창의 내용을 관리하고 실제 프레임버퍼대로 각 내용이

자신의 영역으로 전달되는지 확인하는 일을 한다.

Page 122: 시작하세요! 안드로이드 게임 프로그래밍

96 l 시작하세요! 안드로이드 게임 프로그래밍

색상이란?

독자들은 지금껏 필자가 색상 부분을 무시하고 있었음을 눈치챘을 것이다. 필자는 그림 3-20에

서 color라는 타입을 형성해 놓고는 마치 아무 일도 없다는 듯이 행동했다. 그럼 실제 색상이 무

엇인지 살펴보자.

물리적으로 색상이란 전자기 파장에 대한 레티나 또는 시각 코텍스의 반응이다. 이런 파장은

파폭과 강도를 통해 성격이 규정된다. 우리가 볼 수 있는 파장은 파폭이 400부터 700nm인 파장

이다. 전자기 스펙트럼에서 이런 파장은 가시 스펙트럼이라고도 부른다. 무지개는 이런 가시 스

펙트럼을 보라색부터 노란색, 오렌지, 빨간색까지 잘 보여준다. 모니터가 하는 일은 특정 픽셀에

대해 특정 전자기 파장을 내보냄으로써 각 픽셀의 색상을 사용자가 경험하게끔 하는 것이다. 이

때 디스플레이의 종류가 달라지면 이 목적을 이루는 방식도 달라진다. 이 과정을 단순화하면 다

음과 같다. 화면상의 각 픽셀은 적, 녹, 청의 세 색상 중 한 색상에 해당하는 빛을 내보내는 세 개

의 각기 다른 형광 입자로 이뤄진다. 디스플레이가 리프레시되면 각 픽셀의 형광 입자는 특정 수

단(예를 들어 CRT 디스플레이의 경우 픽셀의 입자가 여러 전자와 충돌한다)에 의해 빛을 발산

한다. 디스플레이는 각 입자에 대해 얼마만큼의 빛을 발산할 수 있는지 제어할 수 있다. 예를 들

어 픽셀이 완전히 빨갛다면 빨간색 입자만 최고 강도로 전자와 충돌할 것이다. 세 가지 기본 색

외에 다른 색상을 표현하려면 기본 색상을 섞으면 된다. 색상 조합은 각 입자가 색상을 내보내는

강도를 다르게 함으로써 이뤄진다. 전자기 파장은 레티나로 나가는 동안 서로 겹친다. 두뇌에서

는 이렇게 섞인 파장을 특정 색상으로 해석한다. 따라서 색상은 기본 색상인 적, 녹, 청의 강도 조

합을 통해 지정할 수 있다.

색상 모델

방금 얘기한 내용을 색상 모델, 특히 RGB 색상 모델이라고 부른다. RGB는 적, 녹, 청색을 말한

다. 색상 모델 가운데는 YUV, CMYK처럼 다양한 색상 모델이 있다. 하지만 대부분의 그래픽 프

로그래밍 API에서는 RGB 색상 모델이 거의 표준이므로 여기서도 이에 대해서만 얘기하겠다.

RGB 색상 모델은 최종 색상이 가산적인 원색인 적, 녹, 청의 조합을 통해 도출된다는 점에서

가산적 색상 모델이라고 부른다. 이런 원색의 조합은 이미 학교에서 실험해본 적이 있을 것이다.

그림 3-1에는 이런 독자들의 기억을 돕기 위해 RGB 색상 조합의 예를 보여주고 있다.

Page 123: 시작하세요! 안드로이드 게임 프로그래밍

03 게임 개발 101 l 97

그림 3-21 ㅣ 적, 녹, 청색에 해당하는 3원색을 섞어서 색상을 조합하는 예제

물론 적, 녹, 청 색상의 구성 비율을 다르게 하면 얼마든지 더 많은 색상을 만들 수 있다. 각 색

상 요소는 0부터 최대 값(예를 들어 1) 사이의 강도 값을 가질 수 있다. 이런 색상 요소를 3차원

의 유클리드 공간상에서의 한 축에 대응되는 값으로 해석하면 그림 3-22 같은 색상 큐브를 만들

수 있다. 각 색상 요소의 강도를 다르게 하면 훨씬 더 많은 색상을 사용할 수 있다. 하나의 색상은

각 색상 요소의 범위가 0.0부터 1.0 사이인 3중값(적, 녹, 청)이라고 할 수 있다. 이때 0.0은 해당

색상의 강도가 전혀 없음을 뜻하며 1.0은 완전한 강도를 뜻한다. 검은 색상은 원점(0, 0, 0)에 있

으며 흰색은 (1, 1, 1)에 있다.

그림 3-22 ㅣ RGB 색상 큐브

Page 124: 시작하세요! 안드로이드 게임 프로그래밍

98 l 시작하세요! 안드로이드 게임 프로그래밍

색상의 디지털 인코딩

그럼 RGB 색상 값을 컴퓨터 메모리에서 어떻게 인코딩해야 할까? 먼저 각 색상 요소에 대해 사

용할 데이터 타입부터 정의해야 한다. 이런 데이터 타입으로는 0.0부터 1.0 사이의 유효 범위를

갖는 부동 소수점 숫자를 사용할 수 있다. 이렇게 하면 각 색상 요소에 대해 꽤 높은 해상도를 사

용할 수 있고 다양한 색상을 사용할 수 있을 것이다. 하지만 이 방식은 아쉽게도 많은 공간을 차

지한다(32비트 ¶oat 또는 64비트 ¶oat의 사용 여부에 따라 픽셀당 3 곱하기 4바이트 또는 3 곱하

기 8바이트).

하지만 디스플레이가 보통 제한된 수의 색상 범위만을 내보내므로 일부 색상을 잃어버리는 손

해를 감수한다면 더 효과적인 연산을 할 수 있다. 이때는 각 색상 요소에 대해 ¶oat을 사용하는

대신 부호 없는 정수를 사용한다. 32비트 정수를 각 색상에 사용할 경우 추가로 얻는 이점은 아

무것도 없다. 하지만 각 색상 요소에 부호 없는 바이트를 사용한다면 다르다. 이 경우 각 색상의

강도는 0부터 255 사이의 범위를 갖게 된다. 1픽셀의 경우 이때 3바이트 또는 24비트가 필요하

다. 이는 2의 24승(16,777,216)에 해당하는 색상을 표현할 수 있다. 이 정도의 색상만으로도 우리

목적에는 충분할 것이다.

그런데 이 색상을 좀 더 줄일 수 있을까? 물론이다. 각 색상 요소를 단일 16비트 단어로 압축하

면 각 픽셀은 2바이트의 저장 공간만 필요로 한다. 이 경우 빨간색은 5비트, 녹색은 6비트, 파란

색은 나머지 5비트를 사용한다. 녹색이 6비트를 사용하는 이유는 사람의 눈이 빨간색과 파란색

보다 녹색에서 더 많은 음영을 볼 수 있기 때문이다. 이들 비트를 모두 합치면 2의 16승(65,536)

에 해당하는 색상을 인코딩할 수 있다. 그림 3-23은 앞에서 얘기한 세 가지 인코딩 방식을 통해

색상을 인코딩하는 모습을 보여준다.

그림 3-23 ㅣ 핑크 색의 색상 인코딩(아쉽게도 이 책의 인쇄판에서는 회색으로 보일 것이다).

¶oat의 경우 32비트 3개의 자바 ¶oat을 사용할 수 있다. 24비트 인코딩의 경우 약간의 문제가

있다. 자바에는 24비트 정수가 없으므로 각 색상 요소를 단일 바이트에 저장하거나 32비트 정수

를 사용하고 앞에 있는 8비트를 사용하지 말아야 한다. 16비트 인코딩의 경우 두 개의 별도 바이

트를 사용하거나 색상 요소를 하나의 short 값에 저장할 수 있을 것이다. 자바에서는 부호 없는

Page 125: 시작하세요! 안드로이드 게임 프로그래밍

03 게임 개발 101 l 99

타입을 지원하지 않는 점에 주의하자. 하지만 2의 보수 덕분에 부호 있는 정수 타입은 부호 없는

정수에 안전하게 저장할 수 있다.

16비트와 24비트 정수 인코딩의 경우 세 가지 색상 요소를 short나 정수 값으로 저장한 순서도

지정해야 한다. 보통 이때는 두 가지 방식을 사용한다. RGB와 BGR이 이에 해당한다. 그림 3-23

에서는 RGB 인코딩을 사용하고 있다. 파란색은 가장 낮은 5 또는 8비트이고, 녹색은 다음 6 또

는 8비트, 빨간색은 가장 위에 있는 5 또는 8비트를 사용한다. BGR 인코딩은 이 순서를 역으로

사용한다. 이 경우 녹색 비트는 그대로 있고 빨간색과 파란색 비트가 자리를 바꾼다. 이 책에서

는 안드로이드의 그래픽 API와 잘 호환된다는 점에서 계속해서 RGB 순서를 사용할 것이다. 그

럼 지금까지 설명한 색상 인코딩을 요약 정리해 보자.

■ 32비트 ¶oat RGB 인코딩은 각 픽셀마다 12바이트를 갖고 있으며 강도는 0.0에서 1.0 사

이에서 변한다.

■ 24비트 정수 RGB 인코딩은 각 픽셀당 3 또는 4바이트를 갖고 있으며 강도는 0부터 255

사이에서 변한다. 각 색상 요소의 순서는 RGB 또는 BGR이 될 수 있다. 이는 RGB888 또

는 BGR888이라고도 부르는데 여기서 8은 색상 요소 당 비트 수를 가리킨다.

■ 16비트 정수 RGB 인코딩은 픽셀당 2바이트를 갖는다. 이때 빨간색과 파란색은 강도가 0

부터 31까지이며 녹색은 강도가 0부터 63까지다. 각 색상 요소의 순서는 RGB 또는 BGR

이 될 수 있다. 이 인코딩 방식도 RGB565 또는 BGR565로 부르기도 하는데, 여기서 5 또

는 6은 각 색상 요소의 비트 수를 나타낸다.

우리가 사용하는 인코딩 타입은 색상 심도라고도 부른다. 생성한 후 디스크나 메모리상에 저

장하는 이미지는 정해진 색상 심도를 갖고 있으며 이는 실제 그래픽 하드웨어와 디스플레이도 마

찬가지다. 오늘날 디스플레이는 보통 24비트의 기본 색상 심도를 갖고 있으며 일부 상황에서는

이보다 적은 심도를 사용하게끔 설정할 수 있다. 그래픽 하드웨어의 프레임버퍼는 다소 유연하므

로 여러 색상 심도를 사용할 수 있다. 우리가 사용하는 이미지 또한 우리가 원하는 색상 심도를

가질 수 있다.

Page 126: 시작하세요! 안드로이드 게임 프로그래밍

100 l 시작하세요! 안드로이드 게임 프로그래밍

알아두기

픽셀당 색상 정보를 인코딩하는 방법에는 여러 가지가 있다. RGB 색상 외에 색상 요소를 하나

만 가질 수 있는 그레이스케일 픽셀도 사용할 수 있다. 이런 색상 인코딩 방식은 자주 사용하

지 않으므로 여기서는 일단 무시하고 넘어가겠다.

이미지 형식과 압축

게임 개발을 하다 보면 디자이너가 와서 Gimp, Paint.NET, 포토샵 같은 그래픽 프로그램에서

작업한 이미지를 건네줄 것이다. 이런 이미지는 디스크상에 다양한 형태로 저장할 수 있다. 그런

데 왜 이런 이미지 형식을 사용해야 할까? 래스터를 바이트 블롭 형태로 디스크에 곧바로 저장하

면 안 될까?

물론 그렇게 해도 된다. 하지만 이렇게 할 경우 얼마만큼의 메모리를 차지할지 생각해 보자. 최

고의 품질을 원할 경우 픽셀을 인코딩할 때 RGB888로 픽셀당 24비트를 사용할 것이다. 이 이미

지가 1,024×1,024 크기라고 가정하자. 그럼 이미지 하나에만 3MB가 소요된다. RGB565 인코딩

방식을 사용하면 이를 대충 2MB로 줄일 수 있을 것이다.

오디오의 경우와 마찬가지로 이미지를 저장하는 데 필요한 메모리 양을 줄이기 위한 다양한

연구가 있었다. 이때도 특정 이미지 저장 목적에 딱 부합하고 최대한 원본 색상 정보를 유지하는

압축 알고리즘을 사용한다. 가장 많이 사용하는 압축 방식은 JPEG과 PNG다. JPEG은 손실 형

식이다. 이 말은 압축 과정에서 원본 정보 중 일부가 사라짐을 뜻한다. PNG는 무손실 형식으로

서 원본과 100퍼센트 동일한 이미지를 재생성한다. 손실 형식은 보통 압축률이 더 뛰어나고 디

스크상에서 더 적은 공간을 차지한다. 따라서 디스크 메모리 제약에 따라 어떤 형식을 사용할지

선택하면 된다.

사운드 효과와 마찬가지로 이미지를 메모리에 로드할 때는 이미지를 먼저 완전히 압축 해제해

야 한다. 따라서 디스크에 있는 압축된 이미지의 크기가 20KB이더라도 램에는 전체 너비 곱하기

높이 곱하기 색상 심도만큼의 저장 공간이 있어야 한다.

일단 로드된 후 압축을 해제하고 나면 이미지는 VRAM에 배치된 프레임버퍼와 마찬가지로 픽

셀 색상 배열 형태로 접근할 수 있다. 차이가 있다면 이미지의 경우 픽셀이 일반 램상에 있다는

것과 색상 심도가 프레임버퍼의 색상 심도와 다를 수 있다는 점이다. 또 로드된 이미지는 프레임

버퍼와 마찬가지로 좌표계도 갖고 있다. 이 좌표계의 중점은 좌측 상단 구석이고 x축 값이 클수

록 우측으로, y축 값이 클수록 아래로 향한다.

Page 127: 시작하세요! 안드로이드 게임 프로그래밍

03 게임 개발 101 l 101

이미지를 로드한 후에는 이미지의 픽셀 색상을 프레임버퍼상의 적절한 위치로 전달해 램에서

프레임버퍼로 이미지를 그릴 수 있다. 이 작업은 직접 하지 않고 이 기능을 제공하는 API를 사용

해 처리한다.

알파 합성과 블렌딩

그래픽 모듈 인터페이스의 설계를 시작하기에 앞서 한 가지 주제를 더 배워야 한다. 바로 이미지

합성이다. 이 주제를 설명할 때는 렌더링할 프레임버퍼가 있고 이 버퍼로 전달할 다양한 이미지

가 이미 램에 로드됐다고 가정하겠다. 그림 3-24에서는 간단한 배경 이미지와 좀비를 해치우는

Bob을 보여준다.

그림 3-24 ㅣ 간단한 배경과 Bob

Bob의 공간을 그리려면 먼저 배경 이미지를 프레임버퍼로 그리고 이어서 프레임버퍼상의 배경

이미지 위에 Bob을 그려야 한다. 이 과정은 여러 이미지를 합쳐 하나의 최종 이미지를 완성한다

는 점에서 합성이라고 부른다. 새로운 드로잉 호출은 프레임버퍼의 현재 내용을 덮어쓰기 때문

에 이미지를 그리는 순서가 중요하다. 그럼 최종 합성 결과는 어떤 모습으로 나올까? 그림 3-25는

이 결과를 보여준다.

그림 3-25 ㅣ 배경과 Bob을 프레임버퍼에 합성한 모습(원하던 결과가 아니다)

Page 128: 시작하세요! 안드로이드 게임 프로그래밍

102 l 시작하세요! 안드로이드 게임 프로그래밍

원치 않는 결과가 나왔다. 그림 3-24에서는 Bob 주변에 흰 픽셀이 있는 것을 볼 수 있다. Bob을

배경 위에 그려서 프레임버퍼로 전달하는 과정에서 흰 픽셀 또한 함께 그려졌고 결과적으로 흰

배경으로 배경을 덮어쓰게 됐다. 그럼 Bob의 픽셀만 보이게 하고 흰 배경은 무시하게 하려면 어

떻게 해야 할까?

이때는 알파 블렌딩을 사용하면 된다. Bob의 경우는 사실 기술적으로는 알파 마스킹이라고

부르는 게 맞지만, 이는 알파 블렌딩의 하위 종류 중 하나일 뿐이다. 그래픽 소프트웨어들은 픽셀

의 RGB 값뿐 아니라 투명도도 지정할 수 있게 해준다. 투명도는 픽셀 색상의 또 다른 구성 요소

라 생각하면 된다. 투명도도 R, G, B 색상 요소와 더불어 인코딩할 수 있다.

앞에서 필자는 24비트 RGB 색상을 32비트 정수로 저장할 수 있다는 데서 살짝 힌트를 주었다.

이때 32비트 정수 중 사용하지 않는 8비트에 알파 값을 사용할 수 있는 것이다. 이 공간에는 픽

셀의 투명도를 0부터 255 사이로 지정할 수 있다. 이때 0은 완전히 투명한 것을 나타내고 255는

완전히 불투명한 것을 나타낸다. 이런 인코딩 방식은 색상 요소의 순서에 따라 ARGB8888 또는

BGRA8888로 부른다. 물론 RGBA8888, ABGR8888 형식도 있다.

16비트 인코딩의 경우 약간 문제가 있다. 16비트 short의 모든 비트를 이미 색상 요소가 차지하

고 있기 때문이다. 이때는 ARGB8888 형식을 모방해 ARGB4444 형식을 정의해야 한다. 이렇게

하면 색상 요소당 4비트씩 RGB 색상 값으로 12비트를 사용할 수 있다.

완전히 투명하거나 완전히 불투명한 픽셀의 렌더링 방식이 어떻게 동작할지는 쉽게 짐작할 수

있을 것이다. 완전히 투명한 픽셀의 경우 0에 해당하는 알파 요소를 가진 픽셀을 그냥 무시하면

된다. 후자의 경우 대상 픽셀을 그냥 대체하면 된다. 픽셀이 완전히 투명하지도 않고 완전히 불투

명하지도 않은 알파 요소를 갖고 있는 경우에는 상황이 좀 더 복잡해진다.

블렌딩을 정식으로 설명하려면 몇 가지를 정의해야 한다.

■ 블렌딩은 두 개의 입력 값과 한 개의 출력 값을 갖고 있으며 이들 값은 RGB 색상(C)에 알

파 값(α)을 더한 값으로 나타난다.

■ 두 개의 입력값은 소스와 목표 값이다. 소스는 목표 이미지(예를 들어 프레임버퍼)에 그리

려고 하는 이미지의 픽셀이다. 목표 값은 소스 픽셀을 가지고 (부분적으로) 덧붙여 그릴

픽셀을 나타낸다.

Page 129: 시작하세요! 안드로이드 게임 프로그래밍

03 게임 개발 101 l 103

■ 결과 값은 RGB와 알파 값으로 표현한다. 하지만 보통 알파 채널은 무시한다. 이 장에서도

설명을 단순화하기 위해 알파 채널은 무시할 것이다.

■ 계산을 간단히 하기 위해 RGB와 알파 값은 0.0부터 1.0 사이의 ¶oat으로 표현한다.

이와 같이 정의하고 나면 다음과 같은 블렌딩 방정식을 만들 수 있다. 가장 간단한 방정식은 다

음과 같다.

red = src.red * src.alpha + dst.red * (1 – src.alpha)

blue = src.green * src.alpha + dst.green * (1 – src.alpha)

green = src.blue * src.alpha + dst.blue * (1 – src.alpha)

이때 src와 dst는 서로 블렌딩하려는 소스와 목표의 픽셀을 나타낸다. 여기서는 두 개의 색상

요소를 블렌딩한다. 이런 블렌딩 방정식에서 목표 알파 값이 빠져 있는 것을 주의해서 보자. 다음

으로 다음 예제를 살펴보고 결과를 확인하자.

src = (1, 0.5, 0.5), src.alpha = 0.5, dst = (0, 1, 0)

red = 1 * 0.5 + 0 * (1 – 0.5) = 0.5

blue = 0.5 * 0.5 + 1 * (1 – 0.5) = 0.75

red = 0.5 * 0.5 + 0 * (1 – 0.5) = 0.25

그림 3-26에는 앞의 방정식으로 인한 결과가 나와 있다. 소스 색상은 핑크이고 목표 색상은 녹

색이다. 두 색상은 최종 결과 색상에 똑같이 기여했으며 그 결과 다소 지저분한 녹색 또는 올리

브 색이 나왔다.

그림 3-26 ㅣ 두 픽셀의 블렌딩

Porter와 Du·는 다양한 블렌딩 방정식을 만들어냈다. 하지만 여기서는 이 책에서 주로 다루

게 될 내용과 밀접한 관련이 있으므로 앞의 방정식을 그대로 사용하겠다. 블렌딩으로 인한 배합

효과를 확인하려면 종이나 그래픽 소프트웨어를 사용해 여러 가지로 실험해보면서 느낌을 익히

기 바란다.

Page 130: 시작하세요! 안드로이드 게임 프로그래밍

104 l 시작하세요! 안드로이드 게임 프로그래밍

알아두기

블렌딩은 폭넓은 주제다. 블렌딩에 대해 더 알기 원한다면 웹에서 Porter와 Duff의 초기 작

품을 찾아볼 것을 권장한다. 하지만 이 책에서 작성할 게임의 경우 앞의 방정식만으로도 충

분하다.

앞의 방정식에서 여러 번의 곱셈을 사용한 것에 주의하자(정확히 6번 사용됐다). 곱셈은 연산

비용이 크므로 가능한 한 줄이는 게 좋다. 블렌딩의 경우 소스 픽셀 색상의 RGB 값에 소스 알파

값을 미리 곱함으로써 곱셈을 세 번 줄일 수 있다. 대부분의 그래픽 소프트웨어는 이미지의 RGB

값과 해당 알파 값의 사전 곱셈 연산을 지원한다. 이 기능을 지원하지 않는 경우에는 메모리에서

로드 시점에 이 작업을 할 수 있다. 하지만 그래픽 API를 사용해 블렌딩을 활용한 이미지를 그릴

때는 올바른 블렌딩 방정식을 꼭 사용해야 한다. 이때는 이미지에서 알파 값을 포함하고 있으므

로 앞의 방정식이 잘못된 결과를 낳을 수 있다. 따라서 이때는 소스 알파를 소스 색상과 곱해서

는 안 된다. 다행히 안드로이드 그래픽 API는 이미지를 블렌딩하는 방법을 완전히 지정할 수 있

게 해준다.

Bob의 경우 흰 픽셀의 알파 값을 그래픽 프로그램에서 0으로 설정한 후 이미지를 ARGB8888

또는 ARGB4444 형식으로 로드하고 알파 값을 미리 곱한 후 올바른 블렌딩 방정식을 사용해 실

제 알파 블렌딩을 수행하는 드로잉 방식을 사용하면 된다. 이 결과는 그림 3-27에 나와 있다.

그림 3-27 ㅣ 왼쪽에 있는 Bob은 블렌딩됐다. 오른쪽에 있는 Bob은 Paint.NET에서의 Bob이다. 체크보

드는 흰 배경 픽셀의 알파 값이 0임을 나타낸다. 따라서 배경 체크보드가 투영돼 보이는 것이다.

알아두기

JPEG 형식은 픽셀당 알파 값 저장을 지원하지 않으므로 이때는 PNG 형식을 사용해야 한다.

Page 131: 시작하세요! 안드로이드 게임 프로그래밍

03 게임 개발 101 l 105

실제 적용

이제 이런 지식을 바탕으로 그래픽 모듈의 인터페이스 설계를 시작해 보자. 먼저 인터페이스의

기능부터 정의하자. 여기서 필자가 말하는 프레임버퍼는 드로잉의 대상이 되는 UI 컴포넌트의

가상 프레임버퍼라는 사실에 주의하자. 이 모듈은 다음과 같은 작업을 수행해야 한다.

■ 디스크로부터 이미지를 로드해 나중에 그릴 수 있게 메모리에 저장한다.

■ 지난 번 프레임으로부터 남은 내용을 지울 수 있게 색상을 사용해 프레임버퍼를 정리한다.

■ 특정 위치의 프레임버퍼 픽셀을 특정 색상으로 설정한다.

■ 프레임버퍼에 선과 사각형을 그린다.

■ 앞에서 로드한 이미지를 프레임버퍼에 그린다. 이때 전체 이미지를 그리거나 이미지의

일부 영역을 그린다. 아울러 블렌딩을 활성화 또는 비활성화해 이미지를 그릴 수 있어야

한다.

■ 프레임버퍼의 크기를 알아온다.

이를 위해 Graphics와 Pixmap이라는 간단한 인터페이스를 설계한다. 먼저 예제 3-6에 나와

있는 Graphics부터 설계해보자.

예제 3-6 ㅣ Graphics 인터페이스

package com.badlogic.androidgames.framework;

public interface Graphics {

public static enum PixmapFormat {

ARGB8888, ARGB4444, RGB565

}

public Pixmap newPixmap(String fileName, PixmapFormat format);

public void clear(int color);

public void drawPixel(int x, int y, int color);

public void drawLine(int x, int y, int x2, int y2, int color);

public void drawRect(int x, int y, int width, int height, int color);

public void drawPixmap(Pixmap pixmap, int x, int y, int srcX, int srcY,

int srcWidth, int srcHeight);

Page 132: 시작하세요! 안드로이드 게임 프로그래밍

106 l 시작하세요! 안드로이드 게임 프로그래밍

public void drawPixmap(Pixmap pixmap, int x, int y);

public int getWidth();

public int getHeight();

}

여기서는 먼저 PixmapFormat이라는 public static enum부터 선언했다. 이 열거형 타입은 지

원할 서로 다른 픽셀 형식을 인코딩한다. 다음으로 Graphics 인터페이스의 다양한 메서드를 볼

수 있다.

■ Graphics.newPixmap() 메서드는 JPEG 또는 PNG 형식으로 된 이미지를 로드한다.

여기서는 로딩 메커니즘의 힌트가 되는 Pixmap 결과에 대해 원하는 형식을 지정한다.

Pixmap 결과 값은 이와 다른 형식이 될 수도 있다. 여기서는 로드된 이미지의 메모리 흔

적을 제어하기 위해 이런 방식을 사용했다(예를 들어 RGB888 또는 ARGB8888 이미지

를 RGB565 또는 ARGB4444 이미지로 로드할 수 있다). 파일명 인자는 애플리케이션의

APK 파일 내 자원을 가리킨다.

■ Graphics.clear() 메서드는 지정된 color로 전체 프레임버퍼를 정리한다. 이 프레임워크의

모든 색상은 32비트 ARGB88888 값으로 지정한다(물론 Pixmap은 다른 형식이 될 수도

있다).

■ Graphics.drawPixel() 메서드는 프레임버퍼의 (x, y) 픽셀을 주어진 color로 설정한다. 이

때 화면 밖에 있는 좌표는 무시된다. 이를 클리핑이라고 부른다.

■ Graphics.drawLine() 메서드는 Graphics.drawPixel() 메서드와 유사한 메서드다. 여기

서는 선의 시작점과 끝점, 더불어 color를 지정한다. 프레임버퍼의 래스터 바깥에 있는 선

영역은 무시한다.

■ Graphics.drawRect() 메서드는 프레임버퍼에 사각형을 그린다. (x, y) 좌표는 프레임버퍼

에서 사각형의 좌측 상단 구석을 나타낸다. 인자인 width와 height는 x, y 좌표상에서의

픽셀 개수를 나타내며, 사각형은 (x, y)부터 시작해 공간을 채운다. y 값은 아랫쪽으로 채

워진다. color 인자는 사각형을 채울 색상을 나타낸다.

■ Graphics.drawPixmap() 메서드는 Pixmap의 사각형 영역을 프레임버퍼에 그린다. (x,

y) 좌표는 프레임버퍼에서의 Pixmap의 대상 위치에 대한 좌측 상단 구석 위치를 지정한

Page 133: 시작하세요! 안드로이드 게임 프로그래밍

03 게임 개발 101 l 107

다. 인자인 srcX와 srcY는 Pixmap의 자체 좌표계에서 Pixmap으로부터 사용하는 사각

형 영역의 좌측 상단 구석에 해당하는 사각형 영역을 나타낸다. srcWidth와 srcHeight는

Pixmap으로부터 그릴 영역의 크기를 지정한다.

■ 끝으로 Graphics.getWidth()와 Graphics.getHeight() 메서드는 프레임버퍼의 너비와 높

이를 픽셀 값으로 반환한다.

Graphics.clear()를 제외한 모든 드로잉 메서드는 앞 절에서 개략적으로 설명한 대로 픽셀에

대해 자동으로 블렌딩을 수행한다. 블렌딩은 드로잉 속도를 조금 개선하기 위해 상황에 따라 비

활성화할 수도 있지만 이 경우 구현체의 로직이 더 복잡해질 것이다. 보통은 Mr. Nom 같은 간단

한 게임에는 항상 블렌딩을 활성화해 놓는 게 좋다.

Pixmap 인터페이스는 예제 3-7에 나와 있다.

예제 3-7 ㅣ Pixmap 인터페이스

package com.badlogic.androidgames.framework;

import com.badlogic.androidgames.framework.Graphics.PixmapFormat;

public interface Pixmap {

public int getWidth();

public int getHeight();

public PixmapFormat getFormat();

public void dispose();

}

합성은 프레임버퍼 내에서 이뤄지므로 이 인터페이스는 매우 간단하며 수정하는 내용도 없다.

■ Pixmap.getWidth()와 Pixmap.getHeight() 메서드는 Pixmap의 너비와 높이를 픽셀 단

위로 반환한다.

■ Pixmap.getFormat() 메서드는 램에 저장된 Pixmap의 PixelFormat을 반환한다.

■ 끝으로 Pixmap.dispose() 메서드가 있다. Pixmap 인스턴스는 메모리와 다른 시스템 자

원도 사용할 수 있다. 이 자원이 필요하지 않다면 이 메서드를 호출해 제거할 수 있다.

Page 134: 시작하세요! 안드로이드 게임 프로그래밍

108 l 시작하세요! 안드로이드 게임 프로그래밍

Mr. Nom을 구현할 때는 이와 같이 간단한 그래픽 모듈을 사용한다. 끝으로 게임 프레임워크

에 대한 내용을 살펴보면서 이 장의 내용을 마무리하자.

게임 프레임워크

지금까지의 기초 내용을 바탕으로 이제 실제 게임 자체의 구현에 대한 얘기를 시작할 수 있게 됐

다. 이를 위해서는 게임에서 수행해야 할 다음과 같은 작업들을 먼저 정의해야 한다.

■ 게임은 모두 동일한 작업을 수행하는 각기 다른 화면으로 나뉘어 있다. 이런 공통 작업에

는 사용자의 입력값 해석, 입력값을 화면 상태에 적용, 화면 렌더링 등이 포함된다. 일부

화면은 사용자 입력을 전혀 받지 않고 일정 시간이 흐른 후 다음 화면으로 전환된다(예를

들어 로고 화면 등).

■ 화면은 어떤 식으로든 관리돼야 한다(예를 들어 현재 화면을 추적하고 다른 화면으로의

전환 방법을 알고 있어야 한다. 이는 기존 화면을 없애고 새 화면을 현재 화면으로 설정하

는 작업으로 요약할 수 있다).

■ 게임 프레임워크에서는 다양한 모듈(그래픽, 오디오, 입력 모듈 등)이 화면에 접근할 수 있

게 함으로써 리소스를 로드하고, 사용자 입력을 가져오고, 사운드를 재생하고, 프레임버

퍼로 렌더링하는 등의 일을 지원해야 한다.

■ 이 게임은 실시간 게임(이 말은 내용이 끊임없이 움직이고 업데이트됨을 뜻한다)이므로

현재 화면은 가능한 한 자주 현재 상태를 업데이트하고 렌더링을 갱신해야 한다. 이 작업

은 보통 메인 루프라는 루프 내에서 한다. 이 루프는 게임이 끝날 때 끝이 난다. 이 루프를

한 번 반복하는 과정은 프레임이라고 부른다. 계산할 수 있는 초당 프레임 수(FPS)는 프

레임 레이트라고 부른다.

■ 시간 얘기가 나온 김에 얘기하자면, 게임에서는 지난 프레임 이후 흘러간 시간 범위도 추

적해야 한다. 이 시간은 잠시 후 살펴볼 프레임 독립적인 움직임에 사용된다.

■ 게임에서는 창의 상태(예를 들어 창이 일시 정지됐는지 재개됐는지)를 추적하고 현재 화

면에 이들 이벤트를 전달해줘야 한다.

■ 게임 프레임워크는 창을 설정하고, 렌더링의 대상이자 사용자로부터 입력을 받는 UI 컴

포넌트를 생성해야 한다.

Page 135: 시작하세요! 안드로이드 게임 프로그래밍

03 게임 개발 101 l 109

그럼 일시 정지나 실행 재개 같은 창 관리 이벤트에 대해서는 잠깐 잊고 이런 내용을 의사 코드

를 통해 작성해 보기로 하자.

createWindowAndUIComponent();

Input input = new Input();

Graphics graphics = new Graphics();

Audio audio = new Audio();

Screen currentScreen = new MainMenu();

float lastFrameTime = currentTime();

while ( !userQuit() ) {

float deltaTime = currentTime() – lastFrameTime;

lastFrameTime = currentTime();

currentScreen.updateState(input, deltaTime);

currentScreen.present(graphics, audio, deltaTime);

}

cleanupResources();

여기서는 먼저 게임의 창과 레더링의 대상이면서 사용자 입력을 받을 UI 컴포넌트를 생성하는

것부터 시작하고 있다. 그럼 다음 저수준 작업을 하는 데 필요한 모든 모듈의 인스턴스를 생성했

다. 이어서 시작 화면의 인스턴스를 생성하고 이를 현재 화면으로 만든 후 현재 시간을 기록했다.

그런 다음 사용자가 게임을 끝낼 때 비로소 끝나게 되는 메인 루프를 시작한다.

게임 루프 내에서는 소위 델타 시간을 계산한다. 이 시간은 마지막 프레임의 시작 이후 지나간

시간을 나타낸다. 그런 다음 현재 프레임의 시작 시간을 기록한다. 델타 시간과 현재 시간은 보

통 초 단위로 계산한다. 이 화면의 경우 델타 시간은 마지막 업데이트 이후 얼마만큼의 시간이

흘렀는지를 알려준다. 이 정보는 프레임 독립적인 움직임을 구현할 때 필요하다(잠시 후 보게 될

것이다).

끝으로 현재 화면의 상태를 업데이트하고 이를 사용자에게 보여준다. 이런 업데이트는 델타 시

간뿐 아니라 화면을 통해 보여주는 입력 상태와도 관련이 있다. 보여줄 내용에는 프레임버퍼로의

화면 상태 렌더링뿐 아니라 화면 상태의 필요에 따른 오디오 재생도 포함된다(예를 들어 마지막

업데이트 이후 총을 발사한 경우 등). 프레젠테이션 메서드에서는 마지막 호출 이후 얼마만큼의

시간이 흘렀는지 등의 정보도 알고 있어야 한다.

메인 루프가 끝나면 모든 리소스를 제거하고 창을 닫는다.

Page 136: 시작하세요! 안드로이드 게임 프로그래밍

110 l 시작하세요! 안드로이드 게임 프로그래밍

지금까지의 내용은 고수준에서 살펴본 가상 게임의 동작 방식이다. 사용자 입력을 처리하고

상태를 업데이트하고 사용자에게 상태를 보여준 후 이 과정을 반복한다(사용자가 게임을 그만

할 때까지).

현대 OS의 UI 애플리케이션은 보통 실시간으로 동작하지 않는다. 대신 운영체제에서 입력 이

벤트나 드로잉 시점을 애플리케이션에게 전달하는 이벤트 기반 패러다임을 통해 동작한다. 이런

이벤트 기반 패러다임은 구동 시점에 애플리케이션이 운영체제에 등록하는 콜백을 통해 이뤄진

다. 이렇게 콜백을 등록한 후 애플리케이션은 운영체제로부터 받은 이벤트 알림을 처리할 책임

을 진다. 이런 이벤트는 모두 소위 UI 스레드 내에서 일어난다. UI 스레드는 UI 애플리케이션의

메인 스레드다. 보통 콜백은 가능한 한 빨리 실행을 마치는 것이 좋으므로 메인 루프는 이런 콜백

내에 구현하지 않는 게 좋다.

대신 게임의 메인 루프는 게임이 시작할 때 실행하는 또 다른 스레드에서 돌린다. 이 말은 입력

이벤트나 창 이벤트 같은 UI 스레드 이벤트를 수신할 경우 각별히 주의해야 함을 뜻한다. 하지만

이런 세부 내용은 나중에 안드로이드용 게임 프레임워크를 구현하면서 따로 처리할 것이다. 지금

은 특정 시점에 UI 스레드와 메인 루프 스레드를 동기화해야 한다는 사실만 기억하면 된다.

Game과 Screen 인터페이스

이제 게임 인터페이스를 설계해 보자. 다음은 이 인터페이스에서 해야 할 일을 나열한 것이다.

■ 창과 UI 컴포넌트를 설정하고 창 및 입력 이벤트를 받을 수 있게끔 콜백을 연결한다.

■ 메인 루프 스레드를 시작한다.

■ 현재 화면을 추적하고 매번 메인 루프가 반복될 때마다(즉 매 프레임마다) 화면을 업데이

트해 보여주도록 명령한다.

■ 창 이벤트(예를 들어 일시 정지 및 재개 이벤트)를 UI 스레드로부터 메인 루프 스레드로

전달하고 이를 다시 현재 화면으로 전달해 이에 따라 상태가 바뀌게끔 한다.

■ 지금까지 개발한 모든 모듈(Input, FileIO, Graphics, Audio)이 접근할 수 있게 해준다.

게임 개발자로서 우리는 메인 루프가 실행 중인 스레드가 무엇인지 및 UI 스레드와 동기화 해

야 하는지 여부는 신경 쓰지 않기로 하겠다. 다만 여기서는 저수준 모듈과 창 이벤트 알림을 활

용해 각기 다른 화면을 구현하기로 한다. 따라서 여기서는 모든 복잡한 내용을 숨겨주는 매우 간

단한 Game 인터페이스를 생성하고 모든 화면을 구현할 때 사용할 Screen 추상 클래스를 구현

Page 137: 시작하세요! 안드로이드 게임 프로그래밍

03 게임 개발 101 l 111

한다. 예제 3-8에는 Game 인터페이스가 나와 있다.

예제 3-8 ㅣ Game 인터페이스

package com.badlogic.androidgames.framework;

public interface Game {

public Input getInput();

public FileIO getFileIO();

public Graphics getGraphics();

public Audio getAudio();

public void setScreen(Screen screen);

public Screen getCurrentScreen();

public Screen getStartScreen();

}

예상한 독자도 있겠지만 이 인터페이스에는 저수준 모듈 인스턴스를 반환하는 몇 개의 게터

메서드가 들어 있다. 이들 모듈 인스턴스는 Game 구현체에서 인스턴스를 생성하고 관리하게 될

것이다.

Game.setScreen() 메서드는 Game의 현재 Screen을 설정한다. 이들 메서드는 내부 스레드 생

성, 창 관리, 현재 화면에게 계속해서 업데이트할 것을 명령하는 메인 로직과 더불어 한 번만 구

현할 것이다.

Game.getCurrentScreen() 메서드는 현재 활성화된 Screen을 반환한다.

우리는 나중에 Game 인터페이스를 구현하기 위해 AndroidGame이라는 추상 클래스를 사용

할 것이다. 이 클래스는 Game.getStartScreen() 메서드를 제외한 모든 메서드를 구현한다. 이 메

서드는 추상 메서드다. 실제 게임에 사용할 AndroidGame 인스턴스를 생성할 때는 이 클래스가

앞의 클래스를 상속하고 Game.getStartScreen() 메서드를 오버라이드해 게임의 첫 번째 화면을

반환하게 할 것이다.

Page 138: 시작하세요! 안드로이드 게임 프로그래밍

112 l 시작하세요! 안드로이드 게임 프로그래밍

게임을 설정하는 법이 얼마나 쉬운지 독자들이 감을 잡을 수 있게 다음 예제 코드를 마련했다

(여기서는 이미 AndroidGame 클래스를 구현했다고 가정한다).

public class MyAwesomeGame extends AndroidGame {

public Screen getStartScreen () {

return new MySuperAwesomeStartScreen(this);

}

}

멋지지 않은가? 이 클래스가 게임을 시작할 화면을 구현하기만 나머지 작업은 AndroidGame

클래스에서 모두 처리해준다. 이후부터는 AndroidGame의 메인 루프 스레드에서 MySuper

AwesomeStartScreen을 가지고 계속 업데이트하게끔 명령하기만 하면 된다. 여기서는 Screen 구

현체의 생성자에 MyAwesomeGame 인스턴스 자체를 넘겨준 것을 주의해서 보자.

알아두기

실제 MyAwesomeGame 클래스의 인스턴스를 어떻게 생성하는지 궁금하다면 간단히 힌트

를 주겠다. 사실 AndroidGame은 Activity를 상속하는데, 이런 Activity는 사용자가 게임을

시작할 때 안드로이드 운영체제에 의해 자동으로 인스턴스가 생성된다.

마지막으로 살펴볼 퍼즐 조각은 Screen 추상 클래스다. 인터페이스 대신 이와 같은 추상 클래

스를 만든 이유는 필요한 내용을 미리 관리하기 위해서다. 이렇게 추상 클래스를 만들면 Screen

의 추상 클래스 구현체에서 반복 코드를 작성하는 일을 줄일 수 있다. 예제 3-9에서는 추상

Screen 클래스를 보여준다.

예제 3-9 ㅣ Screen 클래스

package com.badlogic.androidgames.framework;

public abstract class Screen {

protected final Game game;

public Screen(Game game) {

this.game = game;

}

public abstract void update(float deltaTime);

public abstract void present(float deltaTime);

Page 139: 시작하세요! 안드로이드 게임 프로그래밍

03 게임 개발 101 l 113

public abstract void pause();

public abstract void resume();

public abstract void dispose();

}

이런 데이터 관리는 나쁘지 않다. 생성자에서는 Game 인스턴스를 받고 모든 하위 클래스에서

접근할 수 있는 «nal 멤버에 이를 저장한다. 이런 메커니즘을 활용하면 다음과 같은 두 가지 성

과를 얻을 수 있다.

■ Game의 저수준 모듈에 접근해 오디오를 재생하고, 화면을 그리고, 사용자 입력을 받고,

파일을 읽고 쓸 수 있다.

■ 적절한 시점에 Game.setScreen()을 호출해 새로운 현재 Screen을 설정할 수 있다(예를

들어 새 화면으로 전환되는 버튼을 누르는 시점 등).

첫 번째 내용은 분명히 이해할 수 있을 것이다. Screen 구현체가 의미 있는 일을 하려면 이런

모듈에 접근할 수 있어야 하기 때문이다.

두 번째 내용은 Screen 인스턴스 내에서 쉽게 화면 전환을 구현할 수 있게 해준다. 각 Screen

은 자신의 상태를 기반으로 어떤 Screen으로 전환해야 할지 결정할 수 있다(예를 들어 메뉴 버튼

을 누른 시점 등).

Screen.update()와 Screen.present() 메서드는 이제 바로 이해가 될 것이다. 이들 메서드는 화

면 상태를 업데이트하고 그에 따른 화면 내용을 보여준다. Game 인스턴스는 메인 루프의 매 반

복마다 한 번씩 이들 메서드를 호출한다.

Screen.pause()와 Screen.resume() 메서드는 게임이 일시 정지하거나 실행 재개될 때 호출된

다. 이들 메서드도 Game 인스턴스를 통해 호출되며 현재 활성화된 Screen에 대해 적용된다.

Screen.dispose() 메서드는 Game.setScreen()이 호출될 때 Game 인스턴스가 호출한다.

Game 인스턴스는 이 메서드를 통해 현재 Screen을 제거하고 Screen이 이 메서드를 통해 모든

시스템 자원(예를 들어 Piaxmap에 저장된 그래픽 자원 등)을 반환하게 함으로써 메모리상에 새

화면의 자원 공간을 마련한다. Screen.dispose() 메서드는 각 화면이 영구 저장해야 할 정보를 마

지막으로 저장할 수 있는 시점이기도 하다.

Page 140: 시작하세요! 안드로이드 게임 프로그래밍

114 l 시작하세요! 안드로이드 게임 프로그래밍

간단한 예제

MySuperAwesomeGame 예제에 이어 간단한 구현체인 MySuperAwesomeStartScreen 클래스

를 살펴보자.

public class MySuperAwesomeStartScreen extends Screen {

Pixmap awesomePic;

int x;

public MySuperAwesomeStartScreen(Game game) {

super(game);

awesomePic = game.getGraphics().newPixmap("data/pic.png",

PixmapFormat.RGB565);

}

@Override

public void update(float deltaTime) {

x += 1;

if (x > 100)

x = 0;

}

@Override

public void present(float deltaTime) {

game.getGraphics().clear(0);

game.getGraphics().drawPixmap(awesomePic, x, 0, 0, 0,

awesomePic.getWidth(), awesomePic.getHeight());

}

@Override

public void pause() {

// 할 일 없음

}

@Override

public void resume() {

// 할 일 없음

}

@Override

public void dispose() {

awesomePic.dispose();

}

}

Page 141: 시작하세요! 안드로이드 게임 프로그래밍

03 게임 개발 101 l 115

이 클래스와 더불어 MySuperAwesomeGame 클래스가 하는 일을 자세히 살펴보자.

1. MySuperAwesomeGame 클래스는 생성 시점에 창, 렌더링의 대상이 되고 이벤트를 수

신할 UI 컴포넌트, 창 및 입력 이벤트를 수신할 콜백, 메인 루프 스레드를 차례로 설정

한다. 끝으로 이 클래스는 MySuperAwesomeGame.getStartScreen() 메서드를 호출해

MySuperAwesomeStartScreen() 클래스 인스턴스를 반환한다.

2. MySuperAwesomeStartScreen 생성자에서는 디스크로부터 비트맵을 로드하고 이

를 멤버 변수에 저장한다. 이렇게 하고 나면 화면 설정이 모두 끝나고 제어가 다시

MySuperAwesomeGame 클래스로 넘어간다.

3. 이제 메인 루프 스레드는 방금 생성한 MySuperAwesomeStartScreen.update()와

MySuperAwesomeStartScreen.render() 메서드를 계속해서 호출한다.

4. MySuperAwesomeStartScreen.update() 메서드 내에서는 x라는 멤버 값을 매 프레임마

다 증가시킨다. 이 멤버 값에는 렌더링하려는 이미지의 x좌표가 들어 있다. x좌표가 100

보다 크면 값을 0으로 재설정한다.

5. MySuperAwesomeStar tScreen.render() 메서드에서는 프레임버퍼를 검은색

(0x00000000 = 0)으로 초기화하고 Pixmap을 (x, 0) 위치에 렌더링한다.

6. 메인 루프 스레드는 사용자가 기기의 뒤로가기 버튼을 눌러서 게임을 끝내기 전까지 3-5

단계를 반복한다. 사용자가 게임을 끝낼 경우 Game 인스턴스는 MySuperAwesome

StartScreen.dispose() 메서드를 호출해 Pixmap을 제거한다.

이로써 이 책의 첫 번째 게임을 살펴봤다! 이 게임에서 사용자가 볼 수 있는 내용은 이미지

가 화면 왼쪽에서 오른쪽으로 움직이는 게 전부다. 그다지 재미있는 사용자 경험은 아니지

만 이 부분은 나중에 계속해서 보완할 것이다. 안드로이드에서는 원하는 시간에 얼마든지 게

임을 일시 정지하거나 재개할 수 있다는 사실을 기억하자. MyAwesomeGame 구현체에서는

MySuperAwesomeStartScreen.pause()와 MySuperAwesomeStartScreen.resume() 메서드를

호출할 수 있다. 이 경우 메인 루프 스레드는 애플리케이션이 일시 정지된 동안 정지 상태를 유지

한다.

마지막으로 살펴볼 내용은 프레임 레이트 독립적인 움직임에 대한 것이다.

Page 142: 시작하세요! 안드로이드 게임 프로그래밍

116 l 시작하세요! 안드로이드 게임 프로그래밍

프레임 레이트 독립적인 움직임

사용자의 기기가 앞 절의 게임을 약 60FPS로 실행할 수 있다고 가정하자. 이 경우 매 프레임마다

MySuperAwesomeStartScreen.x를 1픽셀씩 움직이므로 Pixmap은 100프레임 동안 100픽셀만

큼 움직일 것이다. 60FPS의 프레임 레이트에서 이 위치(100, 0)에 도달하기까지는 대략 1.66초가

걸린다.

이번에는 또 다른 사용자가 다른 기기에서 이 게임을 플레이한다고 가정하자. 이 기기는 게

임을 30FPS로 플레이할 수 있다. 이 경우 매초마다 Pixmap는 30픽셀씩 움직이므로 앞의 위치

(100, 0)에 도달하기까지는 3.33초가 걸린다.

이런 결과는 바람직하지 않다. 물론 이렇게 간단한 게임에서는 사용자 경험에 미치는 영향이

없을 수도 있다. 하지만 Pixmap 대신 수퍼마리오가 있을 때 프레임 의존적인 방식으로 마리오

를 움직인다면 어떤 결과가 나올지 생각해 보자. 예를 들어 오른쪽 버튼을 누르고 있으면 마리오

가 오른쪽으로 뛴다고 가정하자. 매 프레임마다 마리오는 Pixmap과 마찬가지로 1픽셀만큼 움직

일 것이다. 이 경우 마리오는 60FPS로 게임을 실행할 수 있는 기기에서 30FPS로 게임을 실행하

는 기기보다 두 배 빠르게 달릴 수 있다. 이렇게 되면 기기 성능에 따라 사용자 경험이 전혀 달라

지게 된다. 이런 문제는 꼭 해결하고 넘어가야 한다.

이 문제에 대한 해결책을 프레임 독립적인 움직임이라고 부른다. Pixmap(또는 마리오)을 매

프레임마다 고정된 양만큼 움직이는 대신 초당 이동 속도를 지정하는 것이다. 예를 들어 매초당

Pixmap을 50픽셀만큼 움직여야 한다고 가정하자. 이때는 초당 50픽셀이라는 값 외에 마지막으

로 Pixmap을 움직인 후 얼마만큼의 시간이 흘렀는지에 대한 정보도 알아야 한다. 이를 위해 여

기서는 델타 시간을 사용한다. 델타 시간은 마지막 업데이트 이후 흐른 시간을 정확히 알려준다.

따라서 MySuperAwesomeStartScreen.update() 메서드의 코드는 다음과 같이 수정해야 한다.

@Override

public void update(float deltaTime) {

x += 50 * deltaTime;

if (x > 100)

x = 0;

}

게임이 60FPS로 일정하게 실행된다면 이 메서드에서 델타 시간은 항상 1/60 ~ 0.016초가 될

것이다. 따라서 매 프레임마다 캐릭터는 50×0.016 ~ 0.83픽셀만큼 움직여야 한다. 60FPS에서 60

×0.83 ~ 50픽셀만큼 움직이게 된다. 이번에는 30FPS를 테스트해보자. 50×1 / 30 ~ 1.66. 이를

Page 143: 시작하세요! 안드로이드 게임 프로그래밍

03 게임 개발 101 l 117

30FPS와 곱하면 이번에도 1초 동안 50픽셀만큼 움직이게 된다. 따라서 게임을 실행하는 기기의

속도와 상관없이 이제 애니메이션과 이동 거리는 실제 시계의 시간처럼 일정하게 움직이게 된다.

이를 실제로 앞의 코드에 적용해 보면 Pixmap은 60FPS에서 전혀 움직이지 않을 것이다. 이는

코드상의 버그 때문이다. 이를 찾아낼 수 있는 시간을 잠깐 주겠다. 이는 미묘한 버그이긴 하지만

게임 개발자들이 흔히 저지르는 실수이기도 하다. x 멤버는 매 프레임마다 실제 정수 값만큼 움

직인다. 0.83을 정수에 더하면 아무런 효과가 없다. 이런 문제를 해결하려면 int 대신 ¶oat으로 x

를 저장해야 한다. 이 말은 Graphics.drawPixmap()을 호출할 경우 int로 다시 형변환해야 함을

뜻한다.

알아두기

보통 안드로이드에서는 부동 소수점 연산이 정수 연산보다 느리지만 그 효과는 미미한 수준이

다. 따라서 여기서는 연산 부담이 좀 더 따르는 부동 소수점 연산을 사용해도 상관없다.

이로써 게임 프레임워크에 대한 내용까지 모두 살펴봤다. Mr. Nom의 화면 디자인은 이 프레임

워크의 클래스와 인터페이스로 직접 변환할 수 있다. 물론 아직 구현해야 할 세부 내용들이 남아

있지만 이런 내용은 다음 장으로 미루겠다. 지금은 이 장의 내용을 끝까지 읽었다는 것에 자부심

을 느끼기를 바란다. 이제 독자들은 안드로이드(및 다른 플랫폼의) 게임 개발자가 될 준비를 모

두 끝냈다.

정리

3장에서 빼곡한 내용과 끝없이 이어지는 정보를 통해 독자들은 게임 개발에 필요한 내용이 무엇

인지 전반적으로 이해할 수 있었다. 이 장에서는 안드로이드 마켓에서 가장 큰 인기를 얻는 게임

장르를 살펴보고 몇 가지 결론을 도출했다. 또 가위와 펜, 종이를 사용해 전체 게임을 처음부터

설계해 봤다. 끝으로 게임 개발의 다양한 이론적인 기반을 살펴보고 이런 이론적인 근거를 토대

로 이 책을 통해 계속해서 구현할 인터페이스의 추상 클래스를 생성해 봤다. 이 장에서 다룬 기

본 지식 중 더 깊이 알고 싶은 내용이 있다면 웹에서 관련 정보를 찾아보자. 이제 키워드는 독자

들의 손에 모두 쥐어졌다. 안정성이 뛰어난 고성능 게임을 개발할 때는 이런 기본 지식이 핵심이

된다. 이제 서론은 이쯤으로 하고 실제 안드로이드 게임 프레임워크를 구현해 보자.