坦克大战(版本1.0-版本1.6)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了坦克大战(版本1.0-版本1.6)相关的知识,希望对你有一定的参考价值。

版本1.0

功能: 添加子弹类

步骤: 1)添加Missile类;

         2)添加x,y,dir等属性以及常量;

         3)添加构造方法、draw方法等必要方法;

         4)根据不同方向,进行不同的运动;

         5)在TankClient中模拟一颗子弹;

         6)new一颗子弹出来;

         7)画出来

注意: 不一定一次写到位,进行多次试验,将步骤分解开来逐一进行调试;

具体代码实现:

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

Missile:新添加的子弹类

 1 import java.awt.Color;
 2 import java.awt.Graphics;
 3 
 4 public class Missile {
 5     //炮弹的移动速度,不要比坦克的移动速度慢,不然你看到的是满屏的坦克追着炮弹跑
 6     public static final int XSPEED=10;
 7     public static final int YSPEED=10;
 8     //炮弹自己的三个属性
 9     int x;
10     int y;
11     Tank.Direction dir;
12     public Missile(int x, int y, Tank.Direction dir) {
13         this.x = x;
14         this.y = y;
15         this.dir = dir;
16     }
17     //炮弹自己的draw方法
18     public void draw(Graphics g){
19         Color c=g.getColor();
20         g.setColor(Color.BLACK);
21         //炮弹形状不要比坦克大,这里设置成10,10;
22         g.fillOval(x, y, 10, 10);
23         g.setColor(c);
24         move();
25     }
26     public  void move() {
27         switch (dir) {
28         case L:
29             x -= XSPEED;
30             break;
31         case R:
32             x += XSPEED;
33             break;
34         case U:
35             y -= YSPEED;
36             break;
37         case D:
38             y += YSPEED;
39             break;
40         case LU:
41             x -= XSPEED;
42             y -= YSPEED;
43             break;
44         case LD:
45             x -= XSPEED;
46             y += YSPEED;
47             break;
48         case RU:
49             x += XSPEED;
50             y -= YSPEED;
51             break;
52         case RD:
53             x += XSPEED;
54             y += YSPEED;
55             break;
56         //炮弹就没有STOP这个枚举类型的值了
57     /*    case STOP:
58             break;*/
59         }
60     }
61 }

TankClient:在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     // 在TankClient中定义炮弹
11     Missile m = new Missile(50, 50, Tank.Direction.R);
12     // 定义虚拟图片,方便后期的一次性显示
13     Image offScreenImage = null;
14 
15     public void paint(Graphics g) {
16         // 把炮弹画出来
17         m.draw(g);
18         // 不改变前景色
19         myTank.draw(g);
20     }
21 
22     // 刷新操作
23     public void update(Graphics g) {
24         if (offScreenImage == null) {
25             offScreenImage = this.createImage(GAME_WIDTH, GAME_HEIGHT);
26         }
27         Graphics gOffScreen = offScreenImage.getGraphics();
28         Color c = gOffScreen.getColor();
29         gOffScreen.setColor(Color.GREEN);
30         gOffScreen.fillRect(0, 0, GAME_WIDTH, GAME_HEIGHT);
31         gOffScreen.setColor(c);
32         paint(gOffScreen);
33         g.drawImage(offScreenImage, 0, 0, null);
34     }
35 
36     public void lauchFrame() {
37         this.setLocation(400, 300);
38         this.setSize(GAME_WIDTH, GAME_HEIGHT);
39         this.setTitle("TankWar");
40         this.addWindowListener(new WindowAdapter() {
41             public void windowClosing(WindowEvent e) {
42                 System.exit(0);
43             }
44         });
45         this.setResizable(false);
46         this.setBackground(Color.GREEN);
47 
48         this.addKeyListener(new KeyMonitor());
49 
50         setVisible(true);
51 
52         new Thread(new PaintThread()).start();
53     }
54 
55     public static void main(String[] args) {
56         TankClient tc = new TankClient();
57         tc.lauchFrame();
58     }
59 
60     private class PaintThread implements Runnable {
61 
62         public void run() {
63             while (true) {
64                 repaint();
65                 try {
66                     Thread.sleep(50);
67                 } catch (InterruptedException e) {
68                     e.printStackTrace();
69                 }
70             }
71         }
72     }
73 
74     // 创建键盘时间监听
75     private class KeyMonitor extends KeyAdapter {
76 
77         // 直接调用myTank自己的方法根据相应的按键信息进行移动
78         public void keyPressed(KeyEvent e) {
79             myTank.KeyPressed(e);
80             // 添加了处理键抬起的事件,可以控制坦克起步以后的状态
81             // 而不是一直按照一个方向走下去
82         }
83         public void keyReleased(KeyEvent e){
84             myTank.keyReleased(e);
85         }
86 
87     }
88 }
View Code

版本1.1

功能:根据主战坦克的方向和位置,打出子弹,让子弹从坦克的中心打出来;

步骤:

       1)增加对Ctrl键的按键处理;

       2)根据“坦克打出一发子弹”这句话,来确定Tank中的方法fire,其返回值为Missle;

       3)根据Tank方向和位置设定子弹的方向和位置并new出来,然后返回(fire方法的实现)

注意: 掌握面向对象的思维方式来确定类应该具有的方法

下面这个图中左上角是坦克的的位置(x,y),圆心中心是坦克的中心,w是坦克的宽度,h是坦克的高度,我们计算炮弹的位置可以通过下面的公式计算:

注意x轴向右递增,y轴向下递增;

    int x=this.x+Tank.WIDTH/2-Missile.WIDTH/2;
    int y=this.y+Tank.HEIGHT/2-Missile.HEIGHT/2;

 

技术分享

具体代码实现:

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     // 将坦克的高度和宽度设置为常量
  9     public static final int WIDTH = 30;
 10     public static final int HEIGHT = 30;
 11     TankClient tc = null;
 12     private int x;
 13     private int y;
 14     // 添加记录按键状态的布尔量
 15     private boolean bL = false;
 16     private boolean bR = false;
 17     private boolean bU = false;
 18     private boolean bD = false;
 19 
 20     // 添加代表方向的量(使用枚举)
 21     enum Direction {
 22         L, R, U, D, LU, LD, RU, RD, STOP
 23     };
 24 
 25     private Direction dir = Direction.STOP;
 26 
 27     public Tank(int x, int y) {
 28         this.x = x;
 29         this.y = y;
 30     }
 31 
 32     public Tank(int x, int y, TankClient tc) {
 33         // 调用那个有两个参数的构造方法
 34         this(x, y);
 35         // 在这个位置初始化tc
 36         this.tc = tc;
 37     }
 38 
 39     // Tank对象的draw方法
 40     public void draw(Graphics g) {
 41         Color c = g.getColor();
 42         g.setColor(Color.RED);
 43         g.fillOval(x, y, WIDTH, HEIGHT);
 44         g.setColor(c);
 45         move();
 46     }
 47 
 48     public void move() {
 49         switch (dir) {
 50         case L:
 51             x -= XSPEED;
 52             break;
 53         case R:
 54             x += XSPEED;
 55             break;
 56         case U:
 57             y -= YSPEED;
 58             break;
 59         case D:
 60             y += YSPEED;
 61             break;
 62         case LU:
 63             x -= XSPEED;
 64             y -= YSPEED;
 65             break;
 66         case LD:
 67             x -= XSPEED;
 68             y += YSPEED;
 69             break;
 70         case RU:
 71             x += XSPEED;
 72             y -= YSPEED;
 73             break;
 74         case RD:
 75             x += XSPEED;
 76             y += YSPEED;
 77             break;
 78 
 79         case STOP:
 80             break;
 81         }
 82     }
 83 
 84     public void locateDirection() {
 85         if (bL && !bU && !bR && !bD)
 86             dir = Direction.L;
 87         else if (bL && bU && !bR && !bD)
 88             dir = Direction.LU;
 89         else if (!bL && bU && !bR && !bD)
 90             dir = Direction.U;
 91         else if (!bL && bU && bR && !bD)
 92             dir = Direction.RU;
 93         else if (!bL && !bU && bR && !bD)
 94             dir = Direction.R;
 95         else if (!bL && !bU && bR && bD)
 96             dir = Direction.RD;
 97         else if (!bL && !bU && !bR && bD)
 98             dir = Direction.D;
 99         else if (bL && !bU && !bR && bD)
100             dir = Direction.LD;
101         else if (!bL && !bU && !bR && !bD)
102             dir = Direction.STOP;
103 
104     }
105 
106     // 坦克自己向哪个方向移动,它自己最清楚;
107     public void KeyPressed(KeyEvent e) {
108         // 获得所按下的键所对应的虚拟码:
109         // Returns the integer keyCode associated with the key in this event
110         int key = e.getKeyCode();
111         // 判断不同的按键,指挥坦克的运动方向
112         switch (key) {
113         // Ctrl键控制打出炮弹
114         case KeyEvent.VK_CONTROL:
115             // fire函数返回的是一个Missile类型的对象
116             tc.m = fire();
117             break;
118         case KeyEvent.VK_LEFT:
119             bL = true;
120             break;
121         case KeyEvent.VK_UP:
122             bU = true;
123             break;
124         case KeyEvent.VK_RIGHT:
125             bR = true;
126             break;
127         case KeyEvent.VK_DOWN:
128             bD = true;
129             break;
130         }
131         locateDirection();
132     }
133 
134     public void keyReleased(KeyEvent e) {
135         int key = e.getKeyCode();
136         // 判断不同的按键,指挥坦克的运动方向
137         // 哪个键按下了,就把对应方向的布尔类型置为false
138         switch (key) {
139         case KeyEvent.VK_LEFT:
140             bL = false;
141             break;
142         case KeyEvent.VK_UP:
143             bU = false;
144             break;
145         case KeyEvent.VK_RIGHT:
146             bR = false;
147             break;
148         case KeyEvent.VK_DOWN:
149             bD = false;
150             break;
151         }
152         // 重新定位一下
153         locateDirection();
154     }
155 
156     public Missile fire() {
157         // 计算子弹的位置,使得子弹从坦克的中间发出来
158         int x = this.x + Tank.WIDTH / 2 - Missile.WIDTH / 2;
159         int y = this.y + Tank.HEIGHT / 2 - Missile.HEIGHT / 2;
160         // 将坦克的位置和方向传递给炮弹
161         Missile m = new Missile(x, y, dir);
162         return m;
163     }
164 }
View Code

Missile:

技术分享
 1 import java.awt.Color;
 2 import java.awt.Graphics;
 3 
 4 public class Missile {
 5     //

以上是关于坦克大战(版本1.0-版本1.6)的主要内容,如果未能解决你的问题,请参考以下文章

坦克大战(版本2.5-版本2.9)

基于Netty的坦克大战网络版本

2019.04.19 坦克大战

Python游戏开发,pygame模块,Python实现升级版坦克大战小游戏

坦克大战1.0版

Tanks坦克大战