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

版本0.1

功能: 产生一个窗口

掌握: 通过Eclipse建立新的项目 为新的项目指定不同的源代码和输出目录 指定项目所用的JDK版本 通过Eclipse建立新的类

注意: 类名和方法名的命名能够见名知意,类名首字母大写,方法名、变量名首字母小写,应用驼峰标识(多个单词组成第一个单词小写,其他单词首字母大写)

具体代码实现:

 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

功能: 添加关闭窗口的事件处理,不允许窗口的大小改动

掌握: 匿名类的用法 思考:匿名类的应用场合? 类短小、不涉及将来的扩展、不涉及重要的业务逻辑 通过Eclipse重写父类的方法

注意: 没掌握匿名类的先照抄,不写也行 不影响最后的运行效果

具体代码实现:

 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

未完待续。。。。。。

原文地址:https://www.cnblogs.com/ysw-go/p/5503281.html