1.关于这个飞机大战

学Java有一段时间了,然后通过Java开发了一些简易安卓APP。最近很想实现以前自己很想写的飞机大战,也练练手。代码和界面参考(抄袭 )了许多,毕竟天下码农一家亲。
游戏大概长下面这样,鼠标点击即开始游戏,然后用鼠标操作飞机移动(鼠标到哪飞机移动到哪,超出游戏界面就暂停)。

2.代码实现

  1. 首先写几个bean。GameStateBean里面存放了一些游戏状态的常量,ImgBean里面存放了游戏所用到的图片资源,这些图片和代码放在同一个包下。
package xyz.xinghai.game.bean;public class GameStateBean {//游戏启动public static final int START = 0;//游戏运行public static final int RUNNING = 1;//游戏暂停public static final int PAUSE = 2;//游戏结束public static final int GAMEOVER = 3;
}
package xyz.xinghai.game.bean;import java.awt.image.BufferedImage;
import java.io.IOException;import javax.imageio.ImageIO;public class ImgBean {public static BufferedImage backgroundImg;//游戏启动图public static BufferedImage startImg;//游戏暂停图public static BufferedImage pauseImg;//游戏结束图public static BufferedImage gameOverImg;//敌机图public static BufferedImage enemyImg;public static BufferedImage beeImg;//子弹图public static BufferedImage bulletImg;public static BufferedImage hero0Img;public static BufferedImage hero1Img;public static BufferedImage bigBeeImg;static {try {backgroundImg = ImageIO.read(ImgBean.class.getResource("background.png"));startImg = ImageIO.read(ImgBean.class.getResource("start.png"));pauseImg = ImageIO.read(ImgBean.class.getResource("pause.png"));gameOverImg = ImageIO.read(ImgBean.class.getResource("gameover.png"));enemyImg = ImageIO.read(ImgBean.class.getResource("airplane.png"));beeImg = ImageIO.read(ImgBean.class.getResource("bee.png"));bulletImg = ImageIO.read(ImgBean.class.getResource("bullet.png"));hero0Img = ImageIO.read(ImgBean.class.getResource("hero0.png"));hero1Img = ImageIO.read(ImgBean.class.getResource("hero1.png"));bigBeeImg = ImageIO.read(ImgBean.class.getResource("bigBee.png"));} catch (IOException e) {e.printStackTrace();}}
}
  1. 游戏中的飞行物体都有显示图片、高度、宽度、在游戏界面中的坐标(x、y)属性和移动(move)、是否飞出游戏界面(outOfBounds)方法。基于这些共同点编写飞行物体的抽象类FlyingObject,所有飞行的物体都继承这个类。
package xyz.xinghai.game;import java.awt.image.BufferedImage;/*** 飞行物体的抽象类*/
public abstract class FlyingObject {//飞行物的图片protected BufferedImage image; //飞行物的宽度protected int width;//飞行物的高度protected int height;//飞行物的x坐标protected int x;//飞行物的y坐标protected int y;//飞行物的移动public abstract void move();//是否飞出游戏界面public abstract boolean outOfBounds();//判断是否被击中 这个不是所有飞行物都有 所以不是抽象方法public boolean shootBy(Bullet bullet) {int x = bullet.x;int y = bullet.y;return (x > this.x && x < (this.x + this.width)) && (y > this.y && y < (this.y + this.height));}
}
  1. 编写游戏中的子弹类和主飞机类。继承自FlyingObject,获得了它的Object属性然后重新abstract方法。因为子弹由主飞机从下面打到上面的,所有子弹移动的时候就是y的坐标根据速度减,判断是否超出了游戏界面也就是直接判断它的y坐标是否小于它的-height。编写主飞机类时,加了doubleFire(值越大飞机打子弹越多)、life(飞机生命)等属性。因为使用鼠标控制主飞机,所以它在移动的时候只是改变了了显示图片,鼠标移到哪里直接调用moveTo方法移动到鼠标的位置即可。
package xyz.xinghai.game;import xyz.xinghai.game.bean.ImgBean;/*** 子弹类**/
public class Bullet extends FlyingObject {//子弹速度private int speed = 3;/*** @param x 游戏界面上的x坐标* @param y 游戏界面上的y坐标*/public Bullet(int x, int y) {this.image = ImgBean.bulletImg;this.width = this.image.getWidth();this.height = this.image.getHeight();this.x = x;this.y = y;}@Overridepublic void move() {this.y -= speed;}@Overridepublic boolean outOfBounds() {return this.y <= -this.height;}
}
package xyz.xinghai.game;import java.awt.image.BufferedImage;import xyz.xinghai.game.bean.ImgBean;public class Hero extends FlyingObject {private int life;private int doubleFire;private BufferedImage[] images;private int index;public Hero() {this.image = ImgBean.hero0Img;this.width = this.image.getWidth();this.height = this.image.getHeight();x = 150;y = 400;life = 3;doubleFire = 0;images = new BufferedImage[]{ImgBean.hero0Img,ImgBean.hero1Img};index = 0;}@Overridepublic void move() {image = images[index++/10%images.length];}@Overridepublic boolean outOfBounds() {return false;}/*** 根据doubleFire的值打不同数目的子弹* @return 子弹数组*/public Bullet[] shoot() {int xSpeed = this.width / 4;int ySpeed = 20;if (doubleFire >= 100) {//三粒子弹 子弹的初始位置不同Bullet[] bs=new Bullet[3];bs[0] = new Bullet(this.x + 1 * xSpeed, this.y - ySpeed);bs[1] = new Bullet(this.x + 2 * xSpeed, this.y - ySpeed);bs[2] = new Bullet(this.x + 3 * xSpeed, this.y - ySpeed);doubleFire -= 2;return bs;} else if (doubleFire < 100 && doubleFire > 0) {Bullet[] bs=new Bullet[2];//两粒子弹bs[0]=new Bullet(this.x + 1* xSpeed, this.y - ySpeed);bs[1]=new Bullet(this.x + 3* xSpeed, this.y - ySpeed);doubleFire -= 2;return bs;} else{//一粒子弹Bullet[] bs = new Bullet[1];bs[0] = new Bullet(this.x + 2 * xSpeed, this.y - ySpeed);return bs;}}/*** 飞机移到指定坐标去* @param x x坐标* @param y y坐标*/public void moveTo(int x, int y) {this.x=x-this.width/2;this.y=y-this.height/2;    }public void addLife(){life+=2;}public int getLife(){return life;}/*** 加火力*/public void addDoubleFire(){doubleFire += 20;}public int getDoubleFire(){return doubleFire;}/*** 生命减少*/public void subtractLife(){life--;}/*** 回到最初的发子弹速度*/public void clealDoubleFire(){doubleFire = 0;}/*** 是否发生碰撞* @param other 其他继承自FlyingObject的飞行物* @return*/public boolean hit(FlyingObject other) {int x1 = other.x - this.width/2;int x2 = other.x + this.width/2 + other.width;int y1 = other.y - this.height/2;int y2 = other.y + this.height/2 + other.height;int x = this.x + this.width/2;int y = this.y + this.height;return (x>x1&&x<x2) && (y>y1&&y<y2);}
}
  1. 编写敌人(打败敌机获得分数)和游戏中奖励(打败带有奖励的敌人获得奖励)的接口。
package xyz.xinghai.game;/*** 敌人接口**/
public interface Enemy {public int getScore();
}
package xyz.xinghai.game;/**1. 奖励接口2.  */
public interface Award {int DOUBLE_FIRE = 0;int LIFE = 1;//生命public int getType();
}
  1. 编写敌机类、游戏中击败有奖励敌机(击败后子弹打得更多)和游戏中较强的敌机(击败后得分更多)。敌机添加了速度和击败得分属性,由于敌机是从游戏界面上面移动到下面的,所以在移动的时候y坐标要随着速度增大。
package xyz.xinghai.game;import java.util.Random;import xyz.xinghai.game.bean.ImgBean;/*** 敌机类**/
public class EnemyPlane extends FlyingObject implements Enemy {//速度private int speed = 2;//得分private int score = 5;public EnemyPlane() {this.image = ImgBean.enemyImg;this.width = this.image.getWidth();this.height = this.image.getHeight();//随机初始化敌机位置Random random = new Random();x = random.nextInt(AircraftBattle.WIDTH - this.width);y = -this.height;}public int getScore() {return score;}@Overridepublic void move() {y += speed;}@Overridepublic boolean outOfBounds() {return this.y >= AircraftBattle.HEIGHT;}public void setScore(int score) {this.score = score;}
}
package xyz.xinghai.game;import java.util.Random;import xyz.xinghai.game.bean.ImgBean;/*** 打败后奖励积分更多**/
public class BigBee extends FlyingObject implements Enemy {private int speed = 1;public BigBee() {this.image = ImgBean.bigBeeImg;this.width = this.image.getWidth();this.height = this.image.getHeight();Random random = new Random();x = random.nextInt(AircraftBattle.WIDTH - this.width);y = -this.height;}@Overridepublic void move() {y += speed;}@Overridepublic boolean outOfBounds() {return this.y >= AircraftBattle.HEIGHT;}@Overridepublic int getScore() {return 40;}
}
package xyz.xinghai.game;import java.util.Random;import xyz.xinghai.game.bean.ImgBean;/**1. 打败后获得子弹加成2. @author 153213.  */
public class Bee extends FlyingObject implements Award {private int xSpeed = 1;private int ySpeed = 2;private int awardType;public int getType() {return awardType;}public Bee() {this.image = ImgBean.beeImg;this.width = this.image.getWidth();this.height = this.image.getHeight();Random rand=new Random();this.x = rand.nextInt(AircraftBattle.WIDTH-this.width);this.y = -this.height;awardType=rand.nextInt(2);}@Overridepublic void move() {y += ySpeed;x += xSpeed;if(x >= AircraftBattle.WIDTH-this.width){xSpeed =-1;}if(x <= 0){xSpeed =1;}}@Overridepublic boolean outOfBounds() {return this.height >= AircraftBattle.HEIGHT;}
}
  1. 编写游戏主窗口。主窗口和背景图片一样大,继承自JPanel主要是想重写paint方法。由于其他类已经写好,剩下的就是在游戏窗口中的逻辑处理了。用数组存储显示在界面上的各种物体,然后开启一个定时器每10ms扫描一次界面上的元素,当有事件发生时就调用对应方法。
package xyz.xinghai.game;import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Arrays;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;import javax.swing.JFrame;
import javax.swing.JPanel;import xyz.xinghai.game.bean.GameStateBean;
import xyz.xinghai.game.bean.ImgBean;/**1. 主程序类2. @author 153213.  */
public class AircraftBattle extends JPanel {private static final long serialVersionUID = 1L;//游戏界面宽度public static final int WIDTH = 400;//游戏界面高度public static final int HEIGHT = 645;private int state = GameStateBean.START;//主飞机private Hero hero = new Hero();//敌机数组private FlyingObject[] flyings = {};//子弹数组private Bullet[] bullets = {};//得分private int score = 0;@Overridepublic void paint(Graphics g) {g.drawImage(ImgBean.backgroundImg, 0, 0, null);paintHero(g);paintFlyingObjects(g);paintBullets(g);paintScoreAndLife(g);patintState(g);}/*** 画得分和生命* @param g 画笔*/private void paintScoreAndLife(Graphics g) {g.setColor(new Color(0xFF0000));g.setFont(new Font(Font.SANS_SERIF,Font.BOLD,30));g.drawString("SCORE:" + score, 10, 25);g.drawString("LIFE:"+ hero.getLife(), 10, 50);g.drawString("DoubleFire:" + hero.getDoubleFire(), 10, 75);}/*** 画主飞机* @param g 画笔*/private void paintHero(Graphics g) {g.drawImage(hero.image, hero.x, hero.y, null);}/*** 画屏幕中的敌机等飞行物体* @param g 画笔*/private void paintFlyingObjects(Graphics g){for(FlyingObject f : flyings)g.drawImage(f.image, f.x, f.y, null);}/*** 画子弹* @param g 画笔*/private void paintBullets(Graphics g){for(Bullet b : bullets)g.drawImage(b.image, b.x, b.y, null);}/*** 绘制游戏状态 * @param g 画笔*/private void patintState(Graphics g) {switch(state){case GameStateBean.START:g.drawImage(ImgBean.startImg, 0, 0, null);break;case GameStateBean.PAUSE:g.drawImage(ImgBean.pauseImg, 0, 0, null);break;case GameStateBean.GAMEOVER:g.drawImage(ImgBean.gameOverImg, 0, 0, null);}}/*** 生成敌机* @return 敌机*/private FlyingObject nextOne() {Random rand = new Random();int type = rand.nextInt(20);if(type < 4) {return new BigBee();} else if (type == 5) {return new Bee();} else {return new EnemyPlane();}}//敌机入场的indexint flyEnteredIndex = 0;/*** 敌机入场的action*/private void enterAction() {flyEnteredIndex++;if(flyEnteredIndex % 40 ==0){FlyingObject obj = nextOne();//更新敌机数组  flyings = Arrays.copyOf(flyings, flyings.length+1);flyings[flyings.length-1] = obj;}}//子弹入场的indexint shootIndex = 0;/*** 主飞机发射子弹的Action 主飞机返回子弹数组 把返回的数组加到游戏子弹数组即可*/private void shootAction(){shootIndex++;if (shootIndex % 30 == 0) {Bullet[] bs = hero.shoot();//更新子弹数组bullets = Arrays.copyOf(bullets, bullets.length+bs.length);System.arraycopy(bs, 0, bullets, bullets.length-bs.length, bs.length);} }/***飞行物移动的action 调用各自的移动方法即可*/private void moveAction(){hero.move();for(FlyingObject f : flyings) f.move();for(Bullet b : bullets)b.move();}/*** 飞行物飞出界面的action 就是把飞出界面的飞行物从数组中去掉*/private void outOfBoundsAction() {int index = 0;FlyingObject[] flyingLives = new FlyingObject[flyings.length];for(FlyingObject f : flyings) if(!f.outOfBounds()) flyingLives[index++] = f;flyings=Arrays.copyOf(flyingLives, index);index = 0;Bullet[] bulletLives = new Bullet[bullets.length];for(Bullet b : bullets) if(!b.outOfBounds()) bulletLives[index++] = b;bullets=Arrays.copyOf(bulletLives, index);}int j = 0;/*** 碰撞的action*/private void collisionAction() {for(int i=0;i < bullets.length;i++){collision(bullets[i],i);}}/*** 碰撞* @param b 子弹* @param bu 碰撞的子弹在子弹数组中的index*/private void collision(Bullet b, int bu) {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 EnemyPlane){Enemy e = (Enemy)one;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 BigBee){//打五下才会挂j++;         if(j==5){Enemy e = (Enemy)one;score += e.getScore();j = 0;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.DOUBLE_FIRE://奖励为火力值hero.addDoubleFire();break;case Award.LIFE://奖励为生命hero.addLife();break;}FlyingObject t = flyings[index];flyings[index] = flyings[flyings.length-1];flyings[flyings.length-1] = t;flyings = Arrays.copyOf(flyings, flyings.length-1);//去掉被子弹撞上的敌人}Bullet tBullet = bullets[bu];bullets[bu] = bullets[bullets.length-1];bullets[bullets.length-1] = tBullet;bullets=Arrays.copyOf(bullets, bullets.length-1);//去掉子弹}}/*** 检查游戏是否结束*/public void checkGameOverAction(){if(GameOver()){state = GameStateBean.GAMEOVER;}}private boolean GameOver() {for(int i=0; i<flyings.length; i++){FlyingObject f = flyings[i];if(hero.hit(f)){hero.subtractLife();hero.clealDoubleFire();FlyingObject t = flyings[i];//将被撞敌人与最后的一个元素交换flyings[i] = flyings[flyings.length-1];flyings[flyings.length-1] = t;flyings = Arrays.copyOf(flyings, flyings.length-1);//去掉被子弹撞上的敌人}}return hero.getLife() <= 0;//命数小于等于0结束}/*** 启动程序的action*/public void action(){MouseAdapter l = new MouseAdapter() {//重写鼠标移动事件public void mouseMoved(MouseEvent e){if(state == GameStateBean.RUNNING){hero.moveTo(e.getX(),e.getY());}}//鼠标点击事件public void mouseClicked(MouseEvent e){switch(state){case GameStateBean.START:state= GameStateBean.RUNNING;break;case GameStateBean.GAMEOVER:state = GameStateBean.START;//清理现场score = 0;hero = new Hero();flyings = new FlyingObject[0];bullets = new Bullet[0];break;}}//鼠标移除public void mouseExited(MouseEvent e){if(state == GameStateBean.RUNNING){state = GameStateBean.PAUSE;}}//鼠标移入public void mouseEntered(MouseEvent e){if(state == GameStateBean.PAUSE){state = GameStateBean.RUNNING;}}};this.addMouseListener(l);//处理鼠标操作事件this.addMouseMotionListener(l);//鼠标的滑动Timer timer = new Timer();//定时器int intervel = 10;//定时间隔(以毫秒为单位)timer.schedule(new TimerTask() {public void run(){if(state == GameStateBean.RUNNING){enterAction();//敌人入场moveAction();//敌人移动shootAction();//子弹入场collisionAction();//子弹与敌人相撞outOfBoundsAction();//删除越界的敌人和子弹checkGameOverAction();//敌人和英雄机相撞                 }repaint();//重新绘制界面}}, intervel, intervel);}public static void main(String[] args) {JFrame gameFrame = new JFrame();gameFrame.setTitle("AircraftBattle");AircraftBattle game = new AircraftBattle();gameFrame.getContentPane().add(game);gameFrame.setSize(new Dimension(WIDTH, HEIGHT));gameFrame.setAlwaysOnTop(true);gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);gameFrame.setLocationRelativeTo(null);gameFrame.setVisible(true);game.action();}
}

3.总结

  1. 代码还是要靠自己动手写才能提升(ಥ﹏ಥ)。
  2. 完整的工程在我的GitHub。戳这里。

Java版本飞机大战相关推荐

  1. 基于Java的飞机大战游戏的设计与实现论文

    源码下载 http://www.byamd.xyz/hui-zong-1/ 摘 要 现如今,随着智能手机的兴起与普及,加上4G(the 4th Generation mobile communicat ...

  2. 基于Java的飞机大战游戏的设计与实现(含源文件)

    欢迎添加微信互相交流学习哦! 项目源码:https://gitee.com/oklongmm/biye 基于Java的飞机大战游戏的设计与实现 摘   要 现如今,随着智能手机的兴起与普及,加上4G( ...

  3. 基于Java的飞机大战游戏的设计与实现(论文+源码)

    毕业设计(论文)任务书 第1页 毕业设计(论文)题目:基于Java的飞机大战游戏的设计与实现毕业设计(论文)要求及原始数据(资料):1.综述基于Java的飞机大战游戏的现状:2.深入了解Java的设计 ...

  4. java版飞机大战代码

    java版飞机大战代码 前言 Plane PlaneStatus类 Power类 Gift Diji play类 over类 MainFrame主类 MyZiDan DijiZiDan Before ...

  5. 【Java】Java基础飞机大战小游戏完整代码

    Java基础飞机大战小游戏完整代码 先来展示一下代码实现结果图 主函数ShootGame 初始化游戏原始背景图片,游戏人物图片,游戏开始结束图片:构建产生敌人算法:产生英雄机算法:发射子弹算法:判断是 ...

  6. 毕业设计 基于Java的飞机大战游戏的设计与实现

    文章目录 前言 一.项目设计 1. 模块设计 功能需求 游戏状态控制功能模块 游戏难度的调整模块 游戏界面绘画功能模块 玩家游戏控制功能模块 2. 实现效果 二.部分源码 项目源码 前言 今天学长向大 ...

  7. 基于Java的飞机大战游戏的设计与实现

    项目介绍 飞机大战主要需要我方飞机和敌方飞机,还有子弹,特殊nPC,开始背景,结束背景,以及背景音乐.我方飞机可以随意移动,敌方飞机无规律出现.游戏玩家通过鼠标移动控制飞机移动,我方飞机在游戏开始时就 ...

  8. 基于Java Swing 飞机大战游戏

    一.项目概要: 基于Java Swing飞机大战游戏,打死飞机,可以随机出现加血包.子弹升级包.并支持根据游戏的分数,调整游戏难度. 二.界面展示: 三.主要代码: package com.maoxu ...

  9. Java实现飞机大战(有图片素材)

    http://[[尚学堂]Java飞机大战3.0重制版,1小时快速上手掌握,源码_课件_资料,基础小白必学项目,毕设练手项目经验_Java项目_java入门_游戏开发]https://www.bili ...

最新文章

  1. SPU表管理之删除SPU表数据
  2. 名校算法博士找工作两月无果,因本科是不知名学校被婉拒
  3. Linux之telnet命令使用详解—网络故障定位(四)
  4. Jmeter工具笔记-Jmeter+influxdb+grafanas设置性能监控过程
  5. 批量正则替换某文件夹中代码(div id=XXXX替换为div id=XXXX)
  6. 【白话机器学习】算法理论+实战之朴素贝叶斯
  7. nginx lua示例
  8. Linux Qt使用POSIX多线程条件变量、互斥锁(量)
  9. C#中的程序集和命名空间
  10. linux 系统调试工具,Linux 系统调试...
  11. JS实现弹性漂浮广告代码
  12. Windows安装补丁_勒索病毒_补丁号
  13. 封装系统(以封装Windows 7为例)
  14. bean named 'transactionManager' available: No matching PlatformTransactionManager bean found for qua
  15. 实现TCP协议端到端的可靠传输 RDT
  16. layim框架+websocket即时通讯功能
  17. 取消GitHub邮箱订阅
  18. 怎么拿到签到王者的勋章?
  19. WAP 2.0 VS WEB 2.0
  20. 解决中端投资痛点,“轻中端”能否抢占投资价值高地?

热门文章

  1. SQL Server备份失败
  2. 175、交换机的基本配置
  3. Java 线程池的作用以及该如何使用
  4. Win10内核驱动强制签名,申请沃通 EV代码签名证书
  5. 汉字转换成拼音用函数
  6. 睡梦中面试腾讯 pcg 移动端开发, 一+二+三+hr面(已oc)
  7. js实现复制并能保留原格式粘贴;vue中点击复制粘贴功能;vue复制功能(不需要插件);
  8. 利用STM32的定时器中断功能编写线阵CCD(ILX554B)的驱动时序
  9. python百度图库爬取
  10. 硕鼠——前些年很好用的视频下载神器