服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - Java开发实现飞机大战

Java开发实现飞机大战

2022-12-05 16:16小孙仗剑走天涯 Java教程

这篇文章主要为大家详细介绍了Java开发实现飞机大战,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了Java实现飞机大战的具体代码,供大家参考,具体内容如下

一、飞机大战

1 封装所有飞行物公共属性和功能的父类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import java.awt.image.BufferedImag
 
/**
 * 封装所有飞行物的公共属性和功能的父类
 */
public abstract class Flyer {
    protected int x; //飞行物左上角x坐标
    protected int y; //飞行物左上角y坐标
    protected int height; //飞行物的高度
    protected int width; //飞行物的宽度
    protected BufferedImage image; //飞行物的图片
 
    /**
     * 要求所有飞行物必须都能移动
     * 但移动的方式由子类自己实现
     */
    public abstract void step();
 
    /**
     * 检查越界的方法
     * @return 是否越界
     */
    public abstract boolean outOfBounds();
 
    /**
     * 专门检测两个矩形飞行物是否碰撞的工具方法
     * 和具体对象无关,所以定义为静态方法
     * @param f1 飞行对象1
     * @param f2 飞行对象2
     * @return 是否碰撞
     */
    public static boolean boom(Flyer f1,Flyer f2){
        //step1: 求出两个矩形的中心点
        int f1x = f1.x + f1.width/2;
        int f1y = f1.y + f1.height/2;
        int f2x = f2.x + f2.width/2;
        int f2y = f2.y + f2.height/2;
        //step2: 横向和纵向碰撞检测
        boolean H = Math.abs(f1x - f2x) < (f1.width + f2.width)/2;
        boolean V = Math.abs(f1y -f2y) < (f1.height + f2.height)/2;
        //step3: 必须两个方向同时碰撞
        return H&V;
    }
 
}

2 封装英雄机属性和功能类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import java.util.Random;
 
/**
 * 封装英雄机的属性和功能类
 */
public class Hero extends Flyer {
 
    private int doubleFire; //双倍火力子弹数
    private int life; //生命值
    private int score; //得分
 
    //对外提供读取生命值的方法
    public int getLife(){
        return life;
    }
 
    //对外提供的获取得分的方法
    public int getScore(){
        return score;
    }
 
    /**
     * 英雄机对象的无参构造方法
     */
    public Hero(){
        image = ShootGame.hero0;
        height = image.getHeight();
        width = image.getWidth();
        x = 127;
        y = 388;
        doubleFire = 0;
        life = 3;
        score = 0;
    }
 
    /**
     * 实现英雄机的动画效果的方法
     * 让英雄机的图片在hero0和hero1之斗切换
     */
    @Override
    public void step() {
        Random r = new Random();
        if(r.nextInt(2) == 0){
            image = ShootGame.hero0;
        }else{
            image = ShootGame.hero1;
        }
    }
 
    @Override
    public boolean outOfBounds() {
        // TODO Auto-generated method stub
        return false;
    }
 
    /**
     * 英雄机随鼠标移动的方法
     * 要求传入鼠标当前的位置
     * @param x 鼠标位置的x坐标
     * @param y 鼠标位置的y坐标
     */
    public void move(int x,int y){
        //传入的x,y是鼠标的坐标
        //move的作用是让英雄机的中心位置和鼠标位置一致
        this.x = x - width / 2;
        this.y = y - height / 2;
    }
 
    /**
     * 英雄机获得分数或奖励的方法
     * @param f 是一个飞行物父类方法,可以指向敌机或者大飞机
     */
    public void getScore_Award(Flyer f){
        //先判断敌人对象的类型
        if(f instanceof Airplane){ //如果敌人是敌机
            //获得敌机对象中的分数,加到当现分数上
            score += ((Airplane)f).getScore();
        }else{ //如果对象是大飞机
            //继续判断大飞机对象中保存的奖励类型
            if(((BigPlane)f).getAwardType() == BigPlane.DOUBLE_FIRE){
                //如果保存的是双倍火力
                doubleFire += 20;
            }else{
                //如果保存的是生命值奖励
                life += 1;
            }
        }
 
    }
 
    /**
     * 英雄机发射子弹的方法
     * @return 新创建出来的子弹对名
     *          可能是一发,也可能 是两发,用数组保存
     */
    public Bullet[] shoot(){
        Bullet[] bullets = null;
        //何时开启双倍火力:
        if(doubleFire != 0){ //创建双倍火力
            bullets = new Bullet[2];
            Bullet b1 = new Bullet(x + width/4 - ShootGame.bullet.getWidth()/2,y + ShootGame.bullet.getWidth());
            Bullet b2 = new Bullet(x + width*3/4 - ShootGame.bullet.getWidth()/2,y + ShootGame.bullet.getWidth());
            bullets[0] = b1;
            bullets[1] = b2;
            //每创建一个双倍火力,doubleFire-1
            doubleFire -= 1;
        }else{
            //单倍火力:
            //子弹x坐标:x+英雄机宽度/2-子弹宽度/2
            //子弹y坐标:y-子弹高度
            bullets = new Bullet[1];
            bullets[0] = new Bullet(x + width/2 - ShootGame.bullet.getWidth()/2,y - ShootGame.bullet.getHeight());
        }
        return bullets;
    }
 
    /**
     * 英雄机自带和敌人碰撞检测方法
     * @param f 可能发生碰撞的敌人
     *          可能是敌机也可能是大飞机
     * @return 是否碰撞
     */
    public boolean hit(Flyer f){
        //调用碰撞检测方法,检测是否碰撞
        boolean r = Flyer.boom(this, f);
        if(r){ //如果碰撞
            life--;
            doubleFire = 0;
        }
        return r;
    }
 
}

3 封装敌机属性和功能的类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import java.util.Random;
 
/**
 * 封装敌机属性和功能的类
 */
public class Airplane extends Flyer {
 
    private int speed = 2; //敌机每次下落2个单位长度
    private int score = 5; //敌机包含的奖励分数
 
    //对外提供的读取敌机奖励分数的方法
    public int getScore(){
        return score;
    }
 
    /**
     * 敌机类的无参构造方法
     */
    public Airplane(){
        image = ShootGame.airplane;
        width = image.getWidth();
        height = image.getHeight();
        y = -height;
        Random r = new Random();
        x = r.nextInt(ShootGame.WIDTH - width);
    }
 
    @Override
    public void step() {
        //敌机每次向下移动一个speed长度
        y += speed;
    }
 
    @Override
    public boolean outOfBounds() {
        //敌机y坐标>游戏界面,越界
        return y > ShootGame.HEIGHT;
    }
 
}

4 封装大飞机属性和功能的类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import java.util.Random;
 
/**
 * 封装大飞机属性和功能的类
 */
public class BigPlane extends Flyer {
 
    /*定义奖励类型的备选项常量*/
    public static final int DOUBLE_FIRE = 0; //奖励类型是0,说明奖励双倍火力
    public static final int FILE = 1; //奖励类型是1,说明奖励一次生命
 
    /*大飞机类私有成员*/
    private int xspeed = 1; //水平移动的速度为1
    private int yspeed = 2; //垂直移动的速度为2
    private int awardType; //当前大飞机保存的奖励类型
 
    //对外提供的读取大飞机奖励类型的方法
    public int getAwardType(){
        return awardType;
    }
 
    /**
     * 大飞机的无参构造方法
     */
    public BigPlane(){
        //step1: 从主程序中获取大飞机图片的静态变量——bigplane
        image = ShootGame.bigplane;
        //step2: 使用图片宽高设置对象宽高
        width = image.getWidth();
        height= image.getHeight();
        //step3: 设置大飞机开始下落的高度
        y = -height;
        //step4:  大飞机对象开始下落的x坐标在0~(界面宽度 - 大飞机图片宽度)之前随机
        Random r = new Random();
        x = r.nextInt(ShootGame.WIDTH - width);
        //在0和1之间随机先择一种奖励类型
        awardType = r.nextInt(2);
    }
 
    @Override
    public void step() {
        //每次x移动一个xspeed,y移动一个yspeed
        x += xspeed;
        y += yspeed;
        //大飞机不能起出边界,一旦超出那么xspeed*(-1),相当于反向移动
        if(x < 0 || x > ShootGame.WIDTH - width){
            xspeed *= -1;
        }
    }
 
    @Override
    public boolean outOfBounds() {
        //大飞机的y坐标>游戏界面,越界
        return y > ShootGame.HEIGHT;
    }
}

5 子弹类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class Bullet extends Flyer{
 
    private int speed = 5; //子弹上升的速度为3
 
    /**
     * 子弹类的带参构造方法
     * 因为子弹对象创造的位置要根据英雄机的位置决定
     * 所以子弹对名的x和y要从外界传入
     * @param x 英雄机指定子弹创造位置的x坐标
     * @param y 英雄机指定子弹创造位置的y坐标
     */
    public Bullet(int x,int y){
        image = ShootGame.bullet;
        width = image.getWidth();
        height = image.getHeight();
        this.x = x;
        this.y = y;
    }
 
    @Override
    public void step() {
        //子弹每次向上移动一个speed长度
        y -= speed;
    }
 
    @Override
    public boolean outOfBounds() {
        //子弹的y坐标+子弹的高度<0,越界
        return (y + height) < 0;
    }
}

6 飞机大战射击的主方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Arrays;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
 
public class ShootGame extends JPanel {
 
    private static final long serialVersionUID = 1L;
 
    //背景图片的大小320*568
    public static final int WIDTH = 320;
    public static final int HEIGHT = 568;
    //游戏界面固定大小336*607
    public static final int FRAME_WIDTH = 336;
    public static final int FRAME_HEIGHT = 607;
 
    /*
     * 游戏启动第一件事是从硬盘加载所有要用到的图片到内存当中
     * 而且仅在启动时加载一次——静态块
     * 缓存在程序中的所有图片,都会反复使用,仅保存一份——静态变量
     * 下面,为每张图片加载一个静态变量,然后在静态块加加载每张图片
     */
    public static BufferedImage background; //背景图片
    public static BufferedImage start; //开始图片
    public static BufferedImage airplane; //敌机图片
    public static BufferedImage bigplane; //大飞机
    public static BufferedImage hero0; //英雄机状态0
    public static BufferedImage hero1; //英雄机状态1
    public static BufferedImage bullet; //子弹
    public static BufferedImage pause; //暂停图片
    public static BufferedImage gameover; //游戏结束
 
    //静态块,在类加载到方法区时执行一次,专门加载静态资源
    static{
        /*
         * java从硬盘中加载图片到内存中:
         * ImageIO.read方法:专门从硬盘中加载图片的静态方法
         * 不用实例化,直接调用
         * ShootGame.class:获得当前类的加载器所在路径
         * ShootGame.class.getRerource("文件名"); 从当前类所在路径加载指定文件到程序中
         */
        try {
            background = ImageIO.read(ShootGame.class.getResource("background.png"));
            airplane = ImageIO.read(ShootGame.class.getResource("airplane.png"));
            bigplane = ImageIO.read(ShootGame.class.getResource("bigplane.png"));
            bullet = ImageIO.read(ShootGame.class.getResource("bullet.png"));
            start = ImageIO.read(ShootGame.class.getResource("start.png"));
            pause = ImageIO.read(ShootGame.class.getResource("pause.png"));
            hero0 = ImageIO.read(ShootGame.class.getResource("hero0.png"));
            hero1 = ImageIO.read(ShootGame.class.getResource("hero1.png"));
            gameover = ImageIO.read(ShootGame.class.getResource("gameover.png"));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
 
    /*
     * 为游戏中的角色定义数据结构,包括:
     * 1个英雄机对象
     * 1个存储所有敌人(敌机和大飞机)的对象数组
     * 1个存储所有子弹的对象数组
     */
    public Hero hero = new Hero();
    public Flyer[] flyers = {}; //存储所有敌人对象的数组
    public Bullet[] bullets = {}; //存储所有子弹对象的数组
 
    //定义游戏状态:当前状态变量:默认为开始状态
    private int state = START;
    //定义游戏状态的备选项常量:
    public static final int START = 0;
    public static final int RUNNING = 1;
    public static final int PAUSE = 2;
    public static final int GAME_OVER = 3;
 
 
    public static void main(String[] args) {
 
        /*
         * java中绘制窗体:JFrame对象——窗框
         * 要想在窗体中绘制内容,还需要嵌入背景面板——JPanel
         */
        JFrame frame = new JFrame("ShootGame");
        frame.setSize(FRAME_WIDTH,FRAME_HEIGHT);//(336, 607);
        frame.setAlwaysOnTop(true); //设置窗体置顶
        //设置窗体关闭同时,退出程序
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null); //设置窗体的位置,null表示居中
 
        /*在窗体中嵌入背景面板对象——JPanel*/
        ShootGame game = new ShootGame(); //创建背景面板对象
        frame.add(game); //将背景面板对象嵌入到窗体对象中
        /*窗体默认不可见!必须调用setVisible方法才能显示窗体*/
        frame.setVisible(true); //自动调用窗体的paint方法
        game.action();
    }
 
    /**
     * 游戏启动时要做的事
     */
    public void action(){
 
        /*游戏开始时,要定义鼠标事件的监听*/
        //step1: 创建MouseAdapter匿名内部类——事件的响应程序
        MouseAdapter l = new MouseAdapter(){
            //step2: 重写希望的鼠标事件——鼠标移动
            @Override
            public void mouseMoved(MouseEvent e) {
                //只有在RUNNING状态下英雄机才跟随鼠标移动
                if(state == RUNNING){
                    //step3: 获得鼠标新位置
                    int x = e.getX();
                    int y = e.getY();
                    //step4: 将鼠标位置传给英雄机的move方法
                    hero.move(x, y);
                }
            }
 
            @Override
            public void mouseClicked(MouseEvent e) {
                if(state == START || state == PAUSE){ //START或者PAUSE状态,单击才会改改为RUNNING状态
                    state = RUNNING;
                }else if(state == RUNNING){ //游戏点击暂停
                    state = PAUSE;
                }else if(state == GAME_OVER){ //游戏结束后单击,游戏初始化
                    state = START;
                    //从GAME_OVER到START,要重新初始化游戏数据
                    flyers = new Flyer[0];
                    bullets = new Bullet[0];
                    hero = new Hero();
                }
            }
 
 
            @Override
            public void mouseExited(MouseEvent e) {
                if(state == RUNNING){
                    //仅在处于RUNNING状态下,鼠标移出才暂停
                    state = PAUSE;
                }
            }
 
            @Override
            public void mouseEntered(MouseEvent e) {
                if(state == PAUSE){
                    state = RUNNING;
                }
            }
 
        }; //匿名内部类要以分号结尾
        /*step5: 要响应鼠标事件,必须将鼠标事件添加到程序的监听器中*/
        this.addMouseMotionListener(l); //支持鼠标的移动事件,不支持鼠标单击事件
        this.addMouseListener(l);; //支持鼠标单击事件
 
        //step1: 创建定时器
        Timer timer = new Timer();
        //step2: 调用定时器对象的schedule方法,做计划
        //       第一个参数:TimerTask类型的匿名内部类
        //               必须重写run方法——核心——要做什么事
        timer.schedule(new TimerTask(){
            //首先定义一个计时器变量index,记录run方法运行的次数
            private int runTimes = 0;
 
            @Override
            public void run() {
                //除了repaint方法,其余功能只在RUNNING状态下执行
                if(state == RUNNING){
                    //每执行一次run方法,runTimes就+1
                    runTimes++;
 
                    //每500亳秒生成一次敌人
                    if(runTimes % 50 == 0){
                        nextOne(); //自动随机创建敌人对象
                    }
                    //遍历每一个对象,调用对象的step方法,移动一次对象的位置
                    for(int i = 0;i < flyers.length;i++){
                        flyers[i].step();
                    }
 
                    //每300亳秒生成一次子弹
                    if(runTimes % 30 == 0){
                        shoot(); //创建一次子弹
                    }
                    //遍历子弹数组的每一个对象,移动位置
                    for(int i = 0;i < bullets.length;i++){
                        bullets[i].step();
                    }
 
                    //英雄机动画效果
                    hero.step();
 
                    //添加子弹和敌人的碰撞检测
                    boom();
 
                    //英雄机碰撞检测
                    hit();
 
                    //添加越界检测
                    outOfBounds();
                }
                /*强调:只要界面发生变化,必须调用repaint方法重新绘制界面*/
                repaint();
            }
 
        }, 10,10); //界面每隔10亳秒变化一次
 
    }
 
 
    @Override
    public void paint(Graphics g) {
        //step1: 绘制背景图片
        g.drawImage(background, 0, 0, null);
        //step2: 绘制英雄机
        paintHero(g);
        //step3: 批量绘制敌人数组
        paintFlyers(g);
        //step4: 批量绘制子弹数组
        paintBullets(g);
        //绘制分数和生命值
        paintScore_Life(g);
 
        //根据游戏状态绘制不同图片
        if(state == START){
            g.drawImage(start, 0, 0, null);
        }else if(state == PAUSE){
            g.drawImage(pause, 0, 0, null);
        }else if(state == GAME_OVER){
            g.drawImage(gameover, 0, 0, null);
        }
 
    }
 
    /**
     * 绘制英雄机对象的方法
     * @param g 画笔
     */
    public void paintHero(Graphics g){
        g.drawImage(hero.image, hero.x, hero.y, null);
    }
 
    /**
     * 遍历敌人数组,批量绘制所有敌人的方法
     * @param g
     */
    public void paintFlyers(Graphics g){
        for(int i = 0;i < flyers.length;i++){
            g.drawImage(flyers[i].image, flyers[i].x, flyers[i].y, null);
        }
    }
 
    /**
     * 遍历子弹数组,批量绘制所有子弹的方法
     * @param g
     */
    public void paintBullets(Graphics g){
        for(int i = 0;i < bullets.length;i++){
            g.drawImage(bullets[i].image, bullets[i].x, bullets[i].y, null);
        }
    }
 
    /**
     * 随机生成1个敌人对象
     * 每生成一个新敌人, flyers数组就要扩容1
     * 然后将新敌人放入数组最后一个元素
     */
    public void nextOne(){
        Random r = new Random();
        Flyer f = null;
        if(r.nextInt(20) == 0){ //只有随机数取0时才创建大飞机
            f = new BigPlane();
        }else{ //其余全部生成敌机
            f = new Airplane();
        }
        //对flyers数组扩容1
        flyers = Arrays.copyOf(flyers, flyers.length + 1);
        //将新敌人放入数组末尾
        flyers[flyers.length - 1] = f;
    }
 
    /**
     * 获得英雄机对象发射的子弹对象
     * 将新的子弹对象保存到子弹数组中,统一管理
     */
    public void shoot(){
        Bullet[] newBullets = hero.shoot(); //获得英雄机返回的新子弹数组
        //根据返回新子弹的数量,扩容子弹数组
        bullets = Arrays.copyOf(bullets, bullets.length + newBullets.length);
        //从newBullets数组中拷贝所有元素到bullets数组末尾
        System.arraycopy(newBullets, 0, bullets, bullets.length - newBullets.length, newBullets.length);
 
    }
 
    /**
     * 遍历子弹数组和敌人数组,进行碰撞检测
     * 一旦发生碰撞,子弹和敌人都减少一个
     */
    public void boom(){
        for(int i = 0;i < bullets.length;i++){
            for(int j = 0;j < flyers.length;j++){
                if(Flyer.boom(bullets[i], flyers[j])){
                    //为英雄机获得分数和奖励
                    hero.getScore_Award(flyers[j]);
                    //从敌人数组中删除被击中的敌机
                    //step1: 使用敌人数组最后一个元素替换被击中的敌机
                    flyers[j] = flyers[flyers.length - 1];
                    //step2: 压缩数组
                    flyers = Arrays.copyOf(flyers, flyers.length - 1);
                    //从子弹数组中删除击中敌机的子弹
                    bullets[i] = bullets[bullets.length - 1];
                    bullets = Arrays.copyOf(bullets, bullets.length -1);
                    i--; //第发现一次碰撞,子弹就要退一个元素,重新检测当前位置
                    break; //只要发现碰撞就退出当前敌人数组的循环
                }
            }
        }
    }
 
    /**
     * 绘制分数和生命值的方法
     * @param g
     */
    public void paintScore_Life(Graphics g){
        int x = 10; //文字在左上角的x坐标
        int y = 15; //文字在左上角的y坐标
        Font font = new Font(Font.SANS_SERIF,Font.BOLD,14);
        g.setFont(font); //设置字体的画笔对象
        //绘制第一行:分数
        g.drawString("SCORE: " + hero.getScore(), x, y);
        //绘制第二行:生命值,y坐标下移20个单位
        y += 20;
        g.drawString("LIFE: " + hero.getLife(), x, y);
    }
 
    /**
     * 检查所有飞行物是否越界
     */
    public void outOfBounds(){
        //检查所有敌人是否越界
        Flyer[] Flives = new Flyer[flyers.length];
        //遍历敌人数组,将存活的敌人对象存到新数组中
        //设置Flives数组的计数器index: 1.标示下一个存活对象的位置
        //                        2.统计Flives中一共有多少元素
        int index = 0;
        for(int i = 0;i < flyers.length;i++){
            if(!flyers[i].outOfBounds()){ //没有越界的对象
                Flives[index] = flyers[i];
                index++;
            } //遍历结束后:
            //index是存活对象的个数
            //Flives数组里是存活的对象,个数为index
            //把Flives数组压缩为index大小
            //压缩后的新数组 应替换回flyers数组
        }
        flyers = Arrays.copyOf(Flives, index);
 
        //检测所有子弹是否越界
        Bullet[] Blives = new Bullet[bullets.length];
        index = 0;
        for(int i = 0;i < bullets.length;i++){
            if(!bullets[i].outOfBounds()){
                Blives[index] = bullets[i];
                index++;
            }
        }
        bullets = Arrays.copyOf(Blives, index);
    }
 
    /**
     * 遍历敌人数组,判断英雄机和每个敌人是否碰撞
     */
    public void hit(){
        Flyer[] lives = new Flyer[flyers.length];
        //记录存活的敌人
        int index = 0;
        for(int i = 0;i < flyers.length;i++){
            if(!hero.hit(flyers[i])){
                lives[index] = flyers[i];
                index++;
            }
        }
        if(hero.getLife() <= 0){ //如果英雄机生命值小于等于0,游戏结束
            state = GAME_OVER;
        }
        //压缩敌人数组,并替换数组
        flyers = Arrays.copyOf(lives, index);
 
    }
}

二、测试结果

Java开发实现飞机大战

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/m0_66345324/article/details/123249377

延伸 · 阅读

精彩推荐
  • Java教程深入剖析 Java 反序列化漏洞

    深入剖析 Java 反序列化漏洞

    最为出名的大概应该是:15年的 Apache Commons Collections 反序列化远程命令执行漏洞,当初影响范围包括:WebSphere、JBoss、Jenkins、WebLogic 和 OpenNMSd 等知名软件,...

    Java极客技术6762021-10-20
  • Java教程hibernate批量操作实例详解

    hibernate批量操作实例详解

    这篇文章主要介绍了hibernate批量操作,结合实例形式分析了Hibernate实现批量插入,更新及删除等操作的具体实现技巧,需要的朋友可以参考下 ...

    新浪网友3222020-04-12
  • Java教程SSH框架网上商城项目第18战之过滤器实现购物登录功能的判断

    SSH框架网上商城项目第18战之过滤器实现购物登录功能的判断

    这篇文章主要为大家详细介绍了SSH框架网上商城项目第18战:过滤器实现购物登录功能的判断,感兴趣的小伙伴们可以参考一下 ...

    eson_152962020-05-11
  • Java教程Java实现synchronized锁同步机制

    Java实现synchronized锁同步机制

    synchronized是java内置的同步锁实现,本文就详细的介绍一下Java实现synchronized锁同步机制,具有一定的参考价值,感兴趣的可以了解一下...

    看山8072022-03-11
  • Java教程如何使用java写Student类的功能

    如何使用java写Student类的功能

    这篇文章主要介绍了如何使用java写Student类的功能,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可...

    小熊同鞋8082021-09-01
  • Java教程Java中常用的类型转换(推荐)

    Java中常用的类型转换(推荐)

    这篇文章主要介绍了Java中常用的类型转换(推荐)的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下 ...

    27780850011992020-05-19
  • Java教程java二叉查找树的实现代码

    java二叉查找树的实现代码

    这篇文章主要为大家详细介绍了java二叉查找树的实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    evasean2112020-12-14
  • Java教程Java API学习教程之正则表达式详解

    Java API学习教程之正则表达式详解

    正则表达式的强大众所周知,它令程序员的头痛程度也数一数二的。下面这篇文章主要给大家介绍了关于Java API学习教程之正则表达式的相关资料,文中通...

    Single_YAM2442020-12-02