본문 바로가기
프로그래밍/안드로이드

AndEngine - 5 - Drawing Lines

by 사악신 2011. 12. 2.

당분간 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 를 상속받고 있는 클래스들이 제법 많은데... 추후 계층도를 정리해볼 필요가 있어 보인다.(피곤해...) 실행하면 다음과 같이 출력된다.

 

반응형

댓글