坦克大戰(版本0.1-版本0.9)

版本0.1java

功能: 產生一個窗口ide

掌握: 經過Eclipse創建新的項目 爲新的項目指定不一樣的源代碼和輸出目錄 指定項目所用的JDK版本 經過Eclipse創建新的類函數

注意: 類名和方法名的命名可以見名知意,類名首字母大寫,方法名、變量名首字母小寫,應用駝峯標識(多個單詞組成第一個單詞小寫,其餘單詞首字母大寫)this

具體代碼實現:spa

 1 import java.awt.Frame;
 2 
 3 public class TankClient extends Frame{
 4 
 5     public static void main(String[] args) {
 6         TankClient tc=new TankClient();
 7         tc.launchFrame();
 8     }
 9     public void launchFrame(){
10         this.setLocation(400,300);
11         this.setSize(800, 600);
12         setVisible(true);
13     }
14 }

版本0.2線程

功能: 添加關閉窗口的事件處理,不容許窗口的大小改動code

掌握: 匿名類的用法 思考:匿名類的應用場合? 類短小、不涉及未來的擴展、不涉及重要的業務邏輯 經過Eclipse重寫父類的方法對象

注意: 沒掌握匿名類的先照抄,不寫也行 不影響最後的運行效果blog

具體代碼實現:事件

 1 import java.awt.Frame;
 2 import java.awt.event.WindowAdapter;
 3 import java.awt.event.WindowEvent;
 4 
 5 public class TankClient extends Frame{
 6 
 7     public static void main(String[] args) {
 8         TankClient tc=new TankClient();
 9         tc.launchFrame();
10     }
11     public void launchFrame(){
12         this.setLocation(400,300);
13         this.setSize(800, 600);
14         this.addWindowListener(new WindowAdapter() {
15 
16             @Override
17             public void windowClosing(WindowEvent e) {
18                 
19                 System.exit(0);
20             }
21             
22         });
23         setResizable(false);
24         setVisible(true);
25     }
26 }

版本0.3

功能: 畫出表明坦克的實心圓

掌握: 如何重寫paint方法

注意: 不要改變原來的前景色

回顧: paint(Graphics g)方法,窗口重畫時自動調用 x軸、y軸的方向(X向右遞增、Y向下遞增)

具體代碼實現:

 1 import java.awt.Color;
 2 import java.awt.Frame;
 3 import java.awt.Graphics;
 4 import java.awt.event.WindowAdapter;
 5 import java.awt.event.WindowEvent;
 6 
 7 public class TankClient extends Frame{
 8 
 9     //重寫paint方法
10     @Override
11     public void paint(Graphics g) {
12         System.out.println(g.getColor());
13         //不要改變原來的前景色,先拿出來,使用之後再改回去
14         //getClolor返回的是this graphics context's current color
15         Color c=g.getColor();
16         g.setColor(Color.RED);
17         //四個參數分別表明Frame的左上角的x、y座標,實心圓的寬width和高height
18         g.fillOval(50,50,30,30);
19         g.setColor(c);
20         
21     }
22     public static void main(String[] args) {
23         TankClient tc=new TankClient();
24         tc.launchFrame();
25     }
26     public void launchFrame(){
27         this.setLocation(400,300);
28         this.setSize(800, 600);
29         this.addWindowListener(new WindowAdapter() {
30 
31             @Override
32             public void windowClosing(WindowEvent e) {
33                 
34                 System.exit(0);
35             }
36             
37         });
38         setResizable(false);
39         //設置背景色
40         this.setBackground(Color.GREEN);
41         setVisible(true);
42     }
43 }

版本0.4

功能: 讓坦克運動起來

步驟: 將位置改變爲變量 啓動線程不斷重畫

思考:爲何使用線程重畫,而不是每按下一個鍵進行一次重畫?

         由於線程重畫更均勻,更能控制重畫的速度。 按鍵重畫不能解決子彈自動飛行的問題。 每次重畫改變Tank位置

掌握: 內部類的使用 思考:內部類有哪些好處?何時使用內部類? 能夠方便的訪問包裝類的方法。不方便公開的,只爲包裝類服務的類應當定義爲內部類。

注意: x, y值得含義,指的是小方塊的左上角點

具體代碼實現:

 1 import java.awt.Color;
 2 import java.awt.Frame;
 3 import java.awt.Graphics;
 4 import java.awt.event.WindowAdapter;
 5 import java.awt.event.WindowEvent;
 6 
 7 public class TankClient extends Frame{
 8     //將坦克的位置設置爲變量
 9     int x=50;
10     int y=50;
11 
12     //重寫paint方法
13     @Override
14     public void paint(Graphics g) {
15         //不要改變原來的前景色,先拿出來,使用之後再改回去
16         //getClolor返回的是this graphics context's current color
17         Color c=g.getColor();
18         g.setColor(Color.RED);
19         //四個參數分別表明Frame的左上角的x、y座標,實心圓的寬width和高
20         g.fillOval(x,y,30,30);
21         g.setColor(c);
22         y+=5;
23     }
24     public static void main(String[] args) {
25         TankClient tc=new TankClient();
26         tc.launchFrame();
27     }
28     public void launchFrame(){
29         //窗體位置
30         this.setLocation(400,300);
31         //窗體尺寸大小
32         this.setSize(800, 600);
33         //窗體title名稱
34         this.setTitle("TankWar");
35         this.addWindowListener(new WindowAdapter() {
36 
37             @Override
38             public void windowClosing(WindowEvent e) {
39                 
40                 System.exit(0);
41             }
42             
43         });
44         setResizable(false);
45         //設置背景色
46         this.setBackground(Color.GREEN);
47         setVisible(true);
48         new Thread(new PaintThread()).start();
49     }
50     //使用內部類,只爲包裝類復位
51     private class PaintThread implements Runnable{
52 
53         @Override
54         public void run() {
55             //重畫,內部會自動調用paint(Graphics g)方法
56             repaint();
57             try {
58                 Thread.sleep(100);
59             } catch (InterruptedException e) {
60                 e.printStackTrace();
61             }
62         }
63         
64     }
65 }

版本0.4.1

功能:使用雙緩衝消除閃爍現象

緣由:刷新重畫頻率太快,paint方法尚未完成 逐條顯示

解決辦法:將全部東西畫在虛擬圖片上,一次性顯示出來

注意:若是不能理解透徹就照抄本版本代碼,不影響對J2SE的練習功效

具體代碼實現:

 1 import java.awt.Color;
 2 import java.awt.Frame;
 3 import java.awt.Graphics;
 4 import java.awt.Image;
 5 import java.awt.event.WindowAdapter;
 6 import java.awt.event.WindowEvent;
 7 
 8 public class TankClient extends Frame {
 9     // 將坦克的位置設置爲變量
10     int x = 50;
11     int y = 50;
12     Image offScreenImage = null;
13 
14     // 重寫paint方法
15     @Override
16     public void paint(Graphics g) {
17         // 不要改變原來的前景色,先拿出來,使用之後再改回去
18         // getClolor返回的是this graphics context's current color
19         Color c = g.getColor();
20         g.setColor(Color.RED);
21         // 四個參數分別表明Frame的左上角的x、y座標,實心圓的寬width和高
22         g.fillOval(x, y, 30, 30);
23         g.setColor(c);
24         y += 50;
25     }
26 
27     @Override
28     public void update(Graphics g) {
29         if (offScreenImage == null) {
30             // 建立的虛擬圖片大小
31             offScreenImage = this.createImage(800, 600);
32         }
33         Graphics gOffScreen = offScreenImage.getGraphics();
34         Color c=gOffScreen.getColor();
35         gOffScreen.setColor(Color.GREEN);
36         gOffScreen.fillRect(0, 0, 800, 600);
37         gOffScreen.setColor(c);
38         paint(gOffScreen);
39         g.drawImage(offScreenImage, 0, 0, null);
40     }
41 
42     public static void main(String[] args) {
43         TankClient tc = new TankClient();
44         tc.launchFrame();
45     }
46 
47     public void launchFrame() {
48         // 窗體位置
49         this.setLocation(400, 300);
50         // 窗體尺寸大小
51         this.setSize(800, 600);
52         // 窗體title名稱
53         this.setTitle("TankWar");
54         this.addWindowListener(new WindowAdapter() {
55 
56             @Override
57             public void windowClosing(WindowEvent e) {
58 
59                 System.exit(0);
60             }
61 
62         });
63         setResizable(false);
64         // 設置背景色
65         this.setBackground(Color.GREEN);
66         setVisible(true);
67         new Thread(new PaintThread()).start();
68     }
69 
70     // 使用內部類,只爲包裝類復位
71     private class PaintThread implements Runnable {
72 
73         @Override
74         public void run() {
75             // 重畫,內部會自動調用paint(Graphics g)方法
76             repaint();
77             try {
78                 Thread.sleep(50);
79             } catch (InterruptedException e) {
80                 e.printStackTrace();
81             }
82         }
83 
84     }
85 }

版本0.5

功能: 代碼重構,將之後可能須要多處改變的量定義爲常量,Frame的寬度和高度(常量名通常大寫)

注意: 常量通常是public static final的。

具體代碼實現:

 1 import java.awt.*;
 2 import java.awt.event.*;
 3 
 4 public class TankClient extends Frame {
 5     public static final int GAME_WIDTH = 800;
 6     public static final int GAME_HEIGHT = 600;
 7     
 8     int x = 50, y = 50;
 9     
10     Image offScreenImage = null;
11     
12     public void paint(Graphics g) {
13         Color c = g.getColor();
14         g.setColor(Color.RED);
15         g.fillOval(x, y, 30, 30);
16         g.setColor(c);
17         
18         y += 5;
19     }
20     
21     public void update(Graphics g) {
22         if(offScreenImage == null) {
23             offScreenImage = this.createImage(GAME_WIDTH, GAME_HEIGHT);
24         }
25         Graphics gOffScreen = offScreenImage.getGraphics();
26         Color c = gOffScreen.getColor();
27         gOffScreen.setColor(Color.GREEN);
28         gOffScreen.fillRect(0, 0, GAME_WIDTH, GAME_HEIGHT);
29         gOffScreen.setColor(c);
30         paint(gOffScreen);
31         g.drawImage(offScreenImage, 0, 0, null);
32     }
33 
34     public void lauchFrame() {
35         this.setLocation(400, 300);
36         this.setSize(GAME_WIDTH, GAME_HEIGHT);
37         this.setTitle("TankWar");
38         this.addWindowListener(new WindowAdapter() {
39             public void windowClosing(WindowEvent e) {
40                 System.exit(0);
41             }
42         });
43         this.setResizable(false);
44         this.setBackground(Color.GREEN);
45         setVisible(true);
46         
47         new Thread(new PaintThread()).start();
48     }
49 
50     public static void main(String[] args) {
51         TankClient tc = new TankClient();
52         tc.lauchFrame();
53     }
54     
55     private class PaintThread implements Runnable {
56 
57         public void run() {
58             while(true) {
59                 repaint();
60                 try {
61                     Thread.sleep(50);
62                 } catch (InterruptedException e) {
63                     e.printStackTrace();
64                 }
65             }
66         }
67     }
68 
69 }
View Code

版本0.6

功能: 讓坦克遵從咱們的指揮,添加鍵盤監聽器類KeyMonitor TankCient添加鍵盤監聽器,針對不一樣的鍵改變坦克的位置,與重畫線程結合產生不一樣方向運動

注意: switch case語句中break語句的運用,寫程序要按部就班

具體代碼實現:

 1 import java.awt.*;
 2 import java.awt.event.*;
 3 
 4 public class TankClient extends Frame {
 5     public static final int GAME_WIDTH = 800;
 6     public static final int GAME_HEIGHT = 600;
 7     
 8     int x = 50, y = 50;
 9     
10     Image offScreenImage = null;
11     
12     public void paint(Graphics g) {
13         Color c = g.getColor();
14         g.setColor(Color.RED);
15         g.fillOval(x, y, 30, 30);
16         g.setColor(c);
17     }
18     
19     public void update(Graphics g) {
20         if(offScreenImage == null) {
21             offScreenImage = this.createImage(GAME_WIDTH, GAME_HEIGHT);
22         }
23         Graphics gOffScreen = offScreenImage.getGraphics();
24         Color c = gOffScreen.getColor();
25         gOffScreen.setColor(Color.GREEN);
26         gOffScreen.fillRect(0, 0, GAME_WIDTH, GAME_HEIGHT);
27         gOffScreen.setColor(c);
28         paint(gOffScreen);
29         g.drawImage(offScreenImage, 0, 0, null);
30     }
31 
32     public void lauchFrame() {
33         this.setLocation(400, 300);
34         this.setSize(GAME_WIDTH, GAME_HEIGHT);
35         this.setTitle("TankWar");
36         this.addWindowListener(new WindowAdapter() {
37             public void windowClosing(WindowEvent e) {
38                 System.exit(0);
39             }
40         });
41         this.setResizable(false);
42         this.setBackground(Color.GREEN);
43         
44         this.addKeyListener(new KeyMonitor());
45         
46         setVisible(true);
47         
48         new Thread(new PaintThread()).start();
49     }
50 
51     public static void main(String[] args) {
52         TankClient tc = new TankClient();
53         tc.lauchFrame();
54     }
55     
56     private class PaintThread implements Runnable {
57 
58         public void run() {
59             while(true) {
60                 repaint();
61                 try {
62                     Thread.sleep(50);
63                 } catch (InterruptedException e) {
64                     e.printStackTrace();
65                 }
66             }
67         }
68     }
69     
70     private class KeyMonitor extends KeyAdapter {
71 
72         public void keyPressed(KeyEvent e) {
73             int key = e.getKeyCode();
74             switch(key) {
75             case KeyEvent.VK_LEFT :
76                 x -= 5;
77                 break;
78             case KeyEvent.VK_UP :
79                 y -= 5;
80                 break;
81             case KeyEvent.VK_RIGHT :
82                 x += 5;
83                 break;
84             case KeyEvent.VK_DOWN :
85                 y += 5;
86                 break;
87             }
88         }
89         
90     }
91 }
View Code

版本0.7

功能: 將坦克單獨包裝成類(Tank)

步驟: 創建Tank類;爲Tank類添加成員變量x、y;添加draw方法,使Tank類獨立控制本身的畫法;添加Tank類處理按鍵的方法;根據Tank類修改TankClient類

掌握: 面向對象的思考方法,細節隱藏、構建單獨的類、首先考慮系統中有哪些類?合適的方法應該出如今合適的類中;

具體代碼實現:

Tank:

 1 import java.awt.*;
 2 import java.awt.event.*;
 3 
 4 public class Tank {
 5     int x;
 6     int y;
 7     public Tank(int x, int y) {
 8         this.x = x;
 9         this.y = y;
10     }
11     public void draw(Graphics g){
12         Color c=g.getColor();
13         g.setColor(Color.RED);
14         g.fillOval(x, y, 30, 30);
15         g.setColor(c);
16     }
17     //坦克本身向哪一個方向移動,它本身最清楚;
18     public void KeyPressed(KeyEvent e){
19         //得到所按下的鍵所對應的虛擬碼:
20         //Returns the integer keyCode associated with the key in this event
21         int key = e.getKeyCode();
22         //判斷不一樣的按鍵,指揮坦克的運動方向
23         switch(key) {
24         case KeyEvent.VK_LEFT :
25             x -= 5;
26             break;
27         case KeyEvent.VK_UP :
28             y -= 5;
29             break;
30         case KeyEvent.VK_RIGHT :
31             x += 5;
32             break;
33         case KeyEvent.VK_DOWN :
34             y += 5;
35             break;
36         }
37     }
38 }
View Code

TankClient:

 1 import java.awt.*;
 2 import java.awt.event.*;
 3 
 4 public class TankClient extends Frame {
 5     //設置成常量,方便之後的改動
 6     public static final int GAME_WIDTH = 800;
 7     public static final int GAME_HEIGHT = 600;
 8     Tank myTank=new Tank(50, 50);
 9     
10     //定義虛擬圖片,方便後期的一次性顯示
11     Image offScreenImage = null;
12     
13     public void paint(Graphics g) {
14         //不改變前景色
15         myTank.draw(g);
16     }
17     
18     //刷新操做
19     public void update(Graphics g) {
20         if(offScreenImage == null) {
21             offScreenImage = this.createImage(GAME_WIDTH, GAME_HEIGHT);
22         }
23         Graphics gOffScreen = offScreenImage.getGraphics();
24         Color c = gOffScreen.getColor();
25         gOffScreen.setColor(Color.GREEN);
26         gOffScreen.fillRect(0, 0, GAME_WIDTH, GAME_HEIGHT);
27         gOffScreen.setColor(c);
28         paint(gOffScreen);
29         g.drawImage(offScreenImage, 0, 0, null);
30     }
31 
32     public void lauchFrame() {
33         this.setLocation(400, 300);
34         this.setSize(GAME_WIDTH, GAME_HEIGHT);
35         this.setTitle("TankWar");
36         this.addWindowListener(new WindowAdapter() {
37             public void windowClosing(WindowEvent e) {
38                 System.exit(0);
39             }
40         });
41         this.setResizable(false);
42         this.setBackground(Color.GREEN);
43         
44         this.addKeyListener(new KeyMonitor());
45         
46         setVisible(true);
47         
48         new Thread(new PaintThread()).start();
49     }
50 
51     public static void main(String[] args) {
52         TankClient tc = new TankClient();
53         tc.lauchFrame();
54     }
55     
56     private class PaintThread implements Runnable {
57 
58         public void run() {
59             while(true) {
60                 repaint();
61                 try {
62                     Thread.sleep(50);
63                 } catch (InterruptedException e) {
64                     e.printStackTrace();
65                 }
66             }
67         }
68     }
69     
70     //建立鍵盤時間監聽
71     private class KeyMonitor extends KeyAdapter {
72 
73         //直接調用myTank本身的方法根據相應的按鍵信息進行移動
74         public void keyPressed(KeyEvent e) {
75             myTank.KeyPressed(e);
76         }
77         
78     }
79 }
View Code

版本0.8

功能: 讓主戰坦克向8個方向行走(左、右、上、下、左上、左下、右上、右下)

步驟:   添加記錄按鍵狀態的布爾量;添加表明方向的量(使用枚舉);根據按鍵狀態肯定Tank方向;根據方向進行下一步的移動(move);

Tank:

  1 import java.awt.*;
  2 import java.awt.event.*;
  3 
  4 public class Tank {
  5     // 方便後期更改
  6     public static final int XSPEED = 5;
  7     public static final int YSPEED = 5;
  8     private int x;
  9     private int y;
 10     // 添加記錄按鍵狀態的布爾量
 11     private boolean bL = false;
 12     private boolean bR = false;
 13     private boolean bU = false;
 14     private boolean bD = false;
 15 
 16     // 添加表明方向的量(使用枚舉)
 17     enum Direction {
 18         L, R, U, D, LU, LD, RU, RD, STOP
 19     };
 20 
 21     private Direction dir = Direction.STOP;
 22 
 23     public Tank(int x, int y) {
 24         this.x = x;
 25         this.y = y;
 26     }
 27 
 28     // Tank對象的draw方法
 29     public void draw(Graphics g) {
 30         Color c = g.getColor();
 31         g.setColor(Color.RED);
 32         g.fillOval(x, y, 30, 30);
 33         g.setColor(c);
 34         move();
 35     }
 36 
 37     public void move() {
 38         switch (dir) {
 39         case L:
 40             x -= XSPEED;
 41             break;
 42         case R:
 43             x += XSPEED;
 44             break;
 45         case U:
 46             y -= YSPEED;
 47             break;
 48         case D:
 49             y += YSPEED;
 50             break;
 51         case LU:
 52             x -= XSPEED;
 53             y -= YSPEED;
 54             break;
 55         case LD:
 56             x -= XSPEED;
 57             y += YSPEED;
 58             break;
 59         case RU:
 60             x += XSPEED;
 61             y -= YSPEED;
 62             break;
 63         case RD:
 64             x += XSPEED;
 65             y += YSPEED;
 66             break;
 67 
 68         case STOP:
 69             break;
 70         }
 71     }
 72 
 73     public void locateDirection() {
 74         if (bL && !bU && !bR && !bD)
 75             dir = Direction.L;
 76         else if (bL && bU && !bR && !bD)
 77             dir = Direction.LU;
 78         else if (!bL && bU && !bR && !bD)
 79             dir = Direction.U;
 80         else if (!bL && bU && bR && !bD)
 81             dir = Direction.RU;
 82         else if (!bL && !bU && bR && !bD)
 83             dir = Direction.R;
 84         else if (!bL && !bU && bR && bD)
 85             dir = Direction.RD;
 86         else if (!bL && !bU && !bR && bD)
 87             dir = Direction.D;
 88         else if (bL && !bU && !bR && bD)
 89             dir = Direction.LD;
 90         else if (!bL && !bU && !bR && !bD)
 91             dir = Direction.STOP;
 92 
 93     }
 94 
 95     // 坦克本身向哪一個方向移動,它本身最清楚;
 96     public void KeyPressed(KeyEvent e) {
 97         // 得到所按下的鍵所對應的虛擬碼:
 98         // Returns the integer keyCode associated with the key in this event
 99         int key = e.getKeyCode();
100         // 判斷不一樣的按鍵,指揮坦克的運動方向
101         switch (key) {
102         case KeyEvent.VK_LEFT:
103             bL = true;
104             break;
105         case KeyEvent.VK_UP:
106             bU = true;
107             break;
108         case KeyEvent.VK_RIGHT:
109             bR = true;
110             break;
111         case KeyEvent.VK_DOWN:
112             bD = true;
113             break;
114         }
115         locateDirection();
116     }
117 }
View Code

TankClient:

 1 import java.awt.*;
 2 import java.awt.event.*;
 3 
 4 public class TankClient extends Frame {
 5     // 設置成常量,方便之後的改動
 6     public static final int GAME_WIDTH = 800;
 7     public static final int GAME_HEIGHT = 600;
 8     Tank myTank = new Tank(50, 50);
 9 
10     // 定義虛擬圖片,方便後期的一次性顯示
11     Image offScreenImage = null;
12 
13     public void paint(Graphics g) {
14         // 不改變前景色
15         myTank.draw(g);
16     }
17 
18     // 刷新操做
19     public void update(Graphics g) {
20         if (offScreenImage == null) {
21             offScreenImage = this.createImage(GAME_WIDTH, GAME_HEIGHT);
22         }
23         Graphics gOffScreen = offScreenImage.getGraphics();
24         Color c = gOffScreen.getColor();
25         gOffScreen.setColor(Color.GREEN);
26         gOffScreen.fillRect(0, 0, GAME_WIDTH, GAME_HEIGHT);
27         gOffScreen.setColor(c);
28         paint(gOffScreen);
29         g.drawImage(offScreenImage, 0, 0, null);
30     }
31 
32     public void lauchFrame() {
33         this.setLocation(400, 300);
34         this.setSize(GAME_WIDTH, GAME_HEIGHT);
35         this.setTitle("TankWar");
36         this.addWindowListener(new WindowAdapter() {
37             public void windowClosing(WindowEvent e) {
38                 System.exit(0);
39             }
40         });
41         this.setResizable(false);
42         this.setBackground(Color.GREEN);
43 
44         this.addKeyListener(new KeyMonitor());
45 
46         setVisible(true);
47 
48         new Thread(new PaintThread()).start();
49     }
50 
51     public static void main(String[] args) {
52         TankClient tc = new TankClient();
53         tc.lauchFrame();
54     }
55 
56     private class PaintThread implements Runnable {
57 
58         public void run() {
59             while (true) {
60                 repaint();
61                 try {
62                     Thread.sleep(50);
63                 } catch (InterruptedException e) {
64                     e.printStackTrace();
65                 }
66             }
67         }
68     }
69 
70     // 建立鍵盤時間監聽
71     private class KeyMonitor extends KeyAdapter {
72 
73         // 直接調用myTank本身的方法根據相應的按鍵信息進行移動
74         public void keyPressed(KeyEvent e) {
75             myTank.KeyPressed(e);
76         }
77 
78     }
79 }
View Code

按下按鍵->KeyPressed監聽->按鍵狀態發生改變->locateDirection()函數->dir的值會發生改變->進而當調用move方法的時候執行相應的操做;

版本0.9

咱們在版本0.8中,按下某個鍵的時候,記錄按鍵狀態的布爾量一直是true,咱們沒法改變坦克的移動方向了,在版本0.9中咱們作下處理

功能: 讓主戰坦克向8個方向行走

步驟: 處理鍵擡起的消息 修改TankClient相關代碼

Tank:

  1 import java.awt.*;
  2 import java.awt.event.*;
  3 
  4 public class Tank {
  5     // 方便後期更改
  6     public static final int XSPEED = 5;
  7     public static final int YSPEED = 5;
  8     private int x;
  9     private int y;
 10     // 添加記錄按鍵狀態的布爾量
 11     private boolean bL = false;
 12     private boolean bR = false;
 13     private boolean bU = false;
 14     private boolean bD = false;
 15 
 16     // 添加表明方向的量(使用枚舉)
 17     enum Direction {
 18         L, R, U, D, LU, LD, RU, RD, STOP
 19     };
 20 
 21     private Direction dir = Direction.STOP;
 22 
 23     public Tank(int x, int y) {
 24         this.x = x;
 25         this.y = y;
 26     }
 27 
 28     // Tank對象的draw方法
 29     public void draw(Graphics g) {
 30         Color c = g.getColor();
 31         g.setColor(Color.RED);
 32         g.fillOval(x, y, 30, 30);
 33         g.setColor(c);
 34         move();
 35     }
 36 
 37     public void move() {
 38         switch (dir) {
 39         case L:
 40             x -= XSPEED;
 41             break;
 42         case R:
 43             x += XSPEED;
 44             break;
 45         case U:
 46             y -= YSPEED;
 47             break;
 48         case D:
 49             y += YSPEED;
 50             break;
 51         case LU:
 52             x -= XSPEED;
 53             y -= YSPEED;
 54             break;
 55         case LD:
 56             x -= XSPEED;
 57             y += YSPEED;
 58             break;
 59         case RU:
 60             x += XSPEED;
 61             y -= YSPEED;
 62             break;
 63         case RD:
 64             x += XSPEED;
 65             y += YSPEED;
 66             break;
 67 
 68         case STOP:
 69             break;
 70         }
 71     }
 72 
 73     public void locateDirection() {
 74         if (bL && !bU && !bR && !bD)
 75             dir = Direction.L;
 76         else if (bL && bU && !bR && !bD)
 77             dir = Direction.LU;
 78         else if (!bL && bU && !bR && !bD)
 79             dir = Direction.U;
 80         else if (!bL && bU && bR && !bD)
 81             dir = Direction.RU;
 82         else if (!bL && !bU && bR && !bD)
 83             dir = Direction.R;
 84         else if (!bL && !bU && bR && bD)
 85             dir = Direction.RD;
 86         else if (!bL && !bU && !bR && bD)
 87             dir = Direction.D;
 88         else if (bL && !bU && !bR && bD)
 89             dir = Direction.LD;
 90         else if (!bL && !bU && !bR && !bD)
 91             dir = Direction.STOP;
 92 
 93     }
 94 
 95     // 坦克本身向哪一個方向移動,它本身最清楚;
 96     public void KeyPressed(KeyEvent e) {
 97         // 得到所按下的鍵所對應的虛擬碼:
 98         // Returns the integer keyCode associated with the key in this event
 99         int key = e.getKeyCode();
100         // 判斷不一樣的按鍵,指揮坦克的運動方向
101         switch (key) {
102         case KeyEvent.VK_LEFT:
103             bL = true;
104             break;
105         case KeyEvent.VK_UP:
106             bU = true;
107             break;
108         case KeyEvent.VK_RIGHT:
109             bR = true;
110             break;
111         case KeyEvent.VK_DOWN:
112             bD = true;
113             break;
114         }
115         locateDirection();
116     }
117 
118     public void keyReleased(KeyEvent e) {
119         int key = e.getKeyCode();
120         // 判斷不一樣的按鍵,指揮坦克的運動方向
121         // 哪一個鍵按下了,就把對應方向的布爾類型置爲false
122         switch (key) {
123         case KeyEvent.VK_LEFT:
124             bL = false;
125             break;
126         case KeyEvent.VK_UP:
127             bU = false;
128             break;
129         case KeyEvent.VK_RIGHT:
130             bR = false;
131             break;
132         case KeyEvent.VK_DOWN:
133             bD = false;
134             break;
135         }
136         // 從新定位一下
137         locateDirection();
138     }
139 }
View Code

TankClient:

 1 import java.awt.*;
 2 import java.awt.event.*;
 3 
 4 public class TankClient extends Frame {
 5     // 設置成常量,方便之後的改動
 6     public static final int GAME_WIDTH = 800;
 7     public static final int GAME_HEIGHT = 600;
 8     Tank myTank = new Tank(50, 50);
 9 
10     // 定義虛擬圖片,方便後期的一次性顯示
11     Image offScreenImage = null;
12 
13     public void paint(Graphics g) {
14         // 不改變前景色
15         myTank.draw(g);
16     }
17 
18     // 刷新操做
19     public void update(Graphics g) {
20         if (offScreenImage == null) {
21             offScreenImage = this.createImage(GAME_WIDTH, GAME_HEIGHT);
22         }
23         Graphics gOffScreen = offScreenImage.getGraphics();
24         Color c = gOffScreen.getColor();
25         gOffScreen.setColor(Color.GREEN);
26         gOffScreen.fillRect(0, 0, GAME_WIDTH, GAME_HEIGHT);
27         gOffScreen.setColor(c);
28         paint(gOffScreen);
29         g.drawImage(offScreenImage, 0, 0, null);
30     }
31 
32     public void lauchFrame() {
33         this.setLocation(400, 300);
34         this.setSize(GAME_WIDTH, GAME_HEIGHT);
35         this.setTitle("TankWar");
36         this.addWindowListener(new WindowAdapter() {
37             public void windowClosing(WindowEvent e) {
38                 System.exit(0);
39             }
40         });
41         this.setResizable(false);
42         this.setBackground(Color.GREEN);
43 
44         this.addKeyListener(new KeyMonitor());
45 
46         setVisible(true);
47 
48         new Thread(new PaintThread()).start();
49     }
50 
51     public static void main(String[] args) {
52         TankClient tc = new TankClient();
53         tc.lauchFrame();
54     }
55 
56     private class PaintThread implements Runnable {
57 
58         public void run() {
59             while (true) {
60                 repaint();
61                 try {
62                     Thread.sleep(50);
63                 } catch (InterruptedException e) {
64                     e.printStackTrace();
65                 }
66             }
67         }
68     }
69 
70     // 建立鍵盤時間監聽
71     private class KeyMonitor extends KeyAdapter {
72 
73         // 直接調用myTank本身的方法根據相應的按鍵信息進行移動
74         public void keyPressed(KeyEvent e) {
75             myTank.KeyPressed(e);
76             // 添加了處理鍵擡起的事件,能夠控制坦克起步之後的狀態
77             // 而不是一直按照一個方向走下去
78         }
79         public void keyReleased(KeyEvent e){
80             myTank.keyReleased(e);
81         }
82 
83     }
84 }
View Code

未完待續。。。。。。

相關文章
相關標籤/搜索