• 坦克大战(完结篇)


    一、系统简介

    使用JAVA语言编写一个人机交互的游戏——坦克大战。该游戏由玩家和电脑双方操作,其中玩家有1辆坦克,但是玩家的坦克有三条命,电脑的坦克在第一关有3辆坦克,第二关有5辆坦克并且坦克的移动速度和子弹的移动速度会比第一关加快,因而难度增加,每一辆坦克只有一条生命。玩家可以通过键盘控制坦克进行移动和发射子弹,电脑坦克通过JAVA语言编写的线程和算法来控制它们自由运动并自动发射子弹,并且电脑的坦克不会重叠运动,当检测到电脑坦克中心距离小于h+15时,坦克会根据算法来改变方向。玩家坦克在没有进行任何操作的情况下处于无敌状态,一旦玩家坦克开始移动或者发射子弹的时候,玩家的坦克就取消无敌状态。玩家的坦克被电脑的坦克击中时有爆炸效果并丧失一条命,按下enter键时可以在原地复活玩家的坦克(前提是玩家的坦克三条生命未用尽),当玩家的坦克生命为0时,游戏就结束,当电脑的所有坦克死亡时,自动进入第二关玩家的坦克生命也会重置为3条生命,第二关所有电脑坦克死亡时玩家获得游戏胜利。

    二、需求分析

       利用JAVA语言实现人机图形交互界面的坦克大战游戏。坦克大战游戏涉及到图片的显示,按键检测,图形界面的设计,图形的设计,算法的设计,多线程操作等技术。

    2.1 功能需求分析

     游戏由玩家和电脑双方操作不同的坦克,坦克种类分为两种,即敌方坦克与我方坦克。我方坦克与子弹通过键盘来控制,而敌方坦克在存活的情况下,可随机自由移动,其中子弹也随机发射。而且我方坦克与敌方的移动都在活动范围内,敌方坦克将要触碰边界时随机自动转换方向,并且敌方坦克坦克也不能出现重叠的现象,即两坦克距离过近时,分别改变方向。

    子弹:子弹也分为玩家坦克子弹和敌方坦克子弹,玩家坦克由玩家控制空格键发射;敌方坦克由敌方坦克随机发射。敌方子弹击中玩家坦克时会有爆炸效果子弹沿直线移动,且超出活动范围时,自动消失。

    方向:坦克与子弹均有四个方向「上0、下—1、左—2、右—3」,并且子弹的方向由坦克的方向决定。

    2.2 界面需求分析

    坦克大战中,为了能清晰的统计双方坦克的数量和生命,就在边界外画出统计的坦克。并且能让玩家更好的体验和操作,就在里面设计了游戏说明。游戏中为了美观,坦克被击败后能更好体验出爆炸效果,我们就引入图片并把图片画到游戏当中。坦克游戏开始界面也是很重要的,所以我们就设计坦克大战一直闪烁,直到单击开始游戏。

    三、系统设计

              3.1 游戏设计

              3.2 UML类图设计

              3.3 界面关系图

    、详细设计

    Tank.java

      1 package tankgames;
      2 
      3 import java.awt.*;
      4 import java.util.ArrayList;
      5 
      6 //创建坦克类
      7 public class Tank {
      8     int x,y,w,h;
      9     int speed;
     10     int direct;
     11     boolean isLive = true;
     12     int life = 3;
     13     Color c1,c2,c3;
     14     
     15     public Tank(){
     16         x=250;
     17         y=400;
     18         w=5;
     19         h=60;
     20         speed=5;
     21         direct=0;
     22     
     23     }
     24 
     25     public Tank(int x, int y, int w, int direct) {
     26         super();
     27         this.x = x;
     28         this.y = y;
     29         this.w = w;
     30         this.h =this.w*12;
     31         this.speed = 5;
     32         this.direct = direct;
     33     }
     34 }
     35 
     36 //创建我的坦克子类
     37 class MyTank extends Tank{
     38     //我的坦克数量
     39     public int size = 3;
     40     //判斷我的坦克是否处于无敌状态
     41     public boolean invincible = true;
     42     //创建颜色对象,并设置颜色
     43     public MyTank(){
     44         this.c1 = new Color(128,128,128);
     45         this.c2 = new Color(0,255,0);
     46         this.c3 = new Color(0,0,255);
     47     }
     48     
     49     public MyTank(int x, int y, int w, int direct) {
     50         super(x, y, w, direct);
     51         this.c1 = new Color(128,128,128);
     52         this.c2 = new Color(0,255,0);
     53         this.c3 = new Color(0,0,255);
     54     }
     55     //创建子弹集合
     56     ArrayList<Shot> ss = new ArrayList<Shot>();
     57     Shot s = null;
     58     //创建子弹,并启动
     59     public void shotEnemyTank(){
     60         //根据坦克的方向确定子弹方向和位置
     61         switch(direct){
     62             case 0: s = new Shot((x-1)+4*w,y,direct);ss.add(s);break;
     63             case 1: s = new Shot(x+h,(y-1)+4*w,direct);ss.add(s);break;
     64             case 2: s = new Shot((x-1)+4*w,y+h,direct);ss.add(s);break;
     65             case 3: s = new Shot(x,(y-1)+4*w,direct);ss.add(s);break;
     66         }
     67         Thread t = new Thread(s);
     68         t.start();
     69     }
     70 }
     71 
     72 //敌人坦克类
     73 class EnemyTank extends Tank implements Runnable{
     74     //敌人坦克的集合
     75     ArrayList<EnemyTank> ets = new ArrayList<EnemyTank>();
     76     //敌人子弹的集合(静态子弹集合)
     77     public static ArrayList<Shot> ss = new ArrayList<Shot>();
     78     public EnemyTank(){
     79         this.c1 = new Color(128,128,128);
     80         this.c2 = new Color(0,255,0);
     81         this.c3 = new Color(0,0,255);
     82     }
     83     
     84     public EnemyTank(int x, int y, int w, int direct) {
     85         super(x, y, w, direct);
     86         this.speed = 3;
     87         this.c1 = new Color(200,200,120);
     88         this.c2 = new Color(0,255,127);
     89         this.c3 = new Color(200,0,0);
     90     }
     91     //获取MyPanel的敌人坦克集合
     92     public void setEts(ArrayList<EnemyTank> ets){
     93         this.ets = ets;
     94     }
     95     //判断坦克之间有没有接触,有就改变方向
     96     public boolean isTouchOtherTank(Tank t){
     97         for(int i=0;i<ets.size();i++){
     98             EnemyTank et = ets.get(i);
     99             if(et != this){
    100                 //判断et和当前坦克的距离,若距离<h+15,则改变方向
    101                 if(distance(t,et)<h+15){
    102                     //距离小于坦克的长度+10时修改坦克的方向
    103                     //direct = (direct+1)%4;
    104                     return true;
    105                 }
    106             }
    107         }
    108         return false;
    109     }
    110     //计算两坦克的距离
    111     private int distance(Tank t1, Tank t2) {
    112         Point p1,p2;
    113         p1 = centerPoint(t1);
    114         p2 = centerPoint(t2);
    115         return (int)(Math.sqrt((p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y)));
    116     }
    117     //返回坦克的中心点
    118     public Point centerPoint(Tank t){
    119         Point p = new Point(0,0);
    120         if(t.direct == 0 || t.direct == 2){
    121             p.x = t.x+4*t.w;
    122             p.y = t.y+6*t.w;
    123         }
    124         else if(t.direct == 1 || t.direct == 3){
    125             p.x = t.x+6*t.w;
    126             p.y = t.y+4*t.w;
    127         }
    128         return p;
    129     }
    130     //让敌人坦克移动的线程
    131     @Override
    132     public void run() {
    133         //让坦克运动
    134         int num = 0;
    135         Tank t;     //t为移动后的坦克
    136         while(true){
    137             t = new Tank(x,y,w,direct);
    138             switch(t.direct){
    139             case 0:t.y -= this.speed;break;
    140             case 1:t.x += this.speed;break;
    141             case 2:t.y += this.speed;break;
    142             case 3:t.x -= this.speed;break;
    143             }
    144             if(isTouchOtherTank(t)){
    145                 changeDirect();     //若重叠则改变方向
    146             }
    147             else{
    148                 x = t.x;
    149                 y = t.y;
    150             }
    151             if(num == 50 || isToBorder()){
    152                 //当坦克沿着一个方向移动一段时间或到达边界后,就改变方向
    153                 num = 0;
    154                 changeDirect();         //改变坦克方向
    155             }
    156             num++;
    157             try {
    158                 Thread.sleep(50);
    159             } catch (Exception e) {}
    160             //添加子弹
    161             if(this.isLive && ss.size()<50 && num%10 == 0){
    162                 Shot s = null;
    163                 switch(direct){
    164                 case 0:s = new Shot((x-1)+4*w,y,direct);break;
    165                 case 1:s = new Shot(x+h,(y-1)+4*w,direct);break;
    166                 case 2:s = new Shot((x-1)+4*w,y+h,direct);break;
    167                 case 3:s = new Shot(x,(y-1)+4*w,direct);break;
    168                 }
    169                 ss.add(s);
    170                 Thread t1 = new Thread(s);
    171                 t1.start();
    172             }
    173         }
    174     }
    175     //坦克改变方向
    176     private void changeDirect() {
    177         int d = (int)(Math.random()*4);
    178         if(d == direct){
    179             direct = (direct+1)%4;
    180         }
    181         else
    182             direct = d;
    183     }
    184     //判断坦克是否到达边界
    185     private boolean isToBorder() {
    186         switch (direct) {
    187         case 0:if(y<4*w)return true;break;
    188         case 1:if(x+h>600-4*w)return true;break;
    189         case 2:if(y+h>500-4*w)return true;break;
    190         case 3:if(x<4*w)return true;break;
    191         }
    192         return false;
    193     }
    194 }
    195 
    196 //创建子弹类
    197 class Shot implements Runnable{
    198     int x;
    199     int y;
    200     int direct;
    201     int speed = 10;
    202     boolean isLive = true;
    203     
    204     public Shot(int x,int y,int direct){
    205         this.x = x;
    206         this.y = y;
    207         this.direct = direct;
    208     }
    209     
    210     //子弹自动移动
    211     @Override
    212     public void run() {
    213         while(true){
    214             //子弹的线程,每50毫秒移动一次
    215             try {
    216                 Thread.sleep(50);
    217             } catch (Exception e) {}
    218             //判断子弹的方向
    219             switch(direct){
    220             case 0:y -= speed;break;
    221             case 1:x += speed;break;
    222             case 2:y += speed;break;
    223             case 3:x -= speed;break;
    224             }
    225             //判断子弹的存活
    226             if(x<=0||y<=0||x>=600||y>=500){
    227                 isLive = false;
    228                 break;
    229             }
    230         } 
    231     }
    232 }

    TankGame.java

      1 package tankgames;
      2 
      3 import java.awt.*;
      4 import java.awt.event.ActionEvent;
      5 import java.awt.event.ActionListener;
      6 import java.awt.event.KeyEvent;
      7 import java.awt.event.KeyListener;
      8 import java.util.ArrayList;
      9 import javax.swing.*;
     10 
     11 public class TankGame extends JFrame implements ActionListener{
     12     private static final long serialVersionUID = 1L;
     13     
     14     boolean startnum = false;//判断是否第一次执行开始游戏菜单
     15     MyPanel mp;
     16     MyStartPanel msp = null;
     17 //  MyStartPanel myStartPanel = new MyStartPanel();
     18     JMenuBar jmb = null;        //菜单条
     19     JMenu jm1 = null;           //菜单
     20     JMenuItem jmi1 = null;      //菜单项
     21 
     22     public static void main(String[] args) {
     23         new TankGame().setVisible(true);
     24 
     25     }
     26     
     27     public TankGame(){
     28         this.setTitle("坦克大战");
     29         this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     30         this.setResizable(false);
     31         this.setBounds(200, 50, 750, 650);
     32         
     33         //创建我的开始面板对象,并添加到我的窗体里面
     34         msp = new MyStartPanel();
     35         this.add(msp);
     36         this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     37         this.setVisible(true);
     38         Thread t = new Thread(msp);
     39         t.start();
     40         
     41         //创建菜单
     42         jmb = new JMenuBar();
     43         jm1 = new JMenu("游戏(G)");
     44         jm1.setMnemonic('G');       //设置快捷键
     45         jmi1 = new JMenuItem("开始新游戏(N)");
     46         jmi1.setMnemonic('N');      //快捷键
     47         jm1.add(jmi1);          //将菜单项添加到菜单中
     48         jmb.add(jm1);           //将菜单添加到菜单条中
     49         this.setJMenuBar(jmb);  //将菜单条添加到窗体中
     50         
     51         //注册键盘事件监听
     52 //      this.addKeyListener(mp);
     53         jmi1.addActionListener(this);//为开始新游戏菜单项注册监听
     54         jmi1.setActionCommand("newgame");//设置其ActionCommand值为"newgame"
     55     }
     56 
     57     @Override
     58     public void actionPerformed(ActionEvent e) {
     59         if(e.getActionCommand().equals("newgame")){
     60             if(startnum){//如果不是第一次执行,则先清空敌人的坦克及其子弹
     61                 while(!mp.ets.isEmpty()){
     62                     mp.ets.get(0).isLive = false;
     63                     mp.ets.get(0).life = 0;
     64                     mp.ets.remove(0);
     65 //              this.remove(mp);
     66                 }
     67                 while(!EnemyTank.ss.isEmpty()){
     68                     EnemyTank.ss.get(0).isLive = false;
     69                     EnemyTank.ss.remove(0);
     70                 }
     71                 this.remove(mp);//移除上一次的游戏面板
     72             }
     73             else{
     74                 this.remove(msp);//移除开始面板
     75             }
     76             startnum = true;
     77             mp = new MyPanel();
     78             Thread t = new Thread(mp);
     79             t.start();
     80             this.remove(msp);
     81             this.add(mp);
     82             this.addKeyListener(mp);
     83             
     84             Tank et =mp.ets.get(0);
     85             this.setVisible(true);
     86         }
     87     }
     88 }
     89 
     90 //创建开始面板
     91 class MyStartPanel extends JPanel implements Runnable{
     92     int times = 0;          //用于控制显示
     93     public void paint(Graphics g){
     94         super.paint(g);
     95         g.fillRect(0, 0, 750, 650);
     96         //提示信息
     97         if(times%2 == 0){
     98             g.setColor(Color.yellow);
     99             //开关信息的字体
    100             Font myFont = new Font("华文新魏",Font.BOLD,90);
    101             g.setFont(myFont);
    102             g.drawString("坦克大战", 180, 290);
    103         }
    104     }
    105     @Override
    106     public void run() {
    107         while(true){
    108             try {
    109                 Thread.sleep(150);
    110             } catch (Exception e) {}
    111             times++;
    112             //重画
    113             this.repaint();
    114         }
    115     }
    116 }
    117 
    118 //创建我的面板子类
    119 class MyPanel extends JPanel implements KeyListener,Runnable{
    120     private static final long serialVersionUID = 1L;
    121     int time = 0;
    122     int level = 1;//用于进入第二关
    123     int total = 0;//用于统计击中的敌人坦克总数
    124     //我的坦克
    125     MyTank myTank;
    126     //敌人的坦克
    127     public static int ensize = 3;
    128     public static int ensize2 = 5;
    129     ArrayList<EnemyTank> ets = new ArrayList<EnemyTank>();
    130     //爆炸的图片
    131     Image image1 = null;
    132     Image image2 = null;
    133     Image image3 = null;
    134     
    135     //将组件添加到面板容器里
    136     public MyPanel(){
    137         this.setLayout(null);
    138         //创建我的坦克
    139         myTank = new MyTank();
    140         //创建敌人的坦克
    141         for(int i=0;i<ensize;i++){
    142             EnemyTank et = new EnemyTank(50+i*150,10,5,2);
    143             Thread t = new Thread(et);
    144             t.start();
    145             ets.add(et);
    146             et.setEts(ets);
    147         }
    148         //爆炸图片
    149         image1 = Toolkit.getDefaultToolkit().getImage(this.getClass().getResource("bomb_1.gif"));
    150         image2=Toolkit.getDefaultToolkit().getImage(this.getClass().getResource("bomb_2.gif"));
    151         image3=Toolkit.getDefaultToolkit().getImage(this.getClass().getResource("bomb_3.gif"));
    152     }
    153     
    154     //在面板容器里画出组件
    155     public void paint(Graphics g){
    156         super.paint(g);
    157         //画边界
    158         g.setColor(new Color(20,20,20));
    159         g.fill3DRect(0, 0, 600, 500, false);
    160         //画我的坦克
    161         if(myTank.isLive){
    162             drawTank(myTank,g);
    163         }
    164         else if(myTank.life>0){
    165             drawBomb(myTank, g);
    166         }
    167         // 画敌人的坦克
    168         for (int i = 0; i < ets.size(); i++) {
    169             EnemyTank et = ets.get(i);
    170             if (et.isLive) {
    171                 drawTank(et, g);
    172                 // 画出敌人坦克的子弹
    173                 for (int j = 0; j < et.ss.size(); j++) {
    174                     Shot s = et.ss.get(j);
    175                     if (s.isLive) {
    176                         g.setColor(new Color(200, 0, 0));
    177                         g.fill3DRect(s.x, s.y, 2, 2, false);
    178                     } else {
    179                         et.ss.remove(s);
    180                     }
    181                 }
    182             } else if (et.life > 0) {
    183                 drawBomb(et, g);
    184             } 
    185             else {
    186                 ets.remove(et);
    187             }
    188         }
    189         //画出我的坦克子弹
    190         for(int i=0;i<myTank.ss.size();i++){
    191             //从子弹集合中取出子弹
    192             Shot myShot = myTank.ss.get(i);
    193             //若子弹集不空,且子弹没有消失,画出子弹
    194             if(myShot != null && myShot.isLive == true){
    195                 g.setColor(new Color(0,0,150));
    196                 g.draw3DRect(myShot.x, myShot.y, 2, 2, false);
    197             }
    198             //子弹消失,从子弹集中删除该子弹
    199             else if(myShot != null && myShot.isLive == false){
    200                 myTank.ss.remove(myShot);
    201             }
    202         }
    203         //画爆炸效果
    204         g.drawImage(image1, 0, 0, 1, 1,this);
    205         //画出提示信息
    206         this.showInfo(g);
    207         //游戏说明
    208         g.setColor(Color.black);
    209         g.drawString("操作说明",615,250);
    210         String str[] = { "   退出   ESC","   向上      ↑ /  W", "   向下      ↓ /  S", "   向左      ← /  A", "   向右      → /  D", "   发射子弹    空格","   原地复活    Enter" };
    211         for(int i=0;i<str.length;i++){
    212             g.drawString(str[i],605,280+30*i);
    213         }
    214         
    215         // 如果我的坦克三条命都用完,游戏结束
    216         if (myTank.size == 0) {
    217             for (int i = 0; i < ets.size(); i++) {
    218                 ets.remove(i);
    219             }
    220             g.setColor(Color.black);
    221             g.fillRect(0, 0, 600, 500);
    222             // 提示信息
    223             if (time % 2 == 0)// 通过显示或不显示产生闪光效果
    224             {
    225                 g.setColor(Color.red);
    226                 // 开关信息的字体
    227                 Font myFont = new Font("仿宋", Font.BOLD, 50);
    228                 g.setFont(myFont);
    229                 g.drawString("Game over!", 200, 250);
    230             }
    231         }
    232         
    233         // 如果将敌人的坦克都击灭,进入到第二关
    234         if (total == ensize && level == 1) {
    235 
    236             myTank = new MyTank();
    237             // 创建敌人的坦克
    238             for (int i = 0; i < ensize2; i++) {
    239                 EnemyTank et = new EnemyTank(15+i*100,10,5,2);
    240                 et.speed=5;
    241                 ets.add(et);
    242                 Thread t = new Thread(et);
    243                 t.start();
    244                 // 将MyPanel的敌人坦克向量交给该敌人坦克
    245                 et.setEts(ets);
    246             }
    247             level = 0;
    248         }
    249         
    250         if (total == 3 + ensize2) {
    251             g.setColor(Color.black);
    252             g.fillRect(0, 0, 600, 500);
    253             // 提示信息
    254             if (time % 2 == 0)// 通过显示或不显示产生闪光效果
    255             {
    256                 g.setColor(Color.CYAN);
    257                 // 开关信息的字体
    258                 Font myFont = new Font("仿宋", Font.BOLD, 50);
    259                 g.setFont(myFont);
    260                 g.drawString("胜利!!", 200, 250);
    261             }
    262         }
    263     }
    264     
    265     //画坦克
    266     public void drawTank(Tank t,Graphics g){
    267         int x = t.x, y = t.y, w = t.w, h = 12*t.w;
    268         //画出向上的坦克
    269         if(t.direct == 0){
    270             Graphics2D g2d = (Graphics2D)g;
    271             g.setColor(t.c1);
    272             g.fill3DRect(x, y, w, h, false);
    273             g.fill3DRect(x+7*w, y, w, h, false);
    274             g.setColor(t.c2);
    275             g.fill3DRect(x+w, y+2*w, 6*w, 8*w, false);
    276             g.fillOval(x+2*w, y+4*w, 4*w, 4*w);
    277             g2d.setColor(t.c3);
    278             g2d.setStroke(new BasicStroke(5.0f));
    279             g2d.drawLine(x+4*w, y, x+4*w, y+6*w);
    280         }
    281         //画出向下的坦克
    282         else if(t.direct == 2){
    283             Graphics2D g2d = (Graphics2D)g;
    284             g.setColor(t.c1);
    285             g.fill3DRect(x, y, w, h, false);
    286             g.fill3DRect(x+7*w, y, w, h, false);
    287             g.setColor(t.c2);
    288             g.fill3DRect(x+w, y+2*w, 6*w, 8*w, false);
    289             g.fillOval(x+2*w, y+4*w, 4*w, 4*w);
    290             g2d.setColor(t.c3);
    291             g2d.setStroke(new BasicStroke(5.0f));
    292             g2d.drawLine(x+4*w, y+6*w, x+4*w, y+12*w);
    293         }
    294         //画出向左的坦克
    295         else if(t.direct == 3){
    296             Graphics2D g2d = (Graphics2D)g;
    297             g.setColor(t.c1);
    298             g.fill3DRect(x, y, h, w, false);
    299             g.fill3DRect(x, y+7*w, h, w, false);
    300             g.setColor(t.c2);
    301             g.fill3DRect(x+2*w, y+w, 8*w, 6*w, false);
    302             g.fillOval(x+4*w, y+2*w, 4*w, 4*w);
    303             g2d.setColor(t.c3);
    304             g2d.setStroke(new BasicStroke(5.0f));
    305             g2d.drawLine(x, y+4*w, x+6*w, y+4*w);
    306         }
    307         //画出向右的坦克
    308         else if(t.direct ==1){
    309             Graphics2D g2d = (Graphics2D)g;
    310             g.setColor(t.c1);
    311             g.fill3DRect(x, y, h, w, false);
    312             g.fill3DRect(x, y+7*w, h, w, false);
    313             g.setColor(t.c2);
    314             g.fill3DRect(x+2*w, y+w, 8*w, 6*w, false);
    315             g.fillOval(x+4*w, y+2*w, 4*w, 4*w);
    316             g2d.setColor(t.c3);
    317             g2d.setStroke(new BasicStroke(5.0f));
    318             g2d.drawLine(x+6*w, y+4*w, x+12*w, y+4*w);
    319         }
    320     }
    321     
    322     //判断子弹是否击中坦克
    323     public boolean isHitTank(Shot s,Tank t){
    324         switch(t.direct){
    325         case 0:
    326         case 2:
    327             if(s.x>t.x&&s.x<t.x+8*t.w&&s.y>t.y&&s.y<t.y+t.h){
    328                 s.isLive = false;
    329                 t.isLive = false;
    330                 return true;
    331             }
    332             break;
    333         case 1:
    334         case 3:
    335             if(s.x>t.x&&s.x<t.x+t.h&&s.y>t.y&&s.y<t.y+8*t.w){
    336                 s.isLive = false;
    337                 t.isLive = false;
    338                 return true;
    339             }
    340             break;
    341         }
    342         return false;
    343     }
    344     
    345     //判断我的子弹是否击中敌人的坦克
    346     public void hitEnemyTank(){
    347         Shot s = null;
    348         for(int i=0;i<myTank.ss.size();i++){
    349             s = myTank.ss.get(i);
    350             if(s.isLive){
    351                 for(int j=0;j<ets.size();j++){
    352                     EnemyTank et =ets.get(j);
    353                     if(et.isLive){
    354                         if(this.isHitTank(s, et)){
    355                             total++;
    356                         }
    357                     }
    358                 }
    359             }
    360         }
    361     }
    362     //判断敌人坦克的子弹是否击中我的坦克
    363     public boolean hitMyTank(){
    364         for(int i=0;i<ets.size();i++){
    365             EnemyTank et = ets.get(i);
    366             for(int j=0;j<et.ss.size();j++){
    367                 Shot s = et.ss.get(j);
    368                 if(myTank.isLive){
    369                     if(isHitTank(s, myTank)){
    370                         return true;
    371                     }
    372                 }
    373             }
    374         }
    375         return false;
    376     }
    377     //画爆炸效果方法
    378     public void drawBomb(Tank t ,Graphics g){
    379         if(t.life>2){
    380             g.drawImage(image1, t.x, t.y, 90, 90, this);
    381         }
    382         else if(t.life>1){
    383             g.drawImage(image2, t.x, t.y, 60, 60, this);
    384         }
    385         else if(t.life>0){
    386             g.drawImage(image3, t.x, t.y, 30, 30, this);
    387         }
    388         t.life--;
    389     }
    390     //画出提示信息
    391     public void showInfo(Graphics g){
    392         g.drawString("剩余生命值", 10, 560);
    393         //敌方tank剩余生命值
    394         EnemyTank et=new EnemyTank(80,530,4,0);
    395         this.drawTank(et, g);
    396         int t = 0;
    397         for (int i = 0; i < ets.size(); i++) {
    398             EnemyTank et1 = ets.get(i);
    399             if (et1.isLive)
    400                 t++;
    401         }
    402         g.drawString(t + "", 125, 560);
    403         //myTank剩余生命值
    404         MyTank mt = new MyTank(300, 530, 4, 0);
    405         this.drawTank(mt, g);
    406         g.drawString(myTank.size + "", 345, 560);
    407         //my得分
    408         mt.x = 630;
    409         mt.y = 100;
    410         this.drawTank(mt, g);
    411         g.setColor(Color.red);
    412         g.drawString("你的成绩为:", 620, 85);
    413         g.drawString(total + "", 645, 180);
    414     }
    415     @Override
    416     public void keyTyped(KeyEvent e) {
    417         
    418     }
    419     //我的坦克移动
    420     @Override
    421     public void keyPressed(KeyEvent e) {
    422         //向左移动
    423         if(e.getKeyCode() == KeyEvent.VK_LEFT || e.getKeyCode() == KeyEvent.VK_A && myTank.isLive){
    424             if(!(myTank.x<=0)){
    425             myTank.x -= myTank.speed;
    426             myTank.direct = 3;
    427             myTank.invincible = false;
    428             }
    429             else{
    430                 myTank.x = myTank.x;
    431                 myTank.direct = 3;
    432             }
    433         }
    434         //向右移动
    435         else if(e.getKeyCode() == KeyEvent.VK_RIGHT || e.getKeyCode() == KeyEvent.VK_D && myTank.isLive){
    436             myTank.invincible = false;
    437             if(myTank.x<600-myTank.h){
    438                 myTank.x += myTank.speed;
    439                 myTank.direct = 1;
    440             }
    441             else{
    442                 myTank.x = myTank.x;
    443                 myTank.direct = 1;
    444             }
    445         }
    446         //向上移动
    447         else if(e.getKeyCode() == KeyEvent.VK_UP || e.getKeyCode() == KeyEvent.VK_W && myTank.isLive){
    448             myTank.invincible = false;
    449             if(!(myTank.y<=0)){
    450                 myTank.y -= myTank.speed;
    451                 myTank.direct =0;
    452             }
    453             else{
    454                 myTank.y = myTank.y;
    455                 myTank.direct = 0;
    456             }
    457         }
    458         //向下移动
    459         else if(e.getKeyCode() == KeyEvent.VK_DOWN || e.getKeyCode() == KeyEvent.VK_S && myTank.isLive){
    460             myTank.invincible = false;
    461             if(myTank.y<500-myTank.h){
    462                 myTank.y += myTank.speed;
    463                 myTank.direct = 2;
    464             }
    465             else{
    466                 myTank.y = myTank.y;
    467                 myTank.direct = 2;
    468             }
    469         }
    470         //发射子弹
    471         else if(e.getKeyCode() == KeyEvent.VK_SPACE && myTank.isLive){
    472             //最多可连发5枚子弹
    473             if(myTank.ss.size() < 5){
    474                 myTank.shotEnemyTank();
    475                 myTank.invincible = false;
    476             }
    477         }
    478         //关闭游戏
    479         else if(e.getKeyCode() == KeyEvent.VK_ESCAPE){
    480             System.exit(0);
    481         }
    482         //按回車鍵,我的坦克原地復活
    483         else if(e.getKeyCode() == KeyEvent.VK_ENTER && myTank.isLive == false && myTank.size>0){
    484             myTank.isLive = true;
    485             myTank.life = 3;
    486             myTank.invincible = true;
    487         }
    488         //刷新图形
    489         this.repaint();
    490     }
    491 
    492     @Override
    493     public void keyReleased(KeyEvent e) {}
    494 
    495     @Override
    496     public void run() {
    497         while(true){
    498             try {
    499                 Thread.sleep(100);
    500             } catch (Exception e) {}
    501             if(myTank.isLive && myTank.invincible == false){
    502             //击中目标坦克
    503             this.hitEnemyTank();
    504             //敌人坦克击中我的坦克
    505             if(this.hitMyTank()){
    506                 myTank.size--;
    507                 }
    508             }
    509             time++;
    510             //重绘
    511             this.repaint();
    512         }
    513     }
    514 }

    五、运行结果

     

     github下载地址:https://github.com/HCychao

  • 相关阅读:
    javaBean为什么要实现Serializable接口?
    OpenLayers3的WMS空间查询实现多个图层
    (WPS) 网络地理信息处理服务
    window.open跳过浏览器拦截
    linux改权限
    element-ui MessageBox的bug
    element-ui上传文件带token
    MySQL启动出现The server quit without updating PID file错误解决办法
    重装应用商店
    vscode在vue-cli中按照ESlint自动格式化代码
  • 原文地址:https://www.cnblogs.com/HHHY/p/10492811.html
Copyright © 2020-2023  润新知