libgdx는 크로스 플랫폼 게임 라이브러리로서 자바로 되어 있다. 일부분은 성능을 위해서 JNI를 통해 네이티브 바이너리를 사용한다.
하나의 코드로 데스크탑과 안드로이드 모두에서 돌릴 수 있도록 추상화 계층을 제공한다. 안드로이드 에뮬레이터가 엄청나게 느려터져서 테스트하기 힘든데, 데스크탑에서 실제로 돌려볼 수 있어서 상당히 편리할 것이다.
플랫폼에 상관 없이 같은 메인 코드를 사용하기 위해서 ApplicationListener 인터페이스를 구현한다. 이 인터페이스는 다음의 여섯 개 메소드로 이루어져 있다.
다른 메소드는 크게 중요하지 않고, render 메소드가 상태 업데이트 로직과 화면 출력 로직을 담당한다. 메소드들을 원하는대로 구현한 뒤, 플랫폼에 따라 다른 AndroidApplication, JoglApplication 등의 객체에 넘겨서 실제로 구동하게 된다.
앞으로 살펴볼 다른 기능에서도 마찬가지이지만, libgdx가 제공하는 API들은 Gdx 클래스의 스태틱 멤버 변수들을 통해 접근한다. (따라서 아무데서나 접근이 가능하다.) 리소스를 불러올 때는 Gdx.files 객체를 사용한다.
Gdx.files에는 여러가지 메소드가 있지만 주로 internal을 사용하게 될 것이다. 안드로이드에서는 assets 디렉토리, 데스크탑에서는 애플리케이션의 최상위 폴더에서 파일을 찾아서 FileHandle 객체를 돌려준다. FileHandle은 libgdx의 다른 API에서 리소스를 읽어오는 데에 쓰인다.
이미지는 Texture 객체로 관리되는데1), Texture 클래스의 생성자에 FileHandle을 넘겨 불러온다. 코드로 쓰면 다음과 같을 것이다.
Texture tex = new Texture(Gdx.files.internal("data/image.png"));
한 가지 아쉬운 점이라면 이미지의 너비와 높이가 각각 2의 n승이어야만 텍스쳐를 만들 수가 있다는 것인데, TexturePacker 유틸리티를 사용하여 이미지 하나에 우겨넣고 TextureAtlas 객체를 사용하여 불러오면 된다.
텍스쳐를 화면에 그릴 때는 SpriteBatch 객체를 사용한다. XNA나 DirectX의 그것과 상당히 유사하게 생긴 API로, 내부적으로는 OpenGL을 사용한다. 그렇기 때문에 Transform Matrix, Projection Matrix 등을 적용해서 3D 효과를 줄 수도 있겠다.
좌표계는 OpenGL을 따라서 화면 좌측 아래가 (0, 0)이고 우측 위가 (화면 너비, 화면 높이)가 된다. 하지만 행렬을 적당히 조작해서 경우에 따라서는 더 편한 좌표계로 바꿔서 사용해도 될 것이다.
SpriteBatch batch = new SpriteBatch(); batch.begin(); batch.draw(tex, X 좌표, Y 좌표, 0, // 소스 X 좌표 0, // 소스 Y 좌표 tex.getWidth(), // 소스 너비 tex.getHeight(), // 소스 높이, Color.WHITE // 오버레이 색깔 (흰색이면 그대로 출력) ); // ... 기타 draw 호출 ... batch.end();
이런 식으로 begin~end 사이에 draw 함수들을 호출하면 된다. draw 함수는 회전이나 크기 조정 등 추가 인수를 받도록 오버로딩 된 사용 방법도 있는데, 자세한 내용은 레퍼런스를 참조하길 바란다.
BitmapFont 클래스를 사용한다.
커스텀 글꼴 생성은 Hiero Font Editor를 사용한다. (버전 2는 작동하지 않음!)
앞서 SpriteBatch 클래스가 OpenGL을 쓴다고 했는데, 정확히는 OpenGL ES를 사용한다. GL ES는 임베디드 환경을 위한 3D 그래픽스 API인데, 기존 OpenGL과는 약간 차이가 있다. 데스크탑 PC에는 구현이 안되어 있지만 libgdx가 OpenGL API로 에뮬레이션을 해주기 때문에, 마음 놓고(?) GL ES를 갖다 쓰면 된다.
아니면 Mesh라는 고수준 클래스를 사용해도 된다. 하지만 3D는 잘 모르므로 자세히 설명은 못하겠다.
입력은 두 가지 방법으로 받아올 수 있다. 첫번째는 InputProcessor 인터페이스를 구현해서 이벤트 기반으로 처리하는 것이고, 두번째는 Gdx.input 객체에서 그냥 폴링하는 것이다. 쉽게 가기 위해 폴링 방식만 설명하겠다.
(멀티)터치 (또는, 마우스) 입력과 키보드 입력을 지원한다. 뭐, 근데 솔직히 안드로이드에서는 거의 터치만 쓸테니까 터치만 예제를 쓰겠다.
if (Gdx.input.isTouched()) { doSomething(Gdx.input.getX(), Gdx.input.getY()); }
아직 자세히 들여다보지 않았다 ㅠㅠ 그런데 보니까 오디오 분석 관련 클래스까지 있는 걸 보니 좀 짱인 듯?!
간단하게만 소개하고 넘어가겠다.
2차원 벡터 Vector2, 3차원 벡터 Vector3, 3x3 행렬 Matrix3, 4x4 행렬 Matrix4 등을 제공한다.
그런데 얘네들에 들어있는 함수(add, mul 등)가 자기 자신을 변형하는 식으로 동작하기 때문에 원하지 않게 값을 변경시키게 될 수가 있으므로 조심해야 한다. cpy 함수로 복사해서 쓰면 안전하다. 성능을 위해 불필요한 복사가 일어나는 것을 막으려고 한 것 같으니 용서해주자.
Intersector 클래스의 스태틱 함수들로 충돌을 검사할 수 있다. line-line, ray-bounding box, ray-plane, ray-sphere 등등 다양한 충돌 검사를 지원한다.
그리고 picking 같은 것도 지원한다.
(유명한) Box2D 물리 엔진을 내장하고 있다. 물론 자바 API로 돼있고.
GUI 위젯 모듈 (TWL), 파티클 엔진(!), 간단한 2D 씬 그래프 엔진, JSON 파서 등도 포함되어 있다.
Lonely Island가 libgdx로 만든 게임이다.