Thứ Sáu, 3 tháng 8, 2012

Load ảnh vào game

Như tiêu đề đã nói rõ, trong bài này chúng ta sẽ học cách load hình ảnh vào game. Như đã nói ở bài trước, chúng ta sẽ viết dựa trên code đã có. Vì vậy bạn nên xem phần đó trước khi học bài này.

Định dạng ảnh
Nên dùng ảnh định dạng PNG vì nó hỗ trợ alpha transparency, tức là ảnh có thể được khử răng cưa và nhìn mượt hơn. Nhưng không phải điện thoại nào cũng có thể hiển thị chính xác ảnh có alpha transparency. Tạm thời chúng ta không nói về vấn đề này, nhưng hãy dùng ảnh PNG.

Độ sâu màu
Hãy chú ý, điện thoại khác nhau thì độ sâu màu khác nhau. Hiện nay độ sâu màu trên điện thoại dao động từ 8 bit (256 màu) đến 24 bit (16.777.216 màu). Điều đó có ý nghĩa, ảnh có độ phân giải cao, hiển thị đẹp trên một thiết bị có độ sâu màu cao sẽ hiển thị xấu trên thiết bị có độ sâu màu thấp, còn bị mất màu, có thể sẽ không nhận được ảnh.
Các thiết bị điện thoại còn có bộ nhớ rất nhỏ, nên ảnh có quá nhiều màu sẽ làm tốn bộ nhớ. Vì vậy bạn nên dùng ảnh ít màu, 8 bit chẳng hạn.

Ví dụ
Hãy lấy ảnh sau làm ví dụ. Devlin đã vẽ một ảnh trái đất có size 16x16 pixel. Ảnh này dùng 34 màu và nặng 502 byte.

Actual Size of Earth (16x16)

earth.png



Enlarged View of Earth (64x64)

earth.png

Hãy save ảnh trên về máy. Vào project trong máy bạn, tạo thư mục tên là image bên trong thư mục res. Như vậy ảnh sẽ được đặt vào nơi có đường dẫn trông giống thế này.
C:\YourDocs\netbean\BasicGameTemplate\src\image

Load ảnh
Bạn mở class clsCanvas.java để làm việc.
Đầu tiên, khai báo biến cho bức ảnh. Hãy đặt tên biến là imgEarth với kiểu dữ liệu Image. Khai báo ngay bên dưới phần khai báo biến có kiểu dữ liệu midMain.


private midMain fParent;
private Image imgEarth;

Bây giờ hãy viết hàm load( ) khởi tạo game. Đây là nơi ảnh sẽ được load lên thiết bị. Hãy viết hàm này sau hàm start( )

public void start(){
   Thread runner = new Thread(this);
   runner.start();
}

    public void load(){
   try{
       // try to load the image file
       imgEarth = Image.createImage("/images/earth.png");
   }catch(Exception ex){
       // exit the app if it fails to load the image
       isRunning = false;
       return;
   }
}


Phương thức createImage( ) của lớp Image dùng để load ảnh vào biến imgEarth. Phương thức này phải được đưa vào trong phương thức try - catch để bắt lỗi nếu ảnh load không thành công. 
Hãy viết một hàm unload( ) để thoát hoặc dọn dẹp rác. Viết hàm này sau hàm load( )


public void load(){
   try{
       // try to load the image file
       imgEarth = Image.createImage("/images/earth.png");
   }catch(Exception ex){
       // exit the app if it fails to load the image
       isRunning = false;
       return;
   }
}

    public void unload(){
   // make sure the object get's destroyed
   imgEarth = null;
}

Bây giờ hãy gọi hàm load( ) trong hàm run( ). Lời gọi hàm được đặt sau lời khai báo biến iKey:
public void run() {
  int iKey = 0;
  load();
  g = getGraphics();

Sau đó gọi hàm unload( ) sau khi hủy biến g bằng giá trị null
  }
  g = null;
  unload();
  fParent.destroyApp(false);

Khi bạn làm xong, lớp clsCanvas sẽ như thế này:


package MyGame;

import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.game.GameCanvas;

public class clsCanvas extends GameCanvas implements Runnable {
private boolean isRunning = true;
private Graphics g;
private midMain fParent;
private Image imgEarth;

public clsCanvas(midMain m) {
    super(true);
    fParent = m;
    setFullScreenMode(true);
}

public void start(){
    Thread runner = new Thread(this);
    runner.start();
}

    public void load(){
    try{
        // try to load the image file
        imgEarth = Image.createImage("/images/earth.png");
    }catch(Exception ex){
        // exit the app if it fails to load the image
        isRunning = false;
        return;
    }
}

public void unload(){
    // make sure the object get's destroyed
    imgEarth = null;
}
public void run() {
   int iKey = 0;
   load();
   g = getGraphics();
   while(isRunning){
   
       iKey = getKeyStates();
   
       if ((iKey & GameCanvas.FIRE_PRESSED) != 0){
           isRunning = false;
       }
   
       //set drawing color to black
       g.setColor(0x000000);
       //fill the whole screen
       g.fillRect(0, 0, getWidth(), getHeight());
       // set drawing color to white
       g.setColor(0xffffff);
       //display the key code last pressed
       g.drawString(Integer.toString(iKey), 2, 2, Graphics.TOP | Graphics.LEFT);
       flushGraphics();
   
       try{
           Thread.sleep(30);
       } catch (Exception ex){
       
       }
   }
   g = null;
   unload();
   fParent.destroyApp(false);
   fParent = null;
}
}

Vẽ ảnh
Để vẽ ảnh lên màn hình, chèn đoạn code sau vào trong hàm run( ) trước khi gọi phương thức flushGraphics()


     
           //draw the image
        g.drawImage(imgEarth, 50, 50, Graphics.TOP | Graphics.LEFT);        
        flushGraphics();

Phương thức drawImage( ) của đối tượng g kiểu  Graphics được dùng để vẽ hình lên màn hình tại tọa độ 50(x) 50(y). Tham số sau cùng, Graphics.TOP | Graphics.LEFT định vị điểm neo của ảnh, ảnh sẽ được vẽ bắt đầu từ điểm đó lên tọa độ đã cho. Với thông số trên thì điểm neo sẽ ở góc trên bên trái của ảnh quả địa cầu.

Lớp clsCanvas sau cùng trông như thế này.


package MyGame;

import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;import javax.microedition.lcdui.game.GameCanvas;

public class clsCanvas extends GameCanvas implements Runnable {
private boolean isRunning = true; 
private Graphics g;
private midMain fParent;
private Image imgEarth;
 public clsCanvas(midMain m) {
     super(true);
     fParent = m;
     setFullScreenMode(true);
 }

 public void start(){
     Thread runner = new Thread(this);
     runner.start();
 }

    public void load(){
     try{
         // try to load the image file
         imgEarth = Image.createImage("/images/earth.png");
     }catch(Exception ex){
         // exit the app if it fails to load the image
         isRunning = false;
         return;
     }
 }

 public void unload(){
     // make sure the object get's destroyed
     imgEarth = null;
 }
 public void run() {
    int iKey = 0;
       load();       g = getGraphics();
    while(isRunning){
     
        iKey = getKeyStates();
     
        if ((iKey & GameCanvas.FIRE_PRESSED) != 0){
            isRunning = false;
        }
     
        //set drawing color to black
        g.setColor(0x000000);
        //fill the whole screen
        g.fillRect(0, 0, getWidth(), getHeight());
        // set drawing color to white
        g.setColor(0xffffff);
        //display the key code last pressed
        g.drawString(Integer.toString(iKey), 2, 2, Graphics.TOP | Graphics.LEFT);
     
           //draw the image
        g.drawImage(imgEarth, 50, 50, Graphics.TOP | Graphics.LEFT);        
        flushGraphics();
     
        try{
            Thread.sleep(30);
        } catch (Exception ex){
         
        }
    }
    g = null;
       unload();       fParent.destroyApp(false);
    fParent = null;
 }
}

Khi xong xuôi tất cả bạn chạy thử chương trình xem kết quả thu được:


Screen Shot of Output

Code trên được thêm phương thức setFullScreenMode(true) để chạy game full màn hình. Bạn cho phương thức  đó vào constructor của lớp clsCanvas là được.

Không có nhận xét nào:

Đăng nhận xét