Bài đăng phổ biến

Chủ Nhật, 28 tháng 10, 2012

AndEngine Bài 2 - Texture và Sprite



Trong bài này chúng ta sẽ học thế nào để load 1 Texture và add chúng tới 1 Sprite, làm thế nào để load 1 Sprite. Và sử dụng accelerometer (Đo cảm biến gia tốc) áp dụng vào bài để sprite nhảy lên, nhảy xuống. Hầu hết các divices android đều có accelerometer được tích hợp sẵn trong máy. Nó làm đa dạng thên đầu vào khi sử dụng các ứng dụng và đặc biệt phục vụ nhiều trong các trò chới game.

Các bạn chú ý tọa độ 2D trong AndEngine như hình sau:


Gốc tọa độ nằm ở góc trái màn hình đúng không. Nó khác với các tọa độ khác trong Opengles 1 và 2.

Trước tiên để bắt đầu với bài này các bạn hãy load ảnh này: 

Và copy nó tới thư mục assets trong Project của bạn. Chúng ta cũng cần thêm 2 biến để load texture.

Bước đầu tiên: Ta khai báo trong AndEngineActivity1Tutorial của chúng ta 2 biến sau:
private BitmapTextureAtlas mBitmapTextureAtlas;
private TextureRegion mPlayerTextureRegion;


Trong bài cuối tôi sẽ viết sau: Chúng ta sẽ học Textures được load trong method "onCreateResource()". Vì vậy để load textrue trên chỉ cần copy và paste vào trong ứng dụng của bạn. và sử lại 1 số trong onCreateResource()

@Override
protected void onCreateResources() {
    /* Load all the textures this game needs. */
    mBitmapTextureAtlas = new BitmapTextureAtlas(this.getTextureManager(), 32, 32);
    mPlayerTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBitmapTextureAtlas, this, "face_box.png", 0, 0);
    mBitmapTextureAtlas.load();
}

Như vậy là texture đã được load xong.
Các bạn chú ý nhìn hình sau đây: Sẽ hiểu ngày BitmapTextureAtlas và TextureRegion

Tiếp theo chúng ta sẽ nghiên cứu về Accelerometer (Cảm biến gia tốc).

Có vài Sensors được hỗ trợ bởi SensorManager. Nhưng chỉ có 1 cái chúng ta cần bây giờ là TYPE_ACCELEROMETER

·         TYPE_ACCELEROMETER
·         A constant describing an accelerometer sensor type.
·         TYPE_ALL
·         A constant describing all sensor types.
·         TYPE_AMBIENT_TEMPERATURE
·         A constant describing an ambient temperature sensor type
·         TYPE_GRAVITY
·         A constant describing a gravity sensor type.
·         TYPE_GYROSCOPE
·         A constant describing a gyroscope sensor type
·         TYPE_LIGHT
·         A constant describing a light sensor type.
·         TYPE_LINEAR_ACCELERATION
·         A constant describing a linear acceleration sensor type.
·         TYPE_MAGNETIC_FIELD
·         A constant describing a magnetic field sensor type.
·         TYPE_ORIENTATION
·         This constant is deprecated. Use SensorManager.getOrientation() instead.
·         TYPE_PRESSURE
·         A constant describing a pressure sensor type.
·         TYPE_PROXIMITY
·         A constant describing an proximity sensor type.
·         TYPE_RELATIVE_HUMIDITY
·         A constant describing a relative humidity sensor type.
·         TYPE_ROTATION_VECTOR
·         A constant describing a rotation vector sensor type.
·         TYPE_TEMPERATURE
·         This constant is deprecated. Use Sensor.TYPE_AMBIENT_TEMPERATURE instead.



package com.PerleDevelopment.AndEngine.tutorial.helper;
 
import android.app.Activity;
import android.content.Context;
 
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
 
public class AccelerometerHelper extends Activity implements SensorEventListener {
 
    private SensorManager mSensorManager;
    private Sensor mAccelerometer;
 
    public static float TILT;
 
    public AccelerometerHelper(Activity oActivity) {
 
     mSensorManager = (SensorManager) oActivity.getSystemService(Context.SENSOR_SERVICE);
 
     if (mSensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER).size() != 0) {
         mAccelerometer = mSensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER).get(0);
  mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME);
        }
 
    }
 
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        // TODO Auto-generated method stub
 
    }
 
    @Override
    public void onSensorChanged(SensorEvent event) {
 
        TILT = event.values[0];
 
    }
 
}


Sau khi ta đã cài đặt SensorManager chúng ta cần chek sensor của chúng ta là có sẵn hay không nếu Size của sensor List là 0 thì điều đó có nghĩa là không có sensor nào. Vì vậy trong các dòng tiếp theo chúng ta cài đặt Sensor của chúng ta được gọi là mAccelerometer và đăng ký càm biến (Sensor) và listener.


  • registerListener(listener, sensor,rate)

                 listener nhận dữ liệu từ Sensor với tốc độ thay đổi rate
                 rate
                        Có vài rate tạm dừng (delay) khác nhau có sẵn

                                        ·                     SENSOR_DELAY_NORMAL
                                        ·                     SENSOR_DELAY_UI
                                        ·                     SENSOR_DELAY_GAME
                                        ·                     SENSOR_DELAY_FASTEST
                                        ·                     delay between events in microseconds



  • TILT = event.values[0]


               ·                     values[0]: Acceleration minus Gx on the x-axis
               ·                     values[1]: Acceleration minus Gy on the y-axis
               ·                     values[2]: Acceleration minus Gz on the z-axis


Lớp AccelerometerHelper là SensorEventListener trong Activity của chúng ta. Trong method onCreateEngineOption() chúng ta chỉ cần  new AccelerometerHelper(this) là ok:

Bước tiếp: Ta sẽ tạo ra 1 abstract class GameObject

Để nhân vật có thể dịch chuyển được chúng ta phải sử dụng "AndEnginePhysicsBox2DExtension" Bây giờ chúng ta tạo 1 lớp gọi là GameObject

package com.example.andenginetutorial1;

import org.andengine.engine.handler.physics.PhysicsHandler;
import org.andengine.entity.sprite.Sprite;
import org.andengine.opengl.texture.region.TextureRegion;
import org.andengine.opengl.vbo.VertexBufferObjectManager;

public abstract class GameObject extends Sprite {

       // ===========================================================
       // Constants
       // ===========================================================

       // ===========================================================
       // Fields
       // ===========================================================

       public PhysicsHandler mPhysicsHandler;

       // ===========================================================
       // Constructors
       // ===========================================================

       public GameObject(float pX, float pY, TextureRegion pTextureRegion,
                     VertexBufferObjectManager pVertexBufferObjectManager) {
              super(pX, pY, pTextureRegion, pVertexBufferObjectManager);
              this.mPhysicsHandler = new PhysicsHandler(this);
              this.registerUpdateHandler(this.mPhysicsHandler);
       }

       // ===========================================================
       // Getter & Setter
       // ===========================================================

       // ===========================================================
       // Methods for/from SuperClass/Interfaces
       // ===========================================================

       @Override
       protected void onManagedUpdate(float pSecondsElapsed) {
              move();

              super.onManagedUpdate(pSecondsElapsed);
       }

       // ===========================================================
       // Methods
       // ===========================================================

       public abstract void move();
}


Chúng ta tạo ra abstract GameObject vì chúng ta phải tạo 1 method abstract move() với mục đích các lớp con của nó cài đặt và thực hiện mọi công việc theo ý muốn trong method move() này. Và mặt khác ta cũng dễ sử dụng trong khi cài đặt trò game của chúng ta như khai báo không cần phải truyền thao số trực tiếp subclass mà chỉ cần truyền vào là GameObject.....

Chúng ta tạo mới 1 PhysicsHandler và đăng ký nó tới lớp này. Và GameObject extends Sprite chúng ta nhận được onManagerUpdate method(). Bên trong nó chúng ta gọi move() method(). Bây giờ chúng ta kết thúc lớp này. Chúng ta cần tạo ra lớp đối tượng chuyển động bên trong


package com.example.andenginetutorial1;

import org.andengine.opengl.texture.region.TextureRegion;
import org.andengine.opengl.texture.region.TiledTextureRegion;
import org.andengine.opengl.vbo.VertexBufferObjectManager;

public class Player extends GameObject {

       // ===========================================================
       // Constants
       // ===========================================================

       final int DEFAULT_VELOCITY = 200;

       // ===========================================================
       // Fields
       // ===========================================================

       boolean jumping = false;

       // ===========================================================
       // Constructors
       // ===========================================================

       public Player(float pX, float pY, TextureRegion pTextureRegion,
                     VertexBufferObjectManager pVertexBufferObjectManager) {
              super(pX, pY, pTextureRegion, pVertexBufferObjectManager);
       }

       // ===========================================================
       // Methods for/from SuperClass/Interfaces
       // ===========================================================

       @Override
       public void move() {

              this.mPhysicsHandler.setVelocityX(-AccelerometerHelper.TILT
                           * DEFAULT_VELOCITY);
              setRotation(-AccelerometerHelper.TILT * 15);
              OutOfScreenX();

              Jumping();

       }

       // ===========================================================
       // Methods
       // ===========================================================

       private void Jumping() {
              if (jumping) {
                     Jump();
              } else {
                     Fall();
              }
       }

       private void Jump() {
              if (mY <= AndEngineTutorial1Activity.CAMERA_HEIGHT / 2) { // mY <= 400
                     jumping = false;
              } else {
                     this.mPhysicsHandler.setVelocityY(-DEFAULT_VELOCITY);
              }
       }

       private void Fall() {
              if (mY >= AndEngineTutorial1Activity.CAMERA_HEIGHT) { // mY >= 800
                     jumping = true;
              } else {
                     this.mPhysicsHandler.setVelocityY(DEFAULT_VELOCITY);
              }
       }

       private void OutOfScreenX() {
              if (mX > AndEngineTutorial1Activity.CAMERA_WIDTH) { // OutOfScreenX
                                                                                                       // (right)
                     mX = 0;
              } else if (mX < 0) { // OutOfScreenX (left)
                     mX = AndEngineTutorial1Activity.CAMERA_WIDTH;
              }
       }
}


Bây giờ để add một sức mạnh tới lớp Player chúng ta chỉ cần thiết lập một tốc độ (velocity) tới PhysicsHandler như trong move() method

Bây giờ là lớp activity của chúng ta:

package com.example.andenginetutorial1;
import org.andengine.engine.camera.Camera;
import org.andengine.engine.options.EngineOptions;
import org.andengine.engine.options.ScreenOrientation;
import org.andengine.engine.options.resolutionpolicy.RatioResolutionPolicy;
import org.andengine.entity.scene.Scene;
import org.andengine.entity.scene.background.Background;
import org.andengine.entity.text.Text;
import org.andengine.entity.util.FPSLogger;
import org.andengine.opengl.font.Font;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlas;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlasTextureRegionFactory;
import org.andengine.opengl.texture.region.TextureRegion;
import org.andengine.opengl.texture.region.TiledTextureRegion;
import org.andengine.ui.activity.SimpleBaseGameActivity;
import org.andengine.util.HorizontalAlign;
import org.andengine.util.color.Color;

import android.graphics.Typeface;


public class AndEngineTutorial1Activity extends SimpleBaseGameActivity {


       public static final int CAMERA_WIDTH = 480;
       public static final int CAMERA_HEIGHT = 800;

       // ===========================================================
       // Fields
       // ===========================================================

       private Camera mCamera;
       private AccelerometerHelper mAccelerometerHelper;
       private Scene mMainScene;

       private BitmapTextureAtlas mPlayerBitmapTextureAtlasmFontTexture;
       private TextureRegion mPlayerTextureRegion;

       private Font mFont;
       // ===========================================================
       // Constructors
       // ===========================================================

       // ===========================================================
       // Getter & Setter
       // ===========================================================

       // ===========================================================
       // Methods for/from SuperClass/Interfaces
       // ===========================================================

       public EngineOptions onCreateEngineOptions() {
              mAccelerometerHelper = new AccelerometerHelper(this);
             
              this.mCamera = new Camera(0, 0, CAMERA_WIDTHCAMERA_HEIGHT);

              return new EngineOptions(true, ScreenOrientation.PORTRAIT_FIXEDnew RatioResolutionPolicy(CAMERA_WIDTHCAMERA_HEIGHT), this.mCamera);
       }

       @Override
       protected void onCreateResources() {
              /* Load all the textures this game needs. */
              this.mPlayerBitmapTextureAtlas = new BitmapTextureAtlas(this.getTextureManager(), 32, 32);
              this.mPlayerTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mPlayerBitmapTextureAtlasthis"face_box.png", 0, 0);
              this.mPlayerBitmapTextureAtlas.load();
        this.mFontTexture = new BitmapTextureAtlas(getTextureManager(), 256, 256);
        this.mFont = new Font(getFontManager(), mFontTexture, Typeface.create(Typeface.DEFAULT, Typeface.BOLD), 14, true, Color.BLACK);
        this.mEngine.getTextureManager().loadTexture(mFontTexture);
        this.mEngine.getFontManager().loadFont(mFont);

       }

       @Override
       protected Scene onCreateScene() {
              this.mEngine.registerUpdateHandler(new FPSLogger()); // logs the frame rate

              /* Create Scene and set background colour to (1, 1, 1) = white */
              this.mMainScene = new Scene();
              this.mMainScene.setBackground(new Background(1, 1, 1));

              /* Centre the player on the camera. */
              final float centerX = (CAMERA_WIDTH - this.mPlayerTextureRegion.getWidth()) / 2;
              final float centerY = (CAMERA_HEIGHT - this.mPlayerTextureRegion.getHeight()) / 2;

              /* Create the sprite and add it to the scene. */
              final Player oPlayer = new Player(centerX, centerY, this.mPlayerTextureRegionthis.getVertexBufferObjectManager());
              this.mMainScene.attachChild(oPlayer);
              //Ellipse ee=new Ellipse(50, 50, 50, 50, getVertexBufferObjectManager());
              final Text textCenter = new Text(20, 60, this.mFont"Trần Minh                       Thuận",getVertexBufferObjectManager());
              this.mMainScene.attachChild(textCenter);
              return this.mMainScene;
       }
}


Về phần mFont tôi thêm vào lớp này nhưng rất dễ hiểu tôi không giải thích thêm.
OK bây giờ chạy OK nhé:

SOURCE CODE: http://www.mediafire.com/?9tbah912bu0vu49
thanks for viewing!

2 nhận xét:

  1. Cảm ơn bạn nhiều.Mong bạn viết thêm nhiều ví dụ về andengine gles2 hơn nữa.

    Trả lờiXóa
  2. public EngineOptions onCreateEngineOptions() {
    mAccelerometerHelper = new AccelerometerHelper(this);

    this.mCamera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);

    return new EngineOptions(true, ScreenOrientation.PORTRAIT_FIXED, new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), this.mCamera);
    }
    Bạn xem lại dùm mình bị lỗi chỗ này

    Trả lờiXóa