坦克大战(版本1.7-版本2.4)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了坦克大战(版本1.7-版本2.4)相关的知识,希望对你有一定的参考价值。
版本1.7
功能:加入爆炸
步骤:
1)添加爆炸类:Explode
用不同直径的圆模拟爆炸: int[] diameter = {4, 7, 12, 18, 26, 32, 49, 30, 14, 6};
加入live: private boolean live = true;
加入位置属性: int x, y;
加入draw方法
2)爆炸应该存在于集合类中:
TankClient加入集合explodes: List<Explode> explodes=new ArrayList<Explode>();
将集合中的爆炸逐一画出(如果死去就去除):在Missile类的draw方法中,当爆炸live==false的时候,tc.missiles.remove(this);
3)击毙一辆坦克后应产生爆炸:
在Missile类的hitTank中,产生爆炸,Explode e=new Explode(x, y, tc); tc.explodes.add(e);
具体代码实现:
Tank:

1 import java.awt.*; 2 import java.awt.event.*; 3 import java.util.Random; 4 5 public class Tank { 6 // 方便后期更改 7 public static final int XSPEED = 5; 8 public static final int YSPEED = 5; 9 // 将坦克的高度和宽度设置为常量 10 public static final int WIDTH = 30; 11 public static final int HEIGHT = 30; 12 TankClient tc; 13 // 区别是我方坦克还是地方坦克,方便据此进行不同的设置 14 private boolean good; 15 16 //判断坦克生死的变量 17 private boolean live=true; 18 19 20 public boolean isLive() { 21 return live; 22 } 23 24 public void setLive(boolean live) { 25 this.live = live; 26 } 27 28 private int x; 29 private int y; 30 // 添加记录按键状态的布尔量 31 private boolean bL = false; 32 private boolean bR = false; 33 private boolean bU = false; 34 private boolean bD = false; 35 36 // 添加代表方向的量(使用枚举) 37 enum Direction { 38 L, R, U, D, LU, LD, RU, RD, STOP 39 }; 40 41 private Direction dir = Direction.STOP; 42 43 // 定义炮筒的方向,我们想办法将炮筒的方法调整成和坦克移动方向一致; 44 // 我们这里会用一条直线来表示炮筒:模拟炮筒 45 // 我们要根据炮筒的方向画直线表示炮筒 46 Direction ptDir = Direction.D; 47 48 //更改构造函数 49 public Tank(int x, int y,boolean good) { 50 this.x = x; 51 this.y = y; 52 this.good=good; 53 } 54 55 //这个位置的构造函数也相应进行了更改 56 public Tank(int x, int y,boolean good,TankClient tc) { 57 // 调用那个有两个参数的构造方法 58 this(x, y,good); 59 // 在这个位置初始化tc 60 this.tc = tc; 61 } 62 63 // Tank对象的draw方法 64 public void draw(Graphics g) { 65 if(!live){ 66 return; 67 } 68 Color c = g.getColor(); 69 if(good){ 70 g.setColor(Color.RED); 71 } 72 else { 73 g.setColor(Color.PINK); 74 } 75 g.fillOval(x, y, WIDTH, HEIGHT); 76 g.setColor(c); 77 // 根据炮筒的方向画直线来表示我们坦克的炮筒 78 switch (ptDir) { 79 case L: 80 // 画直线:四个参数分别代表:坦克中心点的坐标 直线的另一头的的坐标 81 g.drawLine(x + Tank.WIDTH / 2, y + Tank.HEIGHT / 2, x, y 82 + Tank.HEIGHT / 2); 83 break; 84 case R: 85 g.drawLine(x + Tank.WIDTH / 2, y + Tank.HEIGHT / 2, x + Tank.WIDTH, 86 y + Tank.HEIGHT / 2); 87 88 break; 89 case U: 90 g.drawLine(x + Tank.WIDTH / 2, y + Tank.HEIGHT / 2, x + Tank.WIDTH 91 / 2, y); 92 93 break; 94 case D: 95 g.drawLine(x + Tank.WIDTH / 2, y + Tank.HEIGHT / 2, x + Tank.WIDTH 96 / 2, y + Tank.HEIGHT); 97 98 break; 99 case LU: 100 g.drawLine(x + Tank.WIDTH / 2, y + Tank.HEIGHT / 2, x, y); 101 break; 102 case LD: 103 g.drawLine(x + Tank.WIDTH / 2, y + Tank.HEIGHT / 2, x, y 104 + Tank.HEIGHT); 105 106 break; 107 case RU: 108 g.drawLine(x + Tank.WIDTH / 2, y + Tank.HEIGHT / 2, x + Tank.WIDTH, 109 y); 110 111 break; 112 case RD: 113 g.drawLine(x + Tank.WIDTH / 2, y + Tank.HEIGHT / 2, x + Tank.WIDTH, 114 y + Tank.HEIGHT); 115 116 break; 117 /* 118 * case STOP: break; 119 */ 120 } 121 move(); 122 } 123 124 public void move() { 125 switch (dir) { 126 case L: 127 x -= XSPEED; 128 break; 129 case R: 130 x += XSPEED; 131 break; 132 case U: 133 y -= YSPEED; 134 break; 135 case D: 136 y += YSPEED; 137 break; 138 case LU: 139 x -= XSPEED; 140 y -= YSPEED; 141 break; 142 case LD: 143 x -= XSPEED; 144 y += YSPEED; 145 break; 146 case RU: 147 x += XSPEED; 148 y -= YSPEED; 149 break; 150 case RD: 151 x += XSPEED; 152 y += YSPEED; 153 break; 154 155 case STOP: 156 break; 157 } 158 // 如果坦克不是停着的,则将炮筒调整至和坦克移动的方向相同 159 if (this.dir != Direction.STOP) { 160 this.ptDir = this.dir; 161 } 162 if (x < 0) { 163 x = 0; 164 } 165 // 因为我们的游戏界面有那个missileCount标签,所以在y轴方向不能用y是否<0进行判断 166 // 否则的话我们的坦克可以从上面出去 167 if (y < 50) { 168 y = 50; 169 } 170 if (x + Tank.WIDTH > TankClient.GAME_WIDTH) { 171 x = TankClient.GAME_WIDTH - Tank.WIDTH; 172 } 173 if (y + Tank.HEIGHT > TankClient.GAME_HEIGHT) { 174 y = TankClient.GAME_HEIGHT - Tank.HEIGHT; 175 } 176 } 177 178 public void locateDirection() { 179 if (bL && !bU && !bR && !bD) 180 dir = Direction.L; 181 else if (bL && bU && !bR && !bD) 182 dir = Direction.LU; 183 else if (!bL && bU && !bR && !bD) 184 dir = Direction.U; 185 else if (!bL && bU && bR && !bD) 186 dir = Direction.RU; 187 else if (!bL && !bU && bR && !bD) 188 dir = Direction.R; 189 else if (!bL && !bU && bR && bD) 190 dir = Direction.RD; 191 else if (!bL && !bU && !bR && bD) 192 dir = Direction.D; 193 else if (bL && !bU && !bR && bD) 194 dir = Direction.LD; 195 else if (!bL && !bU && !bR && !bD) 196 dir = Direction.STOP; 197 198 } 199 200 // 坦克自己向哪个方向移动,它自己最清楚; 201 public void KeyPressed(KeyEvent e) { 202 // 获得所按下的键所对应的虚拟码: 203 // Returns the integer keyCode associated with the key in this event 204 int key = e.getKeyCode(); 205 // 判断不同的按键,指挥坦克的运动方向 206 switch (key) { 207 case KeyEvent.VK_LEFT: 208 bL = true; 209 break; 210 case KeyEvent.VK_UP: 211 bU = true; 212 break; 213 case KeyEvent.VK_RIGHT: 214 bR = true; 215 break; 216 case KeyEvent.VK_DOWN: 217 bD = true; 218 break; 219 } 220 locateDirection(); 221 } 222 223 public void keyReleased(KeyEvent e) { 224 int key = e.getKeyCode(); 225 // 判断不同的按键,指挥坦克的运动方向 226 // 哪个键按下了,就把对应方向的布尔类型置为false 227 switch (key) { 228 // 为了防止一直按着Ctrl键的时候,炮弹太过于密集 229 // 因此我们定义在Ctrl键抬起的时候才发炮弹 230 // 这样炮弹不至于太过密集 231 case KeyEvent.VK_CONTROL: 232 fire(); 233 break; 234 case KeyEvent.VK_LEFT: 235 bL = false; 236 break; 237 case KeyEvent.VK_UP: 238 bU = false; 239 break; 240 case KeyEvent.VK_RIGHT: 241 bR = false; 242 break; 243 case KeyEvent.VK_DOWN: 244 bD = false; 245 break; 246 } 247 // 重新定位一下 248 locateDirection(); 249 } 250 251 public Missile fire() { 252 // 计算子弹的位置,使得子弹从坦克的中间发出来 253 int x = this.x + Tank.WIDTH / 2 - Missile.WIDTH / 2; 254 int y = this.y + Tank.HEIGHT / 2 - Missile.HEIGHT / 2; 255 // 这个时候我们就根据炮筒的方向来发炮弹了,之前是根据坦克的方向来发炮弹 256 Missile m = new Missile(x, y, ptDir, tc); 257 // 将新产生的炮弹放置到List容器中 258 tc.missiles.add(m); 259 return m; 260 } 261 262 //拿到包围坦克的那个方块 263 public Rectangle getRect() { 264 265 return new Rectangle(x,y,WIDTH,HEIGHT); 266 } 267 }
Missile:

1 import java.awt.Color; 2 import java.awt.Graphics; 3 import java.awt.Rectangle; 4 5 public class Missile { 6 // 炮弹的移动速度,不要比坦克的移动速度慢,不然你看到的是满屏的坦克追着炮弹跑 7 public static final int XSPEED = 10; 8 public static final int YSPEED = 10; 9 // 将子弹的高度和宽度设置为常量 10 public static final int WIDTH = 10; 11 public static final int HEIGHT = 10; 12 // 炮弹自己的三个属性 13 int x; 14 int y; 15 Tank.Direction dir; 16 17 // 定义一个布尔类型的变量来判断炮弹是否已经消亡 18 private boolean live = true; 19 //我们在Missile类中也持有一个TankClient的引用 20 //在炮弹出界的时候就可以从装炮弹的missiles集合中去除该炮弹,不再对其重画 21 private TankClient tc; 22 23 public boolean isLive() { 24 return live; 25 } 26 27 public Missile(int x, int y, Tank.Direction dir) { 28 this.x = x; 29 this.y = y; 30 this.dir = dir; 31 } 32 public Missile(int x,int y,Tank.Direction dir,TankClient tc){ 33 this(x, y, dir); 34 this.tc=tc; 35 } 36 37 // 炮弹自己的draw方法 38 public void draw(Graphics g) { 39 //炮弹消亡就不需要再画出来了 40 if(!live){ 41 tc.missiles.remove(this); 42 return; 43 } 44 Color c = g.getColor(); 45 g.setColor(Color.BLACK); 46 // 炮弹形状不要比坦克大,这里设置成10,10; 47 g.fillOval(x, y, WIDTH, HEIGHT); 48 g.setColor(c); 49 move(); 50 } 51 52 public void move() { 53 switch (dir) { 54 case L: 55 x -= XSPEED; 56 break; 57 case R: 58 x += XSPEED; 59 break; 60 case U: 61 y -= YSPEED; 62 break; 63 case D: 64 y += YSPEED; 65 break; 66 case LU: 67 x -= XSPEED; 68 y -= YSPEED; 69 break; 70 case LD: 71 x -= XSPEED; 72 y += YSPEED; 73 break; 74 case RU: 75 x += XSPEED; 76 y -= YSPEED; 77 break; 78 case RD: 79 x += XSPEED; 80 y += YSPEED; 81 break; 82 // 炮弹就没有STOP这个枚举类型的值了 83 /* 84 * case STOP: break; 85 */ 86 } 87 // 判断炮弹出边界则消亡 88 // 注意x,y只有正数值,x向右递增,y向下递增 89 if (x < 0 || y < 0 || x > TankClient.GAME_WIDTH 90 || y > TankClient.GAME_HEIGHT) { 91 live = false; 92 } 93 } 94 public boolean hitTank(Tank t){ 95 //炮弹的方框和坦克的方框碰在一起了并且坦克是存活着的 96 if(this.getRect().intersects(t.getRect())&&t.isLive()){ 97 t.setLive(false); 98 this.live=false; 99 100 //炮弹击中坦克,发生爆炸 101 Explode e=new Explode(x, y, tc); 102 tc.explodes.add(e); 103 return true; 104 } 105 return false; 106 } 107 //碰撞检测类Rectangle 108 //拿到包围在炮弹周围的小方块 109 public Rectangle getRect(){ 110 return new Rectangle(x,y,WIDTH,HEIGHT); 111 } 112 }
Explode:

1 import java.awt.*; 2 3 public class Explode { 4 //爆炸的位置 5 int x, y; 6 //爆炸是否存在 7 private boolean live = true; 8 9 //持有一个Tankclient的引用 10 private TankClient tc ; 11 12 //定义不同直径大小的爆炸 13 int[] diameter = {4, 7, 12, 18, 26, 32, 49, 30, 14, 6}; 14 //爆炸发生到哪一个阶段了,对应相应大小的直径 15 int step = 0; 16 17 public Explode(int x, int y, TankClient tc) { 18 this.x = x; 19 this.y = y; 20 this.tc = tc; 21 } 22 23 public void draw(Graphics g) { 24 if(!live) { 25 //爆炸发生,将相应直径的爆炸圆从集合explodes中去除 26 tc.explodes.remove(this); 27 return; 28 } 29 30 if(step == diameter.length) { 31 live = false; 32 step = 0; 33 return; 34 } 35 36 Color c = g.getColor(); 37 g.setColor(Color.ORANGE); 38 39 //把不同的圆画出来 40 g.fillOval(x, y, diameter[step], diameter[step]); 41 g.setColor(c); 42 43 step ++; 44 } 45 }
TankClient:

1 import java.awt.*; 2 import java.awt.event.*; 3 import java.util.ArrayList; 4 import java.util.List; 5 6 public class TankClient extends Frame { 7 // 设置成常量,方便以后的改动 8 public static final int GAME_WIDTH = 800; 9 public static final int GAME_HEIGHT = 600; 10 11 // 将当前的TankClient对象传递给myTank; 12 // 目的是方便我们在Tank这个类中访问m(炮弹对象)这个成员变量 13 // 其实就是在Tank类中持有TankClient类对象的一个引用 14 15 //我们这里new我们自己的坦克,用下面的方式 16 Tank myTank = new Tank(50, 50, true,this); 17 18 //新建敌方坦克 19 Tank enemyTank=new Tank(100,100,false,this); 20 //定义爆炸 21 Explode e=new Explode(70, 70, this); 22 //定义一个集合,多个爆炸点 23 List<Explode> explodes=new ArrayList<Explode>(); 24 25 //使用容器装炮弹 26 List<Missile> missiles=new ArrayList<Missile>(); 27 28 // 定义虚拟图片,方便后期的一次性显示 29 Image offScreenImage = null; 30 31 32 public void paint(Graphics g) { 33 //记录屏幕上的子弹数目 34 g.drawString("missiles count:" + missiles.size(), 10, 50); 35
以上是关于坦克大战(版本1.7-版本2.4)的主要内容,如果未能解决你的问题,请参考以下文章