国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

經典再現 基于JAVA平臺開發坦克大戰游戲

2019-11-26 14:11:02
字體:
來源:轉載
供稿:網友

一、需求描述
 1.功能性需求
在功能需求分析階段,我們的主要任務是指定系統必須提供哪些服務,定義軟件完成哪些功能,提供給那些人使用,功能需求是軟件開發的一項基本需求,是需求分析必不可少的一部分。坦克大戰是一款經典游戲了,本游戲學習了一些前輩們的經驗,整體來說講,游戲分為敵我雙方,主要參與戰斗的坦克有玩家控制,敵人坦克可以智能隨機出現在屏幕上,并且移動,發射一定數量的子彈;玩家可以在規定的區域內隨意移動坦克,當有子彈擊中玩家時,玩家死亡,游戲結束;敵人坦克智能運行,敵方坦克由于需要具有一定智能性,隨機出現在屏幕上,自由的轉動例如:碰到邊界知道轉向;子彈的運行:坦克有玩家控制打出,根據不同的坦克位置發射子彈,如果擊中目標,則會產生爆炸效果;在屏幕上面也將消失。

 2.系統性能需求
游戲對于基于計算機系統的性能配置要求是保障能使程序快速,穩定的運行,運行時能夠及時的響應,當游戲中玩家坦克被擊毀,及時提示游戲失敗的信息,能及時有所回應,以滿足游戲的規則需求,另外還要保證玩游戲時候,主窗口的大小是不能夠隨意改動的,保證有可玩性。

 3.功能解決的問題
游戲中需要代碼利用率很好,畢竟是一個實時運行的作品,每毫秒都會有很多個子彈發射,以及很多個坦克的坐標移動,無數次的對比子彈是否擊中坦克,對于鍵盤監聽事件,以及實現線程這個接口,繪圖的重繪刷新等問題;邏輯感需要較強,以及面向對象展現的淋漓盡致;甚至之間的關系搞不清楚,很容易出現意外的情況;游戲中為了使加入一下美觀,增添了爆炸這一現象,那么這就需要當敵人坦克死亡的時候在外面的面板上實現對固定地方圖片進行短暫快速的輪播,實現一個爆炸效果;

總的來說對于坦克大戰所要完成的基本的功能有:圖形化界面、敵我坦克樣式區別、坦克可以發射子彈攻擊對方,但卻不能攻擊隊友,坦克設置一定的生命值;

二、主要功能分析 
在坦克大戰游戲開發過程中,實現的主要的功能;提供給用戶所使用,所以首先要畫出來個坦克。
 1.畫出玩家坦克: 需要在JPanel面板上面設置一張畫紙paint()并用畫筆draw出坦克的大致形狀;
 2.玩家的坦克可以移動: 如果要是坦克運動起來,需要改變坦克的坐標,并且不停的重繪面板,但什么時候讓坦克移動,可以在面板的類中實現事件監聽機制(鍵盤監聽)的接口,當玩家摁下w/d/s/a鍵可以對應上下左右移動;
 3.并在我的畫紙paint()上面畫出敵人坦克;由于敵人坦克與玩家坦克在同一界面,需要畫出在同一畫板上;
 4.玩家的坦克可以發射子彈: 玩家要想發射子彈,要有事件源,便是當用戶摁下J鍵,事件監聽當立刻發射一發子彈,但有需要顯示在用戶的眼前看出效果,所以在面板上面paint()畫出子彈;由于子彈發射出來需要朝著發射放不停的移動,所以不進要一直改變子彈的坐標,還要在子彈速度恰當,所以需要用線程實現,并讓面板的不停重繪,看出效果;
 5.玩家子彈可以連發并且最多發五顆: 玩家若要控制子彈的個數,需要在玩家摁下J鍵時候,來得出當前存活的子彈數量是否小于5,當符合條件,就創建一顆子彈,當玩家發射子彈大小超過五顆,則不再調用系統的開火函數;由于發射子彈不是只發射一顆,所以設置集合存放子彈,開火一次產生一個子彈,知道子彈碰到邊界死亡即是溢出子彈集合;
 6.玩家坦克擊中敵人坦克則消失,并產生爆炸效果;首先要判斷玩家坦克的子彈是否擊中了敵人,所以要有不停判斷擊中敵人的函數,當子彈運行到敵人坦克上,坦克生命需要終結,并產生一顆炸彈,并在paint()畫出炸彈;
 7.敵人的坦克可以智能移動: 如果要是坦克只能移動,需要隨機產生移動方向,由于不停的運動,所以將方法寫入到線程的run函數里面,并控制線程休眠來實現移動速度問題;
 8.敵人坦克以可以發射子彈: 在畫出敵人的同時,在線程中設定一定休眠產生不同方向,不同數量坦克的子彈,并在面板上取出每顆子彈,并畫出;
 9.敵人子彈擊中玩家,玩家消失: 不停的取出敵人的每顆子彈,與玩家坦克進行比對,當子彈觸碰到玩家,玩家爆炸消失;

三、概要設計
 •角色屬性設置

坦克:坦克產生的位置,不同類型坦克的顏色,坦克生命標識符,坦克運動的速度,以及不同方向的坦克;

玩家坦克:繼承坦克基本屬性之后,在次基礎上實現,玩家坦克的自由上下左右移動;以及玩家坦克擁有開火發射子彈這種功能;

敵人坦克:繼承基本坦克屬性之后,需要實現敵人坦克要智能的運動,同時也要在不同位置的坦克對其進行發射子彈線程;

子彈:子彈要有坐標位置,速度,生命值,以及子彈應該可以動,以及子彈也要死亡函數方法的實現;

炸彈:炸彈的坐標,生命,以及生命漸消失的效果方法函數;

 •功能屬性設置

畫紙:paint()應該畫出來玩家坦克,敵人坦克,以及顯示出死亡坦克爆炸效果;

事件監聽:當用戶摁下wdsa,對應的玩家坦克應該進行方向的改變,當用戶發射j則朝發射方向有顆子彈,并且應該一直運行到死亡,除非擊中敵方;

擊中坦克:當子彈擊中到敵方坦克,產生爆炸添加到爆炸集中,并將爆炸信息畫到面紙上;

敵人擊中玩家:取出游戲里所以的敵人,以及每個敵人的子彈與我的坦克去匹配,判斷是否擊中;

玩家擊中敵人:取出玩家的每顆子彈,與每一個敵人的坦克去匹配,判斷是否擊中;并將擊中坦克相關的判斷,放到線程run()里面進行不停并發的判斷;

具體功能分析圖如下:

 •坦克角色屬性分析圖

5

功能畫板分析圖

2

坦克Xmind整體分析圖

1

坦克角色屬性Xmind圖

3

坦克功能屬性Xmind圖

4

6

四、系統實現
 •Members.java

 //Members.javapackage mytank9;import java.util.*;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 = 1;  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){        e.printStackTrace();      }      switch(direct)      {        case 0:          y-=speed;          break;        case 1:          x+=speed;          break;        case 2:          y+=speed;          break;        case 3:          x-=speed;          break;      }//   判斷字段是否碰到邊緣      if(x<0||x>400||y<0||y>300)      {        this.isLive = false;        break;      }    }    }}class Tank{// 坦克橫坐標  int x = 0;// 克縱坐標  int y = 0;// 坦克方向 // 0 表示上,1表示右,2 表示下,3 表示左  int direct = 0;// 坦克速度  int speed = 1;// 坦克顏色  int Color;  boolean isLive = true;  public int getColor() {    return Color;  }  public void setColor(int color) {    Color = color;  }  public int getSpeed() {    return speed;  }  public void setSpeed(int speed) {    this.speed = speed;  }  public int getDirect() {    return direct;  }  public void setDirect(int direct) {    this.direct = direct;  }  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;  }}// 敵人的坦克class EnemyTank extends Tank implements Runnable{    int times = 0;// 定義一個向量,可以存放敵人的子彈  Vector<Shot>ss = new Vector<Shot>();// 敵人添加子彈應該在剛剛創建坦克和敵人的坦克子彈死亡之后  public EnemyTank(int x, int y)  {    super(x, y);   }  @Override  public void run() {    // TODO Auto-generated method stub    while(true)    {        switch(this.direct)        {        case 0:  //       說明坦克正在向上走          for(int i = 0; i < 30; i++)          {//           敵人坦克在我的范圍內移動            if(y>0)            {              y-=speed;            }            try {              Thread.sleep(50);            } catch (InterruptedException e) {              // TODO Auto-generated catch block              e.printStackTrace();            }          }          break;        case 1:          for(int i = 0; i < 30; i++)          {            if(x<400)            {              x+=speed;            }            try {              Thread.sleep(50);            } catch (InterruptedException e) {              // TODO Auto-generated catch block              e.printStackTrace();            }          }          break;        case 2:          for(int i = 0; i < 30; i++)          {            if(y<300)            {              y+=speed;            }            try {              Thread.sleep(50);            } catch (InterruptedException e) {              // TODO Auto-generated catch block              e.printStackTrace();            }          }                  break;        case 3:          for(int i = 0; i < 30; i++)          {            if(x > 0)            {              x-=speed;            }            try {              Thread.sleep(50);            } catch (InterruptedException e) {              // TODO Auto-generated catch block              e.printStackTrace();            }          }              break;        }        //       判斷是否需要給坦克加入新的子彈        this.times++;        if(times%2==0)        {            if(isLive)            {              if(ss.size()<5)              {                Shot s =null;                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 Hero extends Tank{  Vector<Shot> ss = new Vector<Shot>();  Shot s = null;  public Hero(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);      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;  }}

•MyTankGame4.java

 //MyTankGame4.java/* * 功能:坦克游戲2.0 * 1: 畫出坦克 * 2:我的坦克可以上下移動 * 3: 畫出敵人坦克 * 4: 我的坦克可以發子彈  * 5:子彈可以連發(最多可以連發五顆) * 6: 當我的坦克擊中敵人坦克時候,敵人消失(爆炸 *       『 判斷子彈是否擊中坦克;什么時候調用;』 *       爆炸:1先準備三張圖;2定義Bomb類;3在擊中敵人坦克時放入炸彈Vector 4繪制 * 7: 敵人坦克在我規定范圍移動 * 8:敵人坦克也能發子彈 * 9: 當敵人坦克擊中我的坦克,我的坦克消失 */package mytank9;import java.awt.*;import javax.imageio.ImageIO;import javax.swing.*;import java.awt.event.*;import java.io.File;import java.util.*;public class MyTankGame4 extends JFrame{  MyPanel mp = null;  public static void main(String[] args) {    // TODO Auto-generated method stub    MyTankGame4 mytankgame1 = new MyTankGame4();  }  public MyTankGame4(){    mp = new MyPanel();     Thread t = new Thread(mp);    t.start();    this.add(mp);//   注冊監聽    this.addKeyListener(mp);    this.setSize(400, 300);    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    this.setVisible(true);  }}class MyPanel extends JPanel implements KeyListener,Runnable{// 定義一個我的坦克  Hero hero = null;// 定義敵人的坦克  Vector<EnemyTank> ets = new Vector<EnemyTank>();// 定義一個炸彈的集合  Vector<Bomb> bombs = new Vector<Bomb>();// 敵人坦克多少  int enSize = 3;// // 定義三張圖片的圖片的切換,才能組成一顆炸彈  Image image1 = null;  Image image2 = null;  Image image3 = null;// 構造  public MyPanel(){    hero = new Hero(100,100);//   敵人的坦克初始化    for(int i = 0; i <enSize; i++)    {//     創建敵人的坦克對象      EnemyTank et = new EnemyTank((i+1)*50, 0);      et.setColor(0);      et.setDirect(2);//     啟動敵人坦克      Thread t = new Thread(et);      t.start();//     給敵人坦克談價一顆子彈      Shot s = new Shot(et.x+10,et.y+30,2);      et.ss.add(s);      Thread t2 = new Thread(s);      t2.start();//     加入      ets.add(et);    }    try{      image1 = ImageIO.read(new File("bomb_1.gif"));      image2 = ImageIO.read(new File("bomb_2.gif"));      image3 = ImageIO.read(new File("bomb_3.gif"));    }catch(Exception e){      e.printStackTrace();    }//   初始化三張圖片//   image1 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_1.gif"));//   image2 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_2.gif"));//   image3 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_3.gif"));  }  //重新paint  public void paint(Graphics g){    super.paint(g);    g.fillRect(0, 0, 400, 300);//   畫出自己的坦克    if(hero.isLive==true)    {      this.drawTank(hero.getX(), hero.getY(), g, this.hero.direct, 1);    }//   從ss中取出每一顆子彈,并繪制    for(int i = 0; i <hero.ss.size(); i++)    {//     取出子彈      Shot myShot = hero.ss.get(i);//   畫出子彈 畫出一顆子彈,怎么畫出多子彈?遍歷      if(myShot!=null&&myShot.isLive==true)      {        g.draw3DRect(myShot.x, myShot.y, 1, 1, false);      }      if(myShot.isLive==false)      {//       從ss向量中刪除該子彈        hero.ss.remove(myShot);      }    }//   畫出炸彈    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);      }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踢出去      if(b.life == 0)      {        bombs.remove(b);      }    }//   畫出敵人坦克    for(int i = 0 ; i < ets.size(); i++)    {      EnemyTank et = ets.get(i);      if(et.isLive)      {        this.drawTank(et.getX(), et.getY(), g,et.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{//            敵人坦死亡了             et.ss.remove(enemyShot);           }        }      }    }  }// 敵人子彈是否擊我  public void hitMe()  {// 取出每一個敵人坦克    for(int i = 0; i < this.ets.size(); i++)    {//     取出敵人坦克      EnemyTank et = ets.get(i);      if(et.isLive==true)      {        for(int j = 0; j < et.ss.size(); j++)        {  //       取出子彈          Shot enemyShot = et.ss.get(j);          if(enemyShot.isLive==true)          {            this.hitTank(enemyShot, hero);          }        }      }    }  }// 我的子彈是否擊中敵人坦克  public void hitEnemyTank()  {//   判斷是否擊中敵人的坦克    for(int i = 0; i < hero.ss.size(); i++)    {      Shot myShot = hero.ss.get(i);//     判斷子彈是否有效      if(myShot.isLive==true)      {//       取出每一個坦克與它判斷        for(int j = 0; j < ets.size(); j++)        {          EnemyTank et = ets.get(j);          if(et.isLive==true)          {            this.hitTank(myShot,et);          }        }      }    }  }// 寫一個函數專門判斷子彈是否擊中坦克  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;//         創建一顆炸彈,放入Vector          Bomb b = new Bomb(et.x, et.y);          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;            Bomb b = new Bomb(et.x, et.y);            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://       畫出左邊坦克        g.fill3DRect(x, y, 5, 30, false);//       畫出右邊坦克        g.fill3DRect(x+15, y, 5, 30, false);//       畫出中間矩形        g.fill3DRect(x+5, y+5, 10, 20, false);//       畫出原形        g.fillOval(x+5, y+10, 10, 10);//       畫出直線        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://       畫出下邊坦克        g.fill3DRect(x, y, 5, 30, false);//       畫出右邊坦克        g.fill3DRect(x+15, y, 5, 30, false);//       畫出中間矩形        g.fill3DRect(x+5, y+5, 10, 20, false);//       畫出原形        g.fillOval(x+5, y+10, 10, 10);//       畫出直線        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, y+10);        break;    }  }//對鍵摁下做出處理啊 a向左 s 向下 d向右 w向上   @Override  public void keyTyped(KeyEvent e) {    // TODO Auto-generated method stub  }  @Override  public void keyPressed(KeyEvent e) {    // TODO Auto-generated method stub    if(e.getKeyCode()==KeyEvent.VK_W)    {      this.hero.setDirect(0);      this.hero.moveUP();    }else if(e.getKeyCode()==KeyEvent.VK_D)    {      this.hero.setDirect(1);      this.hero.moveRight();    }else if(e.getKeyCode()==KeyEvent.VK_S)    {      this.hero.setDirect(2);      this.hero.moveDown();    }    else if(e.getKeyCode()==KeyEvent.VK_A)    {      this.hero.setDirect(3);      this.hero.moveLeft();    }    if(e.getKeyCode()==KeyEvent.VK_J)    { //     判斷玩家是否摁下J//       開火      if(this.hero.ss.size()<=4&&this.hero.isLive==true)      {        this.hero.shotEnemy();      }    }//   必須重新繪制Panel    this.repaint();  }  @Override  public void keyReleased(KeyEvent e) {    // TODO Auto-generated method stub  }  public void run(){    while(true)    {      try{        Thread.sleep(100);      }catch(Exception e)      {        e.printStackTrace();      }      this.hitEnemyTank();//     函數判斷敵人的子彈是否擊中我      this.hitMe();      this.repaint();    }  }}

五、測試效果

黃色為玩家,擊中玩家

1

敵人發射子彈

2

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 平江县| 万荣县| 弥勒县| 馆陶县| 响水县| 东兰县| 云和县| 江源县| 轮台县| 克山县| 五莲县| 舟山市| 九台市| 东港市| 泸水县| 江安县| 平山县| 永兴县| 松江区| 嘉义县| 天柱县| 石林| 周口市| 丰都县| 鄂尔多斯市| 浦江县| 汤原县| 民权县| 渭源县| 普宁市| 金川县| 新干县| 梁山县| 宣威市| 博罗县| 通化市| 项城市| 盘锦市| 龙山县| 双柏县| 肇庆市|