一、简单介绍
这是一个功能相对全的JAVA版坦克大战,界面绘制是通过JAVA的图形化用户界面完成的,包括了菜单界面和游戏界面。其中菜单界面可以供玩家选择重新开始游戏、暂停、继续、是否播放背景音乐、帮助等操作;游戏界面绘制了坦克、河流、草地、鹰碉堡等经典坦克场景,玩家在游戏界面操作坦克开始对战。
本游戏使用的主要技术有Swing编程、面向对象编程、多线程编程。本想用I/O编程实现保存游戏数据,感觉单机版的没必要就没弄。
游戏实现的主要功能有:
1.坦克可以上下左右、以及左上左下右上右下八个方向移动,移动时添加音效
2.坦克可以发子弹(可以连发),发射时添加音效
3.击中对方坦克时,坦克消失,显示爆炸效果;子弹击中鹰碉堡时,游戏结束;子弹击中墙壁时,子弹消失
4.我方坦克吃到血块时,生命值加满
5.移动过程中检测碰撞,包括坦克与坦克,坦克与草地、河流、墙壁等
6.声音处理(开始音乐、背景音乐等)
7.菜单处理(开始游戏、暂停游戏、继续游戏、帮助等)
8.计分(分关、记录成绩)
二、工程目录
三、具体代码
每个文件都有详细的注释,不理解的可以联系作者,这里只贴出Tank.java和TankClient.java的代码,源代码将会在文章最后面贴出来,话不多说,先上代码
Tank.java代码
package com.xiaoli.tank; import java.awt.Color; import java.awt.Graphics; import java.awt.Rectangle; import java.awt.event.KeyEvent; import java.util.List; import java.util.Random; /** * *Title:Tank *Description:坦克类,包括坦克移动、坦克发射炮弹等 *@author xiaoli *@date2017年1月4日 */ public class Tank { //坦克X方向速度,设置游戏难度时可拓展 public static int XSPEED = 5; //坦克Y方向速度,设置游戏难度时可拓展 public static int YSPEED = 5; //坦克宽度 public static final int WIDTH = 30; //坦克高度 public static final int HEIGHT = 30; //坦克是否活着 private boolean live = true; //坦克的生命值 private int life = 100; //持有对TankClient大管家的引用 TankClient tc; //判断是否是我方坦克,默认true private boolean good=true; //用于记录坦克原来的坐标,碰到墙、坦克时方便退一步 private int oldX,oldY; //绘制坦克的左上角坐标 private int x, y; //用于产生随机数 private static Random r = new Random(); //用于控制敌人随机发出子弹 private int step = r.nextInt(30)+10; //判断是否按下方向键 private boolean bL=false, bU=false, bR=false, bD = false; //枚举类型定义了坦克的八个方向,和静止时的方向 enum Direction {L, LU, U, RU, R, RD, D, LD, STOP}; //坦克的方向 private Direction dir = Direction.STOP; //炮筒的方向 private Direction ptDir = Direction.D; //血条 private BloodBar bar = new BloodBar(); //构造方法 public Tank(int x, int y, boolean good) { this.x = x; this.y = y; this.good = good; } //构造方法 public Tank(int x, int y, boolean good, Direction dir,TankClient tc) { this(x, y, good); this.tc = tc; this.oldX=x; this.oldY=y; this.dir=dir; } /** * *@Description:画出坦克 * @param g */ public void draw(Graphics g) { if(!live) { if(!good) { tc.tanks.remove(this); } return; } Color c = g.getColor(); if(good) g.setColor(Color.RED); else g.setColor(Color.BLUE); g.fillOval(x, y, WIDTH, HEIGHT); g.setColor(c); //血条 if(good) bar.draw(g); switch(ptDir) { case L: g.drawLine(x + Tank.WIDTH/2, y + Tank.HEIGHT/2, x, y + Tank.HEIGHT/2); break; case LU: g.drawLine(x + Tank.WIDTH/2, y + Tank.HEIGHT/2, x, y); break; case U: g.drawLine(x + Tank.WIDTH/2, y + Tank.HEIGHT/2, x + Tank.WIDTH/2, y); break; case RU: g.drawLine(x + Tank.WIDTH/2, y + Tank.HEIGHT/2, x + Tank.WIDTH, y); break; case R: g.drawLine(x + Tank.WIDTH/2, y + Tank.HEIGHT/2, x + Tank.WIDTH, y + Tank.HEIGHT/2); break; case RD: g.drawLine(x + Tank.WIDTH/2, y + Tank.HEIGHT/2, x + Tank.WIDTH, y + Tank.HEIGHT); break; case D: g.drawLine(x + Tank.WIDTH/2, y + Tank.HEIGHT/2, x + Tank.WIDTH/2, y + Tank.HEIGHT); break; case LD: g.drawLine(x + Tank.WIDTH/2, y + Tank.HEIGHT/2, x, y + Tank.HEIGHT); break; } move(); } /* * 坦克移动 */ void move() { this.oldX=x; this.oldY=y; switch(dir) { case L: x -= XSPEED; break; case LU: x -= XSPEED; y -= YSPEED; break; case U: y -= YSPEED; break; case RU: x += XSPEED; y -= YSPEED; break; case R: x += XSPEED; break; case RD: x += XSPEED; y += YSPEED; break; case D: y += YSPEED; break; case LD: x -= XSPEED; y += YSPEED; break; case STOP: break; } if(this.dir != Direction.STOP) { this.ptDir = this.dir; } if(!good){ Direction[] dirs = Direction.values(); if(step==0){ step=r.nextInt(30)+10; int rn = r.nextInt(9); this.dir=dirs[rn]; } step--; //敌人发子弹 if(r.nextInt(40)>36){ this.fire(); } } if(x < 0) x = 0; if(y < 55) y = 55; if(x + Tank.WIDTH > TankClient.GAME_WIDTH) x = TankClient.GAME_WIDTH - Tank.WIDTH; if(y + Tank.HEIGHT > TankClient.GAME_HEIGHT) y = TankClient.GAME_HEIGHT - Tank.HEIGHT; } /** * *@Description:用于撞到墙、坦克时返回上一步 */ private void stay(){ x=oldX; y=oldY; } /** * *@Description:按下键时监听 * @param e */ public void keyPressed(KeyEvent e) { int key = e.getKeyCode(); switch(key) { case KeyEvent.VK_R: tc.bloods.clear(); tc.grasses.clear(); tc.rivers.clear(); tc.walls.clear(); tc.missiles.clear(); tc.tanks.clear(); tc.explodes.clear(); //关卡、分数重置 tc.score=0; tc.level=1; //草地 tc.newGrass(); //河流 tc.newRiver(); //墙 tc.newWall(); //当在区域中没有坦克时,就出来坦克 if (tc.tanks.size() == 0) { tc.newTank(); } tc.myTank = new Tank(220, 560, true, Direction.STOP, tc);//设置自己出现的位置 if(!tc.home.isLive()){ tc.home.setLive(true); } tc.dispose(); new TankClient().lauchFrame(); break; case KeyEvent.VK_LEFT : bL = true; break; case KeyEvent.VK_UP : bU = true; break; case KeyEvent.VK_RIGHT : bR = true; break; case KeyEvent.VK_DOWN : bD = true; break; } locateDirection(); } /** * *@Description:定位坦克的方向 */ void locateDirection() { if(bL && !bU && !bR && !bD) dir = Direction.L; else if(bL && bU && !bR && !bD) dir = Direction.LU; else if(!bL && bU && !bR && !bD) dir = Direction.U; else if(!bL && bU && bR && !bD) dir = Direction.RU; else if(!bL && !bU && bR && !bD) dir = Direction.R; else if(!bL && !bU && bR && bD) dir = Direction.RD; else if(!bL && !bU && !bR && bD) dir = Direction.D; else if(bL && !bU && !bR && bD) dir = Direction.LD; else if(!bL && !bU && !bR && !bD) dir = Direction.STOP; } /** * *@Description:松开键时监听 * @param e */ public void keyReleased(KeyEvent e) { int key = e.getKeyCode(); switch(key) { case KeyEvent.VK_K: if(this.good){ if(!this.live){ this.live=true; this.life=100; //复活次数加1 tc.count++; } } break; case KeyEvent.VK_J: superFire(); break; case KeyEvent.VK_CONTROL: fire(); //发射炮弹音效 new Audio(2); break; case KeyEvent.VK_LEFT : bL = false; new Audio(1); break; case KeyEvent.VK_UP : bU = false; new Audio(1); break; case KeyEvent.VK_RIGHT : bR = false; new Audio(1); break; case KeyEvent.VK_DOWN : bD = false; new Audio(1); break; } locateDirection(); } /** * *@Description:坦克开火 * @return 炮弹对象 */ public Missile fire() { if(!live)return null; int x = this.x + Tank.WIDTH/2 - Missile.WIDTH/2; int y = this.y + Tank.HEIGHT/2 - Missile.HEIGHT/2; Missile m = new Missile(x, y, ptDir,this.good, this.tc); tc.missiles.add(m); return m; } /** * *@Description:坦克根据方向开火 * @return 炮弹对象 */ public Missile fire(Direction dir) { if(!live)return null; int x = this.x + Tank.WIDTH/2 - Missile.WIDTH/2; int y = this.y + Tank.HEIGHT/2 - Missile.HEIGHT/2; Missile m = new Missile(x, y, dir,this.good, this.tc); tc.missiles.add(m); return m; } /** * *@Description:超级炮弹,可以向八个方向开火 */ public void superFire(){ Direction[] dirs = Direction.values(); for(int i=0;i<8;i++){ fire(dirs[i]); } } /** * *@Description:判断坦克是否撞墙 * @param 墙对象 * @return 是否撞墙了 */ public boolean CollidesWithWall(Wall w){ if(this.live&&this.getRect().intersects(w.getRect())){ this.stay(); return true; } return false; } public boolean CollidesWithWalls(List<Wall> walls){ for(int i=0;i<walls.size();i++){ Wall w = walls.get(i); if(this.live&&this.getRect().intersects(w.getRect())){ this.stay(); return true; } } return false; } /** * *@Description:判断坦克是否相撞 * @param 多辆坦克 * @return 是否和坦克相撞了 */ public boolean collidesWithTanks(List<Tank> tanks){ for(int i=0;i<tanks.size();i++){ Tank t = tanks.get(i); if(this!=t){ if(this.live&&t.isLive()&&this.getRect().intersects(t.getRect())){ this.stay(); t.stay(); return true; } } } return false; } /** * *@Description:坦克是否碰到了鹰碉堡 * @param 鹰碉堡对象 * @return 是否碰到了鹰碉堡 */ public boolean CollidesWithHome(Home h){ if(this.live&&h.isLive()&&this.getRect().intersects(h.getRect())){ this.stay(); return true; } return false; } /** * *@Description:坦克是否碰到了河流,主要是地方坦克调用,我方坦克能直接渡河 * @param 河流对象 * @return 是否碰到了河流 */ public boolean CollidesWithRiver(River r){ if(this.live&&this.getRect().intersects(r.getRect())){ this.stay(); return true; } return false; } /** * *@Description:坦克是否碰到了河流,主要是地方坦克调用,我方坦克能直接渡河 * @param 河流集合 * @return 是否碰到了河流 */ public boolean CollidesWithRivers(List<River> rivers){ for(int i=0;i<rivers.size();i++){ River t = rivers.get(i); if(this.live&&this.getRect().intersects(t.getRect())){ this.stay(); return true; } } return false; } public Rectangle getRect() { return new Rectangle(x, y, WIDTH, HEIGHT); } /** * *Title:BloodBar *Description:我方坦克的血条,用于显示我方坦克的生命值 *@author xiaoli *@date2017年1月4日 */ private class BloodBar{ public void draw(Graphics g){ Color c = g.getColor(); g.setColor(Color.PINK); g.drawRect(x,y-10,WIDTH,8); //里面的 g.setColor(Color.PINK); int w =WIDTH*life/100; g.fillRect(x, y-10, w, 8); g.setColor(c); } } /** * *@Description:吃血块,主要是我方坦克调用 * @param 血块对象 * @return 是否吃到了血块 */ public boolean eat(Blood b){ if(this.live&&b.isLive()&&this.getRect().intersects(b.getRect())){ this.life=100; b.setLive(false); tc.bloods.remove(b); //吃血块音效 new Audio(4); return true; } return false; } public boolean isLive() { return live; } public void setLive(boolean live) { this.live = live; } public int getLife() { return life; } public void setLife(int life) { this.life = life; } public boolean isGood() { return good; } }
复制代码
TankClient.java代码
package com.xiaoli.tank; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.Frame; import java.awt.Graphics; import java.awt.Image; import java.awt.Menu; import java.awt.MenuBar; import java.awt.MenuItem; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.ArrayList; import java.util.List; import java.util.Random; import javax.swing.JOptionPane; /** * *Title:TankClient *Description:这个类是大管家,控制着其他类,也是程序入口 *@author xiaoli *@date2017年1月4日 */ public class TankClient extends Frame implements ActionListener { //游戏宽度 public static final int GAME_WIDTH = 800; //游戏高度 public static final int GAME_HEIGHT = 600; //是否开启重绘线程 public static boolean printable=true; //用于产生随机数 Random r = new Random(); //记录复活次数 public static int count=0; //关卡 public static int level=1; //分数 public static int score=0; //菜单条 MenuBar jmb = null; //菜单 Menu jm1 = null, jm2 = null, jm3 = null, jm4 = null; //菜单项 MenuItem jmi1 = null, jmi2 = null, jmi3 = null, jmi4 = null, jmi5 = null, jmi6 = null, jmi7 = null, jmi8 = null, jmi9 = null,jmi10=null,jmi11=null; //从上到下从左到右画墙 Wall w1,w2,w3,w4,w5,w6,w7,w8,w9,w10,w11,w12; //创建我的坦克 Tank myTank = new Tank(220, 560, true,Tank.Direction.STOP, this); //创建鹰碉堡 Home home = new Home(379,556,this); //墙集合,用于存放墙 List<Wall> walls = new ArrayList<Wall>(); //河流集合,用于存放河流 List<River> rivers = new ArrayList<River>(); //定义一个血块 Blood b=null; //血块集合,用于存放血块。用集合的原因是方便删除 List<Blood> bloods = new ArrayList<Blood>(); //草集合,用于存放草 List<Grass> grasses = new ArrayList<Grass>(); //炸弹集合,用于存放炸弹 List<Explode> explodes = new ArrayList<Explode>(); //炮弹集合,用于存放炮弹 List<Missile> missiles = new ArrayList<Missile>(); //坦克集合,用于存放坦克 List<Tank> tanks = new ArrayList<Tank>(); //用于解决双缓冲闪烁现象 Image offScreenImage = null; /** * 绘制场景 */ public void paint(Graphics g) { //分关 if (score >= 1000 * level ) { setLevel(level + 1); // 进入下一关 new Audio(5); grasses.clear(); rivers.clear(); missiles.clear(); tanks.clear(); explodes.clear(); walls.clear(); this.dispose(); new TankClient().lauchFrame(); } //家 home.draw(g); //只能复活一次 if(myTank.getLife()<=0&&count==1){ myTank.setLive(false); home.gameOver(g); } if(r.nextInt(50)>48){ newBlood(); } //敌人死光 if(tanks.size()<=0){ for(int i=0; i<6; i++) { if(i<3){ tanks.add(new Tank(50 + 40*(i+1), 50, false,Tank.Direction.D, this)); }else{ tanks.add(new Tank(50 + 40*(i+1), 50, false,Tank.Direction.R, this)); } } } //g.drawString("血块数量:" + bloods.size(), 10, 50); //g.drawString("子弹数量:" + missiles.size(), 10, 70); //g.drawString("炸弹数量:" + explodes.size(), 10, 90); //g.drawString("坦克数量:" + tanks.size(), 10, 110); g.drawString("关卡:" + level, 10, 90); g.drawString("分数:" + score, 10, 110); g.drawString("生命值:" + myTank.getLife(), 10, 130); g.drawString("复活次数:" + count, 10, 150); //画墙 for(int i=0;i<walls.size();i++){ walls.get(i).draw(g); } for(int i=0; i<missiles.size(); i++) { Missile m = missiles.get(i); m.hitWalls(walls); m.hitTanks(tanks); m.hitTank(myTank); m.hitHome(home); m.draw(g); //if(!m.isLive()) missiles.remove(m); //else m.draw(g); } for(int i=0; i<explodes.size(); i++) { Explode e = explodes.get(i); e.draw(g); } for(int i=0; i<tanks.size(); i++) { Tank t = tanks.get(i); t.CollidesWithWalls(walls); myTank.collidesWithTanks(tanks); t.collidesWithTanks(tanks); t.CollidesWithHome(home); t.CollidesWithRivers(rivers); t.draw(g); } myTank.CollidesWithWalls(walls); myTank.CollidesWithHome(home); //画河流 for(int i=0;i<rivers.size();i++){ rivers.get(i).draw(g); } myTank.draw(g); // 画草地 for (int i = 0; i < grasses.size(); i++) { grasses.get(i).draw(g); } // 画血块 for (int i = 0; i < bloods.size(); i++) { Blood b = bloods.get(i); b.draw(g); myTank.eat(b); } } /** * repaint先调用update再调用paint,用于解决双缓冲闪烁现象 */ public void update(Graphics g) { if(offScreenImage == null) { offScreenImage = this.createImage(GAME_WIDTH, GAME_HEIGHT); } Graphics gOffScreen = offScreenImage.getGraphics(); Color c = gOffScreen.getColor(); gOffScreen.setColor(new Color(0xcce8cf)); gOffScreen.fillRect(0, 0, GAME_WIDTH, GAME_HEIGHT); gOffScreen.setColor(c); paint(gOffScreen); g.drawImage(offScreenImage, 0, 0, null); } /** * 本方法显示程序主窗口 */ public void lauchFrame() { //菜单项 newMenu(); //墙 newWall(); //河流 newRiver(); //草地 newGrass(); //坦克 newTank(); this.setTitle("经典坦克大战游戏 作者:小李"); //this.setLocation(600,300); this.setSize(GAME_WIDTH, GAME_HEIGHT); Dimension dim = Toolkit.getDefaultToolkit().getScreenSize(); setLocation((dim.width - getSize().width) / 2, (dim.height - getSize().height) / 2); this.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); this.setResizable(false); this.addKeyListener(new KeyMonitor()); setVisible(true); new Thread(new PaintThread()).start(); //声音 if(this.level==1){ StartAudio startAudio = new StartAudio("audio/7301.wav"); startAudio.start(); } } /** * *@Description:菜单项 */ public void newMenu(){ // 创建菜单及菜单选项 jmb = new MenuBar(); jm1 = new Menu("游戏"); jm2 = new Menu("暂停/继续"); jm3 = new Menu("帮助"); jm4 = new Menu("游戏难度"); jm1.setFont(new Font("宋体", Font.BOLD, 15));// 设置菜单显示的字体 jm2.setFont(new Font("宋体", Font.BOLD, 15));// 设置菜单显示的字体 jm3.setFont(new Font("TimesRoman", Font.BOLD, 15));// 设置菜单显示的字体 jm4.setFont(new Font("TimesRoman", Font.BOLD, 15));// 设置菜单显示的字体 jmi1 = new MenuItem("重新开始"); jmi2 = new MenuItem("退出"); jmi11= new MenuItem("开启背景音乐"); jmi3 = new MenuItem("暂停"); jmi4 = new MenuItem("继续"); jmi5 = new MenuItem("游戏说明"); jmi6 = new MenuItem("难度1"); jmi7 = new MenuItem("难度2"); jmi8 = new MenuItem("难度3"); jmi9 = new MenuItem("难度4"); jmi10 = new MenuItem("操作说明"); jmi1.setFont(new Font("TimesRoman", Font.BOLD, 15)); jmi2.setFont(new Font("TimesRoman", Font.BOLD, 15)); jmi3.setFont(new Font("TimesRoman", Font.BOLD, 15)); jmi4.setFont(new Font("TimesRoman", Font.BOLD, 15)); jmi5.setFont(new Font("TimesRoman", Font.BOLD, 15)); jm1.add(jmi1); jm1.add(jmi2); jm1.add(jmi11); jm2.add(jmi3); jm2.add(jmi4); jm3.add(jmi5); jm3.add(jmi10); jm4.add(jmi6); jm4.add(jmi7); jm4.add(jmi8); jm4.add(jmi9); jmb.add(jm1); jmb.add(jm2); jmb.add(jm4); jmb.add(jm3); jmi1.addActionListener(this); jmi1.setActionCommand("NewGame"); jmi2.addActionListener(this); jmi2.setActionCommand("Exit"); jmi11.addActionListener(this); jmi11.setActionCommand("startMain"); jmi3.addActionListener(this); jmi3.setActionCommand("Stop"); jmi4.addActionListener(this); jmi4.setActionCommand("Continue"); jmi5.addActionListener(this); jmi5.setActionCommand("help1"); jmi10.addActionListener(this); jmi10.setActionCommand("help2"); jmi6.addActionListener(this); jmi6.setActionCommand("level1"); jmi7.addActionListener(this); jmi7.setActionCommand("level2"); jmi8.addActionListener(this); jmi8.setActionCommand("level3"); jmi9.addActionListener(this); jmi9.setActionCommand("level4"); this.setMenuBar(jmb);// 菜单Bar放到JFrame上 } /** * *@Description:生成墙 */ public void newWall() { if(this.level==1){ w1 = new Wall(210, 200, 100, 30, this); w2 = new Wall(210, 200, 30, 190, this); w3 = new Wall(280, 200, 30, 190, this); w4 = new Wall(210, 370, 100, 30, this); w5 = new Wall(440, 200, 100, 30, this); w6 = new Wall(440, 200, 30, 95, this); w7 = new Wall(470, 265, 70, 30, this); w8 = new Wall(510, 200, 30, 190, this); w9 = new Wall(440, 370, 100, 30, this); w10 = new Wall(379, 530, 43, 20, this); w11 = new Wall(280, 530, 30, 70, this); w12 = new Wall(510, 530, 30, 70, this); walls.add(w1); walls.add(w2); walls.add(w3); walls.add(w4); walls.add(w5); walls.add(w6); walls.add(w7); walls.add(w8); walls.add(w9); walls.add(w10); walls.add(w11); walls.add(w12); }else if(this.level==2){ w1 = new Wall(210, 200, 100, 30, this); w2 = new Wall(210, 200, 30, 190, this); w3 = new Wall(280, 200, 30, 190, this); w4 = new Wall(210, 370, 100, 30, this); w5 = new Wall(410, 200, 30, 70, this); w6 = new Wall(410, 200, 90, 30, this); w7 = new Wall(470, 200, 30, 190, this); w8 = new Wall(470, 370, 90, 30, this); w9 = new Wall(530, 320, 30, 65, this); w10 = new Wall(379, 530, 43, 20, this); w11 = new Wall(280, 530, 30, 70, this); w12 = new Wall(510, 530, 30, 70, this); walls.add(w1); walls.add(w2); walls.add(w3); walls.add(w4); walls.add(w5); walls.add(w6); walls.add(w7); walls.add(w8); walls.add(w9); walls.add(w10); walls.add(w11); walls.add(w12); }else if(this.level>=3){ w1 = new Wall(210, 200, 100, 30, this); w2 = new Wall(210, 200, 30, 190, this); w3 = new Wall(280, 200, 30, 190, this); w4 = new Wall(210, 370, 100, 30, this); w5 = new Wall(430, 200, 90, 30, this); w6 = new Wall(430, 285, 90, 30, this); w7 = new Wall(430, 370, 90, 30, this); w8 = new Wall(500, 200, 30, 200, this); w10 = new Wall(379, 530, 43, 20, this); w11 = new Wall(280, 530, 30, 70, this); w12 = new Wall(510, 530, 30, 70, this); walls.add(w1); walls.add(w2); walls.add(w3); walls.add(w4); walls.add(w5); walls.add(w6); walls.add(w7); walls.add(w8); walls.add(w10); walls.add(w11); walls.add(w12); } } /** * *@Description:生成血块 */ public void newBlood(){ //血块 b = new Blood(); //if(b.CollidesWithWalls(walls)){//血块不能画在墙里面 //return; //} if(bloods.size()==0){ bloods.add(b); } } /** * *@Description:生成河流 */ public void newRiver(){ for(int i=0;i<6;i++){ River river = new River(18+i*30,340); rivers.add(river); river = new River(18+i*30,340+30); rivers.add(river); } for(int i=0;i<6;i++){ River river = new River(568+i*30,340); rivers.add(river); river = new River(568+i*30,340+30); rivers.add(river); } } /** * *@Description:生成草地 */ public void newGrass() { // 草地 for (int i = 0; i < 10; i++) { Grass grass = new Grass((i + 1) * 18, 200); grasses.add(grass); grass = new Grass((i + 1) * 18, 200 + 1 * 18); grasses.add(grass); grass = new Grass((i + 1) * 18, 200 + 2 * 18); grasses.add(grass); grass = new Grass((i + 1) * 18, 200 + 3 * 18); grasses.add(grass); grass = new Grass((i + 1) * 18, 200 + 4 * 18); grasses.add(grass); grass = new Grass((i + 1) * 18, 200 + 5 * 18); grasses.add(grass); grass = new Grass((i + 1) * 18, 200 + 6 * 18); grasses.add(grass); grass = new Grass((i + 1) * 18, 200 + 7 * 18); grasses.add(grass); } for (int i = 1; i <= 11; i++) { Grass grass = new Grass(250 + 18 * 7, 182 + i * 18); grasses.add(grass); grass = new Grass(250 + 18 * 8, 182 + i * 18); grasses.add(grass); grass = new Grass(250 + 18 * 5, 182 + i * 18); grasses.add(grass); grass = new Grass(250 + 18 * 6, 182 + i * 18); grasses.add(grass); } for(int i=0;i<10;i++){ Grass grass = new Grass(550+(i + 1) * 18, 200); grasses.add(grass); grass = new Grass(550+(i + 1) * 18, 200 + 1 * 18); grasses.add(grass); grass = new Grass(550+(i + 1) * 18, 200 + 2 * 18); grasses.add(grass); grass = new Grass(550+(i + 1) * 18, 200 + 3 * 18); grasses.add(grass); grass = new Grass(550+(i + 1) * 18, 200 + 4 * 18); grasses.add(grass); grass = new Grass(550+(i + 1) * 18, 200 + 5 * 18); grasses.add(grass); grass = new Grass(550+(i + 1) * 18, 200 + 6 * 18); grasses.add(grass); grass = new Grass(550+(i + 1) * 18, 200 + 7 * 18); grasses.add(grass); } } /** * *@Description:生成坦克 */ public void newTank(){ for (int i = 0; i < 10; i++) { if (i < 5) { tanks.add(new Tank(50 + 40 * (i + 1), 55, false, Tank.Direction.D, this)); } else { tanks.add(new Tank(50 + 40 * (i + 1), 55, false, Tank.Direction.R, this)); } } } /** * *@Description:主函数、程序入口 * @param args */ public static void main(String[] args) { TankClient tc = new TankClient(); tc.lauchFrame(); } /** * *Title:PaintThread *Description:重绘线程,模拟动态效果 *@author xiaoli *@date2017年1月4日 */ private class PaintThread implements Runnable { public void run() { while(printable) { repaint(); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } } /** * *@Description:按键监听,对坦克、炮弹等进行人机交互 * @param e */ private class KeyMonitor extends KeyAdapter { public void keyReleased(KeyEvent e) { myTank.keyReleased(e); } public void keyPressed(KeyEvent e) { myTank.keyPressed(e); } } /** * 对菜单项操作 */ @Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub if (e.getActionCommand().equals("NewGame")) { printable = false; Object[] options = { "确定", "取消" }; int response = JOptionPane.showOptionDialog(this, "您确认要重新开始!", "", JOptionPane.YES_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[0]); if (response == 0) { this.score=0; this.setLevel(1); printable = true; this.dispose(); new TankClient().lauchFrame(); } else { printable = true; new Thread(new PaintThread()).start(); // 线程启动 } } else if (e.getActionCommand().endsWith("Stop")) { printable = false; // try { // Thread.sleep(10000); // // } catch (InterruptedException e1) { // // TODO Auto-generated catch block // e1.printStackTrace(); // } } else if (e.getActionCommand().equals("Continue")) { if (!printable) { printable = true; new Thread(new PaintThread()).start(); // 线程启动 } // System.out.println("继续"); } else if (e.getActionCommand().equals("Exit")) { printable = false; Object[] options = { "确定", "取消" }; int response = JOptionPane.showOptionDialog(this, "您确认要退出吗", "", JOptionPane.YES_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[0]); if (response == 0) { System.out.println("退出"); System.exit(0); } else { printable = true; new Thread(new PaintThread()).start(); // 线程启动 } } else if (e.getActionCommand().equals("help1")) { printable = false; JOptionPane.showMessageDialog(null, "随着人们精神文化生活的日益丰富,游戏成为了人们生活中必不可少的一部分\n90《坦克大战》更是90后一代人童年的回忆,也是一款经典游戏。\n" + "开发java版坦克大战有利用更深入理解java面向对象编程、swing界面编程、多线程编程"+"\n"+"参考:马士兵坦克大战视频教程、以及互联网资源"+"\n"+"作者邮箱:1275302036@qq.com"+"\n" +"若有关内容侵犯了您的权益,请及时联系作者删除,谢谢!", "提示!", JOptionPane.INFORMATION_MESSAGE); this.setVisible(true); printable = true; new Thread(new PaintThread()).start(); // 线程启动 } else if(e.getActionCommand().equals("help2")){ printable = false; JOptionPane.showMessageDialog(null, "用→ ← ↑ ↓控制方向,CTRL键盘发射,J超级炮弹,K复活(只能复活一次),R重新开始!\n"+"作者邮箱:1275302036@qq.com"+"\n" +"若有关内容侵犯了您的权益,请及时联系作者删除,谢谢!", "提示!", JOptionPane.INFORMATION_MESSAGE); this.setVisible(true); printable = true; new Thread(new PaintThread()).start(); // 线程启动 } else if (e.getActionCommand().equals("level1")) { //Tank.count = 12; Tank.XSPEED = 5; Tank.YSPEED = 5; Missile.XSPEED = 10; Missile.YSPEED = 10; this.dispose(); new TankClient().lauchFrame();; } else if (e.getActionCommand().equals("level2")) { //Tank.count = 12; Tank.XSPEED = 8; Tank.YSPEED = 8; Missile.XSPEED = 14; Missile.YSPEED = 14; this.dispose(); new TankClient().lauchFrame();; } else if (e.getActionCommand().equals("level3")) { //Tank.count = 20; Tank.XSPEED = 12; Tank.YSPEED = 12; Missile.XSPEED = 18; Missile.YSPEED = 18; this.dispose(); new TankClient().lauchFrame();; } else if (e.getActionCommand().equals("level4")) { //Tank.count = 20; Tank.XSPEED = 16; Tank.YSPEED = 16; Missile.XSPEED = 24; Missile.YSPEED = 14; this.dispose(); new TankClient().lauchFrame();; }else if(e.getActionCommand().equals("startMain")){ printable = false; JOptionPane.showMessageDialog(null, "开启后不能关闭!请不要重复点击!", "提示!", JOptionPane.INFORMATION_MESSAGE); this.setVisible(true); printable = true; // 线程启动 new Thread(new PaintThread()).start(); new Audio(0); } } /* * 设置关卡 */ public void setLevel(int level) { //设置三关 if (level > 10) { level = 10; } this.level = level; } } 复制代码