Thứ Năm, 14 tháng 2, 2013

the Sky Fall

Không phải là phim đâu, mà là một trò chơi đơn giản: nhân vật của chúng ta sẽ rơi xuống vào một rừng mũi tên đang bắn lên, chúng ta sẽ điều khiển để nhân vật đừng chạm vào mũi tên nào hết. các bạn cần có 3 file sau, tôi đã chú thích trong từng file hết rồi, chắc các bạn cũng hiểu thôi. Đầu tiên là file muiten.java muiten.java
C:\Users\thanhliem\Documents\NetBeansProjects\SkyFall\src\muiten.java

import javax.microedition.lcdui.*;
import java.util.*;

public class muiten {
//các biến: độ rộng màn hình, cao màn hình, vị trí x, vị trí y, chiều dài mũi tên, tốc độ mũi tên
    int w, h, x, y, len, speed;
    //biến chỉ mốc thời gian di chuyển lần cuối
    long lm = 0;
//    biến số ngẫu nhiên
    Random rd = new Random();
    //biến đầu mũi tên, và biến đuôi mũi tên dùng vẽ hình mũi tên
    byte[][] mim = {
        {0, 1, 0},
        {1, 1, 1}},
            dim = {{1, 0, 1}};
//hàm khởi tạo nhận các giá trị rộng,cao màn hình và một số nguyên ngẩu nhiên
    public muiten(int w, int h, int rd) {
        this.w = w;
        this.h = h;
        this.rd = new Random(rd);
        //dùng hàm general để khởi tạo
        general();
    }
//hàm general xác định tọa độ x, y chiều dài và tốc độ ngẫu nhiên cho mũi tên
    public void general() {
        //hàm Math.abs(số nguyên) chỉ sang trị tuyệt đối, nextInt là lấy số nguyên ngẫu nhiên, dấu % là phép chia lấy dư.
        x = Math.abs(rd.nextInt()) % w;
        y = h + 3;
        len = Math.abs(rd.nextInt()) % (h / 10);
        speed = Math.abs(rd.nextInt()) % 3 + 2;
    }

    public void draw(Graphics g) {
        //lấy màu hiện tại lưu lại vào ocl
        int ocl = g.getColor();
        //dặt màu mới
        g.setColor(ocl & 0xff);
        //cho vẽ mũi tên qua hàm drawmuiten
        drawmuiten(g);
        //đặt lại màu cũ
        g.setColor(ocl);
        //kiểm tra nếu như cách khoảng 20 mili giây từ lần cuối di chuyển lm thì cho mũi tên di chuyển tiếp
        if (lm < System.currentTimeMillis() - 20) {
            y -= speed;
            lm = System.currentTimeMillis();
        }
        //nếu như tọa độ y bé hơn -h/10 thì cho tạo lại mũi tên.
        if (y < -h / 10) {
            general();
        }
    }
//hàm check dùng để kiểm tra xem nhân vật và mũi tên có chạm nhâu không, gồm tọa độ x,y của nhân vật và độ cao rộng của nhân vật
    boolean check(int x, int y, int w, int h) {
        int sx = (this.x - x);
        int sy = (this.y - y);
        if (sx > 0 && sy > 0 && sx <= w && sy <= h) {
            return true;
        }
        return false;
    }
//hàm vẽ mũi tên sẽ vẽ mũi tên theo tọa độ của nó
    public void drawmuiten(Graphics g) {
        //vẽ đầu mũi tên
        for (int i = 0; i < mim.length; i++) {
            for (int j = 0; j < mim[0].length; j++) {
                if (mim[i][j] != 0) {
                    g.fillRect(x + j, y + i, 1, 1);
                }
            }
        }
        //vẽ thân mũi tên
        g.drawLine(x + 1, y, x + 1, y + len);
        //vẽ đuôi mũi tên
        for (int i = 0; i < dim.length; i++) {
            for (int j = 0; j < dim[0].length; j++) {
                if (dim[i][j] != 0) {
                    g.fillRect(x + j, y + len + i, 1, 1);
                }
            }
        }
    }
}

Tiếp theo đó là file skyfall.java: skyfall.java
C:\Users\thanhliem\Documents\NetBeansProjects\SkyFall\src\skyfall.java

import javax.microedition.lcdui.*;
import java.util.*;

public class skyfall extends Canvas {
//biến mt chứa các mũi tên sẽ bay lên từ dưới màn hình
    muiten[] mt = new muiten[10];
    Midlet m;
    //biến ngẩu nhiên rd
    Random rd = new Random();
    //các biến: rộng cao màn hình, tọa độ x, y của nhân vật, biến t số ngẩu nhiên, phím bấm k
    int w, h, x, y, t = 0, k;
    //hình ảnh nhân vật dùng để vẽ
    Image man;
    //các biến đúng sai: di chuyển, chẳn lẻ, kết thúc
    boolean move = false, chan = true, over = false;
    //biến mốc di chuyển lần cuối để tính khoảng thời gian di chuyển
    long lm;

    public skyfall(Midlet m) {
        try {
            this.m = m;
            setFullScreenMode(true);
            //tạo ra các phân tử mũi tên cho mảng mt
            for (int i = 0; i < mt.length; i++) {
                //gồm chiều rộng cao màn hình và một số nguyên ngẫu nhiên
                mt[i] = new muiten(getWidth(), getHeight(), t);
                t = rd.nextInt();
            }
            //ban đầu cho tọa độ nhân vật ở giữa màn hình
            y = getHeight() / 2;
            x = getWidth() / 2;
            //tạo ra hình ảnh nhân vật là ảnh 32x32
            man = Image.createImage("/man.png");
        } catch (Exception e) {
        }
    }

    public void paint(Graphics g) {
        //kiểm tra xem đã bị trúng tên chưa
        over = over();
        //xét xem lần di chuyển cuối cùng và có di chuyển tiếp không, hàm System.currentTimeMillis() dùng lấy thời gian hiện tại ở dạng mili giây.
        if (move && lm < System.currentTimeMillis() - 10) {
            if (k == -3 || k == KEY_NUM4) {
                x--;
            }
            if (k == -4 || k == KEY_NUM6) {
                x++;
            }
            //sau đó gán giá trị thời gian hiện tại cho biến lm
            lm = System.currentTimeMillis();
        }
        //đặt màu mới và tô màn hình
        g.setColor(0x90b5ff);
        g.fillRect(0, 0, getWidth(), getHeight());
        //hàm vẽ này vẽ ra một phần của hình ảnh, bao gồm: hình ảnh, tọa độ x trên ảnh, tọa độ y trên ảnh, chiều rộng cần vẽ, chiểu cao cần vẽ, quay góc, tọa độ vẽ x, tọa độ vẽ y, điểm neo.
        g.drawRegion(man, chan ? 0 : 16, 0, 16, 32, 0, x, y, Graphics.TOP | Graphics.LEFT);
        //sau đó cho biến chẳn lẻ thay đổi, nếu chẳn thì thành lẻ và ngược lại
        chan = !chan;
        //đặt màu mới, vẽ các phần tử muiten trong mảng mt
        g.setColor(0xff);
        for (int i = 0; i < mt.length; i++) {
            mt[i].draw(g);
        }
        //nếu kết thúc over=true thì cho dừng lại, không thì vẽ tiếp.
        if (over) {
        } else {
            repaint();
        }
    }
//hàm over kiểm tra xem có chạm nhân vật và muiten không
    boolean over() {
        for (int i = 0; i < mt.length; i++) {
            if (mt[i].check(x, y, 16, 32)) {
                return true;
            }
        }
        return false;
    }
//hàm xử lí phím, bấm phím nào thì cho k= mã phím đó
    public void keyPressed(int k) {
        move = true;
        this.k = k;
        if (k == -7) {
            //hàm notifyDestroyed của MIDlet dùng để đóng ứng dụng.
            m.notifyDestroyed();
        }
    }
//nếu buông nút bấm thì không cho di chuyển nữa.
    public void keyReleased(int k) {
        move = false;
    }
}

Và cuối cùng là cho hiển thị thông qua một Midlet.java như ta vẫn thường hay dùng: Midlet.java
C:\Users\thanhliem\Documents\NetBeansProjects\SkyFall\src\Midlet.java
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

/**
 * @author thanhliem
 */
public class Midlet extends MIDlet {

    public void startApp() {
        Display.getDisplay(this).setCurrent(new skyfall(this));
    }

    public void pauseApp() {
    }

    public void destroyApp(boolean unconditional) {
    }
}

Các bạn thấy đó, rất là đơn giản phải không nào, để trò chơi thêm phần hấp dẫn bạn có thể thêm biến điểm tính theo lượt những mũi tên được tạo lại sau mỗi lần general mới, trong muiten.java hay là thêm thắt những thứ khác nữa như mạng, vật phẩm chẳng hạn. và đây là file source jar.

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