坦克大战(完结篇)

一、系统简介

使用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

 

posted on 2019-03-08 21:09  HHH燕  阅读(1959)  评论(0编辑  收藏  举报

导航