[[TableOfContents]]

= 스터디 소개 =
 * 그래픽스 엔진 등 공학적인 주제에 초점을 맞춤
 * RPG만들기 에뮬레이터 스마트폰 버전
 * 참고 위키: [http://ko.wikipedia.org/wiki/RPG_%EB%A7%8C%EB%93%A4%EA%B8%B0 RPG만들기 한글], [http://en.wikipedia.org/wiki/RPG_Maker_VX 영문]
 * ~~[http://www.jpct.net/ Java로 만든 3D 물리 엔진]으로 2D 엔진 만들기~~
 * 툴이 아닌 에뮬레이터 위주 
 * UDK로 뭔가 삽질 하다가 멘붕하고 선회한 스터디 -ㅅ-
== 참가자 ==
 * [권순의], [박재민], [박한기]

== 진행 시간 ==
 * 여름방학: 매 주 화, 목 저녁 7시 반 ~ 10시
 * 2학기: 매 주 목요일 오후 5시 이후

= 목표 =
 * 알피지 만들기(RPG Maker, 이하 알만툴)은 누구든지 손쉽게 바람의나라 같은 형식의 2D 롤플레잉 게임을 만들 수 있도록 도와주는 툴이다.

 요즘 한창 날리는 UDK(이쒸....)나, Unity같은 게임엔진과 딸려오는 툴과 같은 개념이다.

 현재 VX Ace버전까지 나와있으며 아직도 전세계에서 많은 이들이 알만툴로 게임을 만들고 있다.
 

 * PC에서 돌아가는 게임 엔진(런타임)은 있지만 요즘 대세인 모바일에서 돌릴 수 있는 런타임이 존재하지 않는다.

 따라서 이번 기회에 알만툴용 모바일 버전 엔진을 만들어 보려고 한다.


 * 제작 순서는 다음과 같이 진행하려고 한다.
 RPGMaker VX Version을 Java로 -> Android용으로 -> Windows용으로... (겨울 방학 끝날 때 쯤엔 완성 되겠지...)

 실질적으로 2단계서부터 모바일화가 진행되며 1단계가 가장 오래 걸릴 듯 싶다.

== 얻고 싶은 것 ==
 * 3D 그래픽스 지식 및 기본 그래픽스 개념
 * 리버스 엔지니어링 노하우
 * 모바일 프로그래밍
 * 게임 로직 및 흐름의 이해
 * 설계 패턴
 * 다양한 프로그래밍 언어의 습득(Java, Ruby, C# 등등..)
= 일정 기록 =
== 2012.07.26 ==
=== 한 것 ===
 * jpct 설치 및 RPG 만들기가 어떻게 생겨 먹은 놈인지 확인
 * jpct 튜토리얼 보고 따라 해 보기 - Hello World!

==== 프로젝트 설정 ====
 1. 이클립스 프로젝트 생성은 생략. 게다가 이미 [http://nforge.zeropage.org/projects/rma/code?viewfunc=browse svn repository]에 등록해놓았음

 1. [http://www.jpct.de/download/net/jpctapi.zip PC용 jPCT 엔진]을 받는다

 1. 받은 엔진 안에는 jpct에 해당하는 jpct.jar과 또다른 그래픽 라이브러리인 lwjgl이 있다. lwjgl.jar까지 라이브러리로 등록한다

 1. lwjgl.jar은 내부적으로 native 함수를 호출한다. 이 native함수는 dll파일에 담겨져 있는데 이클립스에서 Window -> preferences -> java/installed JREs 에서 vm 설정에 -Djava.library.path=D:\Workspace\rma\libs 형식으로 lwjgl.dll 또는 lwjgl64.dll의 폴더 경로를 입력함으로써 참조하게 한다. 이와 관련된 오류는 java.lang.UnsatisfiedLinkError이다.

==== 또다른 방법(2012.08.30) ====
 3. 이클립스 메뉴에서 window -> preferences -> java -> build_path -> user_libraries로 가면 유저 라이브러리를 등록할 수 있다.
 jPCT와 LWJGL을 등록하는데 둘이 묶어서 할 수도 있고 서로 다른 라이브러리로 등록해도 된다.
 lwjgl의 경우 참조하는 dll(안드로이드라면 so) 파일을 등록해야 하는데 이건 native library location에서 경로를 지정해주면 된다.

 4. 프로젝트 속성 -> java build path에서 방금 등록한 유저 라이브러리를 추가한다.

 (개인적으로 이게 더 깔끔한 방법인 것 같다)
=== 참고 ===
 * [http://ppparkje.tistory.com/entry/Java%EB%A5%BC-%EC%9C%84%ED%95%9C-3D-%EC%97%94%EC%A7%84-jPCT 재민이 블로그] - jpct 설치?에 대한 내용

== 2012.07.31 == 
=== 한 것 ===
 * 3D에서 정점, UV좌표, 삼각형의 표현에 대해 설명하고 실제로 객체를 제작해봄

 * 다음 스터디까지 과제로 오각형 만들어오삼
 
 * 파일 분석 정보를 기반으로 parser 제작 시작함. *.rvdata는 들어가는 정보의 종류는 다르지만 일정한 포맷이 있는듯함
 예상보다 파일분석은 빨리 끝날지도.

== 2012.08.02 == 
=== 한 것 ===
 * 과제 검사(FAIL) - 코딩에 앞서 엄밀한 수학 모델링을 먼저 해보는 것이 필요할듯

 * Actors 파일 해석법을 소개하고 다른 파일을 맛보기로 분석해봄

 * Actor를 읽어들이는 [http://wiki.zeropage.org/wiki.php/Code/RPGMaker#s-5 Actors.rvdata용 파일 파서] 제작 완료

== 뻘짓(2012.08.09) ==

 * 알만툴을 이해하기 위해 데이터베이스에 해당하는 *.rvdata를 뜯어봐야겠다 라는 생각을 초기에 했었지만
 곧 뻘짓임을 알았다 -_-;;

 .rvdata 파일은 단지 클래스들을 [http://www.ruby-doc.org/core-1.9.3/Marshal.html Marshal 모듈]을 이용하여 덤프한 내용을 기록한 것임을 알게 되었기 때문이다.

 게다가 알만툴에서 F1키 누르면 나오는 도움말에 Built-in 클래스나 모듈을 제외한 모든 자료구조(RPG::Actor, RPG::Map 등등..)의 소스가 오픈되어 있었다.

 * 따라서 파일분석은 곧바로 때려치고 루비스크립트로 각종 .rvdata들을 불러오는 작업을 시작했다.

== 2012.08.14 ==
=== 한 것 ===
 * built-in class제작 시작함
   워밍업으로 Font, Color 클래스 제작함
== 2012.08.23 ==
 * [박한기] 참가
=== 한 것 ===
 * 프로젝트 오리엔테이션 및 기초이론 소개
 * Audio 초기화 오류 문제 탐색
 * 그래픽이 잘리던 문제 탐색

== 2012.08.28 ==
=== 한 것 ===
 * 오디오는 여전히 말썽(...)
 * BufferedImage 클래스를 사용하여 글자를 출력하는 방법 학습

== 2012.09.07 ==
=== 한 것 ===

== 2012.09.13 == 
=== 한 것 ===
 * 글자의 정렬 구현
 * 프레임워크에서 비트맵과 스프라이트의 개념, uv좌표에 대한 과외(...)
 * ogg파일 출력
 * Tilemap ìž‘ì—…
 Tilemap은 loop이 있는 경우에는 좀더 머리를 써야할듯 싶다

== 2012.09.18 ==
 * 그래픽 엔진을 2D 라이브러리인 [http://slick.cokeandcode.com/ Slick2D]로 교체하고 작업중
  branch 주소 [http://nforge.zeropage.org/svn/rma/branches/slick_version]
  - 메모리 사용 퍼포먼스가 많이 좋아졌다.
  - 코드가 '많이' 간결해졌다.
 * 3D에서도 2D를 구현할 수 있음을 jPCT를 통해 충분히 보였고 이 이상의 작업은 3D지식을 필요로 하지 않기 때문에 3D구현은 여기서 끝내도 좋을 것이라 판단되었다.
= System =
== 게임 루프 ==
일반적인 싱글 스레드 게임의 경우 다음과 같은 큰 루프를 가진다.
{{{#!java
void run()
{
    initialize();
    while( !isGameEnded() )
    {
        logicUpdate();
        renderScene();
    }
    finish();
}
}}}

이 중에서 가장 많은 시간을 렌더링에 소모한다.

안드로이드에서 위 두개의 큰 함수를 같은 스레드에서 루프를 돌리는 것은 상당한 속도 저하가 발생할 수 있다.
따라서 logicUpdate() 함수와 renderScene() 함수를 서로 다른 스레드로 분리하는 것이 성능에도 도움이 되며 프로그램 설계상으로도 보기 좋다.


알만툴은 pc버전의 경우 싱글 스레드이다. 따라서 스레드를 분리하는 작업을 해 주어야 한다.
- [http://warmz.tistory.com/762 커맨드 패턴]을 사용할 예정.

= Graphics =
== 직교투영 렌더링 ==
 * jPCT에서는 명시적으로 Orthographic rendering(직교투영 렌더링)을 지원하지 않는다
   [http://www.jpct.net/forum2/index.php/topic,1789.msg13175.html#msg13175]
   따라서 근사적으로라로 직교투영을 만든다

 * 근사 직교투영 좌표계 만들기 : [http://blog.jidolstar.com/826 안드로이드 jPCT-AE로 (근사) 직교투영(Orthogonal Projection) 실현하기]
   한줄요약: 카메라를 겁나 멀리 갖다두면 근사적으로 직교투영이 됨ㅋ

 * [http://wiki.zeropage.org/wiki.php/Code/RPGMaker?action=show#s-1 실제 구현 코드]

=== ë³´ì •(Interpolation) ===
 * 이를 이용하면 직교투영 좌표가 된 것처럼 보이긴 하지만 depth에 해당하는 z값이 바뀌면 조금이라도 오차가 생기기 때문에 이를 보정하여야 한다
   특히 렌더링 순서를 z값을 조정함으로 결정시키기 때문에 정확한 렌더링을 위해서는 보정 테크닉을 아는 것이 필수이다.
attachment:projection.png
 * 위 그림에서 볼 수 있듯이 실제 Object의 중점과 사람이 느끼는 Object의 위치는 다르다. 크기 역시 마찬가지이다.
   만약 위 그림처럼 Object가 스크린에서 delta만큼 떨어져 있다면 간단한 비례식으로 (length-delta)/length 만큼 크기가 조정되어야 한다

   중심의 이동은 Object의 중심을 O, Projection의 중심을 P라고 할 때 벡터 PO만큼을 이동시키면 된다. 벡터 PO는 카메라 위치와 Object 중심을 잇는 직선의 연장선상에 있다는 것을 생각하면 계산이 간편해진다.

 * [http://wiki.zeropage.org/wiki.php/Code/RPGMaker#s-4 interpolation 구현 코드]
 
== 오브젝트 그리기 ==

=== 삼각형 ===
 * 모든 도형의 기초가 되는 도형이다. 모든 도형은 삼각형만으로 구성할 수 있고 또 쪼갤 수 있다.

 * jpct에서 텍스쳐 있는 삼각형을 그리기 위해 필요한 정보는 다음과 같다

  * 정점(vertex, 꼭지점) : 삼각형은 서로 다른 3개의 한 직선 위에 있지 않은 정점들로 구성된다.

  * uv좌표 : 텍스쳐가 매핑되는 좌표계를 설정한다. (0, 0)부터 (1, 1)까지의 좌표에 텍스쳐 하나가 들어가게 된다
  텍스쳐에 대해서는 나중에 할 말이 있을것.

  * 정점들을 잇는 순서 : 이 순서에 따라 삼각형의 보이는 면과 보이지 않는 면이 결정된다. 
  다른 곳은 잘 모르겠으나 openGL에서는 오른나사의 법칙에 따라 엄지가 가리키는 방향의 면이 보이는 면이다.
  [http://niceyth.springnote.com/pages/3165274 CCW 판별 알고리즘]을 이용해서 순서를 하드코딩하지 않고 자동으로 계산하게 할 수도 있다.

  * Texture : 도형을 색칠하기 위한 정보가 들어있는 2차원 정사각형이라고 생각해도 좋다. 한 변의 길이는 속도를 위해 2의 제곱수여야 한다.
=== 직사각형(FillRect) 그리기 ===
 * 왼쪽 위, 오른쪽 아래 좌표만 알면 그릴 수 있다.
 * 사각형은 2개의 삼각형으로 구성된다.
 * [http://wiki.zeropage.org/wiki.php/Code/RPGMaker?action=show#s-2 실제 구현]

=== 직선(Line) 그리기 ===
 * 직선도 실제로는 너비를 가져야 렌더링이 가능하기 때문에 다음과 같은 구조를 가져야 한다
attachment:line.png

 * vLine = vEnd - vStart
 * normal(vLine과 수직인 벡터) = vLine × (-z방향 벡터) -> normalize하여 길이가 1인 벡터로 만듦.
 * (u1, v1)과 (u1, v2)는 vStart ± (normal/2)
 * (u2, v1)과 (u2, v2)는 vEnd ± (normal/2)
 * [http://wiki.zeropage.org/wiki.php/Code/RPGMaker?action=show#s-3 실제 구현]

== Viewport ==
뷰포트는 일종의 창이라고 할 수 있다. 




attachment:viewport.png

운영체제 윈도우의 개념을 생각하면 편한데, 각 윈도우의 영역을 벗어나는 그래픽 조작은 철저히 차단된다. 이 차단하는 과정을 그래픽스에서는 '''clipping'''이라 한다.

jPCT에서는 FrameBuffer에서 setClippingPlane 함수를 통해 클리핑을 지원하므로 이와 적절한 카메라 조작으로 뷰포트를 구현할 수 있었다.

아래는 실제 구현 화면이다.




attachment:viewportTest.png

위 사진에서는 가운데 아래쪽 윈도우가 뷰포트이다. 윈도우를 가로지르는 굵은 선을 출력했으나 뷰포트 바깥으로는 나가지 않는걸 확인할 수 있다.

== 그래픽 엔진의 구조 ==
※ 이 설계는 변할 수 있음

현재 제작중인 그래픽 엔진의 구조는 크게 두 부분으로 나눌 수 있으며 다음과 같다.
attachment:structure.png

인터페이스 IDrawable 하위 클래스들은 jPCT의 Object3D 객체를 포함하고 있으며 특히 RMPolygon 및 하위 클래스는 내부에 여러개의 IDrawable을 가질 수 있다.

또한 Viewport는 화면의 일부분만을 보여줄 수 있는 클래스로서 IDrawable을 포함할 수 있으며, Sprite, Window 등의 클래스의 슈퍼클래스이다.

가방 안에 가방을 또 넣는 것처럼 뷰포트 안에 또 뷰포트가 들어갈 수 있으며(트리 구조 가능), 최상위 뷰포트는 화면 전체를 아우르는 크기를 갖는다.
= RPG Maker VX 분석 =

알만툴로 만든 게임은 크게 세 부분으로 되어 있다.

 * 게임의 메인 로직을 담당하는 스크립트(루비로 작성됨)
 * 캐릭터 정보, 아이템 정보, 스킬 정보 등의 리소스 부분(파일로 저장되어 있음)
 * 그래픽, 사운드 등 게임의 엔진에 해당하는 부분

.. 이러고보니 철저히 MVC 패턴을 준수한다고 볼 수 있겠다.

알만툴에서는 메인 로직을 수정할 수 있는 스크립트 에디터를 제공함으로 게임 제작에 유연성을 더한다.

툴이 RPG에 최적화된 환경일 뿐이지, 슈팅이나 횡스크롤 게임 등도 얼마든지 만들 수 있다. ~~대신 알만툴의 기능이 쓸모없어질 뿐.~~
== 데이터베이스(리소스) ==
 * 알만툴에서 데이터베이스에 해당하는 .rvdata 파일은 루비 클래스를 덤프한 내용을 기록한 것이다.
 이를 불러오고 저장하는 load_data함수와 save_data함수를 도움말에서 제공하고 있다.

{{{#!vim ruby
def load_data filename
  File.open(filename, "rb") { |f|
    obj = Marshal.load(f)
    return obj
  }
end

def save_data filename, obj
  File.open(filename, "wb") { |f|
    Marshal.dump(obj, f)
  }
end
}}}

== 게임의 메인 로직(스크립트) ==

알만툴에서 F11을 누르면 나오는 스크립트는 게임이 어떻게 진행되는지에 관련된 내용이 담겨 있다.

하지만 우리가 제작하려는 것은 게임 콘텐츠가 아닌 에뮬레이터이기 때문에 구현 참고용으로만 사용할 계획이다.

에뮬레이터에서 메인로직과 관련해 할 일은 단지 메인 로직을 불러주는 일뿐이다.


=== Java에서 루비스크립트 실행하기 ===

 1. [http://jruby.org/download JRuby 홈페이지]에서 JRuby를 설치한다. 64bit OS에서도 32비트 전용으로 설치해야 돌아가는듯 하다.

 2. JRuby설치경로/lib 에 위치한 jruby.jar파일을 프로젝트 라이브러리 폴더에 넣는다.

 3. 이클립스에서 .jar파일 오른쪽 클릭 메뉴에서 build path->add to build path로 등록한다.

 4. 간단하게 코딩한다.
    아래 코드는 프로젝트 내에서 src/ruby/main.rb 파일을 호출하는 코드.
{{{#!vim ruby

	public static void main(String[] args) throws IOException, ScriptException
	{
		ScriptEngine rbEngine = new ScriptEngineManager().getEngineByName("jruby");
		
		// start rubyscript
		rbEngine.eval(new FileReader("src/ruby/main.rb"));
	}
}}}
== 코어(엔진) ==

메인 로직을 보면 각종 그래픽 처리, 입력 처리, 자료구조 등은 따로 제작된 모듈을 사용하는 것을 볼 수 있다.

도움말을 보면 대부분의 게임 내에서 사용하는 이러한 클래스에 대한 명세를 제공하고 있다.

하지만 실제 구현에 대한 소스코드를 제공하지 않기 때문에 '''이런 Built-in 클래스와 모듈은 명세만 보고 직접 구현해야 한다'''.

예제: [http://wiki.zeropage.org/wiki.php/Code/RPGMaker?action=show#s-5 Table 클래스의 구현]
===  JRuby에서 자바 클래스의 사용 ===
 그낭 루비가 아닌 자바로 구현된 JRuby의 경우 루비스크립트 내에서 자바 클래스들을 사용할 수 있다.

 사용방법은 간단한다. 스크립트 상단에 '''require "java"'''를 명시하고, 각종 클래스들을 import하거나 패키지 이름을 모조리 명시하면 자바클래스를 그대로 사용할 수 있다.

 * 예제: [http://wiki.zeropage.org/wiki.php/Code/RPGMaker?action=show#s-6 Color 클래스의 구현]

=== 직접 구현해야 하는 클래스/모듈 목록 ===
* Built-in class
 * Bitmap: 이미지 데이터가 저장되는 클래스
 * Color: 색상 정보(RGBA)를 가지고 있는 클래스
 * Font: 글꼴 정보를 가지고 있는 클래스. .ttf파일을 지원해야 한다.
 * Plane: 이미지가 표시되는 평면 클래스. 이미지가 타일형으로 반복표시된다.
 * Rect: top-left 코너와 너비, 높이 정보를 가지는 클래스.
 * Sprite: Bitmap의 표현이 이루어지는 클래스.
 * Table: 3차원 배열 클래스.
 * Tilemap: 맵의 표시와 관련된 클래스(?)
 * Tone: 이미지의 색상보정을 위한 클래스(?)
 * Viewport: 2D상의 뷰포트를 구현한 클래스
 * Window: 알만툴 내부에서의 윈도우 표시를 담당하는 클래스.
 * RGSSError: 에러처리 클래스. StandardError클래스를 상속함

* Built-in module
 * [http://wiki.zeropage.org/wiki.php/RPGMaker/2012%EB%85%84%EC%8A%A4%ED%84%B0%EB%94%94?action=show#s-5.4 Audio]: 오디오 출력을 담당하는 모듈
 * [http://wiki.zeropage.org/wiki.php/RPGMaker/2012%EB%85%84%EC%8A%A4%ED%84%B0%EB%94%94?action=show#s-4 Graphics]: 그래픽 출력을 담당하는 모듈
 * Input: 유저의 입력(키보드)를 담당하는 모듈
 * RPG: 알만툴의 각종 자료구조들을 담고 있는 모듈
== Audio ==
=== 나와라 소리야 ===
 * [http://www.lwjgl.org/wiki/index.php?title=Main_Page Audio를 위한 Java OpenAL 튜토리얼]
 * .wav파일을 불러 오는 것이 다인데 문제는 사용해야 할 파일들이 midi 아님 ogg 파일 <- 코덱이 있어야 한다나 -ㅅ-
  * [http://blog.naver.com/PostView.nhn?blogId=harkon&logNo=120094059408&parentCategoryNo=7&viewDate=&currentPage=1&listtype=0 참고 1]
  * [http://lwjgl.org/forum/index.php?topic=191.0 참고 2]
  * [http://www.java2s.com/Open-Source/Android/Game/libgdx/com/badlogic/gdx/backends/openal/Mp3.java.htm 참고 3?]

  * OGG 파일을 사용하기 위해선 [http://www.lwjgl.org/wiki/index.php?title=Slick-Util_Library_-_Part_2_-_Loading_Sounds_for_LWJGL Loading Sound]에서 말하길 Slick-Util zip을 받아 라이브러리에 추가하라고 함... 그럼 된다나..
   * [https://bitbucket.org/kevglass/slick/src/tip/trunk/Slick/lib/ 다운로드]
   * jorbis-*.jar 과 jogg-*.jar library jar files 를 classpath 에 넣어야 하는데 그게 Slick-Util zip 있다고..

 * 파일이 재생이 안 됨
  * 박재민: [http://lwjgl.org/forum/index.php/topic,3606.0.html 이 링크]가 재생오류시 도움이 될듯.. 
{{{#!vim ruby
public void bgm_start(String filename, int volume, double pitch) {
	// Initialize OpenAL and clear the error bit.
	try {
		AL.create();
	} catch (LWJGLException le) {
		le.printStackTrace();
		return;
	}
	AL10.alGetError();

	// Load the wav data.
	if (loadALData("test") == AL10.AL_FALSE) {
		System.out.println("Error loading data.");
		return;
	}

	setListenerValues();

	AL10.alSourcePlay(source.get(0));
		
	killALData();
	AL.destroy();
}
}}}
  * 맨 마지막 함수 killALData() 함수와 AL.destroy()가 실행하자마자 종료시킴.. 주석처리 하니까 소리는 나옴 -_-

=== 여러 개 소리가 같이 날 수 있게 만들긔 ===
 * [http://slick.cokeandcode.com/javadoc-util/org/newdawn/slick/openal/Audio.html 오디오 라이브러리]에 playAsSoundEffect()를 여러번 호출하면 여러번 음악 파일이 실행되는 것을 확인 함. 

{{{#!vim ruby
try {	    
        // you can play wavs by loading the complete thing into 
	// a sound
	wavEffect = AudioLoader.getAudio("WAV", ResourceLoader.getResourceAsStream("sound/Test.wav"));
} catch (IOException e) {
	e.printStackTrace();
}

while (Keyboard.next()) {
	if (Keyboard.getEventKeyState()) {
		if (Keyboard.getEventKey() == Keyboard.KEY_T) {
			// play as a one off sound effect
			wavEffect.playAsSoundEffect(1.0f, 1.0f, false);
		}
		if (Keyboard.getEventKey() == Keyboard.KEY_G) {
			wavEffect.stop();
		}
	}
}
}}}
 * 위와 같은 방식으로 키보드를 통한 음악 실행과 정지가 가능하다....
  * 근데 이렇게 하고 보니 기존에 했던 코드가 아무짝에도 쓸모 없다는 사실을 알았다. -_-;

{{{#!vim ruby
public void init(InputStream filename) {
       	   
	try {
	    	// you can play oggs by loading the complete thing into 
		// a sound
		oggEffect = AudioLoader.getAudio("OGG", filename); // java.lang.ArithmeticException: / by zero
		oggEffect.playAsSoundEffect(1.0f, 1.0f, false);
	} catch (IOException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}	
	    
	// polling is required to allow streaming to get a chance to
	// queue buffers.
	SoundStore.get().poll(0);
}	
}}}
 * 왜 저기서 0으로 나눠서 문제가 된다는거지???????
 박재민: 좀더 검색해보니까 '''길이가 짧은 스테레오 ogg파일'''은 문제가 있는듯 보임. 모노로 변환해보니깐 되더라;;
  * 난 안됨 -_- - [권순의]

{{{#!vim ruby
public void init(InputStream filename) {

    	URL file = null;
	try {
		file = new URL(filename);
	} catch (MalformedURLException e1) {
		// TODO Auto-generated catch block
		e1.printStackTrace();
	}
       	   
	 try {
	    	// you can play oggs by loading the complete thing into 
		    // a sound
			oggStream = AudioLoader.getStreamingAudio("OGG", file);
			oggStream.playAsMusic(1.0f, 1.0f, true);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	
	    
	// polling is required to allow streaming to get a chance to
	// queue buffers.
	SoundStore.get().poll(0);
}	
}}}
 * 위와 같이 바꾸었을 경우 getStreamingAudio()에 들어가는 인자가 String, String이 될 수 없고 URL로 바꾸어 주어야 함. 그래서 소리가 날 까 했는데 no protocol: assets/rpgvx_resources/Audio/SE/Cursor.ogg 이라는 아름다운 문자를 날려줌. -ㅅ-...
  * 이 경우 file = new URL(filename); 를 file = new URL("file://" + filename);로 바꾸어 주면 소리가 날 것 처럼 사람들이 써 놨으나 실패. 그래서 절대 경로를 모두 적어주었지만 역시나 파일을 읽는데 실패했다.

{{{#!vim ruby
public void init(InputStream filename) {

    	try {
	    // you can play oggs by loading the complete thing into 
	    // a sound
		oggStream = AudioLoader.getStreamingAudio("OGG", ResourceLoader.getResource(filename));
		oggStream.playAsMusic(1.0f, 1.0f, true);
	} catch (IOException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}		
	    
	// polling is required to allow streaming to get a chance to
	// queue buffers.
	SoundStore.get().poll(0);
}	
}}}
 * Test로 실행이 되었던 소스였으나, 여기선 java.io.BufferedInputStream.read(Unknown Source)라며 즐을 날려 준다 -_-.... 아니 왜!!!
  * 맨 위 처음 Test한 방법과 같은 방법으로 시도 해 보았으나 소리가 안 나서 멘붕하고 있음

= Porting to Android =
※ 공사중
== Project setup ==
pc와 안드로이드는 다른 환경이다. 자바라는 언어가 플랫폼간의 이질성을 초월하는 언어라고는 하지만, 어느 정도는 native한 기능들도 있기 때문에 그에 맞추어 환경을 설정해야 한다.

=== ADT plugin setup ===
 * 이클립스에서 help - install new software로 가서 업데이트 사이트에 '''http://dl-ssl.google.com/android/eclipse/''' 를 입력하면 가능한 업데이트 목록이 나온다.

 * 나오는 목록들 중에 Developer tools - '''Android DDMS''', '''Android development tools'''를 선택한 뒤 설치를 진행한다.

 * 이클립스를 재부팅하면 '''Android SDK'''를 설치할 거냐고 묻는 경우가 있는데, 설치해야 한다.

=== Slick-AE 빌드 ===
Slick2D의 안드로이드 버전인 slick-ae는 따로 jar파일이 제공되지 않는다. 따라서 직접 빌드를 해야 한다.(또는 내가 빌드한 jar을 활용해도 된다)

 * slick은 [http://mercurial.selenic.com/ Mercurial(HG)]로 버전관리를 하기 때문에 미리 Mercurial을 설치한다.

 * ![hg clone https://bitbucket.org/kevglass/slick] 명령으로 slick의 전체 코드를 다운받는다.

 * 이클립스에서 slick의 코드들 중 Slick과 Slick-AE만 각각 프로젝트로 import한다.

 * 빌드하기 전에 '''[http://libgdx.badlogicgames.com/ libgdx]'''를 [http://code.google.com/p/libgdx/downloads/list 최신버전]으로(여기서는 0.9.6) 바꿔야 하는데, 버전이 올라가면서 InputProcessor부분에 인터페이스가 바뀐 부분이 있어 그부분을 새로 고쳐주어야 한다.
 touchUp, touchDown함수는 있는 것을 사용하고, scrolled와 touchMoved 역시 비슷하게 구현해 주자.

 * 이클립스의 package explorer에 보면 Slick-AE에 build.xml이 있다. 이것을 실행하면 빌드가 수행되며, target폴더에 slick-ae.jar 파일이 생성된다.
=== 안드로이드 프로젝트 생성 ===
 * 안드로이드 환경에서 루비스크립트를 실행하기 위해서는 [http://ruboto.org ruboto]라는 프레임워크가 필요하다.
 내부적으로 JRuby를 사용하고 있기 때문에 우리 프로젝트와도 잘 맞는 프레임워크라 할 수 있다.

 [https://github.com/ruboto/ruboto/wiki/Getting-started-with-Ruboto 컴퓨터에 ruboto 세팅하기]
 ※ ruboto를 설치/빌드하기 위해서는 JRuby(또는 그냥 Ruby), Ant(자바용 make)가 필요하다.
 
 * 모든 세팅이 완료된 후 커맨드라인에서 '''ruboto gen app --package <애플리케이션 패키지 이름>''' 으로 앱을 생성하면 알아서 템플릿을 만들어준다.
 그 뒤 생성된 폴더로 가서 '''rake install start'''를 하면 바로 컴파일을 하고 폰으로 옮겨 실행까지 해줘서(...) 디버깅이 가능해진다.

 attachment:ruboto-sample-screenshot.png?width=200 attachment:ruboto-sample-screenshot2.png?width=200 
 기본 앱을 실행한 화면, ruboto가 동작하기 위해서는 마켓에서 [https://play.google.com/store/apps/details?id=org.ruboto.core ruboto-core]을 설치해야 한다. 
 왼쪽 그림에서 이미지를 누르면 ruboto-core을 받을 수 있는 마켓으로 이동한다.
 오른쪽 그림은 core을 설치한 뒤 제대로 실행되는 앱의 모습이다.

== 안드로이드의 OpenGL ==
안드로이드에서는 OpenGL의 경량화 버전인 OpenGL-ES 1.x버전을 지원한다. 일부 기기에서는 2.0이 지원된다.
(하지만 두 버전은 서로 호환이 되지 않는다;)

안드로이드 Activity상에서 OpenGL을 사용하기 위해서는 [http://developer.android.com/reference/android/opengl/GLSurfaceView.html GLSurfaceView]를 사용해야 한다.
다행히도 ruboto wiki에 이 GLSurfaceView을 사용하는 [https://gist.github.com/723691 예제]가 있다. 앞으로 이를 분석하여 응용할 계획이다.

== Rendering Loop == 
기존 slick의 경우 다음과 같은 렌더링 루프를 가진다.

주요 함수는 init()과 updateAndRender() 함수인데 불리는 위치가 pc버전과 안드로이드 버전이 상이하다.

{{{#!vim java
public void start()
{
    init();
    while(running())
        gameLoop();
    finish();
}

protected void gameLoop()
{
    updateAndRender();
}
}}}

단일 스레드이다.

하지만 안드로이드에서는 여러 스레드가 존재한다.

UI 스레드가 있으며, OpenGL을 위한 GL스레드도 있다.

{{{#!vim java
public void start()
{
    init();
    startGLThread();
}

...

protected void inThread()
{
    while(running())
        onDrawFrame();
}

public void onDrawFrame(GL10 gl)
{
    updateAndRender(gl);
}
}}}

구조가 약간 다르기 때문에 조금 혼돈이 오고있다(...)


결국 렌더링 스레드와 로직 스레드가 분리된 방식으로 돌아가야 하는데 지금 프로그램 구조는 두 작업이 하나의 스레드로 수행되고 있다.

이를 고칠 수 있는 방안을 강구해야 한다.
----
[2012년활동지도]