Friday, August 30, 2013

Andengine - Bài 1: Cài đặt BaseGameActivity

BaseGameActivity là activity bạn phải khởi tạo khi làm việc với andengine. Giống như các Activity thông thường BaseGameActivity cũng có life cycle . Sau đây, mình sẽ giới thiệu các thành phần cũng như các phương thức mà bạn phải cài đặt.
Đầu tiên tạo class MyGameActivity extends BaseGameActivity. Lúc này bạn sẽ phải triển khai một vài phương thức, mình sẽ comment chức năng của phương thức đó.

  1. public class MyGameActivity extends BaseGameActivity{

  2. @Override
  3. public EngineOptions onCreateEngineOptions() {
  4. // Cài đặt EngineOptions với 1 camera. Ngoài ra bạn có thể tùy chọn có music,sound hay có Mult iTouch
  5. return null;
  6. }

  7. @Override
  8. public void onCreateResources(
  9. OnCreateResourcesCallback pOnCreateResourcesCallback)
  10. throws Exception {
  11. //Tạo tất cả các Resources. Load các Resourt như ảnh, font chữ, music,sound.
  12. }

  13. @Override
  14. public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback)
  15. throws Exception {
  16. //Tạo scene và attach các thứ mà bạn vẽ vào scene
  17. }

  18. @Override
  19. public void onPopulateScene(Scene pScene,
  20. OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception {
  21. // Attach các thứ mà bạn thường xuyên hiển thị trên Scene.
  22. }
  23. }
Tiếp theo mình sẽ triển khai các phương thức trên :
  1. public class MyGameActivity extends BaseGameActivity{
  2.       private Camera mCamera ;//tạo camera, lưu ý camera không thể thay đổi
  3.       private int CAMERA_HEIGHT = 720;// khai báo chiều cao cho camera
  4.       private int CAMERA_WIDTH = 480;//khai báo chiều dọc cho camera
  5. @Override
  6. public EngineOptions onCreateEngineOptions() {
  7. // Cài đặt EngineOptions với 1 camera. Ngoài ra bạn có thể tùy chọn có music,sound hay có Multi Touch
  8. mCamera = new BoundCamera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
  9. EngineOptions eni = new EngineOptions(true,
  10. ScreenOrientation.PORTRAIT_SENSOR, new FillResolutionPolicy(),
  11. this.mCamera); //set fullscreen = true , theo chiều dọc = PORTRAIT_SENSOR, full màn hình =  new FillResolutionPolicy()
  12. eni.getAudioOptions().setNeedsMusic(true);//set game  có music
  13. eni.getAudioOptions().setNeedsSound(true);//set game có Sound
  14. eni.getTouchOptions().setNeedsMultiTouch(true);
  15. if (MultiTouch.isSupported(this)) {
  16. if (MultiTouch.isSupportedDistinct(this)) {
  17. } else {
  18. }
  19. } else {
  20. Toast.makeText(
  21. this,
  22. "Sorry your device does NOT support MultiTouch!\n\n(Falling back to SingleTouch.)\n\nControls are placed at different vertical locations.",
  23. Toast.LENGTH_LONG).show();
  24. } //set game co multi touch
  25. return eni;
  26. }

  27. @Override
  28. public void onCreateResources(
  29. OnCreateResourcesCallback pOnCreateResourcesCallback)
  30. throws Exception {
  31. //Tạo tất cả các Resources. Load các Resourt như ảnh, font chữ, music,sound.
  32.                 //Phần này mình sẽ hướng dẫn ở các bài sau. Thêm câu lệnh sau
  33.                 pOnCreateResourcesCallback.onCreateResourcesFinished();
  34. }

  35. @Override
  36. public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback)
  37. throws Exception {
  38. //Tạo scene và attach các thứ mà bạn vẽ vào scene
  39.                 Scene currentScene= new Scene();
  40.                pOnCreateSceneCallback.onCreateSceneFinished(currentScene);
  41. }

  42. @Override
  43. public void onPopulateScene(Scene pScene,
  44. OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception {
  45. // Attach các thứ mà bạn thường xuyên hiển thị trên Scene.
  46.                 pOnPopulateSceneCallback..onPopulateSceneFinished();
  47. }
  48. }
Oke. Đến đây bạn đã triển khai xong BaseGameActivity. Việc còn lại bạn phải load các resourt lên và từ resourt đó tạo các hình ảnh để vẽ lên scene. Mình sẽ hướng dẫn cụ thể vào các bài sau.

Design Pattern - Observer


Nó là gì ?

Observer cho phép các đối tượng có thể lắng nghe và phản ứng khi có thông báo từ một đối tượng khác. Tức là khi một đối tượng gửi một thông báo, các đối tượng lắng nghe nó có thể phản ứng lại với thông báo đó.

Sử dụng khi nào ?

Khi bạn muốn các đối tượng liên lạc với nhau. Khi đối tượng này gửi 1 thông điệp thì các đối tượng đăng ký lắng nghe thông điệp sẽ phản ứng lại với thông điệp đó. Đối tượng gửi thông điệp sẽ không cần biết nó sẽ gửi cho ai và đối tượng nhận thông điệp sẽ không cần biết ai gửi thông điệp đó.

Dùng nó như thế nào ?

Giả sử trong một hệ thống bán hàng, mỗi khi có sản phẩm mới hệ thống sẽ thông báo cho tất cả các khách hàng quan tâm đến sản phẩm này. Đầu tiên tôi tạo ra một lớp interface với 1 phương thức sẽ phản ứng khi có sản phẩm mới .

  1. public interface Observer{
  2.    void update(String message);//phương thức phản ứng lại khi nhận được thông báo.
  3. }
Và lớp Customer sẽ triển khai interface trên :

  1. public class Customer implements Observer{
  2. private String name;
  3. private int age;
  4. public Customer(String name, int age) {
  5. super();
  6. this.name = name;
  7. this.age = age;
  8. }

  9. @Override
  10. public void update(String message) {
  11. System.out.println(name + " " + message);
  12. }

  13. }
Tiếp theo tạo một interface với các phương thức, cho phép đối tượng Observer đăng ký phản ứng, hủy đăng ký nhận, và thông báo đến tất cả các đối tượng Observer đã đăng ký :

  1. public interface Subject {  
  2.     public void attachObserver(Observer observer);// thêm đối tượng đăng ký lắng nghe thông báo.
  3.     public void detachObserver(Observer observer);// hủy đối tượng đăng ký lắng nghe thông báo
  4.     public void notifyObserver();//thong bao đến tất cả các đối tượng đã đăng ký thông báo.
  5. }
Và class Product sẽ triển khai interface trên:

  1. public class Product implements Subject{
  2. private List<Observer> obs = new ArrayList<Observer>();
  3. private String nameProduct;
  4. public Product(String nameProduct) {
  5. super();
  6. this.nameProduct = nameProduct;
  7. }

  8. @Override
  9. public void attachObserver(Observer observer) {
  10. obs.add(observer);
  11. }

  12. @Override
  13. public void detachObserver(Observer observer) {
  14. obs.remove(observer);
  15. }

  16. @Override
  17. public void notifyObserver() {
  18. for(Observer ob : obs){
  19. ob.update(nameProduct);
  20. }
  21. }
  22. }
Ok đến đây ta đã có một class có thể thông báo đến các observer và observer sẽ phản ứng lại với thông báo này. Tạo hàm main như sau:
  1. public class Main {
  2. public static void main(String[] args) {
  3. Customer cus1 = new Customer("Ti", 11);
  4. Customer cus2 = new Customer("Teo", 12);
  5. Product product1 = new Product("Laptop");
  6. product1.attachObserver(cus1);//cus1 dang ky phan ung khi có thông báo từ product
  7. product1.attachObserver(cus2);
  8. product1.notifyObserver();//thông báo đến tất cả các Observer.
  9. }
  10. }
Oke vậy đã xong Observer.

Wednesday, August 28, 2013

Các thành phần cơ bản andengine.


Tài liệu về andengine các bạn có thể tìm thấy rất nhiều trên mạng. Mình chỉ liệt kê một số thành phần chính trong andengine và chức năng của nó.
1. Camera : - Xác định một hình chữ nhật với chiều dài và chiều rộng xác định trước để vẽ lên màn hình. Có thể tất cả các thứ trong game sẽ được nhìn thấy trên camera hoặc camera chỉ hiển thị một phần của khung cảnh, bạn phải di chuyển camera để nhìn thấy các phần còn lại (Boundcamera) . Hoặc một camera có thể phóng to, thu nhỏ hoặc cuộn gọi là ZoomCamera.
2. Engine : - Trong game có nhiều tiến trình nhỏ chạy song song. Engine sẽ quản lí tất cả các tiến trình đó. Cái này bạn không cần phải quan tâm nhiều vì andengine sẽ làm việc đó.
3. Scene: - Chứa tất cả các đối tượng mà bạn vẽ trên màn hình. Nó giống như một tờ giấy, trên đó bạn có thể vẻ tất cả các hình, cập nhật chúng và có thế chứa các tờ giấy khác.
4. Entiy : Là những Object sẽ vẽ các bức ảnh của bạn lên scene. Có thể một bức ảnh tỉnh (Sprite), một bức ảnh động (AnimatedSprite), hoặc một bức ảnh có nhiều bức ảnh con trong nó (TitledSprite).
Trên đây là một số thành cơ bản, ngoài ra andengine còn có các gói mở rộng khác, mình sẽ đề cập sau.
Ở các bài viết sau mình sẽ có các hướng dẫn cụ thể, các cài đặt và sử dụng thành phần trong andengine.

Monday, August 26, 2013

Design Pattern .Lời mở đầu!

Design Pattern là một tứ khá là quan trọng mà mọi lập trình viên muốn giỏi đều phải biết. Được sử dụng thường xuyên trong các ngôn ngữ OOP. Nó sẽ cung cấp cho bạn các "mẫu thiết kế", giải pháp để giải quyết các vấn đề chung, thường gặp trong lập trình. Các vấn đề mà bạn gặp phải có thể bạn sẽ tự nghĩ ra cách giải quyết nhưng có thể nó chưa phải là tối ưu. Design Pattern giúp bạn giải quyết vấn đề một cách tối ưu nhất, cung cấp cho bạn các giải pháp trong lập trình OOP.

Trong Design Pattern có 3 nhóm bao gồm:
   - Creational Pattern (nhóm khởi tạo) gồm : Abstract Factory, Factory Method, Singleton, Builder, Prototype. Nó sẽ giúp bạn trong việt khởi tạo đối tượng, như bạn biết để khởi tạo bạn phải sử dụng từ khóa new, nhóm Creational Pattern sẽ sử dụng một số thủ thuật để khởi tạo đối tượng mà bạn sẽ không nhìn thấy từ khóa này.
   - Structural Pattern (nhóm cấu trúc) gồm : Adapter, Bridge, Composite, Decorator, Facade, Proxy và Flyweight.. Nó dùng để thiết lập, định nghĩa quan hệ giữa các đối tượng.
   - Cuối cùng là nhóm Behavioral Pattern gồm : Interpreter, Template Method, Chain of Responsibility, Command,  Iterator, Mediator, Memento, Observer, State, Strategy và Visitor. Nhóm này dùng trong thực hiện các hành vi của đối tượng.

Design Pattern giúp bạn tái sử dụng mã lệnh và dẽ dàng mở rộng.

Để chuẩn bị học Design Pattern bạn cần phải nắm chắc các khái niệm sau :
   - Bốn đặc tính của OOP : Thừa kế, Đa hình, Trừu tượng, Bao đóng.
   - Khái niệm interface và abstract . Cái này cực kỳ quan trọng, để hiểu và áp dụng 2 khái niệm này có thể sẽ mất một thời gian, nhưng khi bạn nắm chắc nó bạn sẽ thấy nó thực sự cần thiết.
   - Bỏ tư duy theo lối cấu trúc, nâng tư duy hoàn toàn OOP.

Nếu có khó khăn trong công việc chuẩn bị trên, bạn có thể liên hệ mình, mình sẽ cố gắng giúp bổ sung cho bạn những kiến thức cơ bạn trong OOP. Sau khi bạn đã nắm chắc các thứ kể trên, bạn nên bắt tay vào học Design Pattern càng sớm càng tốt. Sau khi biết Design Pattern giúp bạn đặt trình cao mới .

Trong loạt bài về Design Pattern sắp tới, mình sẽ đặt ra 3 câu hỏi : Nó là gì? Khi nào thì áp dụng nó? Và Áp dụng nó như thế nào. Hy vọng các bạn có thể hiểu và áp dụng nó một cách nhanh nhất. Mọi thắc mắc trong bài viết các bạn có thể để lại comment hoặc liên hệ với mình. Một số link về Design pattern :
 - http://www.mif.vu.lt/~donatas/PSArchitekturaProjektavimas/Library/refcards/refcard-designpatterns.pdf

 - http://www.uml.org.cn/c++/pdf/DesignPatterns.pdf

Saturday, August 24, 2013

Design Pattern - Singleton

Mẫu thiết kế singleton:
Nó là gì?
Mẫu thiết kế singleton đảm bảo chỉ duy nhất môt thực thể của một class được tạo ra và nó sẽ cung cấp cho bạn một phương thức để truy cập đến thực thế đó.
Kiểm soát việc tạo ra các thực thể nhưng có thể lấy ra thực thế.
Dùng nó trong trường hợp nào?
Khi bạn tạo ra một class mà bạn chỉ muốn chỉ có duy nhất một thực thể là thể hiện của class đó và bạn có thể truy cập đến nó ở bất kỳ nơi đâu khi bạn muốn.
Ví dụ như : Khi bạn tạo ra một class làm việc với file, config ,class lưu collection dùng chung, hoặc database . Bản chỉ cần duy nhất một thực thể của class đó và bạn sẽ sử dụng nó ở bất kỳ nơi đâu.
Dùng nó như thế nào?
Đầu tiên tôi tạo ra một class với tên là Database. Để không class nào có thể khỏi tạo nó (đảm bảo duy nhất có một thực thể) tôi sẽ private contructor của class trên.
  1. public class Database{
       private Database();
    }
Và tạo một thuộc tính có tên là INSTANCE có kiểu Database  và một phương trả về thuộc tính đó. Để các class khác có thể sử dụng phương thức này, tôi thêm từ khóa static để biến phương thức này thành phương thức của lớp.
  1. private Database INSTANCE;
  2. public static Database getInstance(){
  3.    if(INSTANCE == null){
  4.       INSTANCE = new Database();
  5.    }
  6.    return INSTANCE;
  7. }
Như trên tôi kiểm tra xem INSTANCE có bằng null hay không. Nếu bằng null thì tôi tạo một đối tượng. Và trả về INSTANCE.
Có một vấn đề xảy ra. Nếu có hai luồng (thread) chạy song song và thực hiện hàm if thì sẽ có 2 thực thể được tạo ra. Để tránh trường hợp này mình thêm từ khóa synchronized. Khi hàm getInstance đã được chạy thì bất kỳ các luồng khác phải đợi hàm này chạy xong mới gọi được.

  1. public static synchronized Database getInstance(){
  2.    if(INSTANCE == null){
  3.      INSTANCE = new Database();
  4.    }
  5.    return INSTANCE;
  6. }
Ok đến đây đã khá ổn nhưng sử dụng từ khóa synchronized đồng nghĩa với việc các luồng có thể phải đợi chờ lâu vì phải đợi luồng đang gọi hạm getInstance chạy xong mới gọi được. Để tránh trường hợp này, tôi sẽ tạo 1 thực thể của lớp Database ngày khi class này được sử dụng, và sử dụng từ khóa final để ngăn không cho thay đổi đối tượng mà INSTANCE trỏ đến  :

  1. private static final Database INSTANCE = new Database();
Lúc này hàm getInstance sẽ trả về đối tượng INSTANCE:
  1. public static Database getInstance(){
  2.    return INSTANCE;
  3. }

Để truy cập đến thực thể của class Database bạn thực hiện : Database.getInstance() lúc này trả về 1 thực thể có kiểu Database.

OK ! Đến đây bạn có thể chắc chắn rằng sẽ chỉ có duy nhất một thực thể của class Database được tạo ra và bạn có thể sử dụng hàm getInstance để truy cập vào thực thế đó. Việc còn lại là bạn viết các phương thức, các setter, getter cho nó. Đây chính là mẫu thiết kế singleton.