首页 > 代码库 > 坦克大战系列11.0版
坦克大战系列11.0版
好学而不勤问非真好学者。
本讲内容:坦克大战11.0版(面向对象的思想)
一、解决:播放声音
1、定义一个播放声音的类AePlayWave
2、在面板构造方法启动声音
二、同一个包下建二个文件分别为:MyTankGame、Members(负责其它成员譬如:制造坦克、子弹等)
MyTankGame类
/** * 功能:坦克游戏的8.0版本 1:画出坦克 * 2:实现我方坦克可以上下左右移动 * 3:可以發射子彈,子彈可以連發(最多可以发5颗) * 4:画出敌人的坦克 * 5:当我方坦克击中敌人坦克时,敌人的坦克就消失 * 6:消失时显示爆炸效果图 * 7:让敌人的坦克也可以自由随机的上下左右移动并在规定范围内移动。 * 8:让敌人坦克可以发射子弹 * 9:当敌人坦克打到我方会爆炸 * 10:防止敌人坦克重叠运动和我方坦克死亡(即隐身)后,该处被子弹击中不再发生爆炸 * 11:做一个空的Panel 主要用于提示 字体闪烁 * 12:做一个菜单栏,包括 开始新游戏(N)、退出游戏(E) * 13:画出提示坦克数量以及我一共打多少辆坦克 * 14:存盘退出游戏,可以记录当时的地敌人,并可以恢复 */ public class MyTankGame extends JFrame implements ActionListener { // 定义一个开始面板 MyStartPanel startmp = null; MyPanel mp = null; // 做出我需要的菜单 JMenuBar cd = null; JMenu cd1, cd2, cd3; JMenuItem ycd1, ycd2,ycd3,ycd4; public static void main(String[] args) { MyTankGame mtg = new MyTankGame(); } // 构造函数 public MyTankGame() { // 创建菜单以及菜单选项 cd = new JMenuBar(); cd1 = new JMenu("游戏"); cd2 = new JMenu("帮助"); cd3 = new JMenu("设置"); ycd1 = new JMenuItem("开始新游戏(N)"); ycd1.setMnemonic('N'); ycd2 = new JMenuItem("退出游戏(E)"); ycd2.setMnemonic('E'); ycd3 = new JMenuItem("存盘退出游戏(C)"); ycd3.setMnemonic('C'); ycd4 = new JMenuItem("继续上局游戏(S)"); ycd4.setMnemonic('S'); // 注册监听 ycd1.addActionListener(this); ycd1.setActionCommand("start"); ycd2.addActionListener(this); ycd2.setActionCommand("exit"); ycd3.addActionListener(this); ycd3.setActionCommand("saveExit"); ycd4.addActionListener(this); ycd4.setActionCommand("conGame"); cd1.add(ycd1); cd1.add(ycd2); cd1.add(ycd3); cd1.add(ycd4); cd.add(cd1); cd.add(cd2); cd.add(cd3); startmp = new MyStartPanel(); this.setJMenuBar(cd); this.add(startmp); // 启动startmp线程 Thread t = new Thread(startmp); t.start(); // 设置窗体属性 this.setTitle("坦克大战10.0版—小劲"); this.setLocation(300, 300); this.setSize(600, 500); this.setVisible(true); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } public void actionPerformed(ActionEvent e) { if (e.getActionCommand().equals("start")) { mp = new MyPanel("newGame"); this.addKeyListener(mp);// 注册监听 // 启东mp线程 Thread t = new Thread(mp); t.start(); // 删掉旧的面板msp this.remove(startmp); this.add(mp); // 显示刷新JFrame this.setVisible(true); } else if (e.getActionCommand().equals("exit")) { //用户点击了退出系统的菜单 保存击毁敌人坦克数量 Recorder.keepRecording(); System.exit(0); } else if(e.getActionCommand().equals("saveExit")){ System.out.println("22"); //存盘退出保存敌人的数量和敌人的坐标 Recorder rd=new Recorder(); rd.setEts(mp.ets);//知道外面的世界 rd.keeprRecAndEnemyTank(); System.exit(0); }else if(e.getActionCommand().equals("conGame")){ mp = new MyPanel("con"); this.addKeyListener(mp);// 注册监听 // 启东mp线程 Thread t = new Thread(mp); t.start(); // 删掉旧的面板msp this.remove(startmp); this.add(mp); // 显示刷新JFrame this.setVisible(true); } } } // 提示的面板 class MyStartPanel extends JPanel implements Runnable { int times = 0; public void paint(Graphics g) { super.paint(g); g.fillRect(0, 0, 400, 300); // 提示信息 if (times % 2 == 0) { // 设置字体颜色 g.setColor(Color.yellow); // 设置字体 Font myFont = new Font("华文新魏", Font.BOLD, 50); g.setFont(myFont); g.drawString("stage: 1", 120, 150); } } public void run() { while (true) { try { Thread.sleep(400); } catch (Exception e) { e.printStackTrace(); } times++; // 重画 this.repaint(); } } } // 我的面板 class MyPanel extends JPanel implements KeyListener, Runnable { // 定义一个坦克 Tank tank = null; // 定义一个我的坦克 MyTank myTank = null; // 定义敌人的坦克 Vector<EnemyTank> ets = new Vector<EnemyTank>(); //恢复容器 Vector<Node> nodes=new Vector<Node>(); // 定义炸弹的集合 (在击中中创建然后在Panel画出) Vector<Bomb> bombs = new Vector<Bomb>(); int enSize = 6; // 定义三张爆炸需要的图片,组成一颗炸弹 Image image1 = null; Image image2 = null; Image image3 = null; // 构造函数 public MyPanel(String flag) { // 我的坦克 //恢复记录 Recorder.getRecoring(); myTank = new MyTank(150, 250); // 初始化敌人的坦克 if (flag.equals("newGame")) { 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); } } else { nodes=new Recorder().getNodesAndEnNums(); // 恢复敌人的坦克 for (int i = 0; i < nodes.size(); i++) { Node node=nodes.get(i); // 创建一个敌人坦克 EnemyTank et = new EnemyTank(node.x, node.y); et.setColor(0); et.setDirect(node.direct); // 将MyPanel的敌人的坦克容器交给该敌人的坦克 et.getEts(ets); // 启东敌人的坦克 Thread t = new Thread(et); t.start(); // 加入到面板中 ets.add(et); } } //播放开战声音 AePlayWave apw=new AePlayWave("./tank.wav"); apw.start(); // 初始化图片//ImageIO.read可以解决加载慢问题 try { image1 = ImageIO.read(new File("images/bzxg1.gif")); image2 = ImageIO.read(new File("images/bzxg2.gif")); image3 = ImageIO.read(new File("images/bzxg3.gif")); } catch (Exception e) { e.printStackTrace(); } } // 绘制提示信息 public void showInfo(Graphics g) { // 画出提示信息敌人的坦克 this.drawTank(80, 330, g, 0, 0); // 设置字体的颜色 g.setColor(Color.red); g.drawString(Recorder.getEnNum() + "", 110, 350);// +""转成string // 画出提示信息我的坦克记录信息 this.drawTank(130, 330, g, 0, 1); g.setColor(Color.black); g.drawString(Recorder.getMyLife() + "", 160, 350); // 画出玩家的总成绩提示信息 g.setColor(Color.black); // 设置字体的大小 Font f = new Font("宋体", Font.BOLD, 20); g.setFont(f); g.drawString("您的总成绩", 420, 30); // 画出玩家的总共摧毁敌人多少坦克的记录 this.drawTank(420, 60, g, 0, 0); g.setColor(Color.black); g.drawString(Recorder.getAllEnEum() + "", 460, 80); } public void paint(Graphics g) { super.paint(g); // 画出提示信息 this.showInfo(g); // 设置图像的背景色 g.fillRect(0, 0, 400, 300); // 畫出自己的坦克 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) { if (this.hitTank(myShot, et)) {// 判断并执行 Recorder.reduceEnNum(); Recorder.addEnNumRec(); } } } } } } // 敌人的子弹是否击中我方 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) { if (this.hitTank(enemyShot, myTank)) { Recorder.reduceMyNum(); } } } } } // 写一个函数专门判断子弹对否击中敌人的坦克(考虑在什么地方调用函数?在Panel中run()) public boolean hitTank(Shot s, Tank et) { // 判断是否击中 boolean isShotTank = false; // 判断该坦克的方向 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); isShotTank = true; } break; 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); isShotTank = true; } break; } return isShotTank; } // 绘制坦克的函数 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(); } } }
Members类
//播放声音的类 class AePlayWave extends Thread { private String filename; public AePlayWave(String wavfile) { filename = wavfile; } public void run() { File soundFile = new File(filename); AudioInputStream audioInputStream = null; try { audioInputStream = AudioSystem.getAudioInputStream(soundFile); } catch (Exception e1) { e1.printStackTrace(); return; } AudioFormat format = audioInputStream.getFormat(); SourceDataLine auline = null; DataLine.Info info = new DataLine.Info(SourceDataLine.class, format); try { auline = (SourceDataLine) AudioSystem.getLine(info); auline.open(format); } catch (Exception e) { e.printStackTrace(); return; } auline.start(); int nBytesRead = 0; // 这是缓冲 byte[] abData = http://www.mamicode.com/new byte[512];>
本讲就到这里,Take your time and enjoy it坦克大战系列11.0版
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。