Java窗口游戏开发,飞机大战,打飞机,打大飞机,打无敌飞机妙啊!!!!————————香啊~~~~~~~~~~~~~~~~~

Elizabeth ·
更新时间:2024-11-10
· 951 次阅读

身无分文宅家,细发日渐稀疏。 双亲日益劳累,奈何无心寻工。 复试遥遥无期,心情惨惨戚戚。 若问此时作甚?抽烟喝酒扣叮。 ---杂记 2020/3/25-2020/4/12 矫情下,莫认真 接下来奉上近日学习内容 在这里插入图片描述
ok这也是本人的一幅作品,有兴趣的同学可以收藏下。。。。
哈哈哈哈

这些天,我不是很想复习专业课,想打游戏,但是吧,我想我说是个程序员预备役,但是还没自己写过一个小游戏,一直都是做网页开发,搞搞业务逻辑,不妨试试做个游戏??

我在开始之前其实是有思路的,游戏的效果,就是后台逻辑控制出来的,先不谈3D或者其他的复杂的,我感觉如此。就是张图片,然后有攻击力度和敌人的血量,打一下调多少血,或者没血了,敌人消失。我们把敌人图片从游戏界面删除即可。

(其实应该不是那么简单的吧。
各位大神有空可在评论区当面打我脸,本人欢迎。)
在这里插入图片描述
那么放在Java中这个敌人吧,我们可以抽象个类。
然后一个界面里面肯定不止有一个敌人,这是肯定的,那么我们就需要一个容器去存储在界面上有效的敌人,然后当敌人无效时(无效就是说敌人被打死,或者说敌人不在游戏界面我们打不到时),我们将无效的敌人对象删除。
ok,我们再来分析下我们的大业务
英雄机----------我们的主角
敌人--------------小型敌人(一个5分,血量为1),中型敌人(20分之一的概率一个20分,血量为4),大型敌人(满1000出现一个,且血量随着1000的出现而上涨最低为8,一个得20分).‘’奖励敌人‘’(给双倍火力,或者是加一条命)
业务流程没啥好说的,就跟微信我们玩过的一样,见到打就是,然后看最后的得分,和敌人碰到就死,敌人不会发子弹(MD要是敌人会发子弹,我这游戏水平,根本打不到1000分。我是菜鸡,自己弄得游戏也打不好,虽然我可以不死,但这不就没意思了嘛。 )
说句题外话,后面两个敌人一开始是没有的,我随便打,就没死过,除非故意。
但是加上中型还好,加上大型的之后。吼吼吼没超过5000分。。。
在这里插入图片描述
到目前为止
我们分析了有,英雄机,3个敌人,1个‘’奖’励敌人‘’,一共5个实体了吧
那么问题来了
请问,子弹算不算一个实体?
说是英雄机可以装子弹,但是这是游戏,它的子弹是我们给他画出来的。于是,根据找类的原则:

需要维护一定的状态和有一定的行为

那么子弹也要飞的,子弹和敌人碰到,敌人也会减命的这是子弹的行为
子弹的状态是,它的飞行速度和他的图片。
在这里插入图片描述
OK
我们接下来再提取几个公共的功能,抽象出来一个父类。他们都会飞,自己的飞机,子弹和所有敌人都是可以飞的,除了自己的飞机,是由鼠标控制的之外,其他的都有飞行这一选项,
我们用程序模拟这些除自己的飞机之外的类飞行,就是在面板上定时移动其图片,给人感觉他就在移动一样——(是不是说破了就很无聊。。。)
注意了子弹是从下往上打的,敌人是从上往下落的,所以我们对于这个方法,我们要给他声明为抽象方法,然后我们在各自的类进行不同的实现。
对于敌人我们统一再声明个接口,里面存放,敌人生命是否已死,以及得分。这样也方便我们以后添加新的敌人。
对于‘’奖励敌人‘’也是
我们声明一个接口,然后实现该接口,方便日后新增‘’奖励敌人‘’。

下面就是这些类的具体实现啦。 首先是接口和父类 import java.awt.image.BufferedImage; public abstract class FlyingObject { /* * 位置x,y, 大小width length 图片image 每个对象都有这些东西,所以给抽象称父类 */ protected BufferedImage image; protected int width; protected int height; protected int x; protected int y; /** * 飞行物起飞 */ public abstract void step(); /** * 检查是否出界 * * @return true 越界,false不越界 */ public abstract boolean outOfBounds(); /** * 敌人被子弹射 this 代表敌人,bullet是子弹 */ public boolean shootBy(Bullet bullet) { int x1 = this.x; int x2 = x1 + this.width; int y1 = this.y; int y2 = this.y + this.height; int x = bullet.x; int y = bullet.y; return x > x1 && x y1 && y < y2; } } public interface Enemy { // 只要是敌人就能得分,小鸡5分,Boss20分 public int getScore(); public void subtractLife(); public boolean isDie(); public int getLife(); } public interface Award { // 双倍火力值 public int DOUBLE_FILE = 0; public int LIFE = 1; // 获取奖励类型 public int getType(); } 这是各类实体的具体实现 import java.awt.image.BufferedImage; import java.util.Random; public class Hero extends FlyingObject { // 命 private int life; // 火力值 private int doubleFire; // 图片数组 private BufferedImage[] images; // 协助图片切换 private int index; // 构造方法 public Hero() { image = PlaneGame.hero1; width = image.getWidth(); height = image.getHeight(); x = 150; y = 400; life = 3; doubleFire = 0; images = new BufferedImage[2]; images[0] = PlaneGame.hero0; images[1] = PlaneGame.hero1; index = 0; } @Override public void step() { // 10ms走一次 // 100ms换一张图 /* * index++; int a=index/10; int b=a%2; image=images[b]; */ image = images[index++ / 10 % images.length]; } /** * 英雄机发射子弹 */ public Bullet[] shoot() { int xStep = this.width / 4; if (doubleFire > 0) { Bullet[] bs = new Bullet[2]; bs[0] = new Bullet(x + xStep, y); bs[1] = new Bullet(x + (3 * xStep), y); doubleFire -= 2; return bs; } else if (doubleFire x1 && x < x2 && y y1; } public boolean isDie() { // TODO 自动生成的方法存根 return life == 0; } } import java.util.Random; public class Airplane extends FlyingObject implements Enemy { private int speed = 2;// 走步的步数 public int life = 1; // 构造方法 public Airplane() { image = PlaneGame.airplane; width = image.getWidth(); height = image.getHeight(); Random rand = new Random(); // x位于0到窗口宽-敌机宽之间的随机数 x = rand.nextInt(PlaneGame.WIDTH - this.width); y = -this.height; } @Override public int getScore() { // 打掉一个敌机得5分 life--; return 5; } @Override public void step() { y = y + speed;// 敌机向下坠 } public boolean isDie() { return life = PlaneGame.HEIGHT; } @Override public int getLife() { // TODO 自动生成的方法存根 return life; } } import java.util.Random; public class Boss extends FlyingObject implements Enemy { public int life; private int speed; public Boss() { this.life = 5; this.speed = 1; image = PlaneGame.boss; height = image.getHeight(); width = image.getWidth(); Random rand = new Random(); // x位于0到窗口宽-敌机宽之间的随机数 x = rand.nextInt(PlaneGame.WIDTH - this.width); y = -this.height; } @Override public int getScore() { // TODO 自动生成的方法存根 return 30; } public boolean isDie() { return life = PlaneGame.HEIGHT; } @Override public int getLife() { // TODO 自动生成的方法存根 return life; } } import java.util.Random; public class BigBoss extends FlyingObject implements Enemy { public int life = 10; public int speed; public BigBoss(int k) { this.life = this.life * k; this.speed = 1; image = PlaneGame.bigboss; height = image.getHeight(); width = image.getWidth(); Random rand = new Random(); // x位于0到窗口宽-敌机宽之间的随机数 x = rand.nextInt(PlaneGame.WIDTH - this.width); y = -this.height; } @Override public int getScore() { // TODO 自动生成的方法存根 return 200; } @Override public void subtractLife() { life = life - 1; } @Override public boolean isDie() { // TODO 自动生成的方法存根 return life <= 0; } @Override public int getLife() { // TODO 自动生成的方法存根 return life; } @Override public void step() { if (y = PlaneGame.WIDTH - this.width) { // 到窗口最右边,弹回来 xSpeed = -1; } if (x = PlaneGame.HEIGHT; } } import java.util.Random; public class Bullet extends FlyingObject { // 走步步数 private int speed = 3; // 构造方法 // 子弹的x,y根据英雄机走 public Bullet(int x, int y) { image = PlaneGame.bullet; width = image.getWidth(); height = image.getHeight(); this.x = x; this.y = y; } @Override public void step() { // 子弹向上飞 y = y - speed; } @Override public boolean outOfBounds() { // TODO 自动生成的方法存根 return (this.y + this.height) <= 0; } public boolean isDie() { // TODO 自动生成的方法存根 return false; } } 接下来就是业务流程

这部分不算难,只要前面的理解了,这部分的思路很清晰的
具体的业务流程在代码注释里,我写的很清楚哦

package com.jjyu.shoot; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.image.BufferedImage; import java.io.File; 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 PlaneGame extends JPanel { // 窗口宽 public static final int WIDTH = 400; // 窗口高 public static final int HEIGHT = 654; // 背景图 public static BufferedImage background; // 启动图 public static BufferedImage start; // 暂停图 public static BufferedImage pause; // 结束 public static BufferedImage gameover; // 敌机 public static BufferedImage airplane; // Boss飞机 public static BufferedImage boss; //1000分后的超大飞机 public static BufferedImage bigboss; // 蜜蜂 public static BufferedImage bee; // 子弹 public static BufferedImage bullet; // 英雄机0 public static BufferedImage hero0; // 英雄机1 public static BufferedImage hero1; // 开始状态 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; // 当前默认状态 private int state = START; // 英雄机对象 private Hero hero = new Hero(); // 敌人机数组 private FlyingObject[] flyings = {}; // 子弹数组 private Bullet[] bullets = {}; public PlaneGame() { } static { // 初始化静态资源(图片) try { // File file=new File(""); // ImageIO.read(file); background = ImageIO.read(PlaneGame.class .getResource("background.png")); start = ImageIO.read(PlaneGame.class.getResource("start.png")); pause = ImageIO.read(PlaneGame.class.getResource("pause.png")); gameover = ImageIO .read(PlaneGame.class.getResource("gameover.png")); airplane = ImageIO .read(PlaneGame.class.getResource("airplane.png")); bee = ImageIO.read(PlaneGame.class.getResource("bee.png")); boss = ImageIO.read(PlaneGame.class.getResource("boss.png")); bigboss=ImageIO.read(PlaneGame.class.getResource("bigboss.png")); bullet = ImageIO.read(PlaneGame.class.getResource("bullet.png")); hero0 = ImageIO.read(PlaneGame.class.getResource("hero0.png")); hero1 = ImageIO.read(PlaneGame.class.getResource("hero1.png")); } catch (Exception e) { e.printStackTrace(); } } /** * 满1000分来个大Boss * @return 10分之2的概率产生小蜜蜂,20分之1的概率产生大Boss,10分之7的概率产生敌机 */ public FlyingObject nextOne() { if(score!=0&&score%1000==0){ return new BigBoss(score/1000); } Random rand = new Random(); int type = rand.nextInt(200); if (type <= 20) { return new Bee(); } else if (type <= 30) { return new Boss(); } else { return new Airplane(); } } // 敌人入场计数器 int flyEnteredIndex = 0; /** * 生成敌人对象,将对象添加到flying数组中 敌人入场 */ protected void enterAction() { flyEnteredIndex++; if (flyEnteredIndex % 40 == 0) { // 400毫秒走一次 FlyingObject one = nextOne(); // 敌人数组扩容 flyings = Arrays.copyOf(flyings, flyings.length + 1); // 将敌人放在数组最后 flyings[flyings.length - 1] = one; } } /** * 英雄机发射子弹 */ int shootIndex = 0; protected void shootAction() { shootIndex++; if (shootIndex % 30 == 0) { // 300ms一发子弹 Bullet[] bs = hero.shoot(); bullets = Arrays.copyOf(bullets, bullets.length + bs.length); // for(int i=0;i<bs.length;i++){ // bullets[bullets.length-i-1]=bs[i]; // } // 数组的追加 System.arraycopy(bs, 0, bullets, bullets.length - bs.length, bs.length); } } /** * 飞行物飞,10ms走一步 */ protected void stepAction() { hero.step(); for (int i = 0; i < flyings.length; i++) { flyings[i].step(); } for (int i = 0; i < bullets.length; i++) { bullets[i].step(); } } /** * 删除越界敌人和子弹 */ protected void outOfBoundsAction() { // 不越界的敌人个数 int index = 0; FlyingObject[] flyingLives = new FlyingObject[flyings.length]; for (int i = 0; i < flyings.length; i++) { if (!flyings[i].outOfBounds()) { flyingLives[index] = flyings[i]; index++; } } // System.out.println(index); flyings = Arrays.copyOf(flyingLives, index); index = 0; Bullet[] b = new Bullet[bullets.length]; for (Bullet btemp : bullets) { if (!btemp.outOfBounds()) { b[index] = btemp; index++; } } // System.out.println(index); bullets = Arrays.copyOf(b, index); } /** * 所有子弹与所有敌人的碰撞 */ protected void bangAction() { for (int i = 0; i < bullets.length; i++) { // 获取每一个子弹 Bullet b = bullets[i]; int lenBefore = flyings.length; // 1个子弹和所有敌人的碰撞 // 说明子弹被用啦 if (bang(b)) { bullets[i] = bullets[bullets.length - 1]; bullets[bullets.length - 1] = b; bullets = Arrays.copyOf(bullets, bullets.length - 1); i--; } } } /** * 1个子弹与所有敌人的碰撞 * * @param b */ // 得分 int score = 0; protected boolean bang(Bullet b) { int index = -1; for (int i = 0; i < flyings.length; i++) { FlyingObject f = flyings[i]; if (f.shootBy(b)) { // 获取被撞的敌人坐标 index = i; break; } } if (index != -1) { // 获取被撞的敌人 FlyingObject one = flyings[index]; if (one instanceof Enemy) { Enemy e = (Enemy) one; // 玩家加分 System.out.println(e.getLife()); e.subtractLife(); System.out.println(e.getLife()); if(e.isDie()){ System.out.println(e.getLife()); score += e.getScore(); // 将被撞敌人与数组最后一个元素交换 FlyingObject t = flyings[index]; flyings[index] = flyings[flyings.length - 1]; flyings[flyings.length - 1] = t; // 缩容 flyings = Arrays.copyOf(flyings, flyings.length - 1); } } if (one instanceof Award) { Award a = (Award) one; int type = a.getType(); switch (type) { case Award.LIFE: hero.addLife(); break; case Award.DOUBLE_FILE: hero.addDoubleFire(); break; } // 将被撞敌人与数组最后一个元素交换 FlyingObject t = flyings[index]; flyings[index] = flyings[flyings.length - 1]; flyings[flyings.length - 1] = t; // 缩容 flyings = Arrays.copyOf(flyings, flyings.length - 1); } return true; } return false; } /** * 检查游戏结束 */ protected void checkGameOverAction() { // TODO 自动生成的方法存根 if (isGameOver()) { state = GAME_OVER; } } /** * 是否游戏结束 返回true则游戏结束 * * @return */ public boolean isGameOver() { for (int i = 0; i < flyings.length; i++) { FlyingObject f = flyings[i]; if (hero.hit(f)) { hero.subtractLife(); hero.clearDoubleFire(); // 被撞后敌人数组的变化 flyings[i] = flyings[flyings.length - 1]; flyings = Arrays.copyOf(flyings, flyings.length - 1); i--; } } return hero.getLife() <= 0; } public void action() { // 创建侦听器对象 MouseAdapter l = new MouseAdapter() { /** * 重写鼠标移动事件 * * @param e */ public void mouseMoved(MouseEvent e) { if (state == RUNNING) { // 英雄机随便动 // 获取鼠标的x坐标 int x = e.getX(); // 获取鼠标的y坐标 int y = e.getY(); hero.moveTo(x, y); } } /** * 重写鼠标移出事件 */ public void mouseExited(MouseEvent e) { if (state == RUNNING) state = PAUSE; } /** * 重写鼠标移入事件 */ public void mouseEntered(MouseEvent e) { if (state == PAUSE) { state = RUNNING; } } public void mouseClicked(MouseEvent e) { switch (state) { case START: state = RUNNING; break; case GAME_OVER:// 游戏结束状态前 // 所有数据归0 score = 0; hero = new Hero(); flyings = new FlyingObject[0]; bullets = new Bullet[0]; state = START; break; } } }; // 鼠标操作事件 this.addMouseListener(l); // 鼠标移动事件 this.addMouseMotionListener(l); Timer timer = new Timer(); int intervel = 10;// 时间间隔,毫秒为单位 timer.schedule(new TimerTask() { @Override public void run() { if (state == RUNNING) { shootAction();// 子弹入场 // 定时干的那个事,每10个毫秒的事 enterAction(); // 飞行物定时飞 stepAction(); // 删除越界的敌人和子弹 outOfBoundsAction(); // 子弹与敌人撞 bangAction(); // 检查游戏是否结束 checkGameOverAction(); } repaint(); } }, intervel, intervel); } @Override // g当做画笔 public void paint(Graphics g) { // 画背景图 g.drawImage(background, 0, 0, null); // 画英雄机 paintHero(g); // 画子弹对象 paintBullets(g); // 画敌人对象 paintFlyingObjects(g); // 画分和命 paintScoreAndLife(g); // 画状态 paintState(g); } /** * 画状态 * * @param g */ public void paintState(Graphics g) { switch (state) { case START: g.drawImage(start, 0, 0, null); break; case PAUSE: g.drawImage(pause, 0, 0, null); break; case GAME_OVER: g.drawImage(gameover, 0, 0, null); } } public void paintHero(Graphics g) { // 画英雄机 g.drawImage(hero.image, hero.x, hero.y, null); } public void paintBullets(Graphics g) { // 画子弹对象 for (int i = 0; i < bullets.length; i++) { Bullet b = bullets[i]; g.drawImage(b.image, b.x, b.y, null); } } public void paintFlyingObjects(Graphics g) { // 画敌人(敌机,小蜜蜂)对象 for (int i = 0; i < flyings.length; i++) { FlyingObject fo = flyings[i]; g.drawImage(fo.image, fo.x, fo.y, null); } } /** * 画英雄机得分和命 * * @param g */ public void paintScoreAndLife(Graphics g) { g.setColor(new Color(0xffff00)); g.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 20)); g.drawString("得分: " + score, 10, 600); g.drawString("飞机复活次数: " + hero.getLife(), 10, 580); } public static void main(String[] args) { // 创建了框架,窗口 JFrame frame = new JFrame("Fly"); // 创建了面板 PlaneGame game = new PlaneGame(); // 向窗口中加入面板 frame.add(game); // 设置窗口的大小 frame.setSize(WIDTH, HEIGHT); // 设置是否总在顶部 frame.setAlwaysOnTop(true); // 设置默认关闭,关闭窗口时,退出程序 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 设置相对位置为null时居中,否则在屏幕的定点 frame.setLocationRelativeTo(null); // 1、设置窗口可见 2、尽快调用paint()方法 frame.setVisible(true); // 启动程序执行 game.action(); } }

在这里插入图片描述

在这里插入图片描述
素质三连啊,小伙伴们。
素质三连》》》
点赞,关注,收藏》》》》
三连。
阅读辛苦。点赞再走
skr~~


作者:JJyu可及



飞机大战 游戏开发 JAVA

需要 登录 后方可回复, 如果你还没有账号请 注册新账号