Upload
quang-nguyen
View
135
Download
11
Embed Size (px)
Citation preview
Giới thiệu E3droid
E3droid là 1 framework game android 2D.Framework này hoàn toàn free, anh em tha hồ phát triển mà không sợ gì cả. Cái này cũng có khá nhiều ưu điểm như:
Easy to use API Sprites and Sprite Sheets support
Layer management
Sprite Modifiers (Move, Rotate, Scale, Sequence, Reverse, Loop…)
Ease Functions(Exp, Sin, Bounce, Back In…)
Text rendering(fixed and dynamic)
On Screen Analog/Digital Contoller with multi touch support
Tiled maps (Orthogonal maps)
OpenGL ES 1.1 based
Uses Vertex Buffer Object(VBO)
Integrated with XML Layout
2D Physics using Box2D (libgdx powered)
TMX Tiled Map support (map editor can be downloaded from http://www.mapeditor.org/)
Soft input keyboard capability
Lua: Lightweight scripting language support
NEW - JavaScript scripting support
NEW - Audio input capability
NEW - Handy debug console
Lots of example included
… and more!
Mọi thông tin về E3droid các bạn có thể đọc tại link: http://www.e3roid.com/
Hướng dẫn download mã nguồn E3droid
Trước khi code game với E3droid thì chúng ta cần có thư viễn đã nhỉ.link downlaod: http://www.mediafire.com/?2u7cla7s15is553
Hoặc các bạn có thể download trực tiếp từ trang web: https://code.google.com/p/e3roid/dow...oid-1.2.11.zip
Các bạn download về rồi giải nén nhé. Bài sau mình sẽ nói 1 chút về mấy cái file các bạn vừa download về.
Những gì tôi học ngày hôm qua là nhứng gì bạn được đọc ngày hôm nay. Game Android
Cùng xem qua cấu trúc file E3droid.zip
Các bạn đã download được bộ mã nguồn, giờ là lúc chúng ta cùng mổ sẻ nó ra.Khi giải nén thì trong gói này chia làm 2 phần.
Phần 1: (e3roid-1.2.11\E3roid). Trong thư mục này là toàn bộ mã nguồn của E3droid. Nếu bạn nào thích phát triển mã nguồn này thì các bạn có thể build ra 1 framework riêng cho mình.
Phần 2: (e3roid-1.2.11\E3roidExamples). Đây là ví dụ mà framework cung cấp, chúng ta sẽ cùng nhau tìm hiểu từng ví dụ 1.
Bài tiếp theo chúng ta cùng tạo ra 1 project cơ bản bằng E3droid. Chúc các bạn thành công.
Những gì tôi học ngày hôm qua là nhứng gì bạn được đọc ngày hôm nay. Game Android
Bài 1: Vẽ 1 hình đơn giản lên màn hình (E3droid)
Hôm nay mình bắt đầu hướng dẫn các bạn code game với E3droid. Bài đâu tiên luôn là bài đơn giản, mục đích bài đầu này là cho các bạn thấy để vẽ 1 hình rất đơn giản.
Các bạn xem qua code sau đây. Hết dòng code là mình sẽ giải thích.PHP Code:package Bai_1_e3droid.gioi;
import android.view.MotionEvent;
import com.e3roid.E3Activity; import com.e3roid.E3Engine;
import com.e3roid.E3Scene; import com.e3roid.drawable.Shape;
public class Bai_1_e3droidActivity extends E3Activity {
private final static int WIDTH = 320;//Chiều rộng của màn hình private final static int HEIGHT = 480;//Chiều cao của màn hình private final static int BOX_SIZE = 50;//Kích thước của 1 box
private Shape shape1, shape2, shape3, shape4;//Khai báo 4 biến shape @Override public E3Engine onLoadEngine() { E3Engine engine = new E3Engine(this, WIDTH, HEIGHT);//Thiết lập chiều cao và rộng engine.requestFullScreen();//Set màn hình full engine.requestPortrait(); return engine; }
@Override public E3Scene onLoadScene() { E3Scene scene = new E3Scene(); scene.addEventListener(this);//Bắt sự kiện khi bạn chạm lên màn hình //Khỏi tạo màu cho các hình. (Các bạn thử thay đổi các giá trị xem sao nhé) shape1.setColor(1, 0, 0, 1); shape2.setColor(0, 1, 0, 1); shape3.setColor(0, 0, 1, 1); shape4.setColor(1, 1, 0, 1); //Hiện thị các hình này lên. Chú ý: nếu không add mấy cái shape vào thì sẽ không bao giờ nhìn thấy trên //màn hình scene.getTopLayer().add(shape1); scene.getTopLayer().add(shape2); scene.getTopLayer().add(shape3); scene.getTopLayer().add(shape4); return scene; }
@Override public void onLoadResources() { int centerX = getWidth() / 2;//Xác định ví trí trung tâm theo tọa độ X
int centerY = getHeight() / 2;//Xác định ví trí trung tâm theo tọa độ Y //Khởi tạo vị trí cho các hình này khi hiện thị lên màn hình shape1 = new Shape(centerX, centerY, BOX_SIZE, BOX_SIZE); shape2 = new Shape(centerX-BOX_SIZE, centerY-BOX_SIZE, BOX_SIZE, BOX_SIZE); shape3 = new Shape(centerX-BOX_SIZE, centerY, BOX_SIZE, BOX_SIZE); shape4 = new Shape(centerX, centerY-BOX_SIZE, BOX_SIZE, BOX_SIZE); }
@Override public boolean onSceneTouchEvent(E3Scene scene, MotionEvent motionEvent) {
// shape1(red box) rotates and scales when touchEvent ACTION_DOWN occurs. if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) { //Thực hiện xoay hình shape1 và phóng to khi bạn chạm vào màn hình
shape1.rotate(shape1.getAngle() + 20.0f, BOX_SIZE/2, BOX_SIZE/2); shape1.scale(shape1.getScaleX() + 0.2f, shape1.getScaleY() + 0.2f, BOX_SIZE / 2, BOX_SIZE / 2); } return false; } }
Kết quả:
Trong đoạn code này có 2 phần rất quan trọng.Phương thức: public E3Engine onLoadEngine() thường dùng để định nghĩa về màn hình. Ví dụ như chiều cao, chiều rộng, đặt cho màn hình full, đặt màn hình nằm ngang...(Cái này phải nghiên cứu tiếp).
Phương thức: public E3Scene onLoadScene() nơi mà bạn thảo thích sáng tạo, nó như 1 cái bảng để cho các bạn vẽ lên vậy, nhưng cái bảng này nó chia thành các tầng.
Đây là link donwload code Bài 1: http://www.mediafire.com/?t38civsyy1g8rgp
Các bạn download project sau đó dùng eclip mở lên và chạy thử nhé.Nhớ là phải Configure cái thư viện nhé.
Bài 2: Vẽ 1 sprite (E3droid)
Bài này mình sẽ load 1 ảnh và khai báo 1 sprite, sau đó vẽ sprite.
Trong code có coment rồi.(Chỗ nào quên các bạn đọc lại coment ở bài 1 nhé.)
PHP Code:package Bai_2_e3droid.gioi;
import android.view.MotionEvent;
import com.e3roid.E3Activity;import com.e3roid.E3Engine;import com.e3roid.E3Scene;import com.e3roid.drawable.Sprite;import com.e3roid.drawable.texture.AssetTexture;import com.e3roid.drawable.texture.Texture;
public class Bai_2_e3droidActivity extends E3Activity {
private final static int WIDTH = 320; private final static int HEIGHT = 480; //Khai báo 1 sprite có tên là robot private Sprite robot; //Khai báo 1 Texture. Đối tượng này để load ảnh lên private Texture robotTexture;
@Override public E3Engine onLoadEngine() { E3Engine engine = new E3Engine(this, WIDTH, HEIGHT); engine.requestFullScreen(); engine.requestPortrait(); return engine; }
@Override public E3Scene onLoadScene() { E3Scene scene = new E3Scene(); scene.addEventListener(this); int centerX = (getWidth() - robotTexture.getWidth()) / 2; int centerY = (getHeight() - robotTexture.getHeight()) / 2;
//Khởi tạo đối tượng robot và đạt nó nằm ở vị trí chung tâm. robot = new Sprite(robotTexture, centerX, centerY); //add vào màn hình. scene.getTopLayer().add(robot); return scene; }
@Override public void onLoadResources() { //Load ảnh từ thư mục Asset robotTexture = new AssetTexture("robot.png", this); }
@Override public boolean onSceneTouchEvent(E3Scene scene, MotionEvent motionEvent) { if (robot != null) { // robot rotates and scales when touchEvent ACTION_DOWN occurs. if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) { //Xoay đối tượng robot và phóng to robot.rotate(robot.getAngle() + 20.0f, (robotTexture.getWidth() / 2), (robotTexture.getHeight() / 2)); robot.scale(robot.getScaleX() + 0.2f, robot.getScaleY() + 0.2f,(robotTexture.getWidth() / 2), (robotTexture.getHeight() / 2)); } } return false; } }
Kết quả bài 2:
Có chỗ nào mà không hiểu thì các bạn đọc lại bài 1 nhé.
Trong bài 2 này có thêm 1 phương thức mới: public void onLoadResources(). Phương thức này
được gọi khi ta load các tài nguyên (Load ảnh, âm thanh, load font).
Link download code bài 2: http://www.mediafire.com/?omc7ui6blb63mls
Bài 3 mình sẽ hướng dẫn các bạn vẽ sprite và sau đó làm cho sprite này di chuyển trên màn hình.
Chúc các bạn thành công.
Bài viết có hay thì mong cả nhà thanks nhé
Bài 3: Vẽ sprite di chuyển trên màn hình
Bài hôm nay sẽ giới thiệu với các bạn cách vẽ 1 sprite chuyển động trên màn hình. Bài này đơn giản là cho sprite chạy sang trái, nếu nó gặp biên màn hình thì nó chạy sang phải, và ngược lại.
Code: Các bạn đã đọc bài 2 rồi chứ, bài này chỉ thêm chút thôi, phần chữ to và in đậm là phần khác với bài 2.PHP Code:package Bai_3_e3droid.gioi;
import android.view.MotionEvent;
import com.e3roid.E3Activity;import com.e3roid.E3Engine;import com.e3roid.E3Scene;import com.e3roid.drawable.Sprite;import com.e3roid.drawable.texture.AssetTexture;import com.e3roid.drawable.texture.Texture;import com.e3roid.event.SceneUpdateListener;
//Để tạo được vòng lặp trong game ta cần implements SceneUpdateListenerpublic class Bai_3_e3droidActivity extends E3Activity implements SceneUpdateListener {
private final static int WIDTH = 320; private final static int HEIGHT = 480; //Vì sprite của chúng ta chỉ di chuyển theo hương từ trái qua phải nên ta chỉ cần thay đổi // giá trị x. Ta khai báo thêm 1 biến x nữa. int x = 0; //Để biết khi nào là sprite di chuyển chạm vào biên ta thêm 1 biến để xác định điều này. boolean check = false; //Khai báo 1 sprite có tên là robot private Sprite robot;
//Khai báo 1 Texture. Đối tượng này để load ảnh lên private Texture robotTexture;
@Override public E3Engine onLoadEngine() { E3Engine engine = new E3Engine(this, WIDTH, HEIGHT); engine.requestFullScreen(); engine.requestPortrait(); return engine; }
@Override public E3Scene onLoadScene() { E3Scene scene = new E3Scene(); scene.addEventListener(this); //Cứ 30ms là làm tươi màn hình 1 lần scene.registerUpdateListener(30, this); //Khởi tạo đối tượng robot và đạt nó nằm ở vị trí (0,150). robot = new Sprite(robotTexture, 0, 150); //Khởi tạo x=0 x = 0; //Khỏi tạo check = false; check = false; //add vào màn hình. scene.getTopLayer().add(robot); return scene; }
@Override public void onLoadResources() { //Load ảnh từ thư mục Asset robotTexture = new AssetTexture("robot.png", this); }
@Override public boolean onSceneTouchEvent(E3Scene scene, MotionEvent motionEvent) { if (robot != null) { // robot rotates and scales when touchEvent ACTION_DOWN occurs. if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) { //Xoay đối tượng robot và phóng to robot.rotate(robot.getAngle() + 20.0f, (robotTexture.getWidth() / 2), (robotTexture.getHeight() / 2)); robot.scale(robot.getScaleX() + 0.2f, robot.getScaleY() + 0.2f,(robotTexture.getWidth() / 2), (robotTexture.getHeight() / 2)); } } return false; }
@Override public void onUpdateScene(E3Scene arg0, long arg1) { runOnUiThread(new Runnable() { public void run() {
//Ở đây ta sẽ cho sprite di chuyển nào if(!check){//Di chuyển sang phải x = 2; if(robot.getRealX() >= getWidth()){//Khi chạm vào biên ta đổi hướng di chuyển của sprite check = true; } } else{//Di chuyển sang trái x = -2; if(robot.getRealX() <= 0){//Khi chạm vào biên ta đổi hướng di chuyển của sprite check = false; } } //Di chuyển sprite robot.moveRelativeX(x); } }); } }
Vì bài này phát triển từ bài 2 nên mình không up project lên nữa. Các bạn chạy và kiểm tra kết quả nhé.Bài sau mình sẽ làm nhiều hơn. Cho sprite di chuyển ngang dọc tùy ý. Sau đó cho thêm 4-5 sprite cùng di chuyển trên màn hình. Mong cả nhà cùng nghiên cứu.
Hay thì thanks lấy tinh thần viết nhiều hơn nhé.
Bài 4: Vẽ nhiều sprite với sự di chuyển ngẫu nhiên
Bài này mình hướng dẫn các bạn vẽ nhiều sprite lên màn hình, các sprite này di chuyển ngẫu nhiên trên màn hình, nhưng không ra khỏi màn hình nhé.
Code:PHP Code:package Bai_4_e3droid.gioi;
import com.e3roid.E3Activity;import com.e3roid.E3Engine;import com.e3roid.E3Scene;import com.e3roid.drawable.Sprite;import com.e3roid.drawable.texture.AssetTexture;import com.e3roid.drawable.texture.Texture;import com.e3roid.event.SceneUpdateListener;
//Để tạo được vòng lặp trong game ta cần implements SceneUpdateListenerpublic class Bai_4_e3droidActivity extends E3Activity implements SceneUpdateLi
stener {
private final static int WIDTH = 320; private final static int HEIGHT = 480; //Khai báo mảng sprite có tên là robot private Sprite[] robot; //Khai báo 1 Texture. Đối tượng này để load ảnh lên private Texture robotTexture;
//--------------------------------------------------------------------------------------- @Override public E3Engine onLoadEngine() { E3Engine engine = new E3Engine(this, WIDTH, HEIGHT); engine.requestFullScreen(); engine.requestPortrait(); return engine; }
//--------------------------------------------------------------------------------------- @Override public E3Scene onLoadScene() { E3Scene scene = new E3Scene(); scene.addEventListener(this); //Cứ 30ms là làm tươi màn hình 1 lần scene.registerUpdateListener(30, this); //Khởi tạo đối tượng robot. robot = new Sprite[4];//Khai báo mảng gồm 4 sprite //Khởi tạo tứng sprite for(int i=0; i<robot.length;i++) robot[i] = new Sprite(robotTexture, 0, 0);//Đặt toàn bộ ở vị trí (0,0) //add toàn bộ sprite vào màn hình. for(int i=0; i<robot.length;i++) scene.getTopLayer().add(robot[i]); return scene; }
//--------------------------------------------------------------------------------------- @Override public void onLoadResources() { //Load ảnh từ thư mục Asset robotTexture = new AssetTexture("robot.png", this); } //--------------------------------------------------------------------------------------- @Override public void onUpdateScene(E3Scene arg0, long arg1) { runOnUiThread(new Runnable() { public void run() {
dichuyen(robot);//Gọi phương thức di chuyển để làm cho 4 sprite di chuyển ngẫu nhiên nhưng //không di chuyển ra khỏi màn hình } }); } //--------------------------------------------------------------------------------------- //Phương thức cho bạn 1 số ngẫu nhiên từ min->max. public int getRandomIndex(int min, int max) { return (int) (Math.random() * (max - min + 1)) + min; } //--------------------------------------------------------------------------------------- //Phương thức này sẽ làm di chuyển cả 4 sprite với hướng đi là ngẫu nhiên public void dichuyen(Sprite[] sprite){ for(int i=0;i<sprite.length;i++){ int x = getRandomIndex(-10, 10);//Ta lấy giá trị từ -10 -> 10 int y = getRandomIndex(-10, 10); //Kiểm tra xem nếu mà di chuyển theo x,y mà vẫn nằm trong màn hình thì cho di chuyển if(sprite[i].getRealX() + x < getWidth() && sprite[i].getRealX() + x > 0 && sprite[i].getRealY() + y < getHeight() && sprite[i].getRealY() + y > 0) sprite[i].moveRelative(x, y); } } }
Link download project: http://www.mediafire.com/?2e13sgvfrt4p0g1
Bài sau mình sẽ hướng dẫn các bạn làm sao để hiện thị được text và làm nó di chuyển trên màn hình.
Bài 5: Vẽ text và cho text di chuyển
Hôm nay mình hướng dẫn các bạn vẽ 1 text rồi cho text chuyển động từ trên xuống dưới, và ngược lại.
Code:PHP Code:package Bai_5_e3droid.gioi;
import android.graphics.Color;import android.graphics.Typeface;import android.view.MotionEvent;
import com.e3roid.E3Activity;import com.e3roid.E3Engine;import com.e3roid.E3Scene;import com.e3roid.drawable.sprite.TextSprite;import com.e3roid.event.SceneUpdateListener;
//Để tạo được vòng lặp trong game ta cần implements SceneUpdateListenerpublic class Bai_5_e3droidActivity extends E3Activity implements SceneUpdateListener {
private final static int WIDTH = 320; private final static int HEIGHT = 480; //Khai báo 1 sprite text có tên là label private TextSprite label; //2 biến này ý nghĩa giống bài 3 nhé int y = 0; boolean check = false; boolean update_ = false;//Biến này dùng để nhận biết khi nào bạn click vào màn hình thì ta mới cho biến label di chuyển
//--------------------------------------------------------------------------------------- @Override public E3Engine onLoadEngine() { E3Engine engine = new E3Engine(this, WIDTH, HEIGHT); engine.requestFullScreen(); engine.requestPortrait(); return engine; }
//--------------------------------------------------------------------------------------- @Override public E3Scene onLoadScene() { E3Scene scene = new E3Scene(); scene.addEventListener(this); //Cứ 30ms là làm tươi màn hình 1 lần scene.registerUpdateListener(30, this); //Đặt biến label nằm giữa màn hình label.move((getWidth() - label.getWidth()) / 2, (getHeight() - label.getHeight()) / 2); y = 0; check = false; //add biến label lên màn hình scene.getTopLayer().add(label); return scene; }
//--------------------------------------------------------------------------------------- @Override public void onLoadResources() {
//Khởi tạo biến label. Size: 18, font mặc định, màu chữ là Blue, màu nền là Gray label = new TextSprite("Hello E3droid", 25, Color.BLUE, Color.GRAY, Typeface.DEFAULT, this); } //--------------------------------------------------------------------------------------- public boolean onSceneTouchEvent(E3Scene scene, MotionEvent motionEvent) { if (label != null) { if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) { update_ = true; } } return false; } //--------------------------------------------------------------------------------------- @Override public void onUpdateScene(E3Scene arg0, long arg1) { runOnUiThread(new Runnable() { public void run() { if(update_){ //Lần nay ta cho chữ chạy từ trên xuống dưới nhé. Khi gặp biên thì tay thay đổi text if(!check){ y = 2; if(label.getRealY() >= getHeight()){ label.setText("Tôi muốn cùng các bạn làm Game"); label.setColor(Color.YELLOW);//Đặt màu chữ là màu vàng check = true; } } else{ y = -2; if(label.getRealY() <= 0){ check = false; label.setText("Cùng nhau xây dụng Game với E3droid"); label.setColor(Color.RED);//Đặt màu chữ là màu đỏ } } label.moveRelativeY(y); } } }); }}
Các bạn có thể thay đổi màu chữ, màu nền, font, kích thước....Link downlaod project: http://www.mediafire.com/?e94gfj75qrcsyee
Để biết kết quả các bạn vui lòng chạy chương trình nhé.
Bài 6: Mình sẽ viết về trường hợp 2 sprite di chuyển và chạm vào nhau. Nếu 2 sprite này di chuyển chạm vào nhau thì ta cho 2 sprite này nổ tung và biến mất luôn.
Bài 6: Sử dụng đối tượng AnimatedSprite để tạo nhân vật chuyển động.
Hôm nay mình sẽ chỉ cho các bạn 1 điều thú vị. Chắc hẳn các bạn cũng có hỏi "Làm sao mà nhân vật trong game nó lại đi được, ngồi được, tại sao lại có cái vụ nổ giống thật thế ...".Cái đó là di hiệu ứng cả thôi. Bài này mình sẽ cho các bạn thấy tạo ra 1 vụ nổ thật đơn giản.
Nội dung chương trình như sau: thực hiện vẽ 2 mặt cười và 1 quả bom. Mặt cười thứ nhất di chuyển từ trên xuống, mặt cười thứ 2 di chuyển từ dưới lên, khi mà 2 mặt cười này chạm vào nhau thì có 1 vụ nổ sảy ra.
Để cho các bạn dễ nghiên cứu bài này mình sẽ đánh dấu các bước và giải thích lại các bước này. Trong code có chú thích nhưng nó không theo thứ tự.Các bạn xem code thì xem theo chỉ dẫn sau nhé:
1- Khai báoprivate TiledTexture sunmonster;//Biến này để load ảnh nhéprivate TiledTexture explosion;private AnimatedSprite[] sprite;// Cái này là cái mới nè.Mình khai báo 1 mảng AnimatedSprite. //Cái này sẽ dùng để vẽ 1 cái mặt kiểu Yahoo ý, và 1 vụ nổ.
//Cài này dùng để cắt cái ảnh của mình ra để lấy từng Frame 1private ArrayList<AnimatedSprite.Frame> Frames_sunmonster = new ArrayList<AnimatedSprite.Frame>();private ArrayList<AnimatedSprite.Frame> Frames_explosion = new ArrayList<AnimatedSprite.Frame>();
2- Load ảnh và add vào framexem phương thức public void onLoadResources();
3- Khởi tạo các sprite.xem phương thức public E3Scene onLoadScene();Chú ý: trong phương thức này mình cho ẩn đổi tượng bom nhé (sprite[2])
4- Cho 2 mặt cười di chuyển và kiểm tra va chạm, hiện thị vụ nổ.xem phương thức public void onUpdateScene();
Code:PHP Code:
package Bai_6_e3droid.gioi;
import java.util.ArrayList;
import android.view.MotionEvent;
import com.e3roid.E3Activity; import com.e3roid.E3Engine; import com.e3roid.E3Scene; import com.e3roid.drawable.sprite.AnimatedSprite; import com.e3roid.drawable.texture.TiledTexture; import com.e3roid.event.SceneUpdateListener;
//Để tạo được vòng lặp trong game ta cần implements SceneUpdateListener public class Bai_6_e3droidActivity extends E3Activity implements SceneUpdateListener {
private final static int WIDTH = 320; private final static int HEIGHT = 480;
private TiledTexture sunmonster;//Biến này để load ảnh nhé private TiledTexture explosion; private AnimatedSprite[] sprite;// Cái này là cái mới nè.Mình khai báo 1 mảng AnimatedSprite. //Cái này sẽ dùng để vẽ 1 cái mặt kiểu Yahoo ý, và 1 vụ nổ. //Cài này dùng để cắt cái ảnh của mình ra để lấy từng Frame 1 private ArrayList<AnimatedSprite.Frame> Frames_sunmonster = new ArrayList<AnimatedSprite.Frame>(); private ArrayList<AnimatedSprite.Frame> Frames_explosion = new ArrayList<AnimatedSprite.Frame>(); //--------------------------------------------------------------------------------------- @Override public E3Engine onLoadEngine() { E3Engine engine = new E3Engine(this, WIDTH, HEIGHT); engine.requestFullScreen(); engine.requestPortrait(); return engine; }
//--------------------------------------------------------------------------------------- @Override public E3Scene onLoadScene() { E3Scene scene = new E3Scene(); scene.addEventListener(this); //Cứ 30ms là làm tươi màn hình 1 lần scene.registerUpdateListener(30, this);
//Giờ ta sẽ khởi tạo các AnimatedSprite sprite = new AnimatedSprite[3];//Khai bảo mảng này có 3 phần tử
//Đặt các ảnh và các sprite và khởi tạo vị trí của sprite này //Đặt cả 2 đối tượng này ở giữa theo trục x nhé. int centerX = (getWidth() - sunmonster.getTileWidth()) / 2; sprite[0] = new AnimatedSprite(sunmonster, centerX, 50);//Cái này đặt vị trí y=50 centerX = (getWidth() - explosion.getTileWidth()) / 2; sprite[1] = new AnimatedSprite(sunmonster, centerX, getHeight()-50);//Cái này đặt ở cuối màn hình - 50 để bạn thấy nó luôn //Ở trên ta đã khởi tạo và đặt vị trí cho 2 sprite //Giờ ta add frame vào cho sprite sprite[0].animate(100, Frames_sunmonster);//Cứ 100ms là vẽ 1 cái ảnh sprite[1].animate(100, Frames_sunmonster); //Add xong frame rồi. giờ ta cho nó hiện thị thôi. scene.getTopLayer().add(sprite[0]); scene.getTopLayer().add(sprite[1]); //Phần trên ta mới tạo ra 2 cái mặt cưới thồi. Giờ ta thêm 1 cái để làm vụ nổ nhé. sprite[2] = new AnimatedSprite(explosion, (getWidth() - explosion.getTileWidth()) / 2, (getHeight() - explosion.getTileWidth()) / 2);//Đặt nó vào vị trí trung tâm //Add frame sprite[2].animate(100, Frames_explosion); //Hiện thị scene.getTopLayer().add(sprite[2]); //Tạm thời ta cho ẩn sprite[2]ẩn đi. sprite[2].hide(); return scene; }
//--------------------------------------------------------------------------------------- @Override public void onLoadResources() { /*TiledTexture(java.lang.String name, *int width, *int height, *int xindex, *int yindex, *int border, *Context context) */ //Tại sao lại là 192/6: chiều rộng thực tế của ảnh là 192 và trong đó có 6 cái ảnh nhỏ, mỗi ảnh nhỏ là 1 sprite //nên ta mang chia cho 6 để lấy chiều rộng của 1 sprite sunmonster = new TiledTexture("sunmonster.png", 192/6, 32, 0, 0, 0, this);//Load ảnh mặt cười nè. explosion = new TiledTexture("explosion.png", 162/5, 32, 0, 0, 0, this);//Cái này là ảnh tạo ra vụ nổ.
//Ở đây ta thực hiện cắt lấy từng frame của 2 bức ảnh trên Frames_sunmonster = new ArrayList<AnimatedSprite.Frame>(); //Ta dùng phương thức add để lấy từng phần của bức ảnh nhé //.add(new AnimatedSprite.Frame(chỉ số cột, chỉ số hàng)); Chỉ số bắt đầu là 0 nhé. Frames_sunmonster.add(new AnimatedSprite.Frame(0, 0));//Cột 0, hàng 0 Frames_sunmonster.add(new AnimatedSprite.Frame(1, 0));//Cột 1, hàng 0 Frames_sunmonster.add(new AnimatedSprite.Frame(2, 0));//Cột 2, hàng 0 Frames_sunmonster.add(new AnimatedSprite.Frame(3, 0));//Cột 3, hàng 0 Frames_sunmonster.add(new AnimatedSprite.Frame(4, 0));//Cột 4, hàng 0 Frames_sunmonster.add(new AnimatedSprite.Frame(5, 0));//Cột 5, hàng 0 // cái này tương tự cái trên nhé. Frames_explosion = new ArrayList<AnimatedSprite.Frame>(); Frames_explosion.add(new AnimatedSprite.Frame(0, 0)); Frames_explosion.add(new AnimatedSprite.Frame(1, 0)); Frames_explosion.add(new AnimatedSprite.Frame(2, 0)); Frames_explosion.add(new AnimatedSprite.Frame(3, 0)); Frames_explosion.add(new AnimatedSprite.Frame(4, 0)); } //--------------------------------------------------------------------------------------- public boolean onSceneTouchEvent(E3Scene scene, MotionEvent motionEvent) {
return false; } //--------------------------------------------------------------------------------------- /* * Trong vòng lặp này ta sẽ cho 2 mặt cười di chuyển. một mặt di chuyển từ trên xuống, một mặt di chuyển từ dưới * lên. Khi 2 mặt này chạm vào nhau thì có 1 vụ nổ. Khi sảy ra vụ nổ này thì 2 cái mặt cười sẽ biến mất*/ @Override public void onUpdateScene(E3Scene arg0, long arg1) { runOnUiThread(new Runnable() { public void run() { sprite[0].moveRelativeY(2); sprite[1].moveRelativeY(-2);//Mỗi lần ta di chuyển 2px //Giờ ta phải kiểm tra xem khi nào thì 2 đối tượng này chạm vào nhau. //Ở đây mình giả sử rằng nếu mà 2 sprite này mà có cùng tọa đọ y thì là chạm nhau int y1 = sprite[0].getRealY(); int y2 = sprite[1].getRealY(); if(y1 == y2){ //Khi 2 mặt cười này chạm vào nhau ta ẩn 2 mặt cười này đi
sprite[0].hide(); sprite[1].hide();
//Ta cho hiện thị cái vụ nổ lên sprite[2].show(); } } }); } }
Hi. Đây là ví dụ nho nhỏ. Với những bài viết từ bài 1->6 các bạn hoàn toàn viết được 1 game đơn giản rồi.
Bài tiếp theo mình sẽ cho các bạn biết làm sao ta cho thể điều khiển sprite trên màn hình được.(di chuyển theo các hướng mà do ta chỉnh, giống như các bạn cho điện tử 4 nút ấy).
Nếu bài viết có hay thì Thanks nhé.
Cảm ơn các bạn đã đọc bài viết. Chúc các bạn thành công.
Link download project: http://www.mediafire.com/?6mux7mn777h7luhKết quả các bạn vui lòng chạy chương trình nhé.
Bài 7: Điều khiển sprite theo ý muốn
Bài viết hôm nay mình sẽ hướng dẫn các bạn cách tạo ra một phần điều khiển để điều khiển sprite đi theo hướng mà ta điều khiển.Trong code mình có comment rất rõ rồi nên mình không viết gì thêm, có gì không hiểu các bạn ý kiến nhé.
package Bai_7_e3droid.gioi;
import java.util.ArrayList;
import com.e3roid.E3Activity;import com.e3roid.E3Engine;import com.e3roid.E3Scene;import com.e3roid.drawable.controls.StickController;import com.e3roid.drawable.sprite.AnimatedSprite;import com.e3roid.drawable.texture.AssetTexture;import com.e3roid.drawable.texture.TiledTexture;import com.e3roid.event.ControllerEventListener;
//Lần này ta sẽ implements ControllerEventListener nhắm múc đích điều khiển spritepublic class Bai_7_e3droidActivity extends E3Activity implements ControllerEventListener {
private final static int WIDTH = 480; private final static int HEIGHT = 320; private AnimatedSprite sprite;//Cái này bài 6 mình có nói qua rồi.Bài này mình nói thêm 1 chút. //1 AnimatedSprite thì ta thường dùng nó vào các mục đích sau: //-1: Vẽ các sprite mà có nhiều frame //-2: Vẽ 1 sprite nhưng có nhiều hướng di chuyển. //Vẫn còn các bạn tìm hiểu thêm nhé.hihi (Biết mỗi vậy) //Cả 3 biến này dùng để load ảnh thôi private TiledTexture texture; private AssetTexture controlBaseTexture; private AssetTexture controlKnobTexture; //Cũng như bài 6 mình khai báo 4 biến này là 4 hướng của sprite. private ArrayList<AnimatedSprite.Frame> downFrames = new ArrayList<AnimatedSprite.Frame>();//Di chuyển xuống private ArrayList<AnimatedSprite.Frame> upFrames = new ArrayList<AnimatedSprite.Frame>();//DI chuyển lên private ArrayList<AnimatedSprite.Frame> leftFrames = new ArrayList<AnimatedSprite.Frame>();//Di chuyển sang trái private ArrayList<AnimatedSprite.Frame> rightFrames = new ArrayList<AnimatedSprite.Frame>();//Di chuyển sang phải
@Override public E3Engine onLoadEngine() { E3Engine engine = new E3Engine(this, WIDTH, HEIGHT); engine.requestFullScreen(); engine.requestLandscape();//Yêu cầu màn hình nằm ngang return engine; }
@Override public E3Scene onLoadScene() { E3Scene scene = new E3Scene();
//Xác định vị trí trung tâm màn hình int centerX = (getWidth() - texture.getTileWidth()) / 2; int centerY = (getHeight() - texture.getTileHeight()) / 2; //Khởi tạo sprite và đặt nó ở giữa màn hình sprite = new AnimatedSprite(texture, centerX, centerY); sprite.animate(500, downFrames);//Vẽ mỗi sprite sau 500ms. Bắt đầu với hướng xuống dưới scene.getTopLayer().add(sprite);//Hiện thị lên màn hình nào //Đây là đối tượng quan trọng trong bài này. Biến này sẽ giúp chúng ta điều khiển sprite StickController controller = new StickController( controlBaseTexture, controlKnobTexture, 0, getHeight() - controlBaseTexture.getHeight(), scene, this); controller.setAlpha(0.7f); scene.addHUD(controller);//Đưa đối tượng này lên màn hình
scene.addEventListener(controller);//Lắp nghe sự kiện khi ta chạm vào vùng điểu khiển này. //scene.setBackgroundColor(red, green, blue, alpha); scene.setBackgroundColor(0.94f, 1.00f, 0.94f, 1);//Đặt màu nền
return scene; }
@Override public void onLoadResources() { //Mối frame có kích thước là 31x49. texture = new TiledTexture("king.png", 31, 49, 0, 0, 3, 2, this); //Cắt lấy các frame và gắn vào các đối tượng downFrames = new ArrayList<AnimatedSprite.Frame>(); downFrames.add(new AnimatedSprite.Frame(0, 0)); downFrames.add(new AnimatedSprite.Frame(1, 0)); downFrames.add(new AnimatedSprite.Frame(2, 0)); downFrames.add(new AnimatedSprite.Frame(3, 0)); leftFrames = new ArrayList<AnimatedSprite.Frame>(); leftFrames.add(new AnimatedSprite.Frame(0, 1)); leftFrames.add(new AnimatedSprite.Frame(1, 1)); leftFrames.add(new AnimatedSprite.Frame(2, 1)); leftFrames.add(new AnimatedSprite.Frame(3, 1));
rightFrames = new ArrayList<AnimatedSprite.Frame>(); rightFrames.add(new AnimatedSprite.Frame(0, 2)); rightFrames.add(new AnimatedSprite.Frame(1, 2)); rightFrames.add(new AnimatedSprite.Frame(2, 2)); rightFrames.add(new AnimatedSprite.Frame(3, 2));
upFrames = new ArrayList<AnimatedSprite.Frame>(); upFrames.add(new AnimatedSprite.Frame(0, 3)); upFrames.add(new AnimatedSprite.Frame(1, 3)); upFrames.add(new AnimatedSprite.Frame(2, 3)); upFrames.add(new AnimatedSprite.Frame(3, 3)); //Load 2 cái ảnh để vẽ phần điều khiển controlBaseTexture = new AssetTexture("controller_base.png", this); controlKnobTexture = new AssetTexture("controller_knob.png", this); }
public void onControlUpdate(StickController controller, int relativeX, int relativeY, boolean hasChanged) { //Bắt sự kiện khi bạn chạm vào vùng điều khiển //Khi có thay đổi trên vùng điều khiển thì biến hasChanged=true if (hasChanged) { int dir = controller.getDirection(); if (dir == StickController.LEFT) { //Khi ta điều khiển sang hướng trái sprite.animate(500, leftFrames); } else if (dir == StickController.RIGHT) {
//Khi ta điều khiển sang hướng phải sprite.animate(500, rightFrames); } else if (dir == StickController.UP) { //Khi ta điều khiển sang hướng lên trên sprite.animate(500, upFrames); } else if (dir == StickController.DOWN) { //Khi ta điều khiển sang hướng xuống dưới sprite.animate(500, downFrames); } } //Giá trị relativeX,relativeY có thể là 1 số lớn nên ta mang chia cho 5 nhằm giảm giá trị nó xuống //Nếu bạn không chia cho 5 thì chắc chắn nhân vật di chuyển rất nhanh. Các bạn có thể không chia cho 5 để //kiểm tra nhé. int x = sprite.getRealX() + (relativeX / 5); int y = sprite.getRealY() + (relativeY / 5); //Kiểm tra xem nếu di chuyển sprite mà không ra khỏi màn hình thì cho di chuyển if (x > 0 && y > 0 && x < getWidth() - sprite.getWidth() && y < getHeight() - sprite.getHeight()) { sprite.move(x, y); } } }
Link download project:http://www.mediafire.com/?84w3hd1tfwppv99
Bài tiếp theo là gì nhỉ?. Hi bài sau chúng ta cùng nhau vẽ hình nền game, màu nền game.
Bài 8: Tạo cảnh nền cho game
Hôm này là 1 bài đơn giản nhé, các bài trước chưa có cảnh nền cho game nên bài này chúng ta sẽ cho thêm cảnh nền vào. Để đơn giản mình sử dụng lại code bài 7, trong code có comment rất rõ rồi nên mình không viết thêm gì nữa.
PHP Code:package Bai_8_e3droid.gioi;
import java.util.ArrayList;
import com.e3roid.E3Activity; import com.e3roid.E3Engine; import com.e3roid.E3Scene; import com.e3roid.drawable.controls.StickController; import com.e3roid.drawable.sprite.AnimatedSprite; import com.e3roid.drawable.texture.AssetTexture; import com.e3roid.drawable.texture.TiledTexture; import com.e3roid.event.ControllerEventListener;
//Lần này ta sẽ implements ControllerEventListener nhắm múc đích điều khiển sp
rite public class Bai_8_e3droidActivity extends E3Activity implements ControllerEventListener {
private final static int WIDTH = 480; private final static int HEIGHT = 320; private AnimatedSprite sprite;//Cái này bài 6 mình có nói qua rồi.Bài này mình nói thêm 1 chút. //1 AnimatedSprite thì ta thường dùng nó vào các mục đích sau: //-1: Vẽ các sprite mà có nhiều frame //-2: Vẽ 1 sprite nhưng có nhiều hướng di chuyển. //Vẫn còn các bạn tìm hiểu thêm nhé.hihi (Biết mỗi vậy) //Cả 3 biến này dùng để load ảnh thôi private TiledTexture texture; private AssetTexture controlBaseTexture; private AssetTexture controlKnobTexture; //Cũng như bài 6 mình khai báo 4 biến này là 4 hướng của sprite. private ArrayList<AnimatedSprite.Frame> downFrames = new ArrayList<AnimatedSprite.Frame>();//Di chuyển xuống private ArrayList<AnimatedSprite.Frame> upFrames = new ArrayList<AnimatedSprite.Frame>();//DI chuyển lên private ArrayList<AnimatedSprite.Frame> leftFrames = new ArrayList<AnimatedSprite.Frame>();//Di chuyển sang trái private ArrayList<AnimatedSprite.Frame> rightFrames = new ArrayList<AnimatedSprite.Frame>();//Di chuyển sang phải
@Override public E3Engine onLoadEngine() { E3Engine engine = new E3Engine(this, WIDTH, HEIGHT); engine.requestFullScreen(); engine.requestLandscape();//Yêu cầu màn hình nằm ngang return engine; }
@Override public E3Scene onLoadScene() { E3Scene scene = new E3Scene();
//Xác định vị trí trung tâm màn hình int centerX = (getWidth() - texture.getTileWidth()) / 2; int centerY = (getHeight() - texture.getTileHeight()) / 2; //Khởi tạo sprite và đặt nó ở giữa màn hình sprite = new AnimatedSprite(texture, centerX, centerY); sprite.animate(500, downFrames);//Vẽ mỗi sprite sau 500ms. Bắt đầu với hướng xuống dưới scene.getTopLayer().add(sprite);//Hiện thị lên màn hình nào //Đây là đối tượng quan trọng trong bài này. Biến này sẽ giúp chúng ta điều khiển sprite StickController controller = new StickController( controlBaseTexture, controlKnobTexture,
0, getHeight() - controlBaseTexture.getHeight(), scene, this); controller.setAlpha(0.7f); scene.addHUD(controller);//Đưa đối tượng này lên màn hình scene.addEventListener(controller);//Lắp nghe sự kiện khi ta chạm vào vùng điểu khiển này. //=========================================================================================================== //============================================BÀI 8========================================================== //Bài này mình hướng dẫn các bạn cách tạo màu nền, hình nền trong game. //Có 3 phương pháp cơ bản sau //1: Thiết lập màu nền //scene.setBackgroundColor(red, green, blue, alpha); scene.setBackgroundColor(0.94f, 1.00f, 0.94f, 1);//Đặt màu nền. Mình đặt cái này là defaule nhé. //2: Sử dụng 1 bức ảnh nhỏ sau đó là lợp ngói cho toàn bộ màn hình. /* Bitmap tile = BitmapUtil.getTileBitmapFromAsset("tile_border.png", 32, 32, 2, 0, 1, this); Background background_1 = new Background(tile, getWidth(), getHeight(), this); scene.getTopLayer().setBackground(background_1); */ //3: Sử dụng 1 bức ảnh lớn /* Background background_2 = new Background(new TiledTexture("background.png", getWidth(), getHeight(), this)); scene.getTopLayer().setBackground(background_2); */ // Đây là 3 cách đơn giản nhất để tạo ra hình nền trong game. Các bạn bỏ comment phần muốn thực hiện nhé. //=========================================================================================================== //============================================END BÀI 8====================================================== return scene; }
@Override public void onLoadResources() { //Mối frame có kích thước là 31x49. texture = new TiledTexture("king.png", 31, 49, 0, 0, 3, 2, this); //Cắt lấy các frame và gắn vào các đối tượng downFrames = new ArrayList<AnimatedSprite.Frame>(); downFrames.add(new AnimatedSprite.Frame(0, 0)); downFrames.add(new AnimatedSprite.Frame(1, 0)); downFrames.add(new AnimatedSprite.Frame(2, 0));
downFrames.add(new AnimatedSprite.Frame(3, 0)); leftFrames = new ArrayList<AnimatedSprite.Frame>(); leftFrames.add(new AnimatedSprite.Frame(0, 1)); leftFrames.add(new AnimatedSprite.Frame(1, 1)); leftFrames.add(new AnimatedSprite.Frame(2, 1)); leftFrames.add(new AnimatedSprite.Frame(3, 1));
rightFrames = new ArrayList<AnimatedSprite.Frame>(); rightFrames.add(new AnimatedSprite.Frame(0, 2)); rightFrames.add(new AnimatedSprite.Frame(1, 2)); rightFrames.add(new AnimatedSprite.Frame(2, 2)); rightFrames.add(new AnimatedSprite.Frame(3, 2));
upFrames = new ArrayList<AnimatedSprite.Frame>(); upFrames.add(new AnimatedSprite.Frame(0, 3)); upFrames.add(new AnimatedSprite.Frame(1, 3)); upFrames.add(new AnimatedSprite.Frame(2, 3)); upFrames.add(new AnimatedSprite.Frame(3, 3)); //Load 2 cái ảnh để vẽ phần điều khiển controlBaseTexture = new AssetTexture("controller_base.png", this); controlKnobTexture = new AssetTexture("controller_knob.png", this); }
public void onControlUpdate(StickController controller, int relativeX, int relativeY, boolean hasChanged) { //Bắt sự kiện khi bạn chạm vào vùng điều khiển //Khi có thay đổi trên vùng điều khiển thì biến hasChanged=true if (hasChanged) { int dir = controller.getDirection(); if (dir == StickController.LEFT) { //Khi ta điều khiển sang hướng trái sprite.animate(500, leftFrames); } else if (dir == StickController.RIGHT) { //Khi ta điều khiển sang hướng phải sprite.animate(500, rightFrames); } else if (dir == StickController.UP) { //Khi ta điều khiển sang hướng lên trên sprite.animate(500, upFrames); } else if (dir == StickController.DOWN) { //Khi ta điều khiển sang hướng xuống dưới sprite.animate(500, downFrames); } } //Giá trị relativeX,relativeY có thể là 1 số lớn nên ta mang chia cho 5 nhằm giảm giá trị nó xuống //Nếu bạn không chia cho 5 thì chắc chắn nhân vật di chuyển rất nhanh. Các bạn có thể không chia cho 5 để //kiểm tra nhé. int x = sprite.getRealX() + (relativeX / 5); int y = sprite.getRealY() + (relativeY / 5); //Kiểm tra xem nếu di chuyển sprite mà không ra khỏi màn hình thì
cho di chuyển if (x > 0 && y > 0 && x < getWidth() - sprite.getWidth() && y < getHeight() - sprite.getHeight()) { sprite.move(x, y); } } }
Linhk downlaod project: http://www.mediafire.com/?cepckz7yfqkxkp5
Tuy bài viết này đơn giản nhưng nó là 1 thành phần không thể thiếu trong game được.Hi. Bài viết tiếp theo của mình là sử dụng công cụ tạo maps và hướng dẫn các bạn load maps vào game.
Bài 9:(Đã cập nhật ) Hướng dẫn sử dụng phần mềm tạo Máp, tạo 1 maps đơn giản và load maps vào game
Bài này hướng dẫn các bạn sử dụng cái phần mềm tạo maps.
Đây là code minh họa việc sử dụng maps.PHP Code:package Bai_9_e3droid.gioi
import java.util.ArrayList;
import android.os.AsyncTask; import android.util.Log;
import com.e3roid.E3Activity; import com.e3roid.E3Engine; import com.e3roid.E3Scene; import com.e3roid.drawable.modifier.AlphaModifier; import com.e3roid.drawable.modifier.SpanModifier; import com.e3roid.drawable.sprite.TextSprite; import com.e3roid.drawable.tmx.TMXException; import com.e3roid.drawable.tmx.TMXLayer; import com.e3roid.drawable.tmx.TMXTiledMap; import com.e3roid.drawable.tmx.TMXTiledMapLoader; import com.e3roid.util.Debug;
public class Bai_9_e3droidActivity extends E3Activity{
private final static int WIDTH = 320; private final static int HEIGHT = 420; private TMXTiledMap map; private ArrayList<TMXLayer> mapLayers;
//------------------------------------------------------------------------------------------- @Override public E3Engine onLoadEngine() { E3Engine engine = new E3Engine(this, WIDTH, HEIGHT); engine.requestFullScreen(); engine.requestPortrait(); return engine; } //------------------------------------------------------------------------------------------- @Override public E3Scene onLoadScene() { final E3Scene scene = new E3Scene(); //Khai báo biến loadingText, khi load thì ta hiện thị dòng chữ "Loading map..." final TextSprite loadingText = new TextSprite("Loading map...", 24, this); loadingText.move((getWidth() - loadingText.getWidth()) / 2, (getHeight() - loadingText.getHeight()) / 2);//Ta đặt nó gở giữa màn hình loadingText.addModifier(new SpanModifier(500L, new AlphaModifier(0, 0, 1))); scene.getTopLayer().add(loadingText); // Thực hiện load maps new AsyncTask<Void,Integer,TMXTiledMap>() { @Override protected TMXTiledMap doInBackground(Void... params) { try { Log.d("doInBackground","doInBackground"); TMXTiledMapLoader mapLoader = new TMXTiledMapLoader();//Khai báo biến MapLoader //Ở đây ta load map từ thư mực Asset. Các bạn nhớ đánh đúng tên nhé. Đuôi của nó là.tmx TMXTiledMap map = mapLoader.loadFromAsset("mapgame.tmx", Bai_9_e3droidActivity.this); return map; } catch (TMXException e) { Debug.e(e.getMessage()); } return null; } @Override protected void onPostExecute(TMXTiledMap tmxTiledMap) { map = tmxTiledMap; if (tmxTiledMap != null && (mapLayers = map.getLayers()) != null) { for (TMXLayer layer : mapLayers) { Log.d("mapLayers","mapLayers"); layer.setSceneSize(getWidth(), getHeight()); //Vì trong maps có thể có nhiều layer nên ta phải lặp //toàn bộ các layer này. Sau đó ta add vào scene.
scene.getTopLayer().add(layer); scene.getTopLayer().remove(loadingText);//Ta xóa bỏ cái text hiện thi khi ta load maps engine.setRefreshMode(E3Engine.REFRESH_DEFAULT); } } else {//Nếu có lỗi trong khi load thì hiện thị thông báo sau
loadingText.setText("LoadMaps Error"); loadingText.setAlpha(1); loadingText.clearModifier(); } } }.execute(); return scene;//Khi ta load maps xong ta có 1 scene như mấy bài trước } //------------------------------------------------------------------------------------------- @Override public void onLoadResources() { } //------------------------------------------------------------------------------------------- }
Link download: http://www.mediafire.com/?u88tlcrc28xuukc
Bài 10: Viết game hứng bia đơn giản.
Hôm nay mình hướng dẫn các bạn viết game hứng bia đơn giản. Nội dung game như sau.
Người chơi có nhiệm vụ điều chỉnh một cái thùng để hứng bia, những trai bia di chuyển từ trên xuống với tốc độ, vị trí khác nhau. Khi mà người chơi hứng được 1 trai bia thì người chơi được nhận thêm 10 điểm, thời gian chơi 1 lần là 60s.Trong giao diện sẽ hiện thì số điểm hiện tại, thời gian đếm ngược, cái thùng để hứng, các trai bia di chuyển.
Sau đây là code (Trong code có comment rất chi tiết nên mình không giải thích gì thêm).
PHP Code:package Bai_10_e3droid.gioi;
import android.graphics.Color; import android.graphics.Typeface; import android.util.Log; import android.view.Display; import android.view.MotionEvent;
import com.e3roid.E3Activity; import com.e3roid.E3Engine; import com.e3roid.E3Scene; import com.e3roid.drawable.Background;
import com.e3roid.drawable.Shape; import com.e3roid.drawable.Sprite; import com.e3roid.drawable.sprite.TextSprite; import com.e3roid.drawable.texture.AssetTexture; import com.e3roid.drawable.texture.TiledTexture; import com.e3roid.event.SceneUpdateListener;
public class Bai_10_e3droidActivity extends E3Activity implements SceneUpdateListener { //2 biến này là chiều rộng và chiều cao của màn hình game private int WIDTH; private int HEIGHT; //Khai báo biến số thời gian cập nhật lại màn hình private int time_update = 50;//50ms //Biến này để tính điểm người chơi private int diem = 0; //Để hiện thị điểm ta khai báo thêm 1 biến nữa. private TextSprite text_diem; //Khai báo thêm 2 biến để load ảnh private AssetTexture playerTexture = null;//Biến này load cái ảnh hứng bia
private AssetTexture beerTexture = null;//Cái này load cái trai bia //Khai báo các sprite private Sprite player;//Cái này do người chơi điều khiển private Sprite[] arrayBeerSprite;// Đây là 1 mảng sprite là các trai bia. private int[] speed;//Tốc độ của mỗi trai bia private int maxBeer = 20;//Biến này để xác định số trai bia. Mạc định ban đầu là 20 trai private Time t = new Time();//Lớp Time là lớp dẫn xuất Thread để ta tạo ra thời gian đếm ngược private TextSprite text_time;//Hiện thị thời gian còn lại private boolean isPause = false;//Xác định lúc tạm dừng game private TextSprite text_continue;//Biến này dùng để click chơi lại //============================================================================== @Override public E3Engine onLoadEngine() { //Xác định kích thước của màn hình Display display = getWindowManager().getDefaultDisplay(); WIDTH = display.getWidth(); HEIGHT = display.getHeight(); //Đặt màn hình game của ta bằng với màn hình của thiết bị E3Engine engine = new E3Engine(this, WIDTH, HEIGHT); engine.requestFullScreen();//Đặt chế độ full màn hình engine.requestLandscape();//Yêu cầu màn hình xoay ngang return engine; } //==============================================================================
@Override public void onLoadResources() { //Load ảnh playerTexture = new AssetTexture("player.png", this);//Ảnh hứng bia beerTexture = new AssetTexture("beer.png", this);//Ảnh trai bia } //============================================================================== @Override public E3Scene onLoadScene() { // -------------------------------------------- E3Scene scene = new E3Scene(); scene.setBackgroundColor(1.0f, 0.0f, 0, 0f); scene.registerUpdateListener(time_update, this);//Cập nhật màn hình với thời gian là time_update // -------------------------------------------- //Đặt hình nền Background background = new Background(new TiledTexture("bg.jpg", getWidth(), getHeight(), this)); scene.getTopLayer().setBackground(background); //------------------------------------------player--------------------------- int centerX = (WIDTH - playerTexture.getWidth()) / 2;//Xác định vị trí trung tâm theo X int centerY = (HEIGHT - playerTexture.getWidth()) / 2;//Xác định vị trí trung tâm theo X //Ta đặt player này ở vị trí trung tâm theo X và đặt nó nằm dưới gần cuối màn hình player = new Sprite(playerTexture, centerX, getHeight() - playerTexture.getHeight() - 10) { //Cài đặt phương thức này để xử lý khi người chơi chạm vào player và di chuyển player này. @Override public boolean onTouchEvent(E3Scene scene, Shape shape, MotionEvent motionEvent, int localX, int localY) { if (motionEvent.getAction() == MotionEvent.ACTION_MOVE) { //Ta chỉ di chuyển nhân vật theo chiều X. int X = getTouchEventX(scene, motionEvent) - player.getRealX() - player.getWidth() / 2; if(text_continue.getText().length() == 0)//Nếu text_continue mà rỗng thì thực hiện di chuyển player.moveRelativeX(X); } return false; } }; scene.addEventListener(player);//Gắn sự kiện scene.getTopLayer().add(player);//Hiện thị player //------------------------------------------End player--------------------------- //------------------------------------------arrayBeerSprite--------------------------- //Khai bao và khởi tạo mảng beer
arrayBeerSprite = new Sprite[maxBeer]; for(int i = 0; i < maxBeer; i++ ){ //Khởi tạo và đặt ở vị trí getRandomIndex(1,WIDTH-beerTexture.getWidth()),-10 int x = getRandomIndex(1,WIDTH-beerTexture.getWidth()); arrayBeerSprite[i] = new Sprite(beerTexture,x,-10); scene.getTopLayer().add(arrayBeerSprite[i]);//Hiện thị arrayBeerSprite } //------------------------------------------End arrayBeerSprite--------------------------- //Thực hiện khởi tạo tốc độ của từng trai bia speed = new int[maxBeer]; for(int i=0;i<maxBeer;i++) speed[i] = getRandomIndex(3,15);//Ta cho tốc độ min=1, max=10 text_diem = new TextSprite(String.valueOf(diem), 30, this);//Size=30 text_diem.setColor(Color.WHITE);//Đặt màu là trắng //Vị trí hiện thị điểm là góc trên bên phải text_diem.move(WIDTH-50, 20); text_diem.setTypeface(Typeface.DEFAULT_BOLD); scene.getTopLayer().add(text_diem);//Hiện thị lên màn hình //start time text_time = new TextSprite(String.valueOf(t.time), 30, this);//Size=30
text_time.setColor(Color.WHITE);//Đặt màu là trắng //Vị trí hiện thị điểm là góc trên bên trái text_time.move(50, 20); text_time.setTypeface(Typeface.DEFAULT_BOLD); scene.getTopLayer().add(text_time);//Hiện thị lên màn hình t.start();//Bắt đầu tính thời gian text_continue = new TextSprite("", 30, this){ @Override public boolean onTouchEvent(E3Scene scene, Shape shape, MotionEvent motionEvent, int localX, int localY) { if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) { play();//Gọi phương thức play để chơi lại } return false; } }; text_continue.setColor(Color.WHITE);//Đặt màu là trắng //Vị trí hiện thị giữa màn hình text_continue.move(centerX, centerY); text_continue.setTypeface(Typeface.DEFAULT_BOLD); scene.addEventListener(text_continue); scene.getTopLayer().add(text_continue);//Hiện thị lên màn hình return scene; }
//============================================================================== @Override
public void onUpdateScene(E3Scene scene, long time) { runOnUiThread(new Runnable() { public void run() { if(!isPause){ //Thực hiện cho các trai bia di chuyển từ trên xuống dưới for(int i = 0; i < maxBeer ; i++ ){ //Kiểm tra xem nếu mà trai bia nào mà đang > HEIGHT thì ta khởi tạo lại vị trí của trai bia đó if(arrayBeerSprite[i].getRealY() > HEIGHT){ int x = getRandomIndex(1,WIDTH-beerTexture.getWidth()); //Xác định lại vị trí x, y arrayBeerSprite[i].move(x, 0); arrayBeerSprite[i].show(); //Xác định lại tốc độ của trai bia này speed[i] = getRandomIndex(3,15); } //Di chuyển các trai bia với vận tốc đã định arrayBeerSprite[i].moveRelativeY(speed[i]); //Kiểm tra xem nếu trai bia nào va chạm với player thì ta cho ẩn đi và tính điểm //Điều kiện là trai bia này vẫn đang hiện thị if(arrayBeerSprite[i].collidesWith(player) && arrayBeerSprite[i].isVisible()){ arrayBeerSprite[i].hide(); //Khi player hứng được 1 trai thì số điểm tăng lên 10 diem +=10; //Mỗi khi thay đổi điểm ta cập nhật để hiện thị điểm text_diem.setText(String.valueOf(diem)); } } //hiện thị thời gian đếm ngược text_time.setText(String.valueOf(t.time)); //Nếu thời gian mà hết thì tạm dừng gam if(t.time <= 0){ isPause = true; } } else{ //Khi tạm dừng ta hiện thị text là Click_Play. text_continue.setText("Click_Play"); text_diem.setText("0"); } } }); } //============================================================================== //Phương thức tạo số ngẫu nhiên private int getRandomIndex(int min, int max) { return (int) (Math.random() * (max - min + 1)) + min;
}
public boolean play() { //Khi người chơi click vào Click_Play thì chơi lại từ đầu. Số điểm và thời gian được khởi tạo lại if(text_continue.getText().length() > 0){ text_continue.setText(""); t.time = 60; isPause = false; diem = 0; Log.d("Rrsume","Rrsume"); } return false; } }
Link donwload project:http://www.mediafire.com/?4rg777h2ni56bpc
Bài 11: Load maps và điều khiển sprite. Xác định va chạm
Hôm nay mình tiếp tục giới thiệu với các bạn 1 phần quan trọng trong game 2D. Bài này sẽ thực hiện các nội dung sau.
1- Thực hiện load maps.2- Add phần điều khiển.3- Xác định va chạm giữa sprite với các vật cản có trong maps.
Trong bài này chúng ta sẽ load maps mà chúng ta tạo ra, khi điều khiển sprite nếu mà chạm vào các vật cản trên maps thì sprite không di chuyển được, ngược lại thì sprite sẽ được di chuyển. Trong code mình có comment rõ rồi. Có gì thắc mắc thì các bạn cứ ý kiến nhé.
Code:PHP Code:package Bai_11_e3droid.gioi;
import java.util.ArrayList;
import android.os.AsyncTask; import android.util.Log;
import com.e3roid.E3Activity; import com.e3roid.E3Engine; import com.e3roid.E3Scene; import com.e3roid.drawable.Sprite; import com.e3roid.drawable.controls.DigitalController; import com.e3roid.drawable.controls.StickController; import com.e3roid.drawable.modifier.AlphaModifier; import com.e3roid.drawable.modifier.SpanModifier; import com.e3roid.drawable.sprite.TextSprite; import com.e3roid.drawable.texture.AssetTexture; import com.e3roid.drawable.texture.Texture;
import com.e3roid.drawable.tmx.TMXException; import com.e3roid.drawable.tmx.TMXLayer; import com.e3roid.drawable.tmx.TMXTiledMap; import com.e3roid.drawable.tmx.TMXTiledMapLoader; import com.e3roid.event.ControllerEventListener; import com.e3roid.util.Debug;
//Để điều khiển sprite ta cần implements ControllerEventListener public class Bai_11_e3droidActivity extends E3Activity implements ControllerEventListener{
private final static int WIDTH = 320; private final static int HEIGHT = 440; //Các biến để tạo vùng điều khiển private AssetTexture controlBaseTexture; private AssetTexture controlKnobTexture; private DigitalController controller; //Các biến thao tác với Maps private TMXTiledMap map; private ArrayList<TMXLayer> mapLayers; private TMXLayer layer_2;//Đây là đối tượng thể hiện các vật cản //Khai báo 1 sprite có tên là bong private Sprite bong; //Khai báo 1 Texture. Đối tượng này để load ảnh lên private Texture bongTexture; //------------------------------------------------------------------------------------------- @Override public E3Engine onLoadEngine() { E3Engine engine = new E3Engine(this, WIDTH, HEIGHT); engine.requestFullScreen(); engine.requestPortrait(); return engine; } //------------------------------------------------------------------------------------------- @Override public E3Scene onLoadScene() { final E3Scene scene = new E3Scene(); //Khởi tạo, đặt vị trí bên trái góc dưới controller = new DigitalController(controlBaseTexture, controlKnobTexture,0, getHeight() - controlBaseTexture.getHeight(), scene, this); controller.setUpdateInterval(10);//Cập nhật 10ms scene.addEventListener(controller);//Gắn sự kiện //Khai báo biến loadingText, khi load thì ta hiện thị dòng chữ "Loading map..." final TextSprite loadingText = new TextSprite("Loading map...", 24, this); loadingText.move((getWidth() - loadingText.getWidth()) / 2, (getHeight() - loadingText.getHeight()) / 2);//Ta đặt nó gở giữa màn hình loadingText.addModifier(new SpanModifier(500L, new AlphaModifier(0, 0,
1))); scene.getTopLayer().add(loadingText); // Thực hiện load maps new AsyncTask<Void,Integer,TMXTiledMap>() { @Override protected TMXTiledMap doInBackground(Void... params) { try { Log.d("doInBackground","doInBackground"); TMXTiledMapLoader mapLoader = new TMXTiledMapLoader();//Khai báo biến MapLoader //Ở đây ta load map từ thư mực Asset. Các bạn nhớ đánh đúng tên nhé. Đuôi của nó là.tmx TMXTiledMap map = mapLoader.loadFromAsset("mapgame.tmx", Bai_11_e3droidActivity.this); return map; } catch (TMXException e) { Debug.e(e.getMessage()); } return null; } @Override protected void onPostExecute(TMXTiledMap tmxTiledMap) { map = tmxTiledMap; if (tmxTiledMap != null && (mapLayers = map.getLayers()) != null) { for (TMXLayer layer : mapLayers) { Log.d("mapLayers","mapLayers"); layer.setSceneSize(getWidth(), getHeight()); if ("layer2".equals(layer.getName())) { layer_2 = layer;//Layer2 chỉ là cái mà ta tạo ra để xác định những vị trí mà không được //đi vào, nên phần này ta không vẽ. continue; } //Add các layer vào scene scene.getTopLayer().add(layer); //Khởi tạo đối tượng bong và đặt nó nằm ở vị trí (40,40). bong = new Sprite(bongTexture, 40, 40); //add vào màn hình. scene.getTopLayer().add(bong); //Add phần điều khiển vào scene scene.addHUD(controller); scene.getTopLayer().remove(loadingText);//Ta xóa bỏ cái text hiện thi khi ta load maps engine.setRefreshMode(E3Engine.REFRESH_DEFAULT); } } else {//Nếu có lỗi trong khi load thì hiện thị thông báo sau
loadingText.setText("LoadMaps Error");
loadingText.setAlpha(1); loadingText.clearModifier(); } } }.execute(); return scene;//Khi ta load maps xong ta có 1 scene như mấy bài trước } //------------------------------------------------------------------------------------------- @Override public void onLoadResources() { //Load ảnh từ thư mục Asset bongTexture = new AssetTexture("bong.png", this); controlBaseTexture = new AssetTexture("controller_base.png", this); controlKnobTexture = new AssetTexture("controller_knob.png", this); } //------------------------------------------------------------------------------------------- //Khi bạn chạm vào phần điều khiển @Override public void onControlUpdate(StickController controller, int relativeX, int relativeY, boolean hasChanged) { int x = (relativeX / 40); int y = (relativeY / 40); //Nếu kiểm tra ma bong không va chạm vào các bức tường thì ta cho di chuyển if(kt(bong,x,y)) bong.moveRelative(x, y); } //Phương thức kiểm tra xem quả bóng có va chạm với layer2 không. Nếu không chạm thì return true, ngược lại là false public boolean kt(Sprite sprite, int x, int y){ if(layer_2.getTileFromRect(sprite.getCollisionRect(), x, y).size() != 0) return false;//Chạm vào layer2 return true;//Không chạm } }
Ảnh kết quả:
Link download: http://www.mediafire.com/?jutle1b0ckk7cx1
Các bạn chú ý nhé: tất cả các vùng có màu là vật cản, sprite chỉ được di chuyển các vùng có màu trắng.Trong maps ví dụ này có 2 layer nhé, các bạn dùng phần mềm mà bài 9 mình up lên, mở maps ra rồi chọn view->layer để nhìn thấy 2 layer này. 2 layer này có tên là: layer1 và layer2.
Như vậy với ví dụ này chúng ta có thể viết 1 số game như: bắn tăng, bom nước....Hi. Bài tiếp theo của mình là: Hiện thị 1 phần giới thiệu trong game (Ví dụ: Hiện thị logo, hiện thị video, hiện thị ảnh...).
Bài 12: Hiện thị phần giới thiệu game
Bài hôm nay mình sẽ hướng dẫn các bạn tạo ra phần giới thiệu game. Cách giới thiệu thì có rất nhiều, mình chỉ đưa ra 2 gợi ý cho các bạn.
1-Hiện thị 1 bức ảnh.2-Hiện thị 1 video.
Cách 1 các bạn tham khảo link sau: http://vietandroid.com/l%E1%BA%ADp-t...sh-screen.html
Cách 2:Các bạn xem code sau:
Code này cho phép bạn play 1 video từ thư mục raw. Khi video mà hiện thị xong ta thực hiện chuyển nó sang phần game của chúng ta. Để cho đơn giản mình lấy luôn lớp activity ở bài 1.PHP Code:package Bai_12_e3droid.gioi;
import android.app.Activity;import android.content.Intent;import android.media.MediaPlayer;import android.media.MediaPlayer.OnCompletionListener;import android.net.Uri;import android.os.Bundle;import android.view.MotionEvent;import android.view.View;import android.view.View.OnTouchListener;import android.view.Window;import android.view.WindowManager;import android.widget.VideoView;
public class Bai_12_e3droidActivity extends Activity implements OnCompletionListener, OnTouchListener { /** Called when the activity is first created. */ VideoView v; Intent i; @Override public void onCreate(Bundle savedInstanceState) { //Sét full màn hình requestWindowFeature(Window.FEATURE_NO_TITLE);//Không hiện thị tiêu title getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);//Fullscreen super.onCreate(savedInstanceState); setContentView(R.layout.main); v = (VideoView)findViewById(R.id.videoView); Uri u = Uri.parse("android.resource://"+getPackageName() + "/"+R.raw.video);//Lấy video từ thư mục raw v.setVideoURI(u); v.setOnCompletionListener(this);//Khi video đã chạy xong v.setOnTouchListener(this);//Khi chạm vào màn hình v.setKeepScreenOn(true);//Khi hiện thị video thì không cho tự động tắt màn hình v.start(); //Khởi tạo intent mà ta muốn chuyển sang sau khi video chơi xong i = new Intent(this, Bai_1_e3droidActivity.class); }
@Override public void onCompletion(MediaPlayer arg0) { //Khi video chạy xong thì ta dựng lại và chuyển sang phần game this.startActivity(i); finish();//Kết thúc Intent }
@Override public boolean onTouch(View arg0, MotionEvent arg1) { //Khi video chạy xong thì ta dựng lại và chuyển sang phần game this.startActivity(i); finish();//Kết thúc Intent return false; }}
Code bài 1:PHP Code:package Bai_12_e3droid.gioi;
import android.view.MotionEvent;
import com.e3roid.E3Activity;import com.e3roid.E3Engine;import com.e3roid.E3Scene;import com.e3roid.drawable.Shape;
public class Bai_1_e3droidActivity extends E3Activity {
private final static int WIDTH = 320;//Chiều rộng của màn hình private final static int HEIGHT = 480;//Chiều cao của màn hình private final static int BOX_SIZE = 50;//Kích thước của 1 box
private Shape shape1, shape2, shape3, shape4;//Khai báo 4 biến shape @Override public E3Engine onLoadEngine() { E3Engine engine = new E3Engine(this, WIDTH, HEIGHT);//Thiết lập chiều cao và rộng engine.requestFullScreen();//Set màn hình full engine.requestPortrait(); return engine; }
@Override public E3Scene onLoadScene() { E3Scene scene = new E3Scene(); scene.addEventListener(this);//Bắt sự kiện khi bạn chạm lên màn hình //Khỏi tạo màu cho các hình. (Các bạn thử thay đổi các giá trị xem sao nhé) shape1.setColor(1, 0, 0, 1); shape2.setColor(0, 1, 0, 1); shape3.setColor(0, 0, 1, 1); shape4.setColor(1, 1, 0, 1);
//Hiện thị các hình này lên. Chú ý: nếu không add mấy cái shape vào thì sẽ không bao giờ nhìn thấy trên //màn hình scene.getTopLayer().add(shape1); scene.getTopLayer().add(shape2); scene.getTopLayer().add(shape3); scene.getTopLayer().add(shape4); return scene; }
@Override public void onLoadResources() { int centerX = getWidth() / 2;//Xác định ví trí trung tâm theo tọa độ X int centerY = getHeight() / 2;//Xác định ví trí trung tâm theo tọa độ Y //Khởi tạo vị trí cho các hình này khi hiện thị lên màn hình shape1 = new Shape(centerX, centerY, BOX_SIZE, BOX_SIZE); shape2 = new Shape(centerX-BOX_SIZE, centerY-BOX_SIZE, BOX_SIZE, BOX_SIZE); shape3 = new Shape(centerX-BOX_SIZE, centerY, BOX_SIZE, BOX_SIZE); shape4 = new Shape(centerX, centerY-BOX_SIZE, BOX_SIZE, BOX_SIZE); } @Override public boolean onSceneTouchEvent(E3Scene scene, MotionEvent motionEvent) { // shape1(red box) rotates and scales when touchEvent ACTION_DOWN occurs. if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) { //Thực hiện xoay hình shape1 và phóng to khi bạn chạm vào màn hình shape1.rotate(shape1.getAngle() + 20.0f, BOX_SIZE/2, BOX_SIZE/2); shape1.scale(shape1.getScaleX() + 0.2f, shape1.getScaleY() + 0.2f, BOX_SIZE / 2, BOX_SIZE / 2); } return false; }}
Đây là file main.xlmPHP Code:<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:theme="@android:style/Theme.NoTitleBar.Fullscreen"> <VideoView android:id="@+id/videoView" android:layout_width="fill_parent" android:layout_alignParentRight="true" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_alignParentBottom="true" android:layout_height="fill_parent"> </VideoView> </RelativeLayout>
file này có tác dụng làm cho cái video fullscreen luôn.
Để chạy được Intent chúng ta cần thêm vào AndroidManifest.xml.PHP Code:<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="Bai_12_e3droid.gioi" android:versionCode="1" android:versionName="1.0" >
<uses-sdk android:minSdkVersion="8" />
<application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:name=".Bai_12_e3droidActivity" android:label="@string/app_name" android:screenOrientation="landscape"> <intent-filter> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".Bai_1_e3droidActivity" android:label="@string/app_name"> </activity> </application>
</manifest>
Vậy là ta có 1 phần giới thiệu game bằng video rồi. Để test chương trình này chúng ta cần thiết bị thật, nếu dùng emulator thì chỉ nghe thấy tiếng mà không thầy hình, vì tốc độ của emulator rất chậm. Các bạn thử trên thiết bị thật nhé.
Link download project: http://www.mediafire.com/?9unw17z2vuk9f9g
Bài viết tiếp theo của mình là hướng dẫn chèn âm thanh vào game. Khi 2 sprite va chạm vào nhau thì ta phát âm thanh, khi có 1 vụ nổ ta sẽ phát âm thanh vụ nổ.
Bài 13: Thêm âm thanh vào game.
Hôm nay để tiếp tục nhưng bài học về lập trình game minh sẽ giới thiệu cho các bạn cách để chèn âm thanh vào game. Nếu 1 game mà không có âm thanh chắc là game chán lắm.
Nội dung bài viết này như sau:
Để đơn giản không code nhiều mình dùng lại project 6. Trong project 6 ta có xét va chạm giữa 2 sprite, khi 2 sprite này chạm vào nhau thì có vụ nổ. Vậy khi vụ nổ được bật thì cũng là lúc ta phát âm thanh vụ nổ. Ngoài ra khi mới bắt đầu game thì mình có chạy 1 đoạn nhạc nền nữa. Các bạn xem code sau.
Code bài 6 có chút thay đổi nho nhỏ:PHP Code:package Bai_13_e3droid.gioi;import java.util.ArrayList;
import android.view.MotionEvent;
import com.e3roid.E3Activity;import com.e3roid.E3Engine;import com.e3roid.E3Scene;import com.e3roid.drawable.sprite.AnimatedSprite;import com.e3roid.drawable.texture.TiledTexture;import com.e3roid.event.SceneUpdateListener;
//Để tạo được vòng lặp trong game ta cần implements SceneUpdateListenerpublic class Bai_13_e3droidActivity extends E3Activity implements SceneUpdateListener {
private final static int WIDTH = 320; private final static int HEIGHT = 480; //Khai báo 2 biến đê quản lý nhạc nền và âm thanh nổ private Sound nhac_nen; private Sound no;
private TiledTexture sunmonster;//Biến này để load ảnh nhé private TiledTexture explosion; private AnimatedSprite[] sprite;// Cái này là cái mới nè.Mình khai báo 1 mảng AnimatedSprite. //Cái này sẽ dùng để vẽ 1 cái mặt kiểu Yahoo ý, và 1 vụ nổ. //Cài này dùng để cắt cái ảnh của mình ra để lấy từng Frame 1 private ArrayList<AnimatedSprite.Frame> Frames_sunmonster = new ArrayList<AnimatedSprite.Frame>(); private ArrayList<AnimatedSprite.Frame> Frames_explosion = new ArrayList<AnimatedSprite.Frame>(); //--------------------------------------------------------------------------------------- @Override public E3Engine onLoadEngine() { E3Engine engine = new E3Engine(this, WIDTH, HEIGHT); engine.requestFullScreen(); engine.requestPortrait(); return engine; }
//------------------------------------------------------------------------
--------------- @Override public E3Scene onLoadScene() { //Khởi tạo 2 biến quản lý âm thanh nhac_nen = new Sound(this, R.raw.nhacnen); no = new Sound(this, R.raw.no); E3Scene scene = new E3Scene(); scene.addEventListener(this); //Cứ 30ms là làm tươi màn hình 1 lần scene.registerUpdateListener(30, this);
//Giờ ta sẽ khởi tạo các AnimatedSprite sprite = new AnimatedSprite[3];//Khai bảo mảng này có 3 phần tử //Đặt các ảnh và các sprite và khởi tạo vị trí của sprite này //Đặt cả 2 đối tượng này ở giữa theo trục x nhé. int centerX = (getWidth() - sunmonster.getTileWidth()) / 2; sprite[0] = new AnimatedSprite(sunmonster, centerX, 50);//Cái này đặt vị trí y=50 centerX = (getWidth() - explosion.getTileWidth()) / 2; sprite[1] = new AnimatedSprite(sunmonster, centerX, getHeight()-50);//Cái này đặt ở cuối màn hình - 50 để bạn thấy nó luôn //Ở trên ta đã khởi tạo và đặt vị trí cho 2 sprite //Giờ ta add frame vào cho sprite sprite[0].animate(100, Frames_sunmonster);//Cứ 100ms là vẽ 1 cái ảnh sprite[1].animate(100, Frames_sunmonster); //Add xong frame rồi. giờ ta cho nó hiện thị thôi. scene.getTopLayer().add(sprite[0]); scene.getTopLayer().add(sprite[1]); //Phần trên ta mới tạo ra 2 cái mặt cưới thồi. Giờ ta thêm 1 cái để làm vụ nổ nhé. sprite[2] = new AnimatedSprite(explosion, (getWidth() - explosion.getTileWidth()) / 2, (getHeight() - explosion.getTileWidth()) / 2);//Đặt nó vào vị trí trung tâm //Add frame sprite[2].animate(100, Frames_explosion); //Hiện thị scene.getTopLayer().add(sprite[2]); //Tạm thời ta cho ẩn sprite[2]ẩn đi. sprite[2].hide(); //Bắt đầu game thì ta bật nhạc nền. nhac_nen.play(); return scene; }
//---------------------------------------------------------------------------------------
@Override public void onLoadResources() { /*TiledTexture(java.lang.String name, *int width, *int height, *int xindex, *int yindex, *int border, *Context context) */ //Tại sao lại là 192/6: chiều rộng thực tế của ảnh là 192 và trong đó có 6 cái ảnh nhỏ, mỗi ảnh nhỏ là 1 sprite //nên ta mang chia cho 6 để lấy chiều rộng của 1 sprite sunmonster = new TiledTexture("sunmonster.png", 192/6, 32, 0, 0, 0, this);//Load ảnh mặt cười nè. explosion = new TiledTexture("explosion.png", 162/5, 32, 0, 0, 0, this);//Cái này là ảnh tạo ra vụ nổ. //Ở đây ta thực hiện cắt lấy từng frame của 2 bức ảnh trên Frames_sunmonster = new ArrayList<AnimatedSprite.Frame>(); //Ta dùng phương thức add để lấy từng phần của bức ảnh nhé //.add(new AnimatedSprite.Frame(chỉ số cột, chỉ số hàng)); Chỉ số bắt đầu là 0 nhé. Frames_sunmonster.add(new AnimatedSprite.Frame(0, 0));//Cột 0, hàng 0 Frames_sunmonster.add(new AnimatedSprite.Frame(1, 0));//Cột 1, hàng 0 Frames_sunmonster.add(new AnimatedSprite.Frame(2, 0));//Cột 2, hàng 0 Frames_sunmonster.add(new AnimatedSprite.Frame(3, 0));//Cột 3, hàng 0 Frames_sunmonster.add(new AnimatedSprite.Frame(4, 0));//Cột 4, hàng 0 Frames_sunmonster.add(new AnimatedSprite.Frame(5, 0));//Cột 5, hàng 0 // cái này tương tự cái trên nhé. Frames_explosion = new ArrayList<AnimatedSprite.Frame>(); Frames_explosion.add(new AnimatedSprite.Frame(0, 0)); Frames_explosion.add(new AnimatedSprite.Frame(1, 0)); Frames_explosion.add(new AnimatedSprite.Frame(2, 0)); Frames_explosion.add(new AnimatedSprite.Frame(3, 0)); Frames_explosion.add(new AnimatedSprite.Frame(4, 0)); } //--------------------------------------------------------------------------------------- public boolean onSceneTouchEvent(E3Scene scene, MotionEvent motionEvent) { //Khi chạm vào màn hình thì tắt nhạc nền nhac_nen.stop(); return false; } //--------------------------------------------------------------------------------------- /* * Trong vòng lặp này ta sẽ cho 2 mặt cười di chuyển. một mặt di chuyển từ trên xuống, một mặt di chuyển từ dưới * lên. Khi 2 mặt này chạm vào nhau thì có 1 vụ nổ. Khi sảy ra vụ nổ này t
hì 2 cái mặt cười sẽ biến mất*/ @Override public void onUpdateScene(E3Scene arg0, long arg1) { runOnUiThread(new Runnable() { public void run() { sprite[0].moveRelativeY(2); sprite[1].moveRelativeY(-2);//Mỗi lần ta di chuyển 2px if(sprite[0].collidesWith(sprite[1])){//Kiểm tra va chạm //Khi 2 mặt cười này chạm vào nhau ta ẩn 2 mặt cười này đi sprite[0].hide(); sprite[1].hide(); //Ta cho hiện thị cái vụ nổ lên sprite[2].show(); //Khi hiện thị bom thì ta cho phát tiếng nổ.(Cho phép lặp lại) no.loop(); } } }); }}
Ở code này ta khai báo thêm 2 biến để quán lý nhạc nền và nhạc vụ nổ.
Đây là lớp Sound phụ vụ cho việc play, pause, replay..PHP Code:package Bai_13_e3droid.gioi;
import android.content.Context;import android.media.MediaPlayer;
public class Sound { private MediaPlayer mPlayer;
private boolean mPlaying = false; private boolean mLoop = false;
public Sound(Context ctx, int resID) { mPlayer = MediaPlayer.create(ctx, resID); mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { public void onCompletion(MediaPlayer mp) { mPlaying = false; if (mLoop) { mp.start(); } }
}); }
public synchronized void play() {
if (mPlaying) return;
if (mPlayer != null) { mPlaying = true; mPlayer.start(); } } public synchronized void replay() { if (mPlaying) return;
if (mPlayer != null) { mPlaying = true; mPlayer.seekTo(0); mPlayer.start(); } }
public synchronized void stop() { try { mLoop = false; if (mPlaying) { mPlaying = false; mPlayer.pause(); }
} catch (Exception e) { } }
public synchronized void loop() { mLoop = true; mPlaying = true; mPlayer.start(); }
public void release() { if (mPlayer != null) { mPlayer.release(); mPlayer = null; } }}
Các bạn chú ý là các đoạn nhạc được lưu trong thư mục res/raw/ tenfile.
Các bạn chạy thử chương trình nhớ mở loa lên nhé.
Link downlaod project: http://www.mediafire.com/?py0c3vzlcoqskcv
Bài viết tiếp theo của mình là hướng dẫn các bạn cách tạm dừng game trong khi đang chơi để
thiết lập các cài đặt. Củ thể là mình hướng dẫn các bạn thiết lập cài đặt nhạc nền, âm thanh, volume.
Bài 14: Tạm dừng Game và điều chỉnh âm lượng trong Game.
Mấy hôm nhà không có mạng nên lần này post hơi chậm chút, mong cả nhà thông cảm.
Bài này mình hướng dẫn các bạn cách tạm dừng game và điểu chỉnh âm lượng.
Nội dung đơn giản như sau: Khi game đang chạy ta chạm vào màn hình, khi đó sẽ có 1 Dialog hiện thị ra cho bận chỉnh âm lượng, sau khi chỉnh xong ta nhấn OK đẻ kết thúc và game lại tiếp tục.
Code:Main
PHP Code:package Bai_14_e3droid.gioi; import java.util.ArrayList;
import android.media.AudioManager; import android.view.MotionEvent;
import com.e3roid.E3Activity; import com.e3roid.E3Engine; import com.e3roid.E3Scene; import com.e3roid.drawable.sprite.AnimatedSprite; import com.e3roid.drawable.texture.TiledTexture; import com.e3roid.event.SceneUpdateListener;
//Để tạo được vòng lặp trong game ta cần implements SceneUpdateListener public class Bai_14_e3droidActivity extends E3Activity implements SceneUpdateListener {
private final static int WIDTH = 320; private final static int HEIGHT = 480; public boolean isPause = false; public int volume = 15;//Max volume là 15 public AudioManager audioManager;//biến này đung để định lại âm thanh //Khai báo 2 biến đê quản lý nhạc nền và âm thanh nổ private Sound nhac_nen; private Sound no;
private TiledTexture sunmonster;//Biến này để load ảnh nhé private TiledTexture explosion; private AnimatedSprite[] sprite;// Cái này là cái mới nè.Mình khai báo 1 mảng AnimatedSprite.
//Cái này sẽ dùng để vẽ 1 cái mặt kiểu Yahoo ý, và 1 vụ nổ. //Cài này dùng để cắt cái ảnh của mình ra để lấy từng Frame 1 private ArrayList<AnimatedSprite.Frame> Frames_sunmonster = new ArrayList<AnimatedSprite.Frame>(); private ArrayList<AnimatedSprite.Frame> Frames_explosion = new ArrayList<AnimatedSprite.Frame>(); //--------------------------------------------------------------------------------------- @Override public E3Engine onLoadEngine() { E3Engine engine = new E3Engine(this, WIDTH, HEIGHT); engine.requestFullScreen(); engine.requestPortrait(); return engine; }
//--------------------------------------------------------------------------------------- @Override public E3Scene onLoadScene() { //Khởi tạo 2 biến quản lý âm thanh nhac_nen = new Sound(this, R.raw.nhacnen); no = new Sound(this, R.raw.no); audioManager = (AudioManager) this.getSystemService(Bai_14_e3droidActivity.AUDIO_SERVICE); E3Scene scene = new E3Scene(); scene.addEventListener(this); //Cứ 30ms là làm tươi màn hình 1 lần scene.registerUpdateListener(30, this);
//Giờ ta sẽ khởi tạo các AnimatedSprite sprite = new AnimatedSprite[3];//Khai bảo mảng này có 3 phần tử //Đặt các ảnh và các sprite và khởi tạo vị trí của sprite này //Đặt cả 2 đối tượng này ở giữa theo trục x nhé. int centerX = (getWidth() - sunmonster.getTileWidth()) / 2; sprite[0] = new AnimatedSprite(sunmonster, centerX, 50);//Cái này đặt vị trí y=50 centerX = (getWidth() - explosion.getTileWidth()) / 2; sprite[1] = new AnimatedSprite(sunmonster, centerX, getHeight()-50);//Cái này đặt ở cuối màn hình - 50 để bạn thấy nó luôn //Ở trên ta đã khởi tạo và đặt vị trí cho 2 sprite //Giờ ta add frame vào cho sprite sprite[0].animate(100, Frames_sunmonster);//Cứ 100ms là vẽ 1 cái ảnh sprite[1].animate(100, Frames_sunmonster); //Add xong frame rồi. giờ ta cho nó hiện thị thôi.
scene.getTopLayer().add(sprite[0]); scene.getTopLayer().add(sprite[1]); //Phần trên ta mới tạo ra 2 cái mặt cưới thồi. Giờ ta thêm 1 cái để làm vụ nổ nhé. sprite[2] = new AnimatedSprite(explosion, (getWidth() - explosion.getTileWidth()) / 2, (getHeight() - explosion.getTileWidth()) / 2);//Đặt nó vào vị trí trung tâm //Add frame sprite[2].animate(100, Frames_explosion); //Hiện thị scene.getTopLayer().add(sprite[2]); //Tạm thời ta cho ẩn sprite[2]ẩn đi. sprite[2].hide(); //Bắt đầu game thì ta bật nhạc nền. nhac_nen.play(); return scene; }
//--------------------------------------------------------------------------------------- @Override public void onLoadResources() { /*TiledTexture(java.lang.String name, *int width, *int height, *int xindex, *int yindex, *int border, *Context context) */ //Tại sao lại là 192/6: chiều rộng thực tế của ảnh là 192 và trong đó có 6 cái ảnh nhỏ, mỗi ảnh nhỏ là 1 sprite //nên ta mang chia cho 6 để lấy chiều rộng của 1 sprite sunmonster = new TiledTexture("sunmonster.png", 192/6, 32, 0, 0, 0, this);//Load ảnh mặt cười nè. explosion = new TiledTexture("explosion.png", 162/5, 32, 0, 0, 0, this);//Cái này là ảnh tạo ra vụ nổ. //Ở đây ta thực hiện cắt lấy từng frame của 2 bức ảnh trên Frames_sunmonster = new ArrayList<AnimatedSprite.Frame>(); //Ta dùng phương thức add để lấy từng phần của bức ảnh nhé //.add(new AnimatedSprite.Frame(chỉ số cột, chỉ số hàng)); Chỉ số bắt đầu là 0 nhé. Frames_sunmonster.add(new AnimatedSprite.Frame(0, 0));//Cột 0, hàng 0 Frames_sunmonster.add(new AnimatedSprite.Frame(1, 0));//Cột 1, hàng 0 Frames_sunmonster.add(new AnimatedSprite.Frame(2, 0));//Cột 2, hàng 0 Frames_sunmonster.add(new AnimatedSprite.Frame(3, 0));//Cột 3, hàng 0 Frames_sunmonster.add(new AnimatedSprite.Frame(4, 0));//Cột 4, hàng 0 Frames_sunmonster.add(new AnimatedSprite.Frame(5, 0));//Cột 5, hàng 0
// cái này tương tự cái trên nhé. Frames_explosion = new ArrayList<AnimatedSprite.Frame>(); Frames_explosion.add(new AnimatedSprite.Frame(0, 0)); Frames_explosion.add(new AnimatedSprite.Frame(1, 0)); Frames_explosion.add(new AnimatedSprite.Frame(2, 0)); Frames_explosion.add(new AnimatedSprite.Frame(3, 0)); Frames_explosion.add(new AnimatedSprite.Frame(4, 0)); } //--------------------------------------------------------------------------------------- public boolean onSceneTouchEvent(E3Scene scene, MotionEvent motionEvent) {
//Khi chạm vào màn hình thì tắt nhạc nền if(motionEvent.getAction() == MotionEvent.ACTION_DOWN){ CusTomDialog dialog = new CusTomDialog(this, this); isPause = true; dialog.show(); } return false; } //--------------------------------------------------------------------------------------- /* * Trong vòng lặp này ta sẽ cho 2 mặt cười di chuyển. một mặt di chuyển từ trên xuống, một mặt di chuyển từ dưới * lên. Khi 2 mặt này chạm vào nhau thì có 1 vụ nổ. Khi sảy ra vụ nổ này thì 2 cái mặt cười sẽ biến mất*/ @Override public void onUpdateScene(E3Scene arg0, long arg1) { runOnUiThread(new Runnable() { public void run() { if(!isPause){ sprite[0].moveRelativeY(2); sprite[1].moveRelativeY(-2);//Mỗi lần ta di chuyển 2px if(sprite[0].collidesWith(sprite[1])){//Kiểm tra va chạm //Khi 2 mặt cười này chạm vào nhau ta ẩn 2 mặt cười này đi sprite[0].hide(); sprite[1].hide(); //Ta cho hiện thị cái vụ nổ lên sprite[2].show(); //Khi hiện thị bom thì ta cho phát tiếng nổ.(Cho phép lặp lại) no.loop(); } } } }); } }
Điều đáng quan tâm trong dòng code trên là :public boolean isPause = false;public int volume = 15;//Max volume là 15public AudioManager audioManager;//biến này đung để định lại âm thanh
Biến audioManager dùng để điều chỉnh âm lượng media.Muốn điều chỉnh âm lượng media các bạn cần gọi cái nàyaudioManager = (AudioManager) this.getSystemService(Bai_14_e3droidActivity.AUDIO_SERVICE);
Khi bạn click vào màn hình thì ta cho hiện thị dialog:CusTomDialog dialog = new CusTomDialog(this, this);// ở đây ta chuyền kèm theo lớp Bai_14...isPause = true;dialog.show();
ta gán isPause = true để tạm dừng game tạm thời.
File dialog.xml ta thiết kế như sau.PHP Code:<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" >
<SeekBar android:id="@+id/volume" android:layout_width="match_parent" android:layout_height="wrap_content" /> <Button android:id="@+id/ok" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" />
</LinearLayout>
Ta có 1 SeekBar dùng để kéo tăng và giảm âm lượng.
Đây là lớp Customdialog.java.PHP Code:package Bai_14_e3droid.gioi;
import android.app.Dialog; import android.content.Context; import android.media.AudioManager; import android.view.View; import android.widget.Button; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener;
public class CusTomDialog extends Dialog implements android.view.View.OnClickListener, OnSeekBarChangeListener{ Bai_14_e3droidActivity activity; Button ok; SeekBar volume; public CusTomDialog(Context context , Bai_14_e3droidActivity activity ) { super(context); this.activity = activity; setContentView(R.layout.dialog); this.setTitle("Điều chỉnh âm lượng"); ok = (Button)findViewById(R.id.ok); ok.setText("Ok"); ok.setOnClickListener(this);//Add sự kiện khi người dùng click vào button ok volume = (SeekBar)findViewById(R.id.volume); volume.setMax(15); volume.setProgress(this.activity.volume); volume.setOnSeekBarChangeListener(this); } @Override public void onClick(View view) { if(view.getId() ==R.id.ok){ this.activity.isPause = false; CusTomDialog.this.dismiss();//Tắt bỏ dialog này } } @Override public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) { //Khi bạn khéo hay click mà làm thay đổi trạng thái của Seekbar thì ta cập nhật lại giá trị volume this.activity.volume = volume.getProgress(); this.activity.audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, volume.getProgress(), 1); } @Override public void onStartTrackingTouch(SeekBar arg0) { // TODO Auto-generated method stub } @Override public void onStopTrackingTouch(SeekBar arg0) { // TODO Auto-generated method stub }
}
khi ta chuyền Bai_14... thì ta gán nó vào mà biến ta khai bào this.activity = activity;
Âm lượng max của Android là 15 nên mình để mặc định thanh SeekBar là max.
Khi bạn click vào button OK thìthis.activity.isPause = false;//Game được chạy tiếpCusTomDialog.this.dismiss();//Tắt bỏ dialog này
Hi. Có gì các bạn cứ comment mình sẽ commet trả lời nhé.
Link download project: http://www.mediafire.com/?1lr5cybx7nb94m8
Bài sau mình sẽ nói đế vấn đề sử dụng layout. Tại sao lại nói đến vấn đề này . Ví dụ bạn muốn viết 1 game nhưng nó chỉ hoạt động ở 1/10 của màn hình, còn 1 phần còn lại bạn dùng làm việc khác. Cái này là tùy biến.(Hihi)
Bài 15: Tùy chỉnh kích thước hiện thị. Thêm các phần khác vào layout
Hôm này mình sẽ hướng dẫn thêm cho các bạn 1 phần tùy chỉnh.Khi viết game đôi khi ta không cần dùng toàn màn hình mà chỉ dùng 1 phần, các phần còn lại ta làm những thứ khác. ví dụ như hiện thị ảnh, video, text...
Để làm được điều này trong E3droid không khó chút nào cả.
Đầu tiên ta thiết kế layout như sau.HTML Code:<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" >
<LinearLayoutandroid:id="@+id/xmllayout_main"android:layout_width="wrap_content"android:layout_height="wrap_content"android:padding="2px"android:background="#FFF"android:layout_gravity="center"><com.e3roid.opengl.RenderSurfaceView
android:id="@+id/xmllayout_view"android:layout_width="240px" android:layout_height="240px"/>
</LinearLayout><TextView android:id="@+id/bottom_textview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"android:gravity="center"android:textSize="20sp"android:text="@string/app_name"/>
</LinearLayout>
Phần này là phần hiện thị của chúng ta. Fix cao và rộng là 240px<com.e3roid.opengl.RenderSurfaceView android:id="@+id/xmllayout_view"android:layout_width="240px" android:layout_height="240px"/>
Cái này là textview để khi bạn chạm vào vùng hiện thị ta sẽ hiện thị số lần chạm vào vùng hiện thị.<TextView android:id="@+id/bottom_textview"android:layout_width="fill_parent" android:layout_height="wrap_content"android:gravity="center"android:textSize="20sp"android:text="@string/app_name"/>
Kết quả layout khi chạy chương trình như sau:
Đây là code chương trình. Vì code khá đơn giản nên mình đã comment trong code rồi nên không có gì viết thêm. Các bạn xem code sau.
PHP Code:package Bai_15_e3droid.gioi;
import android.graphics.Color; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.widget.TextView;
import com.e3roid.E3Activity; import com.e3roid.E3Engine; import com.e3roid.E3Scene; import com.e3roid.drawable.Background; import com.e3roid.drawable.Sprite; import com.e3roid.drawable.texture.AssetTexture; import com.e3roid.drawable.texture.Texture; import com.e3roid.drawable.texture.TiledTexture; import com.e3roid.opengl.RenderSurfaceView;
public class Bai_15_e3droidActivity extends E3Activity implements OnTouchListener {
private final static int WIDTH = 240; private final static int HEIGHT = 240; private Texture robotTexture; private Sprite robot; //Khai báo biến textview private TextView tv;
@Override protected void onSetContentView() { //Ban đầu ta phải sét contentview của chúng ta là layout main this.setContentView(R.layout.main); //=================================================PHẦN QUAN TRỌNG NHẤT====================================== //Trong layout main ta có surfaceView muốn tham chiếu đến thì ta find id của nó trong layout main. //biến this.surfaceView là gói E3droid cung cấp nên ta không cần khai báo this.surfaceView = (RenderSurfaceView)this.findViewById(R.id.xmllayout_view); this.surfaceView.setRenderer(this.engine); //Ta cần sét đây là engine của chúng ta surfaceView.setOnTouchListener(this);//Lắng nghe sự kiện khi bạn chạm vào vùng hiện thị này //=========================================================================================================== this.tv = (TextView)findViewById(R.id.bottom_textview);//Find textview
this.tv.setBackgroundColor(Color.RED);//Đặt màu nền là màu đỏ } @Override public E3Engine onLoadEngine() { E3Engine engine = new E3Engine(this, WIDTH, HEIGHT, E3Engine.RESOLUTION_FIXED_RATIO); engine.requestFullScreen(); engine.requestPortrait(); return engine; }
@Override public E3Scene onLoadScene() {
E3Scene scene = new E3Scene(); scene.addEventListener(this); int centerX = (getWidth() - robotTexture.getWidth()) / 2; int centerY = (getHeight() - robotTexture.getHeight()) / 2; robot = new Sprite(robotTexture, centerX, centerY); scene.getTopLayer().add(robot); Background background = new Background( new TiledTexture("background.png", getWidth(), getHeight(), this)); scene.getTopLayer().setBackground(background); return scene; }
@Override public void onLoadResources() { robotTexture = new AssetTexture("robot.png", this); } int dem = 0; @Override public boolean onSceneTouchEvent(E3Scene scene, MotionEvent motionEvent) {
if (robot != null) { if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) { // x and y must be adjusted to scene's screen position because
// MotionEvent's getX()&getY() returns pixel position of the actual device. int x = getTouchEventX(scene, motionEvent); int y = getTouchEventY(scene, motionEvent); // Because x and y can be negative or can be out of the view // when using with layout container, x and y values must be checked. if (x >= 0 && y >=0 && x <= getWidth() && y <= getHeight()) { x -= robotTexture.getWidth() / 2; y -= robotTexture.getHeight() / 2; robot.move(x, y); } } } return false; }
@Override public boolean onTouch(View view, MotionEvent motionEvent) { //Mỗi lần ta chạm vào vùng hiện thị thì ta tăng số lần chạm lên và hiện thị nó lên bằng biến tv if(view.getId() == R.id.xmllayout_view && motionEvent.getAction() == MotionEvent.ACTION_DOWN){ dem++; tv.setText(String.valueOf(dem)); }
return false; } }
Link downlaod project:http://www.mediafire.com/?wjmzcu9srxtp7rt
Bài tiếp theo của mình là hướng dẫn cách chuyển từ Intent này sang Intent khác. Trong khi chuyển Intent thì ta sẽ nhận giá trị mà Intent kia truyền theo. Cái này ta có thể áp dụng nhiều sau này.
Bài 16: Chuyển từ activity này sang activity khác và gửi kèm theo dữ liệu
Hôm này mình hướng dẫn các bạn làm 1 thứ mà trong game thực hiện rất nhiều, để chuyển các level trong game thì có nhiều cách,nhưng cách đơn giản nhất trong android là chuyển từ activity này sáng activity khác. Nội dung bài viết này đơn giản là: Khi bạn đang ở activity 1 bạn chạm vào màn hình thì ta chuyển sang activity 2. Số sprite vẽ trong activity 1 là 10 khi chuyển sang activity 2 sẽ là 50 sprite. Tắng số sprite để giúp các bạn thấy rằng dữ liệu ta chuyền theo là nhận được. Mình xử dụng lại code của bài 4 nhé.
Code activity 1:
PHP Code:package Bai_16_e3droid.gioi;
import android.content.Intent; import android.view.MotionEvent;
import com.e3roid.E3Activity; import com.e3roid.E3Engine; import com.e3roid.E3Scene; import com.e3roid.drawable.Sprite; import com.e3roid.drawable.texture.AssetTexture; import com.e3roid.drawable.texture.Texture; import com.e3roid.event.SceneUpdateListener;
//Để tạo được vòng lặp trong game ta cần implements SceneUpdateListener public class Bai_16_e3droidActivity extends E3Activity implements SceneUpdateListener {
private final static int WIDTH = 320; private final static int HEIGHT = 480;
// Khai báo mảng sprite có tên là robot private Sprite[] robot;
// Khai báo 1 Texture. Đối tượng này để load ảnh lên private Texture robotTexture;
// -----------------------------------------------------------------------
---------------- @Override public E3Engine onLoadEngine() { E3Engine engine = new E3Engine(this, WIDTH, HEIGHT); engine.requestFullScreen(); engine.requestPortrait(); return engine; }
// --------------------------------------------------------------------------------------- @Override public E3Scene onLoadScene() {
E3Scene scene = new E3Scene(); scene.addEventListener(this);
// Cứ 30ms là làm tươi màn hình 1 lần scene.registerUpdateListener(30, this);
// Khởi tạo đối tượng robot. robot = new Sprite[10];// Khai báo mảng gồm 4 sprite // Khởi tạo tứng sprite for (int i = 0; i < robot.length; i++) robot[i] = new Sprite(robotTexture, 0, 0);// Đặt toàn bộ ở vị trí // (0,0)
// add toàn bộ sprite vào màn hình. for (int i = 0; i < robot.length; i++) scene.getTopLayer().add(robot[i]); return scene; }
// --------------------------------------------------------------------------------------- @Override public void onLoadResources() { // Load ảnh từ thư mục Asset robotTexture = new AssetTexture("robot.png", this); }
// --------------------------------------------------------------------------------------- public void onUpdateScene(E3Scene arg0, long arg1) { runOnUiThread(new Runnable() { public void run() { dichuyen(robot);// Gọi phương thức di chuyển để làm cho 4 sprite // di chuyển ngẫu nhiên nhưng // không di chuyển ra khỏi màn hình } });
}
// ---------------------------------------------------------------------------------------
// Phương thức cho bạn 1 số ngẫu nhiên từ min->max. public int getRandomIndex(int min, int max) { return (int) (Math.random() * (max - min + 1)) + min; }
// --------------------------------------------------------------------------------------- // Phương thức này sẽ làm di chuyển cả 4 sprite với hướng đi là ngẫu nhiên
public void dichuyen(Sprite[] sprite) { for (int i = 0; i < sprite.length; i++) { int x = getRandomIndex(-10, 10);// Ta lấy giá trị từ -10 -> 10 int y = getRandomIndex(-10, 10);
// Kiểm tra xem nếu mà di chuyển theo x,y mà vẫn nằm trong màn hình // thì cho di chuyển if (sprite[i].getRealX() + x < getWidth() && sprite[i].getRealX() + x > 0 && sprite[i].getRealY() + y < getHeight() && sprite[i].getRealY() + y > 0) sprite[i].moveRelative(x, y); }
}
@Override public boolean onSceneTouchEvent(E3Scene scene, MotionEvent motionEvent) {
//Khi chạm vào màn hình thì tắt activity hiện tại và bật activity 2 lên //Khi bật lên ta chuyền theo số sprite được vẽ Intent i = new Intent(this, Bai_16_e3droidActivity2.class); i.putExtra("so_sprite", 50);//Giá trị chuyền sang là 50 sprite this.startActivity(i); this.finish();//Tắt activity này return false; } }
Ở Activity 1 này chỉ có 1 chỗ cần quan tâm là:Intent i = new Intent(this, Bai_16_e3droidActivity2.class);i.putExtra("so_sprite", 50);//Giá trị chuyền sang là 50 spritethis.startActivity(i);this.finish();//Tắt activity này
Ở đây là khai báo 1 intent là i, i.putextra là phương thức gắn kèm theo biến, ở đây là biến so_sprite, chú ý: đặt tên là gì thì phải nhớ, để khi sang activity 2 ta còn nhận dữ liệu.Khi ta chuyển sang activity 2 thì ta tắt activity 1 đi.
Code activity 2:
PHP Code:
package Bai_16_e3droid.gioi;
import android.os.Bundle; import android.view.MotionEvent;
import com.e3roid.E3Activity; import com.e3roid.E3Engine; import com.e3roid.E3Scene; import com.e3roid.drawable.Sprite; import com.e3roid.drawable.texture.AssetTexture; import com.e3roid.drawable.texture.Texture; import com.e3roid.event.SceneUpdateListener;
//Để tạo được vòng lặp trong game ta cần implements SceneUpdateListener public class Bai_16_e3droidActivity2 extends E3Activity implements SceneUpdateListener {
private final static int WIDTH = 320; private final static int HEIGHT = 480;
// Khai báo mảng sprite có tên là robot private Sprite[] robot;
// Khai báo 1 Texture. Đối tượng này để load ảnh lên private Texture robotTexture;
// --------------------------------------------------------------------------------------- @Override public E3Engine onLoadEngine() { E3Engine engine = new E3Engine(this, WIDTH, HEIGHT); engine.requestFullScreen(); engine.requestPortrait(); return engine; }
// --------------------------------------------------------------------------------------- @Override public E3Scene onLoadScene() {
E3Scene scene = new E3Scene(); scene.addEventListener(this);
// Cứ 30ms là làm tươi màn hình 1 lần scene.registerUpdateListener(30, this);
//============================================================ //Để nhận được dữ liệu từ activity 1 thì khai báo biến sau Bundle b = getIntent().getExtras();//Ta nhận lại intent activity 1 int so_sprite = b.getInt("so_sprite");//Chú ý key phải giống nhau nhé //============================================================ // Khởi tạo đối tượng robot. robot = new Sprite[so_sprite];//Khai báo số lượng sprite (50) // Khởi tạo tứng sprite for (int i = 0; i < robot.length; i++)
robot[i] = new Sprite(robotTexture, 0, 0);// Đặt toàn bộ ở vị trí // (0,0)
// add toàn bộ sprite vào màn hình. for (int i = 0; i < robot.length; i++) scene.getTopLayer().add(robot[i]); return scene; }
// --------------------------------------------------------------------------------------- @Override public void onLoadResources() { // Load ảnh từ thư mục Asset robotTexture = new AssetTexture("robot.png", this); }
// --------------------------------------------------------------------------------------- public void onUpdateScene(E3Scene arg0, long arg1) { runOnUiThread(new Runnable() { public void run() { dichuyen(robot);// Gọi phương thức di chuyển để làm cho 4 sprite // di chuyển ngẫu nhiên nhưng // không di chuyển ra khỏi màn hình } });
}
// --------------------------------------------------------------------------------------- // Phương thức cho bạn 1 số ngẫu nhiên từ min->max. public int getRandomIndex(int min, int max) { return (int) (Math.random() * (max - min + 1)) + min; }
// --------------------------------------------------------------------------------------- // Phương thức này sẽ làm di chuyển cả 4 sprite với hướng đi là ngẫu nhiên
public void dichuyen(Sprite[] sprite) { for (int i = 0; i < sprite.length; i++) { int x = getRandomIndex(-10, 10);// Ta lấy giá trị từ -10 -> 10 int y = getRandomIndex(-10, 10);
// Kiểm tra xem nếu mà di chuyển theo x,y mà vẫn nằm trong màn hình // thì cho di chuyển if (sprite[i].getRealX() + x < getWidth() && sprite[i].getRealX() + x > 0 && sprite[i].getRealY() + y < getHeight() && sprite[i].getRealY() + y > 0) sprite[i].moveRelative(x, y); }
}
@Override public boolean onSceneTouchEvent(E3Scene scene, MotionEvent motionEvent) {
return false; } }
Phần quan trọng trong code activity 2 này là làm sao nhậ được giá trị từ activity 1:
Code sau cho phép ta nhận dữ liệu từ activity 1:
//Để nhận được dữ liệu từ activity 1 thì khai báo biến sauBundle b = getIntent().getExtras();//Ta nhận lại intent activity 1int so_sprite = b.getInt("so_sprite");//Chú ý key phải giống nhau nhé
Khá là đơn giản, bạn chỉ cần khai báo 1 biến kiểu Bundle sau đó getExtras , để nhận dữ liểu kiểu int thì ta dùng getInt. Khi activity put dạng string thì bạn dùng getString là ok.
Để chạy được activity 2 thì các bạn cần có manifest như sau:PHP Code:<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="Bai_16_e3droid.gioi" android:versionCode="1" android:versionName="1.0" >
<uses-sdk android:minSdkVersion="8" />
<application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:name=".Bai_16_e3droidActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!-- Thêm 1 activity mới --> <activity android:name=".Bai_16_e3droidActivity2"></activity> </application>
</manifest>
Để chạy được ta thêm<!-- Thêm 1 activity mới --><activity android:name=".Bai_16_e3droidActivity2"></activity>
Như vậy với cách này chúng ta cỏ thể giái quyết vấn đề chuyển level, chuyển từ menu sang chơi game, từ game over sang hộp thoại nhập tên....Rất nhiều các dùng cái này.
Mình cũng viết được 16 bài rồi nhưng toàn lý thuyết nên mình xin phép chạy trước. Sang bài 17 mình sẽ cùng các bạn xây dựng game đua xe đơn giản. Nội dung về game sẽ được mình gửi lên sớm nhất có thể. Chúc các bạn thành công.
Link download project: http://www.mediafire.com/?s62vrzi33limm1i
Bài 17: Viết game đua xe đơn giản.
Cũng không biết viết cái gì để giúp cho các bạn học tốt hơn, ý tưởng game thì nhiều nhưng để viết ra thì quả là không dễ chút nào cả. Nếu viết 1 game qua khó có lẽ các bạn đọc sẽ tẩu họa nhập mà, lăn ra mà....Hi. Vì những lý do trên nên mình sẽ chỉ viết 1 cái đơn giản thôi.
Hiện tại các bạn có thể downlaod game này để test trên Vimarket với đường link sau: http://vimarket.vn/chi-tiet/GamePlay.Gioi
Link downlaod PROJECT: http://www.mediafire.com/?lxh85oeoldwzulw
Nội dung của game đua xe đơn giản như sau:
1- (Player) Người chơi sẽ điều khiển 1 chiếc Oto. Chiếc oto này có thể chạy sang trái hoặc sang phải (không chạy lên, xuống). Để điều khiển oto này thì ta chỉ cần nghiêng màn hình sang bên nào thì oto chạy sang bến đó.(sử dụng bộ cảm biến).
2- (Car) Các oto khác sẽ di chuyển ngẫu nhiên trên màn hình (Ngẫu nhiên ở đây là oto xuất hiện ở các làn đường ngẫu nhiên, khi rẽ trái hoặc rẽ phải ngẫu nhiên). Các xe oto này sẽ di chuyển từ trên xuống dưới.
3- Khi mỗi Car mà di chuyển hết màn hình thì ta cộng thêm điểm cho người chơi, điểm người troi được hiện thị ở góc trên bên trái màn hình.
4- Trên màn hình khi chơi ta hiện thị thêm 2 phần:+ Hiện thị phần tạm dừng game ở vị trí góc dưới bên trái màn hình.+ Hiện thị phần setting góc dưới bên phải màn hình.
5- Khi Player va chạm với 1 Car nào đó thì trò chơi kết thúc.
6- Để cho đồ họa có gì đó thêm phần hấp dẫn ta sẽ tạo ra khói đàng sau xe của Player.
7- Tại phần setting thì ta chỉ cho thiết lập âm lượng của game.
8- Khi gameover ta lưu số điểm của người chơi lại.(Vì còn đơn giản nên ta lưu dữ liệu dạng file).
9- Khi hiện thị điểm người chơi ta chỉ hiện thị 5 người đạt điểm cao nhất và sắp xếp giảm dần.
10- Có thể reset lại điểm.
Nội dung mình chỉ nói qua vậy thôi, còn một số cái khi làm mình nói tiếp.
Game được chia thành 4 phần chính:
1: Có 1 lớp dành cho phần giới thiệu.(Chức năng chính là hiện thị 1 video giới thiệu về game).
2: Lớp hiện thị phần menu. Lớp này cho bạn chọn để xem thông tin về game, setting và play.
3: Lớp MainGame là lớp quan trọng nhất, nơi mà người chơi điều khiển oto. Lớp này cho phép người chơi điều khiển oto và có chức năng tạm dùng, chơi tiếp, setting.
4: Lớp này khi kết thúc game thì lưu số điểm người chơi mà cao hơn 1 người nào trong danh sách đã có, hiện thị danh sách điểm tốp 5. Có thêm chức năng chơi lại, reset lại điểm, chuyển sang menu.
Tại 3 lớp 2,3,4 khi bạn ấn vào nút back trên thiết bị thì đều có thể thoát được game.
1 số hình ảnh thiết kế trong game:
Thiết kế Menu
Thiết kế setting.
Thiết kế infor:
Thiết kế phần hiện thị danh sách điểm.
Thiết kế giao diện chính.
Hiện tại bản thiết kế của mình là dành cho máy tính bảng có độ phân giải là 600 x 800 px.
Bắt đầu xây dựng game.1- Xây dựng lớp hiện thị phần giới thiệu.
Đầu tiên ta thiết kế XML phần giới thiệu như sau. Tên của layout này là gioithieu.xml
PHP Code:<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:theme="@android:style/Theme.NoTitleBar.Fullscreen"> <VideoView android:id="@+id/videoView" android:layout_width="fill_parent" android:layout_alignParentRight="true" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_alignParentBottom="true" android:layout_height="fill_parent"> </VideoView> </RelativeLayout>
Ở đây ta dùng 1 VideoView để hiện thị video. VideoView này được đặt trong RelativeLayout nhằm múc đích cho ta kéo cái VideoView full màn hình. Layout này đơn giản nên không giải thích thêm.
Đây là video được hiện thị khi chúng ta chạy chương trình.
Phần giới thiệu game là video sau:http://www.youtube.com/watch?v=w0kHD...ature=youtu.be
==> Như vậy phần XML của phần giới thiệu đã xong.Giờ ta chuyển sang phần code Java.Lớp này có tên là GamePlayActivity.java
PHP Code:package GamePlay.Gioi;
import android.app.Activity;import android.content.Intent;import android.media.MediaPlayer;import android.media.MediaPlayer.OnCompletionListener;import android.net.Uri;import android.os.Bundle;import android.view.MotionEvent;import android.view.View;import android.view.View.OnTouchListener;
import android.view.Window;import android.view.WindowManager;import android.widget.VideoView;
public class GamePlayActivity extends Activity implements OnCompletionListener, OnTouchListener {
private VideoView v; private Intent i;
// ---------------------------------------------------------------------------- @Override public void onCreate(Bundle savedInstanceState) { Control.init(this);// Khi play thì khởi tạo lại các biến tĩnh // Sét full màn hình requestWindowFeature(Window.FEATURE_NO_TITLE);// Không hiện thị tiêu đề getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);// Fullscreen super.onCreate(savedInstanceState); setContentView(R.layout.gioithieu); // Hiện thị dòng chữ để thông báo cho người dùng biết khi chạm vào màn // hình thì bỏ qua phần giới thiệu này. Tools.senMessenger(this, "Touch Skip");
v = (VideoView) findViewById(R.id.videoView); Uri u = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.video);// Lấy video từ thư mục raw v.setVideoURI(u); v.setOnCompletionListener(this);// Khi video đã chạy xong v.setOnTouchListener(this);// Khi chạm vào màn hình v.setKeepScreenOn(true);// Khi hiện thị video thì không cho tự động tắt // màn hình v.start();
// Khởi tạo intent mà ta muốn chuyển sang sau khi video chơi xong i = new Intent(this, Menu.class); }
// ---------------------------------------------------------------------------- public void onCompletion(MediaPlayer arg0) { // Khi video chạy xong thì ta dựng lại và chuyển sang phần game this.startActivity(i); finish();// Kết thúc Intent }
// ---------------------------------------------------------------------------- public boolean onTouch(View arg0, MotionEvent arg1) { // Khi người chạm vào màn hình. this.startActivity(i);
finish();// Kết thúc Intent return false; }}
- Phương thức Control.init(this); này thì đến phần sau mời sẽ giải thích cái này.- Các bạn nhớ là file video của chúng ta đặt trong thư mục raw nhé.
Vì bài viết khá là dài nên mình tách thành phần nhỏ.