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

AndEngine - 7 - Drawing a Sprite

by 사악신 2011. 12. 12.

스프라이트를 출력하는 예제인데 기존 AndEngine-Example 에서 이미지를 가져와 사용한다. assets 디렉토리 아래 gfx 디렉토리(다른 이름이어도 상관없다.)를 생성한 후 face_box.png 이미지를 복사하여 넣는다.

 

Activity 의 onResume() 이 호출될 때, 즉, 최초 실행시 this.mGameLoaded 가 false 일때 onLoadResources() 메소드와 onLoadScene() 메소드가 호출된다. 이 메소드에서 스프라이트를 불러오는 작업을 처리한다. 먼저, 이전 사각형을 그리던 소스의 onLoadScene() 메소드와의 차이점을 살펴보자.

@Override
public Scene onLoadScene() {
  this.mEngine.registerUpdateHandler(new FPSLogger());

  final Scene scene = new Scene();
  scene.setBackground(new ColorBackground(0.09804f, 0.6274f, 0.8784f));

  /* Calculate the coordinates for the face, so its centered on the camera. */
  final int centerX = (CAMERA_WIDTH - this.mFaceTextureRegion.getWidth()) / 2;
  final int centerY = (CAMERA_HEIGHT - this.mFaceTextureRegion.getHeight()) / 2;

  /* Create the face and add it to the scene. */
  final Sprite face = new Sprite(centerX, centerY, this.mFaceTextureRegion);
  scene.attachChild(face);

  return scene;
}

scene.attachChild() 호출할 때 이전에서는 Entity의 인스턴스를 파라미터로 전달하였다면 이번에는 Sprite의 인스턴스를 파라미터로 전달하였다. 물론 Sprite 는 Entity 를 상속받고 있다.(BaseRectangle 은 Shape 로부터 상속받고 있으며, 이 Shape 는 Entity 를 상속받고있다.)

Sprite 클래스는 생성시 TextureRegion 클래스를 생성자 파라미터로 전달받는다.

예제에서 멤버 변수로 다음의 클래스들이 추가로 선언되어있는데...

private BitmapTextureAtlas mBitmapTextureAtlas;
private TextureRegion mFaceTextureRegion;

 

TextureRegion 클래스의 인스턴스인 mFaceTextureRegion 을 Sprite 생성시 파라미터로 전달한다. 그리고mFaceTextureRegion 은 onLoadResoureces() 에서 인스턴스화된다.

@Override
public void onLoadResources() {
  this.mBitmapTextureAtlas = new BitmapTextureAtlas(32, 32, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
  BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");
  this.mFaceTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBitmapTextureAtlas, this, "face_box.png", 0, 0);
  this.mEngine.getTextureManager().loadTexture(this.mBitmapTextureAtlas);
}

BitmapTextureAtlasTextureRegionFactory 클래스는 기본적으로 정적 메소드로 이뤄져 있다.

여기서 setAssetBasePath 와 createFromAsset 을 호출한다.

public static void setAssetBasePath(final String pAssetBasePath) {
  if(pAssetBasePath.endsWith("/") || pAssetBasePath.length() == 0) {
    BitmapTextureAtlasTextureRegionFactory.sAssetBasePath = pAssetBasePath;
  } else {
    throw new IllegalArgumentException("pAssetBasePath must end with '/' or be lenght zero.");
  }
}

일단은 이미지들이 위치할 경로를 지정하는 것으로 assets 디렉토리를 기준으로 상대경로를 지정한다. 상기 소스에서는 "gfx/" 로 지정하였다.

public static TextureRegion createFromAsset(final BitmapTextureAtlas pBitmapTextureAtlas, final Context pContext, final String pAssetPath, final int pTexturePositionX, final int pTexturePositionY) {
  final IBitmapTextureAtlasSource bitmapTextureAtlasSource = new AssetBitmapTextureAtlasSource(pContext, BitmapTextureAtlasTextureRegionFactory.sAssetBasePath + pAssetPath);
  return BitmapTextureAtlasTextureRegionFactory.createFromSource(pBitmapTextureAtlas, bitmapTextureAtlasSource, pTexturePositionX, pTexturePositionY);
}

일반적으로 OpenGL 에서의 텍스쳐는 동일한 포맷을 가지고 있는, 하나 또는 여러 이미지를 포함한 OpenGL Object 를 의미한다. 일단은 정해진 크기의 비트맵텍스처를 생성한 후에, 해당 텍스처의 지정한 좌표로 이미지를 로드하고 그 결과를 텍스쳐리전으로 반환하는 것으로 파악된다. 이때, 좌표와 이미지 크기의 결과가 비트맵텍스처의 영역을 벗어날 경우 에러가 발생한다.

그 외, org.anddev.andengine.opengl.texture 패키지의 클래스 다이어그램은 다음과 같다.

아울러 BitmapTexture 추상 클래스를 살펴보면 다음과 같다.

전체 소스는 다음과 같다.

package kr.logy.code.AESample1;

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.scene.Scene;
import org.anddev.andengine.entity.scene.background.ColorBackground;
import org.anddev.andengine.entity.sprite.Sprite;
import org.anddev.andengine.entity.util.FPSLogger;
import org.anddev.andengine.opengl.texture.TextureOptions;
import org.anddev.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlas;
import org.anddev.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlasTextureRegionFactory;
import org.anddev.andengine.opengl.texture.region.TextureRegion;
import org.anddev.andengine.ui.activity.BaseGameActivity;

public class AESample1Activity extends BaseGameActivity {
  private Camera mCamera;

  private static final int CAMERA_WIDTH = 720;
  private static final int CAMERA_HEIGHT = 480;

  private BitmapTextureAtlas mBitmapTextureAtlas;
  private TextureRegion mFaceTextureRegion;   

  @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
    this.mBitmapTextureAtlas = new BitmapTextureAtlas(32, 32, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
    BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");
    this.mFaceTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBitmapTextureAtlas, this, "face_box.png", 0, 0);
    this.mEngine.getTextureManager().loadTexture(this.mBitmapTextureAtlas);     
  }     

  @Override
  public Scene onLoadScene() {
    this.mEngine.registerUpdateHandler(new FPSLogger());
    final Scene scene = new Scene();
    scene.setBackground(new ColorBackground(0.09804f, 0.6274f, 0.8784f));


    /* Calculate the coordinates for the face, so its centered on the camera. */
    final int centerX = (CAMERA_WIDTH - this.mFaceTextureRegion.getWidth()) / 2;
    final int centerY = (CAMERA_HEIGHT - this.mFaceTextureRegion.getHeight()) / 2;


    /* Create the face and add it to the scene. */
    final Sprite face = new Sprite(centerX, centerY, this.mFaceTextureRegion);
    scene.attachChild(face);


    return scene;
  }
}

실행하면 다음과 같이 출력된다.

그나저나 소스를 보면 볼수록 AndEngine 의 설계가 마음에 들지 않는다. ㅠㅠ 여러 오픈소스들을 봐왔지만 OOP 설계를 한 프로젝트 중에 가장 산만하다고 할까?
 

반응형

댓글