韩顺平--Java坦克大战
生活随笔
收集整理的這篇文章主要介紹了
韩顺平--Java坦克大战
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
https://www.bloghut.cn/questionBank
?? 注意:本工程是模塊化進行開發的,所以一些文件( 圖片、存檔路徑、音樂)的路徑需要改成自己對應。
鏈接: 面試題庫
1、說明
??寫了14個版本,終于完成了,項目結構如下
2、游戲效果
(1)擊中敵人
(2)被敵人擊中
3、代碼如下
(1)TankGame 主方法
package cn.bloghut;import cn.bloghut.component.MyPanel; import cn.bloghut.service.Recorder;import javax.swing.*; import java.awt.*; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.Scanner;/*** @Classname TankGame* @Description TODO* @Date 2022/5/8 8:25* @Created by 閑言*/ public class TankGame extends JFrame {private MyPanel panel;public static void main(String[] args) {new TankGame();}public TankGame(){System.out.println("請輸入選擇: 1 表示新游戲,2是繼續上局");Scanner scanner = new Scanner(System.in);//將panel放入到thread中this.panel = new MyPanel(scanner.next());scanner.close();new Thread(panel).start();//設置綁定監聽器this.addKeyListener(panel);this.add(panel);//設置窗體關閉this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.setTitle("閑言-坦克大戰");//獲取當前屏幕分辨率int width = Toolkit.getDefaultToolkit().getScreenSize().width;int height = Toolkit.getDefaultToolkit().getScreenSize().height;//設置窗體大小不可變this.setResizable(false);//設置窗體位置width = (width - 1300) / 2;height = (height - 750) / 2;this.setBounds(width,height,1300,750);this.setBackground(Color.black);//設置窗體顯示this.setVisible(true);//在JFrame 中增加相關關閉窗口的處理this.addWindowListener(new WindowAdapter() {@Overridepublic void windowClosing(WindowEvent e) {Recorder.keepRecord();System.exit(0);}});} }(2)MyPanel 視圖
package cn.bloghut.component;import cn.bloghut.pojo.*; import cn.bloghut.service.PlayAudio; import cn.bloghut.service.Recorder; import cn.bloghut.service.Shot;import javax.swing.*; import java.awt.*; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.io.File; import java.util.Vector;/*** @Classname MyPanel* @Description 坦克大戰繪圖區域* 為了讓panel 不停的重繪子彈,需要將MyPanel* @Date 2022/5/8 8:44* @Created by 閑言*/ public class MyPanel extends JPanel implements KeyListener, Runnable {//定義我的坦克Hero hero = null;//定義敵人坦克Vector<EnemyTank> enemyTanks = new Vector<>();//用于存放炸彈//當子彈擊中坦克時,就加入一個bomb 對象Vector<Bomb> bombs = new Vector<>();//定義三種圖片,用于顯示炸彈Image img1 = null;Image img2 = null;Image img3 = null;//定義一個存放Node 對象的Vector,用于恢復敵人坦克的坐標和放向Vector<Node> nodes = null;//敵人坦克數量int enemyTankSize = 3;public MyPanel(String type) {//判斷記錄文件是否存在//如果存在就正常執行,如果文件不存在,提示只能開啟新的游戲File file = new File(Recorder.getRecordFile());if (!file.exists()){type = "1";System.out.println("文件不存在只能開啟新游戲");}else {nodes = Recorder.getNodesAndTanks();}//初始化我的坦克hero = new Hero(150, 150);//設置坦克速度hero.setSpeed(5);switch (type) {case "1"://初始化敵人坦克for (int i = 0; i < enemyTankSize; i++) {EnemyTank enemyTank = new EnemyTank(100 * (i + 1), 0);enemyTank.setDirection(2);//啟動敵人坦克線程new Thread(enemyTank).start();//給該enemyTank 加入一顆子彈Shot shot = new Shot(enemyTank.getX() + 20, enemyTank.getY() + 60, enemyTank.getDirection());//加入到enemyTank.getShots().add(shot);//為每個坦克,放入所有的敵人對象enemyTank.setEnemyTanks(enemyTanks);//啟動shotnew Thread(shot).start();enemyTanks.add(enemyTank);}break;case "2": //繼續上局游戲//初始化敵人坦克for (int i = 0;i < nodes.size();i++){Node node = nodes.get(i);EnemyTank enemyTank = new EnemyTank(node.getX(),node.getY());enemyTank.setDirection(node.getDirection());//啟動敵人坦克線程new Thread(enemyTank).start();//給該enemyTank 加入一顆子彈Shot shot = new Shot(enemyTank.getX() + 20, enemyTank.getY() + 60, enemyTank.getDirection());//加入到enemyTank.getShots().add(shot);//為每個坦克,放入所有的敵人對象enemyTank.setEnemyTanks(enemyTanks);//啟動shotnew Thread(shot).start();enemyTanks.add(enemyTank);}break;default:System.out.println("你的輸入有誤");}//獲取項目路徑//1.獲取圖片資源String parent = System.getProperty("user.dir");parent += "\\";//2.初始化圖片img1 = Toolkit.getDefaultToolkit().getImage(parent + "bomb_1.gif");img2 = Toolkit.getDefaultToolkit().getImage(parent + "bomb_2.gif");img3 = Toolkit.getDefaultToolkit().getImage(parent + "bomb_3.gif");//存放敵人坦克信息Recorder.setEnemyTanks(enemyTanks);//播放指定的音樂new PlayAudio("bg.wav").start();}@Overridepublic void paint(Graphics g) {super.paint(g);//填充矩形,默認黑色g.fillRect(0, 0, 1000, 750);//畫出游戲信息showInfo(g);//畫自己坦克if (hero != null && hero.isLive()) {drawTank(hero.getX(), hero.getY(), g, hero.getDirection(), 1);}//畫出自己射擊的子彈//不為空,且處于發射狀態if (hero.getShot() != null && hero.getShot().isLive()) {g.draw3DRect(hero.getShot().getX(), hero.getShot().getY(), 2, 2, false);}if (hero.getShots().size() > 0) {for (int i = 0; i < hero.getShots().size(); i++) {Shot shot = hero.getShots().get(i);if (shot != null && shot.isLive()) {g.draw3DRect(shot.getX(), shot.getY(), 2, 2, false);} else {//如果shot對象已經無效,就從子彈集合中移除hero.getShots().remove(shot);}}}//畫敵人坦克for (int i = 0; i < enemyTanks.size(); i++) {EnemyTank enemyTank = enemyTanks.get(i);//判斷當前坦克是否還存活,只有存活的時候才去畫if (enemyTank.isLive()) {drawTank(enemyTank.getX(), enemyTank.getY(), g, enemyTank.getDirection(), 0);//繪制敵人坦克子彈Vector<Shot> shots = enemyTank.getShots();for (int j = 0; j < shots.size(); j++) {Shot shot = shots.get(j);//子彈存活的時候才繪制if (shot.isLive()) {g.draw3DRect(shot.getX(), shot.getY(), 1, 1, false);} else {//子彈出邊界了,移除子彈enemyTank.getShots().remove(shot);}}}}//如果bombs 集合中有對象,就畫出for (int i = 0; i < bombs.size(); i++) {Bomb bomb = bombs.get(i);//根據當前炸彈的life值畫出對應的圖片if (bomb.getLife() > 6) {g.drawImage(img1, bomb.getX(), bomb.getY(), 60, 60, this);} else if (bomb.getLife() > 3) {g.drawImage(img2, bomb.getX(), bomb.getY(), 60, 60, this);} else {g.drawImage(img3, bomb.getX(), bomb.getY(), 60, 60, this);}//讓這個炸彈的生命值減少bomb.lifeDown();//如果bomb 生命值為0,就從集合中刪除if (bomb.getLife() == 0) {bombs.remove(bomb);}}}/*** 顯示 擊毀敵方的坦克信息** @param g 畫圖*/public void showInfo(Graphics g) {g.setColor(Color.BLACK);Font font = new Font("宋體", Font.BOLD, 25);g.setFont(font);g.drawString("您累計擊毀敵方坦克", 1020, 30);drawTank(1020, 60, g, 0, 0);g.setColor(Color.BLACK);g.drawString(Recorder.getAllEnemyTankTotal() + "", 1080, 100);}/*** 繪制坦克** @param x 坦克的左上角x坐標* @param y 坦克的左上角y坐標* @param g 畫筆* @param direction 坦克方向(上下左右)* @param type 坦克類型*/public void drawTank(int x, int y, Graphics g, int direction, int type) {//根據不同類型的坦克設置不同顏色switch (type) {case 0://0 敵人的坦克g.setColor(Color.cyan);break;//case 1://1 我們的坦克g.setColor(Color.yellow);break;}//根據坦克的方向來繪制坦克//direction 0-向上,1-向右,2-向下,3-向左switch (direction) {case 0://左右兩邊輪子g.fill3DRect(x, y, 10, 60, false);g.fill3DRect(x + 30, y, 10, 60, false);//畫矩形g.fill3DRect(x + 10, y + 10, 20, 40, false);//畫圓g.fillOval(x + 10, y + 20, 20, 20);//畫炮桿--起點終點g.drawLine(x + 20, y + 30, x + 20, y);break;case 1:g.fill3DRect(x, y, 60, 10, false);//上邊輪子g.fill3DRect(x, y + 30, 60, 10, false);//下邊輪子//畫矩形g.fill3DRect(x + 10, y + 10, 40, 20, false);//畫圓g.fillOval(x + 20, y + 10, 20, 20);//畫炮桿--起點終點g.drawLine(x + 30, y + 20, x + 60, y + 20);break;case 2://兩邊輪子g.fill3DRect(x, y, 10, 60, false);g.fill3DRect(x + 30, y, 10, 60, false);//畫矩形g.fill3DRect(x + 10, y + 10, 20, 40, false);//畫圓g.fillOval(x + 10, y + 20, 20, 20);//畫炮桿--起點終點g.drawLine(x + 20, y + 30, x + 20, y + 60);break;case 3:g.fill3DRect(x, y, 60, 10, false);//上邊輪子g.fill3DRect(x, y + 30, 60, 10, false);//下邊輪子//畫矩形g.fill3DRect(x + 10, y + 10, 40, 20, false);//畫圓g.fillOval(x + 20, y + 10, 20, 20);//畫炮桿--起點終點g.drawLine(x + 30, y + 20, x, y + 20);break;default:System.out.println("暫時沒有處理");}}@Overridepublic void keyTyped(KeyEvent e) {}@Overridepublic void keyPressed(KeyEvent e) {int code = e.getKeyCode();//判斷用戶按下的按鍵if (KeyEvent.VK_W == code) { //向上//移動時判斷不能重疊hero.setDirection(0);hero.moveUp();} else if (KeyEvent.VK_D == code) { //向右hero.setDirection(1);hero.moveRight();} else if (KeyEvent.VK_S == code) { //向下hero.setDirection(2);hero.moveDown();} else if (KeyEvent.VK_A == code) { //向左hero.setDirection(3);hero.moveLeft();}//判斷是否是射擊if (KeyEvent.VK_J == code) {//如果為空,說明是第一次發射//發送一顆子彈 // if (hero.getShot() == null || !(hero.getShot().isLive())){ // hero.shotEnemyTank(); // }//發射多顆子彈hero.shotEnemyTank();}//重繪this.repaint();}//如果我們的坦克可以發射多發子彈//在判斷我方子彈是否擊中敵人坦克時,就需要把我們的子彈集合所有的子彈取出,都取出和敵人的所有坦克進行判斷//編寫方法,判斷我方的子彈是否擊中敵人坦克/*** 判斷子彈和坦克** @param shots 子彈集合* @param tank 坦克*/public void hitTank(Vector<Shot> shots, Tank tank) {for (int i = 0; i < shots.size(); i++) {hitTank(shots.get(i), tank);}}/*** 判斷子彈和坦克** @param s 子彈* @param tank 坦克*/public void hitTank(Shot s, Tank tank) {switch (tank.getDirection()) {case 0://坦克向上case 2://坦克向下if (s.getX() > tank.getX() && s.getX() < tank.getX() + 40 &&s.getY() > tank.getY() && s.getY() < tank.getY() + 60) {s.setLive(false);tank.setLive(false);//當我的子彈擊中敵人坦克后,將enemyTank 坦克從集合中去掉enemyTanks.remove(tank);//當我方擊毀一輛敵方坦克時,就對一個值++(前提不是我放坦克)if (!(tank instanceof Hero)) {Recorder.addlEnemyTankTotal();}//創建bomb對象,加入到bombs集合Bomb bomb = new Bomb(tank.getX(), tank.getY());bombs.add(bomb);}break;case 1://坦克向右case 3://坦克向左if (s.getX() > tank.getX() && s.getX() < tank.getX() + 60 &&s.getY() > tank.getY() && s.getY() < tank.getY() + 40) {s.setLive(false);tank.setLive(false);//打我的子彈擊中敵人坦克后,將enemyTank 坦克從集合中去掉enemyTanks.remove(tank);//當我方擊毀一輛敵方坦克時,就對一個值++(前提不是我放坦克)if (!(tank instanceof Hero)) {Recorder.addlEnemyTankTotal();}//創建bomb對象,加入到bombs集合Bomb bomb = new Bomb(tank.getX(), tank.getY());bombs.add(bomb);}break;}}@Overridepublic void keyReleased(KeyEvent e) {}@Overridepublic void run() {//每隔100毫秒,重繪區域while (true) {try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}//判斷是否擊中敵人坦克hitEnemy();//判斷敵人坦克是否擊中我們hitHero();this.repaint();}}/*** 判斷是否擊中敵人坦克*/public void hitEnemy() {if (hero.getShot() != null && hero.getShot().isLive()) {//遍歷敵人所有的坦克for (int i = 0; i < enemyTanks.size(); i++) {EnemyTank enemyTank = enemyTanks.get(i);//發射單個子彈 // hitTank(hero.getShot(),enemyTank);//發射多顆子彈hitTank(hero.getShots(), enemyTank);}}}/*** 判斷敵人坦克是否擊中*/public void hitHero() {if (enemyTanks.size() > 0) {//拿到所有敵人的坦克-下的子彈,判斷是否重合如果重合則顯示爆炸for (int i = 0; i < enemyTanks.size(); i++) {EnemyTank enemyTank = enemyTanks.get(i);//判斷是否擊中//敵人的子彈Vector<Shot> shots = enemyTank.getShots();if (shots.size() > 0) {for (int j = 0; j < shots.size(); j++) {Shot shot = shots.get(j);if (hero.isLive() && shot.isLive()) {//判斷子彈和坦克是否重合hitTank(shots, hero);}}}}}} }(3)Bomb 爆炸類
package cn.bloghut.pojo;/*** @Classname Bomb* @Description TODO* @Date 2022/5/8 16:18* @Created by 閑言*/ public class Bomb {private int x,y;//炸彈坐標private int life = 9;//炸彈生命周期private boolean isLive = true;//是否存活public Bomb(int x, int y) {this.x = x;this.y = y;}//減少生命值public void lifeDown(){if (life > 0){life--;}else {isLive = false;}}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 getLife() {return life;}public void setLife(int life) {this.life = life;}public boolean isLive() {return isLive;}public void setLive(boolean live) {isLive = live;} }(4)EnemyTank 敵方坦克類
package cn.bloghut.pojo;import cn.bloghut.service.Shot;import java.util.Vector;/*** @Classname EnemyTank* @Description TODO* @Date 2022/5/8 11:06* @Created by 閑言*/ @SuppressWarnings("All") public class EnemyTank extends Tank implements Runnable {//在敵人坦克類,保存多個shotprivate Vector<Shot> shots = new Vector<>();//敵人坦克 可以得到敵人坦克的Vector//1.EnemyTank 在mypanel里面private Vector<EnemyTank> enemyTanks = new Vector<>();public EnemyTank(int x, int y) {super(x, y);}public Vector<Shot> getShots() {return shots;}public void setShots(Vector<Shot> shots) {this.shots = shots;}public Vector<EnemyTank> getEnemyTanks() {return enemyTanks;}/*** 提供一個方法,可以將mypanel 的成員 Vector<EnemyTank> enemyTanks = new Vector<>();* 設置到 private Vector<EnemyTank> enemyTanks = new Vector<>();* @param enemyTanks 敵人坦克集合*/public void setEnemyTanks(Vector<EnemyTank> enemyTanks) {this.enemyTanks = enemyTanks;}//編寫方法,判斷當前的敵人坦克,是否和 enemyTanks 中2的 其他坦克發生了重疊 或者是碰撞public boolean isTouchEnemyTank(){//判斷當前敵人坦克(this) 方向switch (this.getDirection()){case 0: //上//讓當前的this 敵人坦克 和 其他所有的敵人坦克比較for (int i = 0;i< enemyTanks.size();i++){//從vector中取出一輛敵人的坦克EnemyTank enemyTank = enemyTanks.get(i);//不和自己比較if (this != enemyTank){/*1.如果敵人坦克是上/下方向 x的范圍是什么【enemyTank.getX() ,enemyTank.getX() + 40】y的范圍是什么【enemyTank.getY() ,enemyTank.getY() + 60】*/if (enemyTank.getDirection() == 0 || enemyTank.getDirection() == 2){//2.當前坦克的左上角坐標【this.getX(),this.getY()】if (this.getX() >= enemyTank.getX() && this.getX() <= enemyTank.getX() + 40 &&this.getY() >= enemyTank.getY() && this.getY() <= enemyTank.getY() + 60){return true;}//3.當前坦克的右上角坐標【this.getX() + 40,this.getY()】if (this.getX() + 40 >= enemyTank.getX() && this.getX() + 40 <= enemyTank.getX() + 60 &&this.getY() >= enemyTank.getY() && this.getY() <= enemyTank.getY() + 40){return true;}}/*1.如果敵人坦克是左/右方向 x的范圍是什么【enemyTank.getX() ,enemyTank.getX() + 60】y的范圍是什么【enemyTank.getY() ,enemyTank.getY() + 40】*///如果敵人坦克是左/右方向if (enemyTank.getDirection() == 1 || enemyTank.getDirection() == 3){//2.當前坦克的左上角坐標【this.getX(),this.getY()】if (this.getX() >= enemyTank.getX() && this.getX() <= enemyTank.getX() + 60 &&this.getY() >= enemyTank.getY() && this.getY() <= enemyTank.getY() + 40){return true;}//3.當前坦克的右上角坐標【this.getX() + 40,this.getY()】if (this.getX() + 40 >= enemyTank.getX() && this.getX() + 40 <= enemyTank.getX() + 60 &&this.getY() >= enemyTank.getY() && this.getY() <= enemyTank.getY() + 40){return true;}}}}break;case 1: //右//讓當前的this 敵人坦克 和 其他所有的敵人坦克比較for (int i = 0;i< enemyTanks.size();i++){//從vector中取出一輛敵人的坦克EnemyTank enemyTank = enemyTanks.get(i);//不和自己比較if (this != enemyTank){/*1.如果敵人坦克是上/下方向 x的范圍是什么【enemyTank.getX() ,enemyTank.getX() + 40】y的范圍是什么【enemyTank.getY(),enemyTank.getY() + 40】*/if (enemyTank.getDirection() == 0 || enemyTank.getDirection() == 2){//2.當前坦克的右上角坐標【this.getX() + 60,this.getY()】if (this.getX() + 60 >= enemyTank.getX() && this.getX() + 60 <= enemyTank.getX() + 40 &&this.getY() >= enemyTank.getY() && this.getY() <= enemyTank.getY() + 60){return true;}//3.當前坦克的右下角坐標【this.getX() + 60,this.getY() + 40】if (this.getX() + 60 >= enemyTank.getX() && this.getX() + 60 <= enemyTank.getX() + 40 &&this.getY() + 40 >= enemyTank.getY() && this.getY() + 40 <= enemyTank.getY() + 60){return true;}}/*1.如果敵人坦克是左/右方向 x的范圍是什么【enemyTank.getX(),enemyTank.getX() + 60】y的范圍是什么【enemyTank.getY(),enemyTank.getX() + 40】*///如果敵人坦克是左/右方向if (enemyTank.getDirection() == 1 || enemyTank.getDirection() == 3){//2.當前坦克的右上角坐標【this.getX() + 60,this.getY()】if (this.getX() + 60 >= enemyTank.getX() && this.getX() + 60 <= enemyTank.getX() + 60 &&this.getY() >= enemyTank.getY() && this.getY() <= enemyTank.getY() + 40){return true;}//3.當前坦克的右下角坐標【this.getX() + 60,this.getY() + 40】if (this.getX() + 60 >= enemyTank.getX() && this.getX() + 60 <= enemyTank.getX() + 60 &&this.getY() + 40 >= enemyTank.getY() && this.getY() + 40 <= enemyTank.getY() + 40){return true;}}}}break;case 2: //下//讓當前的this 敵人坦克 和 其他所有的敵人坦克比較for (int i = 0;i< enemyTanks.size();i++){//從vector中取出一輛敵人的坦克EnemyTank enemyTank = enemyTanks.get(i);//不和自己比較if (this != enemyTank){/*1.如果敵人坦克是上/下方向 x的范圍是什么【enemyTank.getX() ,enemyTank.getX() + 40】y的范圍是什么【enemyTank.getY(),enemyTank.getY() + 60】*/if (enemyTank.getDirection() == 0 || enemyTank.getDirection() == 2){//2.當前坦克的左下角坐標【this.getX(),this.getY() + 60】if (this.getX() >= enemyTank.getX() && this.getX() <= enemyTank.getX() + 40 &&this.getY() + 60 >= enemyTank.getY() && this.getY() + 60 <= enemyTank.getY() + 60){return true;}//3.當前坦克的右下角坐標【this.getX() + 40,this.getY() + 60】if (this.getX() + 40 >= enemyTank.getX() && this.getX() + 40 <= enemyTank.getX() + 40 &&this.getY() + 60 >= enemyTank.getY() && this.getY() + 60 <= enemyTank.getY() + 60){return true;}}/*1.如果敵人坦克是左/右方向 x的范圍是什么【enemyTank.getX(),enemyTank.getX() + 60】y的范圍是什么【enemyTank.getY(),enemyTank.getX() + 40】*///如果敵人坦克是左/右方向if (enemyTank.getDirection() == 1 || enemyTank.getDirection() == 3){//2.當前坦克的左下角坐標【this.getX(),this.getY() + 60】if (this.getX() >= enemyTank.getX() && this.getX() <= enemyTank.getX() + 60 &&this.getY() + 60 >= enemyTank.getY() && this.getY() + 60 <= enemyTank.getY() + 40){return true;}//3.當前坦克的右下角坐標【this.getX() + 40,this.getY() + 60】if (this.getX() + 40 >= enemyTank.getX() && this.getX() + 40 <= enemyTank.getX() + 60 &&this.getY() + 60 >= enemyTank.getY() && this.getY() + 60 <= enemyTank.getY() + 40){return true;}}}}break;case 3: //左//讓當前的this 敵人坦克 和 其他所有的敵人坦克比較for (int i = 0;i< enemyTanks.size();i++){//從vector中取出一輛敵人的坦克EnemyTank enemyTank = enemyTanks.get(i);//不和自己比較if (this != enemyTank){/*1.如果敵人坦克是上/下方向 x的范圍是什么【enemyTank.getX() ,enemyTank.getX() + 40】y的范圍是什么【enemyTank.getY(),enemyTank.getY() + 60】*/if (enemyTank.getDirection() == 0 || enemyTank.getDirection() == 2){//2.當前坦克的左上角坐標【this.getX(),this.getY()】if (this.getX() >= enemyTank.getX() && this.getX() <= enemyTank.getX() + 40 &&this.getY() >= enemyTank.getY() && this.getY() <= enemyTank.getY() + 60){return true;}//3.當前坦克的左下角坐標【this.getX(),this.getY() + 40】if (this.getX() >= enemyTank.getX() && this.getX() <= enemyTank.getX() + 40 &&this.getY() + 40 >= enemyTank.getY() && this.getY() + 40 <= enemyTank.getY() + 60){return true;}}/*1.如果敵人坦克是左/右方向 x的范圍是什么【enemyTank.getX(),enemyTank.getX() + 60】y的范圍是什么【enemyTank.getY(),enemyTank.getX() + 40】*///如果敵人坦克是左/右方向if (enemyTank.getDirection() == 1 || enemyTank.getDirection() == 3){//2.當前坦克的左上角坐標【this.getX(),this.getY()】if (this.getX() >= enemyTank.getX() && this.getX() <= enemyTank.getX() + 60 &&this.getY() >= enemyTank.getY() && this.getY() <= enemyTank.getY() + 40){return true;}//3.當前坦克的左下角坐標【this.getX(),this.getY() + 40】if (this.getX() >= enemyTank.getX() && this.getX() <= enemyTank.getX() + 60 &&this.getY() + 40 >= enemyTank.getY() && this.getY() + 40 <= enemyTank.getY() + 40){return true;}}}}break;}return false;}@Overridepublic void run() {while (true) {//這里我們判斷如果shots size() == 0,創建一顆子彈,放入到shots集合,并啟動if (isLive() && shots.size() < 3) {Shot s = null;//判斷坦克的方向,創建對應的子彈switch (getDirection()) {case 0:s = new Shot(getX() + 20, getY(), 0);break;case 1:s = new Shot(getX() + 60, getY() + 20, 1);break;case 2:s = new Shot(getX() + 20, getY() + 60, 2);break;case 3:s = new Shot(getX(), getY() + 20, 3);break;}//添加到容器shots.add(s);//啟動線程new Thread(s).start();}//當前坦克的方向來繼續移動for (int i = 0; i < 30; i++) {switch (getDirection()) {case 0://向上if (getY() > 0 && !isTouchEnemyTank()){moveUp();}try {Thread.sleep(50);} catch (InterruptedException e) {e.printStackTrace();}break;case 1://向右if (getX() + 60 < 1000 && !isTouchEnemyTank()){moveRight();}try {Thread.sleep(50);} catch (InterruptedException e) {e.printStackTrace();}break;case 2://向下if (getY() + 60 < 722 && !isTouchEnemyTank()){moveDown();}try {Thread.sleep(50);} catch (InterruptedException e) {e.printStackTrace();}break;case 3://向左if (getX() > 0 && !isTouchEnemyTank()){moveLeft();}try {Thread.sleep(50);} catch (InterruptedException e) {e.printStackTrace();}break;}}try {Thread.sleep(50);} catch (InterruptedException e) {e.printStackTrace();}//然后隨機的改變方向int direction = (int) (Math.random() * 4);setDirection(direction);//一旦寫并發程序,一定要考慮清楚該線程什么時候結束//被子彈打中了,結束線程if (!isLive()) {break;}}} }(5)Hero 我方坦克類
package cn.bloghut.pojo;import cn.bloghut.service.Shot;import java.util.Vector;/*** @Classname Hero* @Description 自己坦克* @Date 2022/5/8 8:43* @Created by 閑言*/ public class Hero extends Tank{//定義一個shot對象,表示射擊行為private Shot shot = null;//可以發射多顆子彈private Vector<Shot> shots = new Vector<>();public Hero(int x, int y) {super(x, y);}//射擊public void shotEnemyTank(){//控制面板上子彈數量if (shots.size() >= 5){return;}//創建short對象,根據當前hero對象的位置方向來創建shot對象switch (getDirection()){case 0:shot = new Shot(getX() + 20,getY(),0);break;case 1:shot = new Shot(getX() + 60,getY() +20,1);break;case 2:shot = new Shot(getX() + 20,getY() + 60,2);break;case 3:shot = new Shot(getX(),getY() + 20,3);break;}//把進創建的short放到集合中shots.add(shot);//啟動shot線程new Thread(shot).start();}public Vector<Shot> getShots() {return shots;}public void setShots(Vector<Shot> shots) {this.shots = shots;}public Shot getShot() {return shot;}public void setShot(Shot shot) {this.shot = shot;} }(6)Node 記錄敵方坦克類(繼續上局游戲用)
package cn.bloghut.pojo;/*** @Classname Node* @Description 一個node 對象,表示一個敵人坦克的信息* @Date 2022/5/9 10:47* @Created by 閑言*/ public class Node {private int x;private int y;private int direction;public Node(int x, int y, int direction) {this.x = x;this.y = y;this.direction = direction;}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 getDirection() {return direction;}public void setDirection(int direction) {this.direction = direction;} }(7)Tank 坦克父類
package cn.bloghut.pojo;/*** @Classname Tank* @Description 坦克實體* @Date 2022/5/8 8:43* @Created by 閑言*/ public class Tank {private int x;private int y;private int direction;///坦克方向0-上 1-右 2-下 3-左private int speed = 1;//坦克速度private 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 getDirection() {return direction;}public void setDirection(int direction) {this.direction = direction;}//上下左右移動方法public void moveUp(){//坦克不能出邊界if (y > 0){y-=speed;}}public void moveRight(){if (x + 60 < 1000){x+=speed;}}public void moveDown(){if (y + 60 < 722){y+=speed;}}public void moveLeft(){if (x > 0){x-=speed;}}public boolean isLive() {return isLive;}public void setLive(boolean live) {isLive = live;}public int getSpeed() {return speed;}public void setSpeed(int speed) {this.speed = speed;} }(8)PlayAudio 播放背景音樂類
package cn.bloghut.service;import javax.sound.sampled.*; import java.io.*;/*** @author ajun* Date 2021/7/16* @version 1.0* 播放音樂*/ public class PlayAudio extends Thread {private String filename;public PlayAudio(String wavfile) {String path = System.getProperty("user.dir");filename = path+"\\"+wavfile;}@Overridepublic void run() {// 從項目資源目錄下加載背景音樂AudioInputStream audioInputStream = null;try {audioInputStream = AudioSystem.getAudioInputStream(new BufferedInputStream(new FileInputStream(filename)));} 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 = new byte[512];try {while (nBytesRead != -1) {nBytesRead = audioInputStream.read(abData, 0, abData.length);if (nBytesRead >= 0)auline.write(abData, 0, nBytesRead);}} catch (IOException e) {e.printStackTrace();return;} finally {auline.drain();auline.close();}} }(9)Recorder 記錄游戲數據類
package cn.bloghut.service;import cn.bloghut.pojo.EnemyTank; import cn.bloghut.pojo.Node;import java.io.*; import java.util.Vector;/*** @Classname Recorder* @Description 用于記錄* @Date 2022/5/9 10:00* @Created by 閑言*/ public class Recorder {//定義變量,記錄我方擊毀敵人坦克數量private static int allEnemyTankTotal = 0;//定義IO 對象,準備寫數據到文件中private static BufferedWriter bufferedWriter = null;private static BufferedReader bufferedReader = null;private static String recordFile;//存儲敵人坦克private static Vector<EnemyTank> enemyTanks = null;//定義一個Node 的Vector ,用于保存敵人的信息nodeprivate static Vector<Node> nodes = new Vector<>();static {String parentPath = System.getProperty("user.dir");recordFile = parentPath + "\\record.txt";}/*** 該方法在繼續上局時調用* 用于讀取record.txt 文件,恢復相關信息* @return 敵人坦克信息*/public static Vector<Node> getNodesAndTanks(){try {bufferedReader = new BufferedReader(new FileReader(recordFile));//擊毀數量allEnemyTankTotal = Integer.parseInt(bufferedReader.readLine());//獲取敵人坦克信息String dataLine = "";while ((dataLine = bufferedReader.readLine()) != null){String[] split = dataLine.split(" ");if (split.length == 3){Node node = new Node(Integer.parseInt(split[0]), Integer.parseInt(split[1]), Integer.parseInt(split[2]));nodes.add(node);}}}catch (Exception e){e.printStackTrace();}finally {if (bufferedReader != null){try {bufferedReader.close();} catch (IOException e) {e.printStackTrace();}}}return nodes;}public static void setEnemyTanks(Vector<EnemyTank> enemyTanks) {Recorder.enemyTanks = enemyTanks;}public static int getAllEnemyTankTotal() {return allEnemyTankTotal;}public static void setAllEnemyTankTotal(int allEnemyTankTotal) {Recorder.allEnemyTankTotal = allEnemyTankTotal;}/*** 當我方坦克擊毀一輛敵人坦克,就應當對這個值++*/public static void addlEnemyTankTotal(){allEnemyTankTotal++ ;}/*** 當游戲退出時,我們將 allEnemyTankTotal 保存到*/public static void keepRecord(){try {bufferedWriter = new BufferedWriter(new FileWriter(recordFile));bufferedWriter.write(allEnemyTankTotal+"\r\n");//變量敵人坦克集合,然后根據情況保存//OOP 編程思想,定義一個屬性,通過SET 方法得到敵人的坦克集合if (enemyTanks.size() > 0){for (int i = 0; i < enemyTanks.size(); i++) {EnemyTank enemyTank = enemyTanks.get(i);//為了保險,判斷一下是否存活if (enemyTank.isLive()){//保存enemy坦克信息String record = enemyTank.getX() + " " + enemyTank.getY() + " " + enemyTank.getDirection();bufferedWriter.write(record);bufferedWriter.newLine();}}}}catch (Exception e){e.printStackTrace();}finally {if (bufferedWriter != null){try {bufferedWriter.close();} catch (IOException e) {e.printStackTrace();}}}}public static String getRecordFile() {return recordFile;}public static void setRecordFile(String recordFile) {Recorder.recordFile = recordFile;} }(10)Shot 子彈類
package cn.bloghut.service;/*** @Classname Shot* @Description TODO* @Date 2022/5/8 14:15* @Created by 閑言*/ public class Shot implements Runnable{private int x;//子彈x坐標private int y;//子彈x坐標private int direction = 0;//子彈方向private int speed = 2;//子彈速度private boolean isLive = true; //子彈是否還存活@Overridepublic void run() {//射擊行為while (true){//線程休眠 50 毫秒try {Thread.sleep(50);} catch (InterruptedException e) {e.printStackTrace();}//根據方向來改變x ,y坐標switch (direction){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);//當子彈碰到敵人坦克時,也應該結束線程//當子彈移動到面板的邊界時,銷毀子彈if (!(x >= 0 && x <= 1000 && y >= 0 && y <= 750 && isLive)){//設置子彈是否存活狀態isLive = false;System.out.println("子彈線程退出");break;}}}//構造子彈public Shot(int x, int y, int direction) {this.x = x;this.y = y;this.direction = direction;}public boolean isLive() {return isLive;}public void setLive(boolean live) {isLive = live;}public int getDirection() {return direction;}public void setDirection(int direction) {this.direction = direction;}public int getSpeed() {return speed;}public void setSpeed(int speed) {this.speed = speed;}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;}@Overridepublic String toString() {return "Shot{" +"x=" + x +", y=" + y +", direction=" + direction +", speed=" + speed +", isLive=" + isLive +'}';} }?? 注意:本工程是模塊化進行開發的,所以一些文件( 圖片、存檔路徑、音樂)的路徑需要改成自己對應。
總結
以上是生活随笔為你收集整理的韩顺平--Java坦克大战的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 碧桂园博智林机器人总部大楼_碧桂园职院新
- 下一篇: android webview 图表,A