Thứ Tư, 14 tháng 8, 2013

nhập văn bản trực tiếp từ Canvas

thường thì muốn nhập chuỗi thì ta thiết kế sử dụng TextBox hoặc là TextField trên Form, nhưng trong game nên hạn chế cho người dùng sử dụng giao diện bậc cao như vậy. Ta sẽ cho nhập văn bản trực tiếp từ bàn phím trên Canvas dựa vào hàm keyPressed(int i) :
C:\Users\WIN7\Documents\NetBeansProjects\textfield\src\textfield.java
  1 //textfield.java
  2 import javax.microedition.lcdui.*;
  3 
  4 public class textfield {
  5 
  6     int x, y, w, lk = 0, np = 0, fh, tcolor = 0, bgcolor = 0xf0f0f0;
  7     String s = "", title;
  8     //mảng ac chứa các kí tự cần thiết tương ứng với các phím bấm từ 0 đến 9
  9     String[] ac = {" 0", ".,1", "abc2", "def3", "ghi4", "jkl5", "mno6", "pqrs7", "tuv8", "wxyz9"};
 10     long lp = 0, rr = 0;
 11     boolean focus = false;
 12     Font f = Font.getFont(0, 0, 8);
 13 //hàm khởi tạo textfield nhận các giá trị tiêu đề (title), vị trí đặt hộp text(x, y), và chiều rộng hộp (w)
 14     public textfield(String title, int x, int y, int w) {
 15         this.title = title;
 16         this.x = x;
 17         this.y = y;
 18         this.w = w;
 19         fh = f.getHeight();
 20     }
 21 
 22     String getString() {
 23         return s;
 24     }
 25 //hàm paint này dùng vẽ textfield lên Graphic (g) và được dùng trên Canvas, nó nhận các biến tham số: Graphics g, biến mã phím int k, và biến boolean focus chỉ định là có thực hiện thao tác với textfield này không
 26     public void paint(Graphics g, int k, boolean focus) {
 27         g.setFont(f);
 28         this.focus = focus;
 29         //nếu có tác động focus==true thì cho thực hiện vẽ chuỗi theo mã phím
 30         if (focus && cr() - lp > rr) {
 31             add(k);
 32         }
 33         //các hàm vẽ liên quan đến việc vẽ chuỗi s ra màn hình
 34         int slen = f.stringWidth(s);
 35         int kh = slen - w;
 36         g.setColor(bgcolor);
 37         g.fillRect(x, y + fh, w, fh);
 38         g.drawString(title + ":", x, y, Graphics.TOP | Graphics.LEFT);
 39         g.setColor(tcolor);
 40         g.setClip(x, y + fh, w, fh);
 41         g.drawString(s + (focus ? "|" : ""), x - (kh > 0 ? kh : 0), y + fh, Graphics.TOP | Graphics.LEFT);
 42 
 43 
 44     }
 45 
 46     void add(int k) {
 47         //nếu key là -3(phím qua trái) thì cho xóa kí tự
 48         if (k == -3 && s.length() > 0) {
 49             s = s.substring(0, s.length() - 1);
 50             lk = k;
 51             lp = cr();
 52         } else if (k == -6) {//nếu key là -6 thì thôi không tác động đến textfield này nữa
 53             focus = false;
 54         } else {
 55             //tìm vị trí của phím bấm từ 0 đến 9, do phím 0 có mã phím là 48 nên ta lần lượt trừ cho 48 sẽ tương ứng với vị trí của bảng kí tự trong mảng chuổi ac
 56             int sk = k - 48;
 57             //nếu như sk lớn hơn 0 thì cho thực hiện tiếp, tương đương là bấm các phím từ 0->9
 58             if (sk >= 0) {
 59                 //nếu thời gian hiện tại trừ lp(lần nhấn sau cùng) <800 và phím nhấn lần này giống với phím bấm lần sau cùng thì cho tăng np (index cần lấy của kí tự trong chuỗi).
 60                 if (cr() - 800 < lp && lk == sk) {
 61                     np++;
 62                     if (np == ac[sk].length()) {
 63                         np = 0;
 64                     }
 65                     s = s.substring(0, s.length() - 1);
 66                     s += ac[sk].charAt(np);
 67                 } else {//ngược lại thì cho thêm vào kí tự thích hợp với phím bấm(kí tự đầu tiên tương ứng các mảng giá trị)
 68                     np = 0;
 69                     s += ac[sk].charAt(np);
 70                 }
 71                 //đặt mả phím sau cùng và lk (phím bấm sau cùng) và thời gian bấm sau cùng lp (lần nhấn sau cùng)
 72                 lk = sk;
 73                 lp = cr();
 74             }
 75 
 76         }
 77     }
 78 //hàm cr() trả lại thời gian hiện thời
 79     long cr() {
 80         return System.currentTimeMillis();
 81     }
 82 }
 83 
 84 class canvas extends Canvas {
 85 //tạo một biến textfield mới, với tiêu đề là "nhập văn bản", ở tọa độ (0,120) và chiều rông màn hình
 86     textfield tf = new textfield("nhập văn bản", 0, 120, 40);
 87     int w = getWidth(), h = getHeight(), k = 0;
 88 
 89     public canvas() {
 90     }
 91 
 92     public void paint(Graphics g) {
 93         g.setColor(0);
 94         g.fillRect(0, 0, w, h);
 95         //thực hiện lệnnh vẽ textfield ra màn hình lên Graphics g và với mã phím k
 96         tf.paint(g, k, true);
 97         k=0;
 98         repaint();
 99     }
100 
101     public void keyPressed(int k) {
102         this.k = k;
103     }
104 
105     public void keyReleased(int k) {
106         this.k = 0;
107     }
108 }
• ở đây chúng ta chỉ cần lưu ý là trong textfield.java có các biến đảm nhận thời gian như là lp, để xác định lần nhấn phím sau cùng mà người dùng nhấn. sau đó so sánh với giá trị thời gian hiện tại lấy từ hàm cr(), nếu như mà hai giá trị này chênh nhau quá 800ms thì cho cộng vào chuỗi một kí tự mới tương ứng với index 0 trong giá trị của phím trong mảng chuỗi ac. Còn nếu như mà thấy thời gian chênh nhau giữa lp và cr() trong 800ms trở lại và mã phím cũng là mã phím nhấn sau cùng thì cho tăng index lấy kí tự trong mã phím hiện tại và kết quả là thay đổi kí tự vừa mới ghi lúc nãy chứ không thêm kí tự mới nào. • Tải jar •Tải zip

một đội quân địch, cấp độ khó

trong trò chơi mà chơi với những AI thì lúc nào chúng cũng thua mình thôi, do đó cần tạo ra độ khó bằng cách tăng số lượng của chúng. tôi sẽ tạo ra một đạo quân địch từ những gì mà ta đã có và thêm vào đó một vài thứ khác.
ta sẽ tạo ra một class E, bao gồm một biến xe T và những giá trị như mã key, biến đúng sai die , như sau:
//E.java
import javax.microedition.lcdui.*;

public class E {
T x;
boolean die;
int k;
public E(int x, int y, int color, int w,int h){
die=false;
this.x=new T(x,y,color,w,h);}
void paint(Graphics g,int k){
x.paint(g,k);}
}

. Sau đó trong game.java ta sửa lại như sau:
//game.java

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

public class game extends Canvas {
String[] smenu={"play game","help","about"};
int w,h,fh,mindex=0,mode=0,k,ak,cx=3;
Midlet m;
Font f=Font.getDefaultFont();
T t,x;
E[] e;
long lai=0;
Random rd=new Random();

public game(Midlet m){
this.m=m;
setFullScreenMode(true);
w=getWidth();
h=getHeight();
fh=f.getHeight();
t=new T(0,0,0xf0f0f0,w,h);
x=new T(w-16*3,h-16*3,0x6060f0,w,h);
//khởi tạo e
e=new E[cx];
for(int i=0;i<e.length;i++){
e[i]=new E(w-16*3,h-16*3,0x6060f0,w,h);}
}

public void paint(Graphics g){
g.setColor(0);
g.fillRect(0, 0, w, h);
g.setColor(0xf0f0f0);
switch(mode){
case 0: //vẽ menu
//vẽ thanh index
g.fillRect(0, (h-fh*3)/2+mindex*fh, w, fh);
//vẽ các menu
for(int i=0;i<smenu.length;i++){
if(i==mindex){g.setColor(0);}else{g.setColor(0xf0f0f0);}
g.drawString(smenu[i],w/2 ,( h-fh*3)/2+i*fh, Graphics.HCENTER|Graphics.TOP);
}
break;
case 1: //vẽ game play
g.drawString(smenu[0], w/2, h/2, Graphics.BASELINE|Graphics.HCENTER);
t.paint(g, k);
x.paint(g, (ak=ai(x,ak)));
if(check(t,x)){x.color-=0x000010;}
if(check(x,t)){t.color-=0x100000;}

//biến n đếm số xe đã được vẽ trong e
int n=0;
for(int i=0;i<e.length;i++){
//chỉ vẽ ra tới 3 xe tăng, nếu nhiều hơn thì chờ đến lượt
if(n==2)continue; 
//nếu chưa trúng đạn thì vẽ ra
if(!e[i].die)
{n++;
e[i].k=ai(e[i].x,e[i].k);
e[i].paint(g,e[i].k);

//check xem có trúng đạn của ta không, nếu có thì cho chết die=true
if(check(t,e[i].x))e[i].die=true;
if(check(e[i].x,t)){
//xe ta bị trúng đạn
//game over, kết thúc trò chơi, hay mất mạng, mất máu gì đó
}}
}
break;
case 2: //vẽ help
g.drawString(smenu[1], w/2, h/2, Graphics.BASELINE|Graphics.HCENTER);
break;
case 3: //vẽ about
g.drawString(smenu[2], w/2, h/2, Graphics.BASELINE|Graphics.HCENTER);
break;}

//vẽ nút lệnh
g.setColor(0xf0f0f0);
g.drawString("exit", 0, h, Graphics.LEFT|Graphics.BOTTOM);
g.drawString("back", w, h, Graphics.RIGHT|Graphics.BOTTOM);
repaint();}

protected void keyReleased(int k){this.k=0;}

public void keyPressed(int k){
this.k=k;
//cho di chuyển vị trí thanh menu
if(mode==0){
if(k==-1)mindex--;
if(k==-2)mindex++;
if(mindex<0)mindex=smenu.length-1;
if(mindex==smenu.length)mindex=0;
//thay đổi mode khi lựa chọn menu
if(k==-5)mode=mindex+1;
//các lệnh cho menu góc màn hình
if(k==-6)m.notifyDestroyed();}
if(k==-7)mode=0;}

boolean check(T a, T b){
int xc=(a.d.x-b.x)/16/3;
int yc=(a.d.y-b.y)/16/3;
if(xc==0&amp;&amp;yc==0&amp;&amp;a.d.f!=-1){
b.color-=0x100010;
return true;}
return false;}

int ai(T a,int ak){
if(lai<System.currentTimeMillis()-2000){
lai=System.currentTimeMillis();
int k=Math.abs(rd.nextInt())%4;
return -(k+1);}
if(System.currentTimeMillis()%25==0)
return -(1+a.f);
if(rd.nextInt()%3==0&amp;&amp;a.d.f==-1){return -5;}
return 0;}
}

. Kết quả đây, trò chơi gần như hoàn thiện, các bạn có thể thêm phần level cho trò chơi hoặc gì đó hay ho một chút...

source here