당분간 AndEngine Examples 에 있는 예제 소스들을 하나하나 살펴볼 생각인데, 관련 프로젝트를 계속해서 생성하는 것 보다 기존 샘플 프로젝트(2011/12/01 - [프로그래밍/안드로이드] - AndEngine - 2 - 샘플 프로젝트 생성)를 수정하고 지우는 식으로 테스트해볼까한다.
사실, 이렇게 블로그에 포스팅하는 것은 누군가를 가르치기 위한~ 거창한 목표 때문이 아니고, 일종의 호사스런 학습일지라고보면 된다. 그 말인 즉슨~ 자바도 잘 모르고, 안드로이드도 잘 모르고 심지어 OpenGL 도 잘 모른다는 뭐 그런 얘기다.(내 전공은 Object Pascal & VCL...)
일단, Jude Community 등을 통하여 AndEngine 의 자바소스들을 Import 하여 클래스 다이어그램을 뽑아보며 전체 구조를 살펴보고 있는데... 어떤 프로그램이든 항상 분석은 Entry Point 에서 시작하는데 안드로이드 앱의 경우 특별한 Entry Point 가 존재하지 않고, Activity 들 중 하나를 런처에 연결하는 식인 것으로 보인다. 그리고 공식홈페이지에서 찾은 Activity 의 Life Cycle...
(http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle)
앱이 기동하면서 호출되는 이벤트들이니까. 일단 머릿속에 갈무리하고~ 이 Activity 를 상속받은 AndEngine 의 Activity 소스를 살펴보면 될 것이다. 그리하여 패키지 org.anddev.andengine.ui 의 클래스 다이어그램은 다음과 같다.
주목할 놈은 BaseGameActivity 이고, Override 한 Activity 메소드는, onCreate(), onResume(), onPause(), onDestory() 네가지이다.
onCreate() 에서 OnLoadEngine() 을 호출하여 Engine 클래스의 인스턴스를 받아오는 것을 알 수 있다.
@Override
protected void onCreate(final Bundle pSavedInstanceState) {
super.onCreate(pSavedInstanceState);
this.mPaused = true;
this.mEngine = this.onLoadEngine();
this.applyEngineOptions(this.mEngine.getEngineOptions());
this.onSetContentView();
}
onResume() 에서 doResume() 을 호출하고, 이때 처음 게임을 로드할때 리소스와 Scene 클래스의 인스턴스를 받아오는 것을 알 수 있다.
private void doResume() {
if(!this.mGameLoaded) {
this.onLoadResources();final Scene scene = this.onLoadScene();this.mEngine.onLoadComplete(scene);
this.onLoadComplete();this.mGameLoaded = true;
}
this.mPaused = false;
this.acquireWakeLock(this.mEngine.getEngineOptions().getWakeLockOptions());
this.mEngine.onResume();
this.mRenderSurfaceView.onResume();
this.mEngine.start();
this.onResumeGame();}
onPause() 의 경우 doPause() 를 호출한다.
private void doPause() {
this.mPaused = true;
this.releaseWakeLock();
this.mEngine.onPause();
this.mEngine.stop();
this.mRenderSurfaceView.onPause();
this.onPauseGame();}
끝으로 onDestroy() 의 소스
@Override
protected void onDestroy() {
super.onDestroy();
this.mEngine.interruptUpdateThread();
this.onUnloadResources();
}
붉은색 표기한 것은 모두 IGameInerface 의 메소드이다. 일단, BaseGameActivity 는 추상 클래스이므로 자바에서는 인스턴스화 할 수 없다.(싸랑하는~ 오브젝트 파스칼에선 가능한 일~) 따라서 실제 작업시엔 이 BaseGameActivity 를 상속받은 후, 추상 메소드 및 인터페이스의 메소드들 중 미구현 된 녀석들을 Overrride 또는 구현해 주어야한다.
재미난 것은 추상 클래스인 BaseGameActivity 에서 abstract 메소드는 존재하지 않는다. 대신 abstract 메소드에 해당 하는 녀석들을 묶어서 IGameInterface 로 빼낸 느낌이 들었다.(요런 설계 살펴보는 걸 좋아한다. 캬캬~ 아, 그러고보니 주석의 코멘트를 보니 Zynga 에서 AndEngine 을 관리하는 것으로 보였다. 대박)
자자, 기본적인 것은 파악된 거 같고 이제 원래 목적인 Line Example 을 살펴봐야겠다.
일단, onLoadEngine(), onLoadResources(), onLoadScene(), onLoadComplete() 를 구현하였고 이 중 실제 코드가 존재하는 메소드는 onLoadEngine() 과 onLoadScene() 이 두 놈이다.
@Override
public Engine onLoadEngine() {
this.mCamera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
return new Engine(new EngineOptions(true, ScreenOrientation.LANDSCAPE, new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), this.mCamera));
}
@Override
public Scene onLoadScene() {
this.mEngine.registerUpdateHandler(new FPSLogger());
final Scene scene = new Scene();
scene.setBackground(new ColorBackground(0.09804f, 0.6274f, 0.8784f));
final Random random = new Random(RANDOM_SEED);
for(int i = 0; i < LINE_COUNT; i++) {
final float x1 = random.nextFloat() * CAMERA_WIDTH;
final float x2 = random.nextFloat() * CAMERA_WIDTH;
final float y1 = random.nextFloat() * CAMERA_HEIGHT;
final float y2 = random.nextFloat() * CAMERA_HEIGHT;
final float lineWidth = random.nextFloat() * 5;
final Line line = new Line(x1, y1, x2, y2, lineWidth);
line.setColor(random.nextFloat(), random.nextFloat(), random.nextFloat());
scene.attachChild(line);
}
return scene;
}
일단 눈에 띄는 클래스들을 붉은색 표기하였다. 그리고 핵심인 Engine 의 생성 부분을 살펴보면~
Engine 의 생성자
public Engine(final EngineOptions pEngineOptions)
EngineOptions 의 생성자
public EngineOptions(final boolean pFullscreen, final ScreenOrientation pScreenOrientation, final IResolutionPolicy pResolutionPolicy, final Camera pCamera)
pFullscreen: true 또는 false
ScreenOrientation: enum 형으로 LANDSCAPE 또는 PORTRAIT
IResolutionPolicy: 아래 다이어그램 참고. 해상도와 관련한 것으로 파악되는데 클래스명으로 유추해볼때 비율, 고정, 상대 등...
Camera: 아래 다이어그램 참고
으어~ 이렇게 가다가는 포스팅하다가 지치겠는데...;; 사실 소스들의 내용은 그다지 어려워보이지 않는다. 전체 소스는 다음과 같으며 나머지 클래스들에 대한 분석은 후에 좀 더 자세히 살펴봐야겠다.
package kr.logy.code.AESample1;
import java.util.Random;
import org.anddev.andengine.engine.Engine;
import org.anddev.andengine.engine.camera.Camera;
import org.anddev.andengine.engine.options.EngineOptions;
import org.anddev.andengine.engine.options.EngineOptions.ScreenOrientation;
import org.anddev.andengine.engine.options.resolutionpolicy.RatioResolutionPolicy;
import org.anddev.andengine.entity.primitive.Line;
import org.anddev.andengine.entity.scene.Scene;
import org.anddev.andengine.entity.scene.background.ColorBackground;
import org.anddev.andengine.entity.util.FPSLogger;
import org.anddev.andengine.ui.activity.BaseGameActivity;
public class AESample1Activity extends BaseGameActivity {
private Camera mCamera;
private static final long RANDOM_SEED = 1234567890;
private static final int CAMERA_WIDTH = 720;
private static final int CAMERA_HEIGHT = 480;
private static final int LINE_COUNT = 100;
@Override
public void onLoadComplete() {
}
@Override
public Engine onLoadEngine() {
this.mCamera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
return new Engine(new EngineOptions(true, ScreenOrientation.LANDSCAPE, new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), this.mCamera));
}
@Override
public void onLoadResources() {
// TODO Auto-generated method stub
}
@Override
public Scene onLoadScene() {
this.mEngine.registerUpdateHandler(new FPSLogger());
final Scene scene = new Scene();
scene.setBackground(new ColorBackground(0.09804f, 0.6274f, 0.8784f));
final Random random = new Random(RANDOM_SEED);
for(int i = 0; i < LINE_COUNT; i++) {
final float x1 = random.nextFloat() * CAMERA_WIDTH;
final float x2 = random.nextFloat() * CAMERA_WIDTH;
final float y1 = random.nextFloat() * CAMERA_HEIGHT;
final float y2 = random.nextFloat() * CAMERA_HEIGHT;
final float lineWidth = random.nextFloat() * 5;
final Line line = new Line(x1, y1, x2, y2, lineWidth);
line.setColor(random.nextFloat(), random.nextFloat(), random.nextFloat());
scene.attachChild(line);
}
return scene;
}
}
Scene 클래스의 인스턴스를 생성하고 Line 클래스의 인스턴스를 해당 씬에 추가해준다. 이때 attachChild() 메소드의 파라미터로 IEntity 가 사용된다. 물론, Line 클래스는 IEntity 를 상속하고있다. 이 IEntity 를 상속받고 있는 클래스들이 제법 많은데... 추후 계층도를 정리해볼 필요가 있어 보인다.(피곤해...) 실행하면 다음과 같이 출력된다.
'프로그래밍 > 안드로이드' 카테고리의 다른 글
AndEngine - 7 - Drawing a Sprite (0) | 2011.12.12 |
---|---|
AndEngine - 6 - Drawing Rectangles (0) | 2011.12.06 |
AndEngine - 4 - Examples (1) | 2011.12.01 |
AndEngine - 3 - Extensions 추가하기 (0) | 2011.12.01 |
AndEngine - 2 - 샘플 프로젝트 생성 (0) | 2011.12.01 |
댓글