版本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 }
版本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 }
版本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 }
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 }
版本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 }
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 }
按下按键->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 }
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 }
未完待续。。。。。。