Java实现经典坦克大战及源代码下载
目錄
一、簡單介紹
二、工程目錄
三、具體代碼
四、運行效果截圖
五、總結
六、說明與下載
一、簡單介紹
? ? ? ? 這是一個功能相對全的Java版坦克大戰,界面繪制是通過Java的圖形化用戶界面swing完成的,包括了菜單界面和游戲界面。其中菜單界面可以供玩家選擇重新開始游戲、暫停、繼續、是否播放背景音樂、設置游戲難度等操作;游戲界面繪制了坦克、河流、草地、墻壁、鷹碉堡等經典坦克場景,玩家在游戲界面操作自己的坦克開始對戰。
? ? ? ? ?本游戲使用的主要技術有Swing編程、面向對象編程、多線程編程。本想用I/O編程實現保存游戲數據,感覺單機版的沒必要就沒弄了。
游戲實現的主要功能有:
1、我方坦克默認可以渡河,碰到墻壁不能走,鷹碉堡被擊中游戲結束
2、坦克可以上下左右、以及左上左下右上右下八個方向移動,移動時添加音效
3、坦克可以發子彈(可以連發),發射時添加音效
4、擊中對方坦克時,坦克消失,顯示爆炸效果;子彈擊中墻壁時,子彈消失
5、我方坦克吃到血塊時,生命值加30(可以自己設定);我方被擊中時每次血量減50
6、移動過程中檢測碰撞,包括坦克與坦克,坦克與草地、河流、墻壁等
7、聲音處理(開始音樂、背景音樂、移動音效、爆炸音效等)
8、菜單處理(重新開始、暫停/繼續游戲、是否播放背景音樂、設置游戲難度、幫助等)
9、默認擊中一個敵人得100分,達到1500分進入下一關,一共設置了3關
10、生命數,默認兩條命,命數用完游戲結束
二、工程目錄
?
images文件夾存放草、鷹碉堡和河流圖片,墻壁是用畫筆畫的;audio存放所有音效文件;所有java代碼都存放在com.chuenhung.tank包下面。
三、具體代碼
由于篇幅有限,這里只貼出Tank類源代碼。Tank類是公用的,通過good變量來區分我方和敵人坦克。
Tank類源代碼:
package com.chuenhung.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; /*** *@Description 坦克類,包括坦克移動、坦克發射炮彈等*@author Chuenhung*@email 1271826574@qq.com*@date 2017年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;// 判斷是否是我方坦克,默認trueprivate 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();// 剩余生命數private int remainLives =2;// 構造方法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_J:superFire();break;case KeyEvent.VK_SPACE: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 w 墻對象* @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 tanks 多輛坦克* @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 h 鷹碉堡對象* @return 是否碰到了鷹碉堡*/public boolean CollidesWithHome(Home h){if(this.live&&h.isLive()&&this.getRect().intersects(h.getRect())){this.stay();return true;}return false;}/*** * @Description 坦克是否碰到了河流,主要是地方坦克調用,我方坦克能直接渡河* @param r 河流對象* @return 是否碰到了河流*/public boolean CollidesWithRiver(River r){if(this.live&&this.getRect().intersects(r.getRect())){this.stay();return true;}return false;}/*** *@Description 坦克是否碰到了河流,主要是地方坦克調用,我方坦克能直接渡河* @param rivers 河流集合* @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);}/*** *@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 b 血塊對象* @return 是否吃到了血塊*/public boolean eat(Blood b){if(this.live&&b.isLive()&&this.getRect().intersects(b.getRect())){this.life= life + 30;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;}public int getRemainLives() {return remainLives;}public void setRemainLives(int remainLives) {this.remainLives = remainLives;} }四、運行效果截圖
重新開始、暫停、繼續、發射子彈、爆炸效果演示:
渡河、吃血塊功能演示:
?
五、總結
源代碼參考了馬老師的Java坦克大戰視頻教程以及眾多互聯網資源,這次練手有利于深入理解Java面向對象編程、Swing界面編程以及多線程編程
大部分功能是本人在實訓期間完成(2016.12.30),當時有興趣想鞏固一下Java知識就開始做了
這個坦克大戰到這里就告一個段落,時間荏苒,馬上就要畢業了,要學的東西很多的,希望以后能夠做出更加優秀的作品。
該程序謹供參考,不得用于商業用途,希望大神能提出更多優化的建議,一起交流。
若有關內容侵犯了您的權益請及時聯系作者刪除,作者郵箱1271826574@qq.com
更新于2021/06/04
六、說明與下載
下載地址
備用下載地址
總結
以上是生活随笔為你收集整理的Java实现经典坦克大战及源代码下载的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: html检查输入为空,html inpu
- 下一篇: java美元兑换,(Java实现) 美元