1

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn















2

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn
Mục lục
1. LÀM THẾ NÀO ĐỂ LÀM 1 GAME ? CÁCH GÌ TỐT NHẤT ĐỂ LÀM GAME ? ............................................................................. 3
2. BAO LÂU THÌ SẼ HOÀN THÀNH XONG 1 GAME ? .................................................................................................................... 3
3. TẠI SAO LẠI PHẢI SỬ DỤNG ANDENGINE MÀ KHÔNG PHẢI 1 ENGINE NÀO KHÁC ? ........................................................ 3
4. NHỮNG BƯỚC ĐẦU TIÊN TRONG LẬP TRÌNH GAME VỚI ANDENGINE (GLES2): ............................................................... 3
5. CÁC EXTENTIONS VÀ EXAMPLE CỦA ANDENGINE ................................................................................................................ 5
6. NHỮNG VẤN ĐỀ CHÍNH TRONG ANDENGINE ........................................................................................................................... 7
7. XÂY DỰNG CÁC THÀNH PHẦN ĐỂ TẠO NÊN 1 GAME (GLES2) .............................................................................................. 9
8. XÂY DỰNG CÁC THÀNH PHẦN ĐỂ TẠO NÊN 1 GAME (GLES1) ............................................................................................ 16
















3

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn
1. Làm thế nào để làm 1 game ? Cách gì tốt nhất để làm game ?
Đó thật sự là 1 vấn đề khó để trả lời vì viết 1 game sử dụng trên nhiều platform thì cần rất nhiều công sức bỏ ra để thực
hiện và cần có 1 sự kiên nhẫn nhất định để thực hiện.Nên nó không phải là cách làm tốt nhất.Trong bài viết này sẽ sử dụng 1
Engine để giúp việc thực hiện 1 game trở nên dễ dàng thực hiện hơn.
2. Bao lâu thì sẽ hoàn thành xong 1 game ?
Tùy theo độ sâu của trò chơi mà có thể chiếm cả năm trời lập trình hoặc chỉ tốn vài ngày để thực hiện nếu nó không có độ
hoành tráng trong game.
3. Tại sao lại phải sử dụng AndEngine mà không phải 1 Engine nào khác ?
Có rất nhiều Engine dùng để làm 1 game sử dụng nhiều nhất ở Việt Nam đơn cử là E3Droid hoặc AndEngine hoặc libgdx
,nhưng tại sao lại nên sử dụng AndEngine ?.Chính vì sự thuận tiện để thực hiện 1 cách dễ dàng để làm game và nó cho bạn 1
sự tự do để sử dụng các nguồn tài nguyên mà Android và Java đã cung cấp để thực hiện . Đó là 1 framework cho bạn nhiều sự
tự do nhiều hơn những framework khác nhưng bạn cũng cần phải bỏ ra chút ít công sức nữa nếu muốn sản phẩm bạn làm ra
nó sẽ là tốt nhất .Có những Framework hạn chế sự tự do tưong tác của bạn lại nên khiến cho game rất đơn giản trong cách
chơi ví dụ như libgdx và cón 1 phần quan trọng nữa là cộng đồng làm game hiện tại ở Việt Nam thì AndEngine đang phát triển
rất mạnh.
4. Những bước đầu tiên trong lập trình game với AndEngine (GLES2):
Cài đặt và chuẩn bị những yêu cầu về phần mềm
o JDK : Tốt nhất nên cài đặt phiên bản mới nhất để được sự hỗ trợ tốt nhất tại đây
o ADT : Sử dụng IDE của phát triển Android tại đây
o AndEngine Source : Bộ thư viện download tại đây , bạn có thể xem các example về các tính năng mà bộ
framework này hỗ trợ tại đây
Example đầu tiên : Hello world với AndEngine GLES2
Import thư viện AndEngine :

Tạo Project HelloWorld và import thư viện AndEngine :
4

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn

Add image HelloWorld vào trong thư mục asset tải hình tại đây
Activity sử dụng AndEngine đều phải extend lại SimpleBaseGameActivity hoặc BaseGameActivity.
Khai báo 2 biến quan trọng :
private ITexture mHelloWorldTexture;
private ITextureRegion mHelloWorldTextureRegion;
Kích thước vùng hiển thị :
private static final int CAMERA_WIDTH = 800;
private static final int CAMERA_HEIGHT = 480;
Trong phuơng thức onCreateEngineOptions :
final Camera camera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);//Quản lý cấu hình màn hình
return new EngineOptions(true, ScreenOrientation.LANDSCAPE_SENSOR,
new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), camera);
Trong phuơng thức onCreateResources:
//Sử dụng resource đang có trong thư mục assets
this.mHelloWorldTexture = new AssetBitmapTexture(this.getTextureManager(),
this.getAssets(), "helloworld.png");
this.mHelloWorldTextureRegion = TextureRegionFactory.extractFromTexture(
this.mHelloWorldTexture);
this.mHelloWorldTexture.load();
Trong phuơng thức onCreateScene:
//Quản lý tất cả những gì bạn vẽ trên vùng hiển thị
this.mEngine.registerUpdateHandler(new FPSLogger());
final Scene scene = new Scene();
5

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn
scene.getBackground().setColor(Color.YELLOW);
final float centerX = CAMERA_WIDTH / 2;
final float centerY = CAMERA_HEIGHT / 2;
final Sprite sprite = new Sprite(centerX, centerY,
this.mHelloWorldTextureRegion, this.getVertexBufferObjectManager());
scene.attachChild(sprite); // 1 đối tượng hình là 1 sprite trong AndEngine
return scene;
Kết quả của example trên :


5. Các Extentions và Example của AndEngine
Đầu tiên đến với AndEngine ta có 1 bất lợi là không có document cho framework này,nhưng bù lại ta có 1 lượng example
rất lớn đủ để viết 1 game theo ý muốn.Phần này sẽ huớng dẫn bạn cách thêm các Extention của AndEngine .
Download Project Example tại đây
Download Project Extention:
1. AndEngine
2. AndEngineAugmentedRealityExtension
3. AndEngineMODPlayerExtension
4. AndEngineSVGTextureRegionExtension
5. AndEnginePhysicsBox2DExtension
6. AndEngineMultiplayerExtension
7. AndEngineTMXTiledMapExtension
8. AndEngineScriptingExtension
9. AndEngineCocosBuilderExtension
10. AndEngineLiveWallpaperExtension
11. AndEngineCocosBuilderExtensionCCRotatingSpriteExtension(sm4)
12. AndEngineCocosBuilderExtensionCCRotatingSpriteExtension(nicolasgramlich)
6

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn

Sau khi import vào ta nên Clean All Project .
Và fix những lỗi sau trước khi xem các example của AndEngine :
1. Lỗi của SVG Extension :
Add unimplemented các phuơng thức còn thiếu,bởi vì SVG extension không có trong version AnchorCenter.
2. Lỗi của Scripting Extension :
.Sử dụng search -> file sau đó replace import org.andengine.util.color.Color; thành import
org.andengine.util.adt.color.Color;
.Xóa class RectangularShapeProxy bởi vì nó không sử dụng trong version AnchorCenter.
3. Lỗi của AndEngine Examples :
Cuối cùng ta sẽ tiếp tục fix lỗi đối với AndEngineExample ,danh sách lỗi như sau :
Search Replace
import org.andengine.extension.multiplayer.protocol import org.andengine.extension.multiplayer
import
org.andengine.extension.multiplayer.exception.BluetoothException;
import org.andengine.util.exception.BluetoothException;
7

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn
import org.andengine.entity.particle.modifier.ExpireParticleInitializer;
import
org.andengine.entity.particle.initializer.ExpireParticleInitializer;
import org.andengine.extension.multiplayer.util.IPUtils; import org.andengine.util.IPUtils;
import org.andengine.extension.multiplayer.util.WifiUtils; import org.andengine.util.WifiUtils;
if(!AndEngine.isDeviceSupported()) { if(!AndEngine.isDeviceSupported(this)) {
Các IOExceltion báo lỗi ta chuyển thành Exception.
Các lỗi thư viện còn lại , ta remove dòng Import thư viện và add lại đối với các hàm cần thư viện.
Run Appliation để xem thành quả .
6. Những vấn đề chính trong AndEngine
 Camera :
Camera trong game nó xác định màn hình hiển thị và trình bày cho người chơi thấy ,nó giống như 1 máy quay phim
trong 1 không gian 2 chiều và ta có thể tương tác phóng to hoặc thu nhỏ , điều khiển các vật thể tuơng tác với game.
Nó xác định một hình chữ nhật với chiều dài và chiều rộng xác định trước để vẽ lên màn hình. Có thể tất cả các thứ
trong game sẽ được nhìn thấy trên camera hoặc camera chỉ hiển thị một phần của khung cảnh, bạn phải di chuyển
camera để nhìn thấy các phần còn lại (Boundcamera) . Hoặc một camera có thể phóng to, thu nhỏ hoặc cuộn gọi là
ZoomCamera.
 Scene :
Nó chứa tất cả các đối tượng mà bạn vẽ trên màn hình. Nó giống như một tờ giấy, trên đó bạn có thể vẻ tất cả các
hình, cập nhật chúng và có thế chứa các tờ giấy khác.
1 game giống như 1 bộ phim được trình chiếu đến người xem mà trong đó nó bao gồm các hoạt cảnh và các hành
động diễn ra trong 1 “bộ phim” ,những cảnh này được biên tập lại và sắp xếp với nhau 1 cách cố định nó sẽ tạo thành 1
bộ phim hoàn chỉnh .
 Layer :
Các scene là tập hợp các layer đồ họa nó nằm chồng lên nhau giống như các cel được sử dụng làm phim hoạt
hình như hồi xưa ,ngoài ra các layer còn tạo hiệu ứng 2
1
/2D.
 Sprite :
Nó được ví như các “diễn viên” trong 1 bộ phim ,nó có thể là 1 con người hoặc 1 đồ vật,nó có thể di chuyển hoặc
không và nó có thể di chuyển trong các scene ,cấu trúc của 1 sprite bao gồm tập hợp các hình ảnh sprite được gọi là
sprite sheet.
 Entity :
Là những Object sẽ vẽ các bức ảnh của bạn lên scene. Có thể một bức ảnh tỉnh (Sprite), một bức ảnh động
(AnimatedSprite), hoặc một bức ảnh có nhiều bức ảnh con trong nó (TitledSprite).
Trong AndEngine các entity(thực thể) là những thứ được vẽ hoặc hiển thị trên màn hình nó chính là các sprite ví dụ
như 1 viên gạch hoặc 1 đối tuợng hình học hoặc 1 dòng kẻ được vẽ trên màn hình.Tất cả các thực thể đều có các
thuộc tính như màu sắc,độ co giãn,góc xoay, vị trí đặt và nó có thể chỉnh sửa lại giá trị nếu mình muốn.
 Modifier :
Modifier có thể thay đổi thuộc tính của các Entity và nó rất mạnh nhất là trong AndEngine .Nó có thể sử dụng trên
bất kỳ Entity nào đó và nó sẽ được thay đổi và cập nhật ngay lập tức trong khi game vẫn đang diễn ra .Trong 1 game
chúng TATT modifier thường xuyên sử dụng để tạo các hiệu ứng với Sprite và Entity khác.
8

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn
 Texture :
 Texture Region :
 Engine :
Trong game có nhiều tiến trình nhỏ chạy song song. Engine sẽ quản lí tất cả các tiến trình đó. Cái này bạn không
cần phải quan tâm nhiều vì andengine sẽ làm việc đó.
 BaseGameActivity :
Là 1 lớp mở rộng của lớp Activity trong android,nó là cơ sở cho mỗi scene trong game ,nó làm tất cả các công việc
của chung của tất cả các scene và các thiết lập trong engine của game ,đối với các cảm biến và vòng đời của mỗi
Activity.
 Physics Connector :
AndEngine bao gồm cả tính năng vật lý cơ bản ở trong bộ engine,Box2D Physics Engine là phần mở rộng lớn vào
những khả năng này.Chúng kết nối các đối tượng trong AndEngine với Box2D thông qua kết nối vật lý.Nếu trong game
của bạn không sử dụng Box2D thì game se không có bất cứ tương tác vật lý thông qua kết nối vật lý.
 Box2D Physics Engine :
AndEngine bao gồm bộ mã nguồn mở Jbox2 nó là 1 cổng của engine Box2D vật lý.Nó có thể sử dụng để mô
phỏng tương tác thực tế của các đối tượng trong những các sau :
+Trọng lực (Gravity)
+Stable stacking
+Mô phỏng vật lý của các cơ quan trong cơ thể




















9

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn
7. Xây dựng các thành phần để tạo nên 1 game (GLES2)
3 thành phần quan trọng của 1 Activity kế thừa từ SimpleBaseGameActivity:



















Mỗi 1 Activity sẽ có 1 vùng hiển thị hoạt cảnh (Scene) riêng và tất cả được quản lý bằng mEngine.
7.1 Cảnh nền (Background) :
Tùy theo thể loại game mà người sử dụng sẽ làm cảnh nền cho phù hợp,được chia ra làm 3 loại :
+Repeating Spire Background (Cảnh nền được khởi tạo full màn hình bẳng Spire được lặp theo chiều X và Y):
1.Method onCreateEngineOptions() : Khai báo mặc định như trên
2.Method onCreateResources() :












// Load ảnh từ thư mục Asset,loại Texture là Repeating
this.mBackgroundTexture = new AssetBitmapTexture(this.getTextureManager(), this.getAssets(),
"gfx/background_grass.png", TextureOptions.REPEATING_NEAREST);
this.mBackgroundTexture.load();

final ITextureRegion backgroundTextureRegion =
TextureRegionFactory.extractFromTexture(this.mBackgroundTexture);

// Thực hiện repeat theo chiều cao và chiều rộng của camera
this.mGrassBackground = new RepeatingSpriteBackground(CAMERA_WIDTH,CAMERA_HEIGHT,
backgroundTextureRegion,this.getVertexBufferObjectManager());
@Override
public EngineOptions onCreateEngineOptions() {
// Khởi tạo vùng quan sát (Camera) : Mặc định mỗi 1 Activity sẽ có chung phần khai báo,chiều
rộng,chiều cao,định hướng hiển thị sẽ tùy theo người sử dụng xét
final Camera camera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
return new EngineOptions(true, ScreenOrientation.LANDSCAPE_SENSOR, new
RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), camera);
}
@Override
public void onCreateResources() throws IOException {
// Khởi tạo nguồn tài nguyên từ Asset/Drawable/Folder bất kỳ/Load từ bộ nhớ
...
}
@Override
public Scene onCreateScene() {
// Khởi tạo vùng hiển thị hoạt cảnh (Scene) bao gồm các Spire/Particle/Button Sprite...
...
}

10

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn
3.Method onCreateScene() :



Source đính kèm
RepeatingBackground.zip

+AutoParallax Background (Tạo cảnh nền di chuyển):
1.Method onCreateEngineOptions() : Khai báo mặc định như trên
2.Method onCreateResources() :














3.Method onCreateScene() :














final Scene scene = new Scene();
scene.setBackground(this.mGrassBackground);
this.mParallaxLayerBackTexture = new
AssetBitmapTexture(this.getTextureManager(), this.getAssets(),
"gfx/parallax_background_layer_back.png");
this.mParallaxLayerBackTextureRegion =
TextureRegionFactory.extractFromTexture(this.mParallaxLayerBackTexture);
this.mParallaxLayerBackTexture.load();

this.mParallaxLayerMidTexture = new AssetBitmapTexture(this.getTextureManager(),
this.getAssets(), "gfx/parallax_background_layer_mid.png");
this.mParallaxLayerMidTextureRegion =
TextureRegionFactory.extractFromTexture(this.mParallaxLayerMidTexture);
this.mParallaxLayerMidTexture.load();

this.mParallaxLayerFrontTexture = new
AssetBitmapTexture(this.getTextureManager(), this.getAssets(),
"gfx/parallax_background_layer_front.png");
this.mParallaxLayerFrontTextureRegion =
TextureRegionFactory.extractFromTexture(this.mParallaxLayerFrontTexture);
this.mParallaxLayerFrontTexture.load();
final Sprite parallaxLayerBackSprite = new Sprite(0, 0, this.mParallaxLayerBackTextureRegion,
vertexBufferObjectManager);
parallaxLayerBackSprite.setOffsetCenter(0, 0);
autoParallaxBackground.attachParallaxEntity(new ParallaxEntity(0.0f,
parallaxLayerBackSprite));

final Sprite parallaxLayerMidSprite = new Sprite(0, CAMERA_HEIGHT -
this.mParallaxLayerMidTextureRegion.getHeight() - 80, this.mParallaxLayerMidTextureRegion,
vertexBufferObjectManager);
parallaxLayerMidSprite.setOffsetCenter(0, 0);
autoParallaxBackground.attachParallaxEntity(new ParallaxEntity(-5.0f,
parallaxLayerMidSprite));

final Sprite parallaxLayerFrontSprite = new Sprite(0, 0,
this.mParallaxLayerFrontTextureRegion, vertexBufferObjectManager);
parallaxLayerFrontSprite.setOffsetCenter(0, 0);
autoParallaxBackground.attachParallaxEntity(new ParallaxEntity(-10.0f,
parallaxLayerFrontSprite));
11

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn
Source đính kèm
ParallaxBackground.zip

+TMX TiledMap (Tạo Background từ TiledMap):Thuận lợi là tạo map dễ dàng do sử dụng Tool
Source đính kèm
TMXTiledBackground.zip

7.2 Các đối tượng :
7.2.1 ANIMATE SPRITE :
Cũng như Sprite nhưng Animate Sprite có thêm chức năng hoạt ảnh bằng cách chia 1 tấm ảnh ra thành nhiều vùng
và duyệt từng vùng của tấm ảnh khiến ta thấy ảnh chuyển động.
VD : Với tấm ảnh bên dưới để hoạt cảnh ta chia tấm ảnh ra 12 vùng:

1.Method onCreateEngineOptions() : Khai báo mặc định như trên
2.Method onCreateResources() :
TiledTextureRegion mSnapdragonTextureRegion mSnapdragonTextureRegion =
BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(this.mBitmapTextureAtlas, this,
"snapdragon_tiled.png", 4, 3);
3.Method onCreateScene() :
final AnimatedSprite snapdragon = new AnimatedSprite(CAMERA_WIDTH * 0.33f, CAMERA_HEIGHT * 0.66f,
this.mSnapdragonTextureRegion, this.getVertexBufferObjectManager());
snapdragon.animate(100); //Di chuyển sang vùng khác với độ trễ là 100ms
scene.attachChild(snapdragon);
Source đính kèm
AnimatedSprites.zip

7.2.2 BUTTON SPRITE :
Với những đối tượng không cần đến chuyển động thì Button Sprite là hợp lý nhất vì nó sẽ hạn chế được tài nguyên
sử dụng tấm ảnh mà không cần hoạt cảnh,các sử kiện trong GLES2 đối với Button Sprite gần như tương tự như
Widget Button của Android nhưng khác đối với sự kiện Long Click,đối với phần này phải viết riêng ra.
12

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn
Chúng ta để ý kỹ là nếu như làm 1 button thì nó sẽ có hover effect và over effect,Sprite hoặc là Animated Sprite sẽ
không có 2 phần này còn muốn thực hiện thì ta sẽ khởi tạo 2 Sprite hoặc 2 Animated Sprite và khi Click lên mà giữ lâu
thì sẽ Visible = true Sprite hoặc Animated Sprite Hover lên thả ra thì Visible = false Sprite hoặc Animated Sprite Hover
1.Method onCreateEngineOptions() : Khai báo mặc định như trên
2.Method onCreateResources() :
this.mBuildableBitmapTextureAtlas = new BuildableBitmapTextureAtlas(this.getTextureManager(), 512, 512);
this.mButtonNormalTextureRegion =
BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBuildableBitmapTextureAtlas, this,
"button_normal.png");//Button ở trạng thái bình thường
this.mPressedTextureRegion =
BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBuildableBitmapTextureAtlas, this,
"button_pressed.png");");//Button ở trạng thái khi click lên
this.mDisabledTextureRegion =
BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBuildableBitmapTextureAtlas, this,
"button_disabled.png");//Button ở trạng thái khi Enable = false
try {
this.mBuildableBitmapTextureAtlas.build(new BlackPawnTextureAtlasBuilder<IBitmapTextureAtlasSource,
BitmapTextureAtlas>(0, 0, 0));
this.mBuildableBitmapTextureAtlas.load();
} catch (TextureAtlasBuilderException e) {
Debug.e(e);
}
3.Method onCreateScene() :
buttonSprite = new ButtonSprite(centerX, centerY, this.mButtonNormalTextureRegion,
this.mPressedTextureRegion, this.mDisabledTextureRegion, this.getVertexBufferObjectManager(), this); ");//Cả 3
trạng thái của 1 button sẽ được gom lại cho 1 Button Sprite
Source đính kèm
ButtonSprite.zip

7.2.3 SPRITE :
Đối với những yêu cầu như thể hiện 1 đối tượng tĩnh nào đó mà không quan trọng lắm trong game vd như cây cối
hoặc mây trôi thuyển trôi xe chạy .v.v… thì Sprite là sẽ phù hợp nhất để thực hiện.
1.Method onCreateEngineOptions() : Khai báo mặc định như trên
2.Method onCreateResources() :
this.mFaceTexture = new AssetBitmapTexture(this.getTextureManager(), this.getAssets(), "gfx/face_box.png");
this.mFaceTextureRegion = TextureRegionFactory.extractFromTexture(this.mFaceTexture);
this.mFaceTexture.load();
3.Method onCreateScene() :
13

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn
final Sprite sprite = new Sprite(centerX, centerY, this.mFaceTextureRegion,
this.getVertexBufferObjectManager());
scene.attachChild(sprite);
Source đính kèm
Sprite.zip

7.2.4 PARTICLE SYSTEM :
Hệ thống hạt bản thân cũng là các Sprite kèm theo các chuyển động theo 1 Path với thời gian sống của mỗi hạt
được đính kèm theo mỗi hạt để tiết kiệm bộ nhớ mỗi khi sử dụng,đối với những yêu cầu như làm tuyết rơi,hoa rơi,lá
rơi,hiệu ứng lửa,nước chảy .v.v… thì Particle System là 1 lựa chọn phù hợp nhất.
1.Method onCreateEngineOptions() : Khai báo mặc định như trên
2.Method onCreateResources() :
this.mParticleTexture = new AssetBitmapTexture(this.getTextureManager(), this.getAssets(),
"gfx/particle_fire.png", TextureOptions.BILINEAR_PREMULTIPLYALPHA);
this.mParticleTextureRegion = TextureRegionFactory.extractFromTexture(this.mParticleTexture);
this.mParticleTexture.load();
3.Method onCreateScene() :
final BatchedPseudoSpriteParticleSystem particleSystem = new BatchedPseudoSpriteParticleSystem(new
PointParticleEmitter(0, ParticleSystemCoolExample.CAMERA_HEIGHT), 6, 10, 200,
this.mParticleTextureRegion,this.getVertexBufferObjectManager());
particleSystem.setBlendFunction(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE);

particleSystem.addParticleInitializer(new VelocityParticleInitializer<Entity>(15, 22, -60, -90));
particleSystem.addParticleInitializer(new AccelerationParticleInitializer<Entity>(5, 15));

//Góc xoay khi khởi tạo,nó sẽ random từ 0->360 độ
particleSystem.addParticleInitializer(new RotationParticleInitializer<Entity>(0.0f, 360.0f));

//Màu lúc khởi tạo theo hệ màu RBG
particleSystem.addParticleInitializer(new ColorParticleInitializer<Entity>(1.0f, 0.0f, 0.0f));

//Thời gian sống của mỗi hạt
particleSystem.addParticleInitializer(new ExpireParticleInitializer<Entity>(11.5f));

//Scale lớn ra theo thời gian thực
particleSystem.addParticleModifier(new ScaleParticleModifier<Entity>(0, 5, 0.5f, 2.0f));

particleSystem.addParticleModifier(new AlphaParticleModifier<Entity>(2.5f, 3.5f, 1.0f, 0.0f));
particleSystem.addParticleModifier(new AlphaParticleModifier<Entity>(3.5f, 4.5f, 0.0f, 1.0f));
14

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn

//Màu sẽ chuyển từ màu nào sang màu nào theo hệ màu RBG
particleSystem.addParticleModifier(new ColorParticleModifier<Entity>(0.0f, 11.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f));

particleSystem.addParticleModifier(new AlphaParticleModifier<Entity>(4.5f, 11.5f, 1.0f, 0.0f));
Source đính kèm
ParticleSystem.zip


7.2.5 TEXT :
Các thông điệp hiển thị theo dạng text và có thể sửa đổi do người sử dụng thì chỉ duy nhất có Text mới có thể làm
được.
1.Method onCreateEngineOptions() : Khai báo mặc định như trên
2.Method onCreateResources() :
//Định đường dẫn chứa Font cần sử dụng
FontFactory.setAssetBasePath("font/");

//Khai báo kích thước,màu sắc,loại font cần sử dụng
this.mDroidFont = FontFactory.createFromAsset(this.getFontManager(), this.getTextureManager(), 256, 256,
TextureOptions.BILINEAR, this.getAssets(), "Droid.ttf", FONT_SIZE, true, Color.BLACK);
this.mDroidFont.load();3.Method onCreateScene() :
3.Method onCreateScene() :
final VertexBufferObjectManager vertexBufferObjectManager = this.getVertexBufferObjectManager();

//Set text và hiển thị lên Scene với kiểu Font đã được định nghĩa như trên
scene.attachChild(new Text(centerX, 400, this.mDroidFont, "Droid Font", vertexBufferObjectManager));

//Cập nhật text liên tục
scene.registerUpdateHandler(new TimerHandler(1 / 10.0f, true, new ITimerCallback() {
@Override
public void onTimePassed(final TimerHandler pTimerHandler) {
textExample.setText(String.format("FPS: %.2f", fpsCounter.getFPS()));
}
}));
Source đính kèm
TextExample.zip

15

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn
7.3 Tương tác vật lý : Tương tác vật lý đóng vai trò quan trọng trong 1 game giúp người dùng tương tác trực tiếp với
các Sprite giúp game thêm sinh động và hấp dẫn,có nhiều phần trong AndEngine Physics,nhưng đây là những phần
cốt lõi nhất.
7.3.1 XÁC ĐỊNH VA CHẠM GIỮA 2 SPRITE :
1.Method onCreateScene() :
scene.registerUpdateHandler(new IUpdateHandler() {
@Override
public void reset() { }
@Override
public void onUpdate(final float pSecondsElapsed) {
// CollidesWith : Xác định va chạm giữa vật thể A và vật thể B
if(centerRectangle.collidesWith(sprite)) {
centerRectangle.setColor(1, 0, 0);
} else {
centerRectangle.setColor(0, 1, 0);
}
...
}
});
Source đính kèm
CollisionDetection.zip

7.3.2 TOUCH AND DRAG :
1.Method onCreateScene() :
final Sprite sprite = new Sprite(centerX, centerY, this.mFaceTextureRegion, this.getVertexBufferObjectManager()) {
@Override
public boolean onAreaTouched(final TouchEvent pSceneTouchEvent, final float pTouchAreaLocalX, final float
pTouchAreaLocalY) {
this.setPosition(pSceneTouchEvent.getX() - this.getWidth() / 2, pSceneTouchEvent.getY() - this.getHeight() / 2);
return true;
}
};
Source đính kèm
TouchAndDrag.zip

7.4 Scene Manager : Trong 1 game,mỗi 1 cảnh hiện trên màn hình là 1 scene bao gồm các hoạt cảnh,như vậy nếu nhiều
scene thì việc quản lý và chuyển đổi qua lại giữa các scene sẽ như thế nào,do đó ta sẽ cần 1 Scene Manager để quản
lý tất cả các Scene.
16

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn
Trong Example bên dưới sẽ demo việc load 1 game từ Scene Splash Screen xong sẽ đến Scene Menu
Screen,việc chuyển giữa các Scene sẽ mượt hơn khi dùng "sceneManager.setCurrentScene(AllScenes.MENU);“.
Source đính kèm
SceneManager.zip

8. Xây dựng các thành phần để tạo nên 1 game (GLES1 chỉ nên tham khảo thêm)
Chúng ta sẽ lấy thư viện được build sẵn để sử dụng khi xây dựng game, file bên dưới đang sử dụng AndEngine GLES1:

8.1 Dựng ảnh nền (Background):
public class MainActivity extends BaseGameActivity {

// Khai báo thêm 2 biến quan trọng
private Camera MyCamera;// Biến này thường để cấu hình màn hình
private Scene MyScene;// Quản lý những gì bạn vẽ.

private int WIDTH = 320;
private int HEIGHT = 480;

@Override
public Engine onLoadEngine() {
// Khởi tạo vùng hiện thị là 320*480
this.MyCamera = new Camera(0, 0, WIDTH, HEIGHT);
// Yêu cầu màn hình hiện thị nằm ngang thì ScreenOrientation.LANDSCAPE
Engine engine = new Engine(new EngineOptions(true,
ScreenOrientation.PORTRAIT, new RatioResolutionPolicy(WIDTH,
HEIGHT), this.MyCamera));
return engine;
}
@Override
public void onLoadResources() {}
@Override
public Scene onLoadScene() {
MyScene = new Scene();
// Dựng màu ảnh nền từ hệ màu RGB
MyScene.setBackground(new ColorBackground(0.09804f, 0.6274f, 0.8784f));
return MyScene;
17

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn
}

@Override
public void onLoadComplete() {}
}
Source đính kèm
AndEngine_Test01.rar

8.2 Thao tác với hiển thị text:
public class MainActivity extends BaseGameActivity {

// Khai báo thêm 2 biến quan trọng
private Camera MyCamera;// Biến này thường để cấu hình màn hình
private Scene MyScene;// Quản lý những gì bạn vẽ.

private int WIDTH = 320;// Chiều rộng vùng hiện thị
private int HEIGHT = 480;// Chiều cao vùng hiện thị

private BitmapTextureAtlas mFontTexture;// Lưu font vào bộ nhớ
private Font mFont;// Dùng để lưu lại font

@Override
public Engine onLoadEngine() {
// Khởi tạo vùng hiện thị là 320*480
this.MyCamera = new Camera(0, 0, WIDTH, HEIGHT);
// Yêu cầu màn hình hiện thị nằm ngang thì ScreenOrientation.LANDSCAPE
Engine engine = new Engine(new EngineOptions(true,
ScreenOrientation.PORTRAIT, new RatioResolutionPolicy(WIDTH,
HEIGHT), this.MyCamera));
return engine;
}

@Override
public void onLoadResources() {
this.mFontTexture = new BitmapTextureAtlas(256, 256,
TextureOptions.BILINEAR_PREMULTIPLYALPHA);
// Tạo font mạc định và style là chữ đậm, cỡ chứ 14 màu đen
this.mFont = new Font(this.mFontTexture, Typeface.create(
Typeface.DEFAULT, Typeface.BOLD), 14, true, Color.BLACK);
18

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn
// Load
this.mEngine.getTextureManager().loadTexture(this.mFontTexture);
this.mEngine.getFontManager().loadFont(this.mFont);
}

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

MyScene = new Scene();
MyScene.setBackground(new ColorBackground(0.09804f, 0.6274f, 0.8784f));// Đặt màu nền

// Khai báo 3 hiến text. Dùng HorizontalAlign để căn lề.
final Text textCenter = new Text(20, 60, this.mFont,
"Text A",
HorizontalAlign.CENTER);
final Text textLeft = new Text(20, 200, this.mFont,
"Text B",
HorizontalAlign.LEFT);
final Text textRight = new Text(20, 340, this.mFont,
"Text C",
HorizontalAlign.RIGHT);

// Hiện thị lên màn hình
MyScene.attachChild(textCenter);
MyScene.attachChild(textLeft);
MyScene.attachChild(textRight);

return MyScene;
}

@Override
public void onLoadComplete() {}

}
Source đính kèm
AndEngine_Test02.rar

8.3 Cập nhật game thời gian thực :
19

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn
public class MainActivity extends BaseGameActivity {

//Khai báo thêm 2 biến quan trọng
private Camera MyCamera;//Biến này thường để cấu hình màn hình
private Scene MyScene;//Quản lý những gì bạn vẽ.

private int WIDTH = 320;//Chiều rộng vùng hiện thị
private int HEIGHT = 480;//Chiều cao vùng hiện thị

private BitmapTextureAtlas mFontTexture;//Lưu font vào bộ nhớ
private Font mFont;//Dùng để lưu lại font
private int dem = 0;

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

@Override
public Engine onLoadEngine() {
//Khởi tạo vùng hiện thị là 320*480
this.MyCamera = new Camera(0, 0, WIDTH, HEIGHT);
//Yêu cầu màn hình hiện thị nằm ngang thì ScreenOrientation.LANDSCAPE
Engine engine = new Engine(new EngineOptions(true, ScreenOrientation.PORTRAIT,
new RatioResolutionPolicy(WIDTH, HEIGHT),
this.MyCamera));
return engine;
}

@Override
public void onLoadResources() {
this.mFontTexture = new BitmapTextureAtlas(256, 256, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
//Tạo font mạc định và style là chữ đậm, cỡ chứ 14 màu đen
this.mFont = new Font(this.mFontTexture, Typeface.create(Typeface.DEFAULT, Typeface.BOLD), 14, true,
Color.BLACK);
//Load
this.mEngine.getTextureManager().loadTexture(this.mFontTexture);
this.mEngine.getFontManager().loadFont(this.mFont);
20

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn
}

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

MyScene = new Scene();
MyScene.setBackground(new ColorBackground(0.09804f, 0.6274f, 0.8784f));//Đặt màu nền

//Khai báo ChangeableText dùng để hiện thị thời gian theo từng giây
final ChangeableText textchange = new ChangeableText(10, 10, this.mFont, "", 10);//Tối đa hiện thị 10 ký tự
MyScene.attachChild(textchange);
//Cập nhật (coi như vòng lặp hoạt cảnh)
MyScene.registerUpdateHandler(new IUpdateHandler() {
@Override
public void reset() {}
//Muốn cập nhật cái gì thì cho vào đây
@Override
public void onUpdate(float pSecondsElapsed) {
try {
//Tạm dừng cập nhật trong 1s
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//Cập nhật lại những gì bạn cần vẽ lại liên tục
dem++;
textchange.setText(String.valueOf(dem));//Cứ sau 1s ta lại hiện thị đếm
}
});
return MyScene;
}
@Override
public void onLoadComplete() {}
}
Source đính kèm
AndEngine_Test03.rar

21

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn
8.4 Tạo 1 sprite :
Thêm 1 ảnh vào thư mục asset :
Pic 1 : ball.png

Đoạn code chính trong BaseGameActivity
public class MainActivity extends BaseGameActivity {
// Khai báo thêm 2 biến quan trọng
private Camera MyCamera;// Biến này thường để cấu hình màn hình
private Scene MyScene;// Quản lý những gì bạn vẽ.

private int WIDTH = 320;// Chiều rộng vùng hiện thị
private int HEIGHT = 480;// Chiều cao vùng hiện thị

private BitmapTextureAtlas bitmapTextureAtlas;// Lưu ảnh trong bộ nhớ
private TextureRegion textureRegion;// Lưu khi load ảnh
private Sprite sprite;// Sprite quả bóng

@Override
public Engine onLoadEngine() {
// Khởi tạo vùng hiện thị là 320*480
this.MyCamera = new Camera(0, 0, WIDTH, HEIGHT);
// Yêu cầu màn hình hiện thị nằm ngang thì ScreenOrientation.LANDSCAPE
Engine engine = new Engine(new EngineOptions(true,
ScreenOrientation.PORTRAIT, new RatioResolutionPolicy(WIDTH,
HEIGHT), this.MyCamera));
return engine;
}

@Override
public void onLoadResources() {
// Khai báo vùng lưu trữ ảnh có kích thước 256,256. Đây là cái khó nhất
// đó. Sẽ giải thích sau.
this.bitmapTextureAtlas = new BitmapTextureAtlas(256, 256,
TextureOptions.BILINEAR_PREMULTIPLYALPHA);
// Load ảnh
22

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn
this.textureRegion = BitmapTextureAtlasTextureRegionFactory
.createFromAsset(this.bitmapTextureAtlas, this, "ball.png", 0,
0);
mEngine.getTextureManager().loadTextures(this.bitmapTextureAtlas);
}

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

MyScene = new Scene();
MyScene.setBackground(new ColorBackground(0.09804f, 0.6274f, 0.8784f));// Đặt màu nền

// Đặt sprite tại vị trí x = 100,y = 100
this.sprite = new Sprite(100, 100, this.textureRegion);
MyScene.attachChild(sprite);// Add vào MyScene

// Cập nhật (coi như vòn lặp hoạt cảnh)
MyScene.registerUpdateHandler(new IUpdateHandler() {
@Override
public void reset() {
// TODO Auto-generated method stub
}

boolean chuyen = false;

// Muốn cập nhật cái gì thì cho vào đây
@Override
public void onUpdate(float pSecondsElapsed) {
try {
// Tạm dừng cập nhật trong 10 ms
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Di chuyển sang phải
if (!chuyen) {
sprite.setPosition(sprite.getX() + 5, 100);
if (sprite.getX() > 200)// Vượt quá giới hạn thì cho di
23

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn
// chuyển ngược lại
chuyen = true;
} else {
sprite.setPosition(sprite.getX() - 5, 100);
if (sprite.getX() < 10)
chuyen = false;
}
}
});

return MyScene;
}

@Override
public void onLoadComplete() {}
}
Source đính kèm
AndEngine_Test04.rar

8.5 Tuơng tác với giao diện và sprite :
Thêm 1 ảnh vào thư mục asset :
Pic 1 : ball.png

Đoạn code chính trong BaseGameActivity
public class MainActivity extends BaseGameActivity {

// Khai báo thêm 2 biến quan trọng
private Camera MyCamera;// Biến này thường để cấu hình màn hình
private Scene MyScene;// Quản lý những gì bạn vẽ.

private int WIDTH = 320;// Chiều rộng vùng hiện thị
private int HEIGHT = 480;// Chiều cao vùng hiện thị

private BitmapTextureAtlas bitmapTextureAtlas;// Lưu ảnh trong bộ nhớ
24

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn
private TextureRegion textureRegion;// Lưu khi load ảnh
private Sprite sprite;// Sprite quả bóng

/** Called when the activity is first created. */
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

@Override
public Engine onLoadEngine() {
// Khởi tạo vùng hiện thị là 320*480
this.MyCamera = new Camera(0, 0, WIDTH, HEIGHT);
// Yêu cầu màn hình hiện thị nằm ngang thì ScreenOrientation.LANDSCAPE
Engine engine = new Engine(new EngineOptions(true,
ScreenOrientation.PORTRAIT, new RatioResolutionPolicy(WIDTH,
HEIGHT), this.MyCamera));
return engine;
}

@Override
public void onLoadResources() {
// Khai báo vùng lưu trữ ảnh có kích thước 256,256. Đây là cái khó nhất
// đó. Sẽ giải thích sau.
this.bitmapTextureAtlas = new BitmapTextureAtlas(256, 256,
TextureOptions.BILINEAR_PREMULTIPLYALPHA);
// Load ảnh
this.textureRegion = BitmapTextureAtlasTextureRegionFactory
.createFromAsset(this.bitmapTextureAtlas, this, "ball.png", 0,
0);
mEngine.getTextureManager().loadTextures(this.bitmapTextureAtlas);
}

@Override
25

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn
public Scene onLoadScene() {
this.mEngine.registerUpdateHandler(new FPSLogger());

MyScene = new Scene();
MyScene.setBackground(new ColorBackground(0.09804f, 0.6274f, 0.8784f));// Đặt màu nền

// =================LẮNG NGHE SỰ KIỆN CHẠM VÀO MÀN HÌNH MyScene=======================
// Bắt sự kiện khi chạm vào MyScene
MyScene.setTouchAreaBindingEnabled(true);// cho phép lắng nghe
MyScene.setOnSceneTouchListener(new IOnSceneTouchListener() {
public boolean onSceneTouchEvent(final Scene pScene,
final TouchEvent pSceneTouchEvent) {
System.out.println("MyScene onSceneTouchEvent: chạm vào màn hình");
System.out.println("Tọa độ X = " + pSceneTouchEvent.getX());
System.out.println("Tọa độ Y = " + pSceneTouchEvent.getY());

// Khi chạm vào màn hình ta di chuyển sprite theo tọ độ y.
sprite.setPosition(sprite.getX(), pSceneTouchEvent.getY());
return true;
}
});
// =====================LẮNG NGHE SỰ KIỆN KHI CHẠM VÀO SPRITE==========================
// Đặt sprite tại vị trí x = 100,y = 100
this.sprite = new Sprite(100, 100, this.textureRegion) {
// Lắng nghe sự kiện khi chạm vào sprite
@Override
public boolean onAreaTouched(final TouchEvent pSceneTouchEvent,
final float pTouchAreaLocalX, final float pTouchAreaLocalY) {
if (pSceneTouchEvent.getAction() == TouchEvent.ACTION_DOWN) {
System.out.println("Sprite onAreaTouched: chạm vào sprite");
System.out.println("Tọa độ X = " + pTouchAreaLocalX);
System.out.println("Tọa độ Y = " + pTouchAreaLocalY);
}
return true;
}
};
MyScene.attachChild(sprite);// Add vào MyScene
MyScene.registerTouchArea(sprite);// Phải đăng ký là cho phép sprite này được lắng nghe sự kiện
// ======================================================================================
// Cập nhật (coi như vòn lặp hoạt cảnh)
26

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn
MyScene.registerUpdateHandler(new IUpdateHandler() {
@Override
public void reset() {
// TODO Auto-generated method stub
}

boolean chuyen = false;

// Muốn cập nhật cái gì thì cho vào đây
@Override
public void onUpdate(float pSecondsElapsed) {
try {
// Tạm dừng cập nhật trong 10 ms
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Di chuyển sang phải
if (!chuyen) {
sprite.setPosition(sprite.getX() + 5, sprite.getY());
if (sprite.getX() > 200)// Vượt quá giới hạn thì cho di chuyển ngược lại
chuyen = true;
} else {
sprite.setPosition(sprite.getX() - 5, sprite.getY());
if (sprite.getX() < 10)
chuyen = false;
}
}
});

return MyScene;
}

@Override
public void onLoadComplete() {}
}
Source đính kèm
27

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn
AndEngine_Test05.rar

8.6 Tạo sprite chuyển động từ 1 ảnh :
Thêm 1 ảnh vào thư mục asset :
Pic 1 : sprite.png

Đoạn code chính trong BaseGameActivity
public class MainActivity extends BaseGameActivity {
//Khai báo thêm 2 biến quan trọng
private Camera MyCamera;//Biến này thường để cấu hình màn hình
private Scene MyScene;//Quản lý những gì bạn vẽ.

private int WIDTH = 320;//Chiều rộng vùng hiện thị
private int HEIGHT = 480;//Chiều cao vùng hiện thị

private BitmapTextureAtlas bitmapTextureAtlas;//Lưu ảnh trong bộ nhớ
private TiledTextureRegion tiledTextureRegion;//Lưu khi load ảnh
private AnimatedSprite animatedSprite ;//AnimatedSprite

/** Called when the activity is first created. */
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
28

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn
return true;
}

@Override
public Engine onLoadEngine() {
//Khởi tạo vùng hiện thị là 320*480
this.MyCamera = new Camera(0, 0, WIDTH, HEIGHT);
//Yêu cầu màn hình hiện thị nằm ngang thì ScreenOrientation.LANDSCAPE
Engine engine = new Engine(new EngineOptions(true, ScreenOrientation.PORTRAIT,
new RatioResolutionPolicy(WIDTH, HEIGHT), this.MyCamera));
return engine;
}

@Override
public void onLoadResources() {
//Bức ảnh chỉ rộng 512 và cao 512 nên ta khai báo theo đúng kích thước để đỡ tốn bộ nhớ
this.bitmapTextureAtlas = new BitmapTextureAtlas(512, 512, TextureOptions.BILINEAR);
//Số 4 ở đây là 4 cột và 4 hàng
this.tiledTextureRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(this.bitmapTextureAtlas, this,
"sprite.png", 0, 0, 4, 4);
this.mEngine.getTextureManager().loadTexture(this.bitmapTextureAtlas);
}

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

MyScene = new Scene();
MyScene.setBackground(new ColorBackground(0.09804f, 0.6274f, 0.8784f));//Đặt màu nền

//=====================LẮNG NGHE SỰ KIỆN CHẠM VÀO MÀN HÌNH
MyScene===============================
//Bắt sự kiện khi chạm vào MyScene
MyScene.setTouchAreaBindingEnabled(true);//cho phép lắng nghe
MyScene.setOnSceneTouchListener(new IOnSceneTouchListener() {
public boolean onSceneTouchEvent(final Scene pScene, final TouchEvent pSceneTouchEvent) {
System.out.println("Sprite onSceneTouchEvent: chạm vào màn hình");
System.out.println("Tọa độ X = "+pSceneTouchEvent.getX());
System.out.println("Tọa độ Y = "+pSceneTouchEvent.getY());

29

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn
//Khi chạm vào màn hình ta di chuyển AnimatedSprite theo tọ độ y.
animatedSprite.setPosition(animatedSprite.getX(), pSceneTouchEvent.getY());
return true;
}
});
//====================LẮNG NGHE SỰ KIỆN KHI CHẠM VÀO ANIMATEDSPRITE=============================
//Đặt AnimatedSprite tại vị trí x = 100,y = 100
this.animatedSprite = new AnimatedSprite(100, 100, this.tiledTextureRegion){
//Lắng nghe sự kiện khi chạm vào sprite
@Override
public boolean onAreaTouched(final TouchEvent pSceneTouchEvent, final float pTouchAreaLocalX, final float
pTouchAreaLocalY) {
if(pSceneTouchEvent.getAction() == TouchEvent.ACTION_DOWN){
System.out.println("AnimatedSprite onAreaTouched: chạm vào animatedSprite");
System.out.println("Tọa độ X = "+pTouchAreaLocalX);
System.out.println("Tọa độ Y = "+pTouchAreaLocalY);
}
return true;
}
};
animatedSprite.animate(100);//Sau 100milis ta sẽ đổi bức ảnh
MyScene.attachChild(animatedSprite);//Add vào MyScene
MyScene.registerTouchArea(animatedSprite);//Phải đăng ký là cho phép AnimatedSprite này được lắng nghe sự kiện
//=====================================================================================
//Cập nhật (coi như vòng lặp hoạt cảnh)
MyScene.registerUpdateHandler(new IUpdateHandler() {
@Override
public void reset() {
// TODO Auto-generated method stub
}

boolean chuyen = false;
//Muốn cập nhật cái gì thì cho vào đây
@Override
public void onUpdate(float pSecondsElapsed) {
try {
//Tạm dừng cập nhật trong 10 ms
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
30

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn
e.printStackTrace();
}
//Di chuyển sang phải
if(!chuyen){
animatedSprite.setPosition(animatedSprite.getX()+5, animatedSprite.getY());
if(animatedSprite.getX() > 200)//Vượt quá giới hạn thì cho di chuyển ngược lại
chuyen = true;
}else{
animatedSprite.setPosition(animatedSprite.getX()-5, animatedSprite.getY());
if(animatedSprite.getX() < 10)
chuyen = false;
}
}
});
return MyScene;
}
@Override
public void onLoadComplete() {}

}
Source đính kèm
AndEngine_Test06.rar

8.7 Tạo kết hợp sprite chuyển động và ảnh nền :
Thêm 1 ảnh vào thư mục asset :
Pic 1: sprite.png

Pic 2: ball.png
31

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn

Đoạn code chính trong BaseGameActivity :
public class MainActivity extends BaseGameActivity {
//Khai báo thêm 2 biến quan trọng
private Camera MyCamera;//Biến này thường để cấu hình màn hình
private Scene MyScene;//Quản lý những gì bạn vẽ.

private int WIDTH = 320;//Chiều rộng vùng hiện thị
private int HEIGHT = 480;//Chiều cao vùng hiện thị


private BitmapTextureAtlas bitmapTextureAtlas;//Lưu ảnh trong bộ nhớ
private TiledTextureRegion tiledTextureRegion;//Lưu khi load ảnh
private AnimatedSprite animatedSprite ;//AnimatedSprite

private RepeatingSpriteBackground mGrassBackground;//Khai báo đối tượng để làm thực hiện lặp ảnh tạo cảnh nền

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}

@Override
public Engine onLoadEngine() {
//Khởi tạo vùng hiện thị là 320*480
this.MyCamera = new Camera(0, 0, WIDTH, HEIGHT);
//Yêu cầu màn hình hiện thị nằm ngang thì ScreenOrientation.LANDSCAPE
Engine engine = new Engine(new EngineOptions(true, ScreenOrientation.PORTRAIT,
new RatioResolutionPolicy(WIDTH, HEIGHT),
this.MyCamera));
return engine;
}

@Override
public void onLoadResources() {
32

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn
//Bức ảnh chỉ rộng 64 và cao 32 nên ta khai báo theo đúng kích thước để đỡ tốn bộ nhớ
this.bitmapTextureAtlas = new BitmapTextureAtlas(512, 512, TextureOptions.BILINEAR);
//Số 2 ở đây là 2 cột. Số 1 tức là có 1 hàng
this.tiledTextureRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(this.bitmapTextureAtlas, this,
"sprite.png", 0, 0, 4, 4);

//Load ảnh từ thư mục Assets
this.mGrassBackground = new RepeatingSpriteBackground(WIDTH, HEIGHT, this.mEngine.getTextureManager(), new
AssetBitmapTextureAtlasSource(this, "ball.png"));

this.mEngine.getTextureManager().loadTexture(this.bitmapTextureAtlas);
}

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

MyScene = new Scene();
MyScene.setBackground(this.mGrassBackground);//Đặt đối tượng mGrassBackground làm cảnh nền


//=====================LẮNG NGHE SỰ KIỆN CHẠM VÀO MÀN HÌNH MyScene==============================
//Bắt sự kiện khi chạm vào MyScene
MyScene.setTouchAreaBindingEnabled(true);//cho phép lắng nghe
MyScene.setOnSceneTouchListener(new IOnSceneTouchListener() {
public boolean onSceneTouchEvent(final Scene pScene, final TouchEvent pSceneTouchEvent) {
System.out.println("Sprite onSceneTouchEvent: chạm vào màn hình");
System.out.println("Tọa độ X = "+pSceneTouchEvent.getX());
System.out.println("Tọa độ Y = "+pSceneTouchEvent.getY());

//Khi chạm vào màn hình ta di chuyển AnimatedSprite theo tọ độ y.
animatedSprite.setPosition(animatedSprite.getX(), pSceneTouchEvent.getY());
return true;
}
});
//====================LẮNG NGHE SỰ KIỆN KHI CHẠM VÀO ANIMATEDSPRITE============================
//Đặt AnimatedSprite tại vị trí x = 100,y = 100
this.animatedSprite = new AnimatedSprite(100, 100, this.tiledTextureRegion){
//Lắng nghe sự kiện khi chạm vào sprite
@Override
33

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn
public boolean onAreaTouched(final TouchEvent pSceneTouchEvent, final float pTouchAreaLocalX, final float
pTouchAreaLocalY) {
if(pSceneTouchEvent.getAction() == TouchEvent.ACTION_DOWN){
System.out.println("AnimatedSprite onAreaTouched: chạm vào animatedSprite");
System.out.println("Tọa độ X = "+pTouchAreaLocalX);
System.out.println("Tọa độ Y = "+pTouchAreaLocalY);
}
return true;
}
};
animatedSprite.animate(100);//Sau 100milis ta sẽ đổi bức ảnh
MyScene.attachChild(animatedSprite);//Add vào MyScene
MyScene.registerTouchArea(animatedSprite);//Phải đăng ký là cho phép AnimatedSprite này được lắng nghe sự kiện
//======================================================================================
//Cập nhật (coi như vòng lặp hoạt cảnh)
MyScene.registerUpdateHandler(new IUpdateHandler() {
@Override
public void reset() {
// TODO Auto-generated method stub
}

boolean chuyen = false;
//Muốn cập nhật cái gì thì cho vào đây
@Override
public void onUpdate(float pSecondsElapsed) {
try {
//Tạm dừng cập nhật trong 10 ms
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//Di chuyển sang phải
if(!chuyen){
animatedSprite.setPosition(animatedSprite.getX()+5, animatedSprite.getY());
if(animatedSprite.getX() > 200)//Vượt quá giới hạn thì cho di chuyển ngược lại
chuyen = true;
}else{
animatedSprite.setPosition(animatedSprite.getX()-5, animatedSprite.getY());
if(animatedSprite.getX() < 10)
34

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn
chuyen = false;
}
}
});

return MyScene;
}
@Override
public void onLoadComplete() {}
}
Source đính kèm
AndEngine_Test07.rar

8.8 Xác định va chạm giữa 2 sprite với nhau :
Thêm 1 ảnh vào thư mục asset :
Pic 1: bg_image.png

Pic 3 : ball.png

Đoạn code chính trong BaseGameActivity :
public class MainActivity extends BaseGameActivity {
//Khai báo thêm 2 biến quan trọng
private Camera MyCamera;//Biến này thường để cấu hình màn hình
private Scene MyScene;//Quản lý những gì bạn vẽ.

private int WIDTH = 320;//Chiều rộng vùng hiện thị
private int HEIGHT = 480;//Chiều cao vùng hiện thị


35

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn
private BitmapTextureAtlas bitmapTextureAtlas;//Lưu ảnh trong bộ nhớ
private TextureRegion textureRegion;//Lưu khi load ảnh
private Sprite sprite1,sprite2;//Sprite quả bóng

private BitmapTextureAtlas bg_bitmapTextureAtlas;//Lưu ảnh trong bộ nhớ
private TextureRegion bg_textureRegion;//Lưu khi load ảnh
private Sprite bg_sprite;//Sprite tạo cảnh nền

/** Called when the activity is first created. */
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

@Override
public Engine onLoadEngine() {
//Khởi tạo vùng hiện thị là 320*480
this.MyCamera = new Camera(0, 0, WIDTH, HEIGHT);
//Yêu cầu màn hình hiện thị nằm ngang thì ScreenOrientation.LANDSCAPE
Engine engine = new Engine(new EngineOptions(true, ScreenOrientation.PORTRAIT,
new RatioResolutionPolicy(WIDTH, HEIGHT),
this.MyCamera));
return engine;
}

@Override
public void onLoadResources() {
//Khai báo vùng lưu trữ ảnh có kích thước 256,256. Đây là cái khó nhất đó. Sẽ giải thích sau.
this.bitmapTextureAtlas = new BitmapTextureAtlas(256, 256, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
//Load ảnh
this.textureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.bitmapTextureAtlas, this, "ball.png", 0,
0);
mEngine.getTextureManager().loadTextures(this.bitmapTextureAtlas);
36

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn


this.bg_bitmapTextureAtlas = new BitmapTextureAtlas(512, 512, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
this.bg_textureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.bg_bitmapTextureAtlas, this,
"bg_image.png", 0, 0);
mEngine.getTextureManager().loadTextures(this.bg_bitmapTextureAtlas);
}

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

MyScene = new Scene();
this.bg_sprite = new Sprite(0, 0, this.bg_textureRegion);
MyScene.setBackground(new SpriteBackground(this.bg_sprite));

//Đặt sprite1 tại vị trí x = 0,y = 100
this.sprite1 = new Sprite(0, 100, this.textureRegion);
MyScene.attachChild(sprite1);//Add vào MyScene

//Đặt sprite2 tại vị trí x = 300,y = 100
this.sprite2 = new Sprite(300, 100, this.textureRegion);
MyScene.attachChild(sprite2);//Add vào MyScene

//Cập nhật (coi như vòng lặp hoạt cảnh)
MyScene.registerUpdateHandler(new IUpdateHandler() {
@Override
public void reset() {
// TODO Auto-generated method stub
}

//Muốn cập nhật cái gì thì cho vào đây
@Override
public void onUpdate(float pSecondsElapsed) {
//Quả bóng đầu tiên là chạy từ phải qua trái
MainActivity.this.sprite1.setPosition(MainActivity.this.sprite1.getX()+1, MainActivity.this.sprite1.getY());

//Quả bóng thứ 2 sẽ chạy được lại từ trái qua phải
MainActivity.this.sprite2.setPosition(MainActivity.this.sprite2.getX()-1, MainActivity.this.sprite2.getY());

37

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn
//Nếu 2 quảng bóng này va chạm vào nhau ta cho nó quay lại vị trí khởi tạo
if(MainActivity.this.sprite1.collidesWith(MainActivity.this.sprite2)){
MainActivity.this.sprite1.setPosition(0, MainActivity.this.sprite1.getY());
MainActivity.this.sprite2.setPosition(300, MainActivity.this.sprite2.getY());
}
}
});
return MyScene;
}
@Override
public void onLoadComplete() {}
}
8.9 Tạo controler tương tác với sprite :
Thêm 1 ảnh vào thư mục asset :
Pic 1 : ControlBase.png

Pic 2 : ControlKnob.png

Pic 3 : ball.png

Pic 4 : bg_image.png
38

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn

Đoạn code chính trong BaseGameActivity :
public class MainActivity extends BaseGameActivity {
//Khai báo thêm 2 biến quan trọng
private Camera MyCamera;//Biến này thường để cấu hình màn hình
private Scene MyScene;//Quản lý những gì bạn vẽ.

private int WIDTH = 480;//Chiều rộng vùng hiện thị
private int HEIGHT = 320;//Chiều cao vùng hiện thị

private BitmapTextureAtlas bitmapTextureAtlas;//Lưu ảnh trong bộ nhớ
private TextureRegion textureRegion;//Lưu khi load ảnh
private Sprite sprite;//Sprite quả bóng

private BitmapTextureAtlas bg_bitmapTextureAtlas;//Lưu ảnh trong bộ nhớ
private TextureRegion bg_textureRegion;//Lưu khi load ảnh
private Sprite bg_sprite;//Sprite tạo cảnh nền

//Khai báo các biến dùng cho vùng điều khiển
private DigitalOnScreenControl mDigitalOnScreenControl;
private BitmapTextureAtlas mOnScreenControlTexture;
private TextureRegion mOnScreenControlBaseTextureRegion;
private TextureRegion mOnScreenControlKnobTextureRegion;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
39

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn

@Override
public Engine onLoadEngine() {
//Khởi tạo vùng hiện thị là 320*480
this.MyCamera = new Camera(0, 0, WIDTH, HEIGHT);
//Yêu cầu màn hình hiện thị nằm ngang thì ScreenOrientation.LANDSCAPE
Engine engine = new Engine(new EngineOptions(true, ScreenOrientation.LANDSCAPE,
new RatioResolutionPolicy(WIDTH, HEIGHT), this.MyCamera));
return engine;
}

@Override
public void onLoadResources() {
//Khai báo vùng lưu trữ ảnh có kích thước 256,256. Đây là cái khó nhất đó. Sẽ giải thích sau.
this.bitmapTextureAtlas = new BitmapTextureAtlas(256, 256, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
//Load ảnh
this.textureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.bitmapTextureAtlas, this, "ball.png", 0,
0);
mEngine.getTextureManager().loadTextures(this.bitmapTextureAtlas);

this.bg_bitmapTextureAtlas = new BitmapTextureAtlas(512, 512, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
this.bg_textureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.bg_bitmapTextureAtlas, this,
"bg_image.png", 0, 0);
mEngine.getTextureManager().loadTextures(this.bg_bitmapTextureAtlas);

//Load phần điều khiển
this.mOnScreenControlTexture = new BitmapTextureAtlas(256, 256, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
this.mOnScreenControlBaseTextureRegion =
BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mOnScreenControlTexture, this, "ControlBase.png", 0, 0);
this.mOnScreenControlKnobTextureRegion =
BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mOnScreenControlTexture, this, "ControlKnob.png", 128, 0);
this.mEngine.getTextureManager().loadTextures(this.mOnScreenControlTexture);
}

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

MyScene = new Scene();
this.bg_sprite = new Sprite(0, 0, this.bg_textureRegion);
40

Trương Thanh Anh Tuấn
Email:tuanatt@nahi.vn
MyScene.setBackground(new SpriteBackground(this.bg_sprite));

//Đặt sprite1 tại vị trí x = 100,y = 100
this.sprite = new Sprite(100, 100, this.textureRegion);
MyScene.attachChild(sprite);//Add vào MyScene

//=======================================ĐIỂM QUAN TRỌNG NHẤT================
//Khai báo và sử lý điều kiện khi ta chạm vào vùng điều khiển
mDigitalOnScreenControl = new DigitalOnScreenControl(0, HEIGHT - this.mOnScreenControlBaseTextureRegion.getHeight(),
this.MyCamera, this.mOnScreenControlBaseTextureRegion, this.mOnScreenControlKnobTextureRegion, 0.1f,
new IOnScreenControlListener() {
public void onControlChange(final BaseOnScreenControl pBaseOnScreenControl, final float pValueX, final float
pValueY) {
// vùng điều khiển thay đổi ta sẽ cho sprite di chuyển theo hướng ta điều khiển
MainActivity.this.sprite.setPosition(MainActivity.this.sprite.getX() + pValueX, MainActivity.this.sprite.getY() + pValueY);
}
});
mDigitalOnScreenControl.getControlBase().setBlendFunction(GL10.GL_SRC_ALPHA,
GL10.GL_ONE_MINUS_SRC_ALPHA);
mDigitalOnScreenControl.getControlBase().setAlpha(0.7f);
mDigitalOnScreenControl.getControlBase().setScaleCenter(0, 128);
mDigitalOnScreenControl.getControlBase().setScale(0.8f);
mDigitalOnScreenControl.getControlKnob().setScale(0.8f);
mDigitalOnScreenControl.refreshControlKnobPosition();

MyScene.setChildScene(mDigitalOnScreenControl);
//==============================================================================
return MyScene;
}

@Override
public void onLoadComplete() {}
}
Source đính kèm
AndEngine_Test09.rar

Nguồn tham khảo:
+android.vn
+andengine.org