标签:
人生在勤,不索何获。——张衡
本讲内容:坦克大战8.0版(面向对象的思想)
一、解决:防止敌人坦克重叠运动
1、定义一个Vector容器,装所有敌人的坦克(为了得到所有坦克坐标)
2、定义一个方法getEts()可以得到敌人的坦克(为了得到所有坦克坐标)
3、在我的我的面板的构造方法调用getEts()
4、定义一个判断是否碰到了别的敌人的坦克的方法isTouchOtherEnemy()
5、在设置敌人坦克随机走动那调用isTouchOtherEnemy()
二、解决:我方坦克死亡(即隐身)后,该处被子弹击中不再发生爆炸
1、在敌人的子弹是否击中我方的hitMe()中加入我方坦克有生命时才调用
三、同一个包下建二个文件分别为:MyTankGame、Members(负责其它成员譬如:制造坦克、子弹等)
MyTankGame类
package a; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.*; /** * 功能:坦克游戏的8.0版本 * 1:画出坦克 * 2:实现我方坦克可以上下左右移动 * 3:可以發射子彈,子彈可以連發(最多可以发5颗) * 4:画出敌人的坦克 * 5:当我方坦克击中敌人坦克时,敌人的坦克就消失 * 6:消失时显示爆炸效果图 * 7:让敌人的坦克也可以自由随机的上下左右移动并在规定范围内移动。 * 8:让敌人坦克可以发射子弹 * 9:当敌人坦克打到我方会爆炸 * 10:防止敌人坦克重叠运动和我方坦克死亡(即隐身)后,该处被子弹击中不再发生爆炸 */ public class MyTankGame extends JFrame { MyPanel mp = null; public static void main(String[] args) { MyTankGame mtg = new MyTankGame(); } // 构造函数 public MyTankGame() { mp = new MyPanel(); this.addKeyListener(mp);// 注册监听 // 启东mp线程 Thread t = new Thread(mp); t.start(); this.add(mp); // 设置窗体属性 this.setTitle("坦克大战7.0版—小劲"); this.setLocation(300, 300); this.setSize(500, 400); this.setVisible(true); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } } // 我的面板 class MyPanel extends JPanel implements KeyListener, Runnable { // 定义一个坦克 Tank tank = null; // 定义一个我的坦克 MyTank myTank = null; // 定义敌人的坦克 Vector<EnemyTank> ets = new Vector<EnemyTank>(); // 定义炸弹的集合 (在击中中创建然后在Panel画出) Vector<Bomb> bombs = new Vector<Bomb>(); int enSize = 10; // 定义三张爆炸需要的图片,组成一颗炸弹 Image image1 = null; Image image2 = null; Image image3 = null; // 构造函数 public MyPanel() { // 我的坦克 myTank = new MyTank(150, 250); // 初始化敌人的坦克 for (int i = 0; i < enSize; i++) { // 创建一个敌人坦克 EnemyTank et = new EnemyTank((i + 1) * 50, 0); et.setColor(0); et.setDirect(2); //将MyPanel的敌人的坦克容器交给该敌人的坦克 et.getEts(ets); // 启东敌人的坦克 Thread t = new Thread(et); t.start(); // 加入到面板中 ets.add(et); } // 初始化图片 image1 = Toolkit.getDefaultToolkit().getImage( Panel.class.getResource("/bzxg1.gif")); image2 = Toolkit.getDefaultToolkit().getImage( Panel.class.getResource("/bzxg2.gif")); image3 = Toolkit.getDefaultToolkit().getImage( Panel.class.getResource("/bzxg3.gif")); } public void paint(Graphics g) { super.paint(g); /* * 因为当打到第一辆坦克的时候才创建一个炸弹,第一次爆炸的时候图还没加载(加载图片内存太大)。 所以第一次就不能正常显示了, * 所以才会出现第一辆坦克没有爆炸效果,因为在击中第一辆坦克之前, * vector里并没有放入炸弹。想要第一辆坦克有爆炸效果,那么在击中第一辆坦克之前就创建一颗炸弹 */ g.drawImage(image1, 100, 100, 30, 30, this); g.drawImage(image2, 100, 100, 30, 30, this); g.drawImage(image3, 100, 100, 30, 30, this); // 设置图像的背景色 g.fillRect(0, 0, 600, 400); // 畫出自己的坦克 if(myTank.isLive){ this.drawTank(myTank.getX(), myTank.getY(), g, myTank.direct, 1); } // 画出敌人的坦克 for (int i = 0; i < ets.size(); i++) { EnemyTank et = ets.get(i); if (et.isLive) { this.drawTank(ets.get(i).getX(), ets.get(i).getY(), g, ets.get( i).getDirect(), 0); // 画出敌人的子弹 for (int j = 0; j < et.ss.size(); j++) { // 取出子弹 Shot enemyShot = et.ss.get(j); if (enemyShot.isLive) { g.draw3DRect(enemyShot.x, enemyShot.y, 1, 1, false); } else { // 如果敌人的坦克死亡就从Vector中移除子弹 et.ss.remove(enemyShot); } } } } // 画出炸弹 for (int i = 0; i < bombs.size(); i++) { // 取出炸弹 Bomb b = bombs.get(i); if (b.life > 6) { g.drawImage(image1, b.x, b.y, 30, 30, this); // this表示就在当前面板上绘制 } else if (b.life > 4) { g.drawImage(image2, b.x, b.y, 30, 30, this); } else { g.drawImage(image3, b.x, b.y, 30, 30, this); } // 减小b的生命值 b.lifeDown(); // 如果炸弹的生命值为0,就把炸弹bombs去掉 if (b.life == 0) { bombs.remove(b); } } // 我的坦克从ss中取出每一颗子弹并画出 for (int i = 0; i < myTank.ss.size(); i++) { Shot myShot = myTank.ss.get(i); // 画子弹,畫出一顆子彈 if (myShot != null && myTank.s.isLive == true) { g.draw3DRect(myShot.x, myShot.y, 1, 1, false); } // 删除符合条件的子弹 if (myShot.isLive == false) { // 从ss中删掉该子弹 myTank.ss.remove(myShot);// 不要写i } } } //判断我的子弹是否击中敌人的坦克 public void hitEnemyTank(){ // 判断是否击中敌人的坦克 for (int i = 0; i < myTank.ss.size(); i++) { // 取出子弹 Shot myShot = myTank.ss.get(i); // 判断子弹是否有效 if (myShot.isLive) { // 取出每一个敌人的坦克与之匹配, for (int j = 0; j < ets.size(); j++) { // 取出坦克 EnemyTank et = ets.get(j); if (et.isLive) { this.hitTank(myShot, et); } } } } } //敌人的子弹是否击中我方 public void hitMe(){ //取出每一个敌人的坦克 for(int i=0;i<this.ets.size();i++){ //取出坦克 EnemyTank et=ets.get(i); //取出每一颗子弹 for(int j=0;j<et.ss.size();j++){ //取出子弹 Shot enemyShot=et.ss.get(j); if(myTank.isLive){ this.hitTank(enemyShot, myTank); } } } } // 写一个函数专门判断子弹对否击中敌人的坦克(考虑在什么地方调用函数?在Panel中run()) public void hitTank(Shot s, Tank et) { // 判断该坦克的方向 switch (et.direct) { // 如果敌人的坦克的方向是向上或者向下 case 0: case 2: if (s.x > et.x && s.x < et.x + 20 && s.y > et.y && s.y < et.y + 30) { // 击中 // 子弹死亡 s.isLive = false; // 敌人坦克死亡 et.isLive=false; // 创建一颗炸弹,放入到Vcetor Bomb b = new Bomb(et.x, et.y); // 放入到Vector bombs.add(b); } case 1: case 3: if (s.x > et.x && s.x < et.x + 30 && s.y > et.y && s.y < et.y + 20) { // 击中 // 子弹死亡 s.isLive = false; // 敌人坦克死亡 et.isLive = false; // 创建一颗炸弹,放入到Vcetor Bomb b = new Bomb(et.x, et.y); // 放入到Vector bombs.add(b); } } } // 绘制坦克的函数 public void drawTank(int x, int y, Graphics g, int direct, int type) { switch (type) { case 0: g.setColor(Color.cyan); break; case 1: g.setColor(Color.yellow); break; } // 判断方向 switch (direct) { case 0: // 向上 // 画出我的坦克(到时候会封装成一个函数) // 1:绘制左边的矩形 g.fill3DRect(x, y, 5, 30, false); // 2:绘制右边的矩形 g.fill3DRect(x + 15, y, 5, 30, false); // 3:绘制中间矩形 g.fill3DRect(x + 5, y + 5, 10, 20, false); // 4:画出圆形 g.fillOval(x + 5, y + 10, 10, 10); // 5:绘制炮筒 g.drawLine(x + 10, y + 15, x + 10, y); break; case 1: // 向右 // 绘制上面的矩形 g.fill3DRect(x, y, 30, 5, false); // 绘制下面的矩形 g.fill3DRect(x, y + 15, 30, 5, false); // 绘制中间的矩形 g.fill3DRect(x + 5, y + 5, 20, 10, false); // 画出圆形 g.fillOval(x + 10, y + 5, 10, 10); // 绘制炮筒 g.drawLine(x + 15, y + 10, x + 30, y + 10); break; case 2: // 向下 // 1:绘制左边的矩形 g.fill3DRect(x, y, 5, 30, false); // 2:绘制右边的矩形 g.fill3DRect(x + 15, y, 5, 30, false); // 3:绘制中间矩形 g.fill3DRect(x + 5, y + 5, 10, 20, false); // 4:画出圆形 g.fillOval(x + 5, y + 10, 10, 10); // 5:绘制炮筒 g.drawLine(x + 10, y + 15, x + 10, y + 30); break; case 3: // 向左 // 绘制上面的矩形 g.fill3DRect(x, y, 30, 5, false); // 绘制下面的矩形 g.fill3DRect(x, y + 15, 30, 5, false); // 绘制中间的矩形 g.fill3DRect(x + 5, y + 5, 20, 10, false); // 画出圆形 g.fillOval(x + 10, y + 5, 10, 10); // 绘制炮筒 g.drawLine(x + 15, y + 10, x - 3, y + 10); break; } } // 键按下处理 a s w d public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_W) { // 向上 前进 this.myTank.setDirect(0); this.myTank.moveUp(); } else if (e.getKeyCode() == KeyEvent.VK_D) { // 向右前进 this.myTank.setDirect(1); this.myTank.moveRight(); } else if (e.getKeyCode() == KeyEvent.VK_S) { // 向下前进 this.myTank.setDirect(2); this.myTank.moveDown(); } else if (e.getKeyCode() == KeyEvent.VK_A) { // 向左前进 this.myTank.setDirect(3); this.myTank.moveLeft(); } if (e.getKeyCode() == KeyEvent.VK_J) {// 不用else if是為了防止走動時發不了子彈 // 判断玩家是否按下J键 開火 if (this.myTank.ss.size() < 5) {// 使最多发5颗子弹 this.myTank.shotEnemy(); } } // 重新绘制窗口 this.repaint(); } public void keyReleased(KeyEvent e) { } public void keyTyped(KeyEvent e) { } public void run() { // 每隔100毫秒重新绘制子弹 while (true) { try { Thread.sleep(100); } catch (Exception e) { e.printStackTrace(); } this.hitEnemyTank(); //调用 判断敌人的子弹是否击中我的方法 this.hitMe(); // 重新绘制窗口 this.repaint(); } } }
package a; import java.util.Vector; //炸弹类 class Bomb {// 炸弹不会移动不用实现线程 // 定义炸弹的坐标 int x, y; // 炸弹的生命 int life = 9; boolean isLive = true; public Bomb(int x, int y) { this.x = x; this.y = y; } // 减少生命值 public void lifeDown() { if (life > 0) { life--; } else { this.isLive = false; } } } // 子弹类 class Shot implements Runnable {// 创建线程使子弹跑起来 //子弹在哪创建就在启动线程 int x; int y; int direct; int speed = 5; // 是否还活着 boolean isLive = true; public Shot(int x, int y, int direct) { this.x = x; this.y = y; this.direct = direct; } public void run() { while (true) { try { Thread.sleep(50); } catch (Exception e) { // TODO: handle exception } switch (direct) { case 0: // 子弹向上 y -= speed; break; case 1: x += speed; break; case 2: y += speed; break; case 3: x -= speed; break; } // System.out.println("子弹的坐标x="+x+"子弹的y坐标y="+y); // 子弹何时死亡 // 判断该子弹是否碰到边缘 if (x < 0 || x > 500 || y < 0 || y > 400) { this.isLive = false; break; } } } } // 定义一个坦克类 class Tank { // 表示坦克的横坐标x 和纵坐标y int x = 0; int y = 0; // 定义方向 0表示向上 1表示右, 2表示下 3表示左 int direct = 0; // 坦克颜色 int color = 0; // 坦克速度 int speed = 5; boolean isLive = true; public Tank(int x, int y) { this.x = x; this.y = y; } public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; } public int getDirect() { return direct; } public void setDirect(int direct) { this.direct = direct; } public int getSpeed() { return speed; } public void setSpeed(int speed) { this.speed = speed; } public int getColor() { return color; } public void setColor(int color) { this.color = color; } } // 敌人的坦克 class EnemyTank extends Tank implements Runnable { int times; // 子弹 Shot s = null; // 定义子弹容器使可以連發 Vector<Shot> ss = new Vector<Shot>(); // 定义一个容器,可以访问到MyPanel 上所有的坦克 Vector<EnemyTank> ets = new Vector<EnemyTank>(); public EnemyTank(int x, int y) { super(x, y); } // 得到MyPanel中的敌人的坦克容器(在哪调用) public void getEts(Vector<EnemyTank> ets) { this.ets = ets; } // 判断是否碰到了别的敌人的坦克 public boolean isTouchOtherEnemy() { boolean b = false; switch (this.direct) { case 0: // 我的坦克向上 // 取出所有的敌人的坦克 for (int i = 0; i < ets.size(); i++) { // 取出第一个坦克 EnemyTank et = ets.get(i); // 如果不是自己 if (et != this) { // 如果敌人的方向是向上或者向下 if (et.direct == 0 || et.direct == 2) { if (this.x >= et.x && this.x <= et.x + 20 && this.y >= y && this.y <= et.y + 30) { return true; } if (this.x + 20 >= et.x && this.x + 20 <= et.x + 20 && this.y >= et.y && this.y <= et.y + 30) { return true; } } if (et.direct == 3 || et.direct == 1) { if (this.x >= et.x && this.x <= et.x + 20 && this.y >= y && this.y <= et.y + 20) { return true; } if (this.x + 20 >= et.x && this.x + 20 <= et.x + 30 && this.y >= et.y && this.y <= et.y + 20) { return true; } } } } break; case 1: // 我的坦克向右 // 取出所有的敌人的坦克 for (int i = 0; i < ets.size(); i++) { // 取出第一个坦克 EnemyTank et = ets.get(i); // 如果不是自己 if (et != this) { // 如果敌人的方向是向上或者向下 if (et.direct == 0 || et.direct == 2) { if (this.x + 30 >= et.x && this.x + 30 <= et.x + 20 && this.y >= y && this.y <= et.y + 30) { return true; } if (this.x + 30 >= et.x && this.x + 30 <= et.x + 20 && this.y + 20 >= et.y && this.y + 20 <= et.y + 30) { return true; } } if (et.direct == 3 || et.direct == 1) { if (this.x + 30 >= et.x && this.x + 30 <= et.x + 20 && this.y >= y && this.y <= et.y + 20) { return true; } if (this.x + 30 >= et.x && this.x + 30 <= et.x + 30 && this.y + 20 >= et.y && this.y + 20 <= et.y + 20) { return true; } } } } break; case 2: // 我的坦克向下 // 取出所有的敌人的坦克 for (int i = 0; i < ets.size(); i++) { // 取出第一个坦克 EnemyTank et = ets.get(i); // 如果不是自己 if (et != this) { // 如果敌人的方向是向上或者向下 if (et.direct == 0 || et.direct == 2) { if (this.x >= et.x && this.x <= et.x + 20 && this.y + 30 >= y && this.y + 30 <= et.y + 30) { return true; } if (this.x + 20 >= et.x && this.x <= et.x + 20 && this.y + 30 >= et.y && this.y + 30 <= et.y + 30) { return true; } } if (et.direct == 3 || et.direct == 1) { if (this.x >= et.x && this.x <= et.x + 20 && this.y + 30 >= y && this.y + 30 <= et.y + 20) { return true; } if (this.x + 20 >= et.x && this.x + 20 <= et.x + 30 && this.y + 30 >= et.y && this.y + 30 <= et.y + 20) { return true; } } } } break; case 3: // 我的坦克向左 // 取出所有的敌人的坦克 for (int i = 0; i < ets.size(); i++) { // 取出第一个坦克 EnemyTank et = ets.get(i); // 如果不是自己 if (et != this) { // 如果敌人的方向是向上或者向下 if (et.direct == 0 || et.direct == 2) { // 我的上一点 if (this.x >= et.x && this.x <= et.x + 20 && this.y >= y && this.y <= et.y + 30) { return true; } // 我的下一点 if (this.x >= et.x && this.x <= et.x + 20 && this.y + 20 >= et.y && this.y + 20 <= et.y + 30) { return true; } } if (et.direct == 3 || et.direct == 1) { if (this.x + 20 >= et.x && this.x + 20 <= et.x + 20 && this.y >= y && this.y <= et.y + 20) { return true; } if (this.x >= et.x && this.x <= et.x + 30 && this.y + 20 >= et.y && this.y + 20 <= et.y + 20) { return true; } } } } break; } return b; } public void run() { while (true) { switch (this.direct) { case 0:// 说明坦克正在向上移动 for (int i = 0; i < 30; i++) { if (y > 0 && !this.isTouchOtherEnemy()) {// 在规定范围行动 y -= speed; } try { Thread.sleep(50); } catch (Exception e) { e.printStackTrace(); } } break; case 1:// 说明坦克正在向右移动 for (int i = 0; i < 30; i++) { if (x < 440 && !this.isTouchOtherEnemy()) {// 注意坐标是左上边 x += speed; } try { Thread.sleep(50); } catch (Exception e) { e.printStackTrace(); } } break; case 2:// 说明坦克正在向下移动 for (int i = 0; i < 30; i++) { if (y < 340 && this.isTouchOtherEnemy()) { y += speed; } try { Thread.sleep(50); } catch (Exception e) { e.printStackTrace(); } } break; case 3:// 说明坦克正在向左移动 for (int i = 0; i < 30; i++) { if (x > 0 && !this.isTouchOtherEnemy()) { x -= speed; } try { Thread.sleep(50); } catch (Exception e) { e.printStackTrace(); } } break; } this.times++; // 判断是否需要给坦克加入新的子弹 if (times % 2 == 0) {// 使3秒添加一次(因为sleep1.5秒) if (isLive) { if (ss.size() < 5) { // 每辆每3秒添加子弹 switch (direct) { case 0: s = new Shot(x + 10, y, 0); ss.add(s); break; case 1: s = new Shot(x + 30, y + 10, 1); ss.add(s); break; case 2: s = new Shot(x + 10, y + 30, 2); ss.add(s); break; case 3: s = new Shot(x, y + 10, 3); ss.add(s); break; } // 启动子弹 Thread t = new Thread(s); t.start(); } } } // 让坦克随机产生一个新的方向 this.direct = (int) (Math.random() * 4); // 判断敌人的坦克是否死亡 if (this.isLive == false) { // 让坦克死亡后推出线程 break; } } } } // 我的坦克 class MyTank extends Tank { // 子弹 Shot s = null; // 定义子弹容器使可以連發 Vector<Shot> ss = new Vector<Shot>(); public MyTank(int x, int y) { super(x, y); } // 开火 public void shotEnemy() {// 子弹在哪创建就在启动线程 switch (this.direct) { case 0: // 創建一顆子彈 s = new Shot(x + 10, y, 0); ss.add(s);// 放入子弹容器 然后在JPanel畫出來 break; case 1: s = new Shot(x + 30, y + 10, 1); ss.add(s); break; case 2: s = new Shot(x + 10, y + 30, 2); ss.add(s); break; case 3: s = new Shot(x, y + 10, 3); ss.add(s); break; } // 创建线程并启动 Thread t = new Thread(s); t.start(); } // 坦克向上移动 public void moveUp() { y -= speed; } // 坦克向右移动 public void moveRight() { x += speed; } // 向下移动 public void moveDown() { y += speed; } // 向左边移动 public void moveLeft() { x -= speed; } }
本讲就到这里,Take your time and enjoy it
标签:
原文地址:http://blog.csdn.net/liguojin1230/article/details/42560967