坦克大战(版本2.5-版本2.9)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了坦克大战(版本2.5-版本2.9)相关的知识,希望对你有一定的参考价值。
版本2.5
功能:添加“血块”
步骤:
1)添加blood类
2)添加必要的方法:eat方法等
3)让blood对象固定轨迹运动, 并在一定时间后消失
具体代码实现:
新增的blood类:
1 import java.awt.Color; 2 import java.awt.Graphics; 3 import java.awt.Rectangle; 4 5 //模拟血块,坦克吃了可以补血 6 public class Blood { 7 int x, y, w, h; 8 9 TankClient tc; 10 11 private boolean live = true; 12 13 public void setLive(boolean live) { 14 this.live = live; 15 } 16 17 public boolean isLive() { 18 return live; 19 } 20 21 int step = 0; 22 23 // 定义血块的位置,是不断变化的 24 private int position[][] = { { 350, 300 }, { 360, 300 }, { 375, 275 }, 25 { 400, 200 }, { 360, 270 }, { 365, 290 }, { 340, 280 } }; 26 27 public Blood() { 28 x = position[0][0]; 29 y = position[0][1]; 30 w = h = 15; 31 } 32 33 //血块的draw方法 34 public void draw(Graphics g) { 35 if (!live) { 36 return; 37 } 38 Color c = g.getColor(); 39 g.setColor(Color.MAGENTA); 40 g.fillRect(x, y, w, h); 41 g.setColor(c); 42 move(); 43 } 44 45 private void move() { 46 step++; 47 if (step == position.length) { 48 step = 0; 49 } 50 x = position[step][0]; 51 y = position[step][1]; 52 } 53 54 public Rectangle getRect() { 55 return new Rectangle(x, y, w, h); 56 } 57 }
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 }
Missile:
1 import java.awt.Color; 2 import java.awt.Graphics; 3 import java.awt.Rectangle; 4 import java.util.List; 5 6 public class Missile { 7 // 炮弹的移动速度,不要比坦克的移动速度慢,不然你看到的是满屏的坦克追着炮弹跑 8 public static final int XSPEED = 10; 9 public static final int YSPEED = 10; 10 // 将子弹的高度和宽度设置为常量 11 public static final int WIDTH = 10; 12 public static final int HEIGHT = 10; 13 // 炮弹自己的三个属性 14 int x; 15 int y; 16 Tank.Direction dir; 17 18 // 同一阵营的的坦克发出的子弹不能伤害自己人 19 private boolean good; 20 // 定义一个布尔类型的变量来判断炮弹是否已经消亡 21 private boolean live = true; 22 // 我们在Missile类中也持有一个TankClient的引用 23 // 在炮弹出界的时候就可以从装炮弹的missiles集合中去除该炮弹,不再对其重画 24 private TankClient tc; 25 26 public boolean isLive() { 27 return live; 28 } 29 30 public Missile(int x, int y, Tank.Direction dir) { 31 this.x = x; 32 this.y = y; 33 this.dir = dir; 34 } 35 36 public Missile(int x, int y, boolean good, Tank.Direction dir, TankClient tc) { 37 this(x, y, dir); 38 this.good = good; 39 this.tc = tc; 40 } 41 42 // 炮弹自己的draw方法 43 public void draw(Graphics g) { 44 // 炮弹消亡就不需要再画出来了 45 if (!live) { 46 tc.missiles.remove(this); 47 return; 48 } 49 Color c = g.getColor(); 50 g.setColor(Color.BLACK); 51 // 炮弹形状不要比坦克大,这里设置成10,10; 52 g.fillOval(x, y, WIDTH, HEIGHT); 53 g.setColor(c); 54 move(); 55 } 56 57 public void move() { 58 switch (dir) { 59 case L: 60 x -= XSPEED; 61 break; 62 case R: 63 x += XSPEED; 64 break; 65 case U: 66 y -= YSPEED; 67 break; 68 case D: 69 y += YSPEED; 70 break; 71 case LU: 72 x -= XSPEED; 73 y -= YSPEED; 74 break; 75 case LD: 76 x -= XSPEED; 77 y += YSPEED; 78 break; 79 case RU: 80 x += XSPEED; 81 y -= YSPEED; 82 break; 83 case RD: 84 x += XSPEED; 85 y += YSPEED; 86 break; 87 // 炮弹就没有STOP这个枚举类型的值了 88 /* 89 * case STOP: break; 90 */ 91 } 92 // 判断炮弹出边界则消亡 93 // 注意x,y只有正数值,x向右递增,y向下递增 94 if (x < 0 || y < 0 || x > TankClient.GAME_WIDTH 95 || y > TankClient.GAME_HEIGHT) { 96 live = false; 97 } 98 } 99 100 public boolean hitTank(Tank t) { 101 // 炮弹的方框和坦克的方框碰在一起了并且坦克是存活着的,后面的判断我们是一伙的我就不打你了 102 if (this.live && this.getRect().intersects(t.getRect()) && t.isLive() 103 && this.good != t.isGood()) { 104 if (t.isGood()) { 105 t.setLife(t.getLife() - 20); 106 if (t.getLife() <= 0) { 107 t.setLive(false); 108 } 109 } else { 110 t.setLive(false); 111 } 112 this.live = false; 113 114 // 炮弹击中坦克,发生爆炸 115 Explode e = new Explode(x, y, tc); 116 tc.explodes.add(e); 117 return true; 118 } 119 return false; 120 } 121 122 // 碰撞检测类Rectangle 123 // 拿到包围在炮弹周围的小方块 124 public Rectangle getRect() { 125 return new Rectangle(x, y, WIDTH, HEIGHT); 126 } 127 128 // 添加hitTanks方法 129 public boolean hitTanks(List<Tank> tanks) { 130 for (int i = 0; i < tanks.size(); i++) { 131 if (hitTank(tanks.get(i))) { 132 return true; 133 } 134 } 135 return false; 136 137 } 138 139 public boolean hitWall(Wall w) { 140 if (this.live && this.getRect().intersects(w.getRect())) { 141 this.live = false; 142 return true; 143 } 144 return false; 145 } 146 }
Wall:
1 import java.awt.Graphics; 2 import java.awt.Rectangle; 3 4 //墙 5 public class Wall { 6 int x, y, w, h; 7 TankClient tc; 8 9 public Wall(int x, int y, int w, int h, TankClient tc) { 10 super(); 11 this.x = x; 12 this.y = y; 13 this.w = w; 14 this.h = h; 15 this.tc = tc; 16 } 17 18 public void draw(Graphics g) { 19 g.fillRect(x, y, w, h); 20 } 21 22 // 碰撞检测 23 public Rectangle getRect() { 24 return new Rectangle(x, y, w, h); 25 } 26 }
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 BloodBar bb = new BloodBar(); 18 // 坦克的生命值 19 private int life = 100; 20 21 public int getLife() { 22 return life; 23 } 24 25 public void setLife(int life) { 26 this.life = life; 27 } 28 29 public boolean isGood() { 30 return good; 31 } 32 33 public void setGood(boolean good) { 34 this.good = good; 35 } 36 37 // 判断坦克生死的变量 38 private boolean live = true; 39 40 public boolean isLive() { 41 return live; 42 } 43 44 public void setLive(boolean live) { 45 this.live = live; 46 } 47 48 private int x; 49 private int y; 50 51 // 记录坦克上一步的位置,防止坦克一碰到wall,就会依附在上面 52 private int oldx; 53 private int oldy; 54 55 // 随机数产生器,方便敌方坦克可以任意移动 56 private static Random r = new Random(); 57 // 添加记录按键状态的布尔量 58 private boolean bL = false; 59 private boolean bR = false; 60 private boolean bU = false; 61 private boolean bD = false; 62 63 // 添加代表方向的量(使用枚举) 64 enum Direction { 65 L, R, U, D, LU, LD, RU, RD, STOP 66 }; 67 68 private Direction dir = Direction.STOP; 69 70 // 定义炮筒的方向,我们想办法将炮筒的方法调整成和坦克移动方向一致; 71 // 我们这里会用一条直线来表示炮筒:模拟炮筒 72 // 我们要根据炮筒的方向画直线表示炮筒 73 Direction ptDir = Direction.D; 74 75 // 为了让敌方坦克在一定方向运动移动时间再自动变换方向 76 private int step = r.nextInt(12) + 3; 77 78 // 更改构造函数 79 public Tank(int x, int y, boolean good) { 80 this.x = x; 81 this.y = y; 82 this.oldx = x; 83 this.oldy = y; 84 this.good = good; 85 } 86 87 // 这个位置的构造函数也相应进行了更改 88 public Tank(int x, int y, boolean good, Direction dir, TankClient tc) { 89 // 调用那个有两个参数的构造方法 90 this(x, y, good); 91 this.dir = dir; 92 // 在这个位置初始化tc 93 this.tc = tc; 94 } 95 96 // Tank对象的draw方法 97 public void draw(Graphics g) { 98 if (!live) { 99 // 如果死亡的是敌方坦克,在tanks集合中去除该坦克 100 if (!good) { 101 tc.tanks.remove(this); 102 } 103 // 如果是我方坦克,直接返回 104 return; 105 } 106 Color c = g.getColor(); 107 if (good) { 108 g.setColor(Color.YELLOW); 109 } else { 110 g.setColor(Color.PINK); 111 } 112 g.fillOval(x, y, WIDTH, HEIGHT); 113 g.setColor(c); 114 // 判断一下,我方坦克才有血条显示 115 if (good) { 116 117 bb.draw(g); 118 } 119 // 根据炮筒的方向画直线来表示我们坦克的炮筒 120 switch (ptDir) { 121 case L: 122 // 画直线:四个参数分别代表:坦克中心点的坐标 直线的另一头的的坐标 123 g.drawLine(x + Tank.WIDTH / 2, y + Tank.HEIGHT / 2, x, y 124 + Tank.HEIGHT / 2); 125 break; 126 case R: 127 g.drawLine(x + Tank.WIDTH / 2, y + Tank.HEIGHT / 2, x + Tank.WIDTH, 128 y + Tank.HEIGHT / 2); 129 130 break; 131 case U: 132 g.drawLine(x + Tank.WIDTH / 2, y + Tank.HEIGHT / 2, x + Tank.WIDTH 133 / 2, y); 134 135 break; 136 case D: 137 g.drawLine(x + Tank.WIDTH / 2, y + Tank.HEIGHT / 2, x + Tank.WIDTH 138 / 2, y + Tank.HEIGHT); 139 140 break; 141 case LU: 142 g.drawLine(x + Tank.WIDTH / 2, y + Tank.HEIGHT / 2, x, y); 143 break; 144 case LD: 145 g.drawLine(x + Tank.WIDTH / 2, y + Tank.HEIGHT / 2, x, y 146 + Tank.HEIGHT); 147 148 break; 149 case RU: 150 g.drawLine(x + Tank.WIDTH / 2, y + Tank.HEIGHT / 2, x + Tank.WIDTH, 151 y); 152 153 break; 154 case RD: 155 g.drawLine(x + Tank.WIDTH / 2, y + Tank.HEIGHT / 2, x + Tank.WIDTH, 156 y + Tank.HEIGHT); 157 158 break; 159 /* 160 * case STOP: break; 161 */ 162 } 163 move(); 164 } 165 166 public void move() { 167 // 记录坦克上一步的位置 168 this.oldx = x; 169 this.oldy = y; 170 switch (dir) { 171 case L: 172 x -= XSPEED; 173 break; 174 case R: 175 x += XSPEED; 176 break; 177 case U: 178 y -= YSPEED; 179 break; 180 case D: 181 y += YSPEED; 182 break; 183 case LU: 184 x -= XSPEED; 185 y -= YSPEED; 186 break; 187 case LD: 188 x -= XSPEED; 189 y += YSPEED; 190 break; 191 case RU: 192 x += XSPEED; 193 y -= YSPEED; 194 break; 195 case RD: 196 x += XSPEED; 197 y += YSPEED; 198 break; 199 200 case STOP: 201 break; 202 } 203 // 如果坦克不是停着的,则将炮筒调整至和坦克移动的方向相同 204 if (this.dir != Direction.STOP) { 205 this.ptDir = this.dir; 206 } 207 if (x < 0) { 208 x = 0; 209 } 210 // 因为我们的游戏
以上是关于坦克大战(版本2.5-版本2.9)的主要内容,如果未能解决你的问题,请参考以下文章