飞机大战源代码
一款飞机大战游戏
·
Airplane:
package cn.tedu.cn; import java.awt.image.BufferedImage; public class Airplane extends FlyingObject implements EnemyScore{ private int speed; //移动速度 public Airplane(){ //构造方法 super(48,50); //小敌机的宽高 speed = 2; //移动速度 } /*重写step()移动*/ public void step() { y+=speed; //y+向下 } private int index = 1; //爆破图的下标 /*重写getImage()获取图片*/ public BufferedImage getImage() { //每十毫秒走一次 if(isLive()) { return Images.airs[0]; }else if(isDead()) { BufferedImage img = Images.airs[index++]; //获取爆破图 if(index==Images.airs.length) { //到最后一张了 state = REMOVE; //将当前状态修改为REMOVE删除状态 } return img; //返回爆破图 } return null; //删除状态不返回图片 /* * index=1 * 10M img=airs[1] index=2 airs[1] * 20M img=airs[2] index=3 airs[2] * 30M img=airs[3] index=4 airs[3] * 40M img=airs[4] index=5 airs[4] * (REMOVE) * 50M 不返回图片 */ } public int getScore() { return 1; //打掉小敌机玩家得1 分 } }
Bee:
package cn.tedu.cn; import java.awt.image.BufferedImage; import java.util.Random; public class Bee extends FlyingObject implements EnemyAward{ private int xSpeed; private int ySpeed; private int awardType; public Bee(){ super(60,51); Random rand = new Random(); xSpeed = 1; ySpeed = 2; awardType = rand.nextInt(2); //0到1之间 } public void step() { x+=xSpeed; //x向左向右 y+=ySpeed; //y+向下 if(x<=0 || x>=World.WIDTH-width){ //若x<=0或X>=(窗口宽-蜜蜂宽),表示到头了 xSpeed*=-1; //切换方向(正便=变负、负变正) } } private int index = 1; //爆破图的下标 /*重写getImage()获取图片*/ public BufferedImage getImage() { //每十毫秒走一次 if(isLive()) { return Images.bees[0]; }else if(isDead()) { BufferedImage img = Images.bees[index++]; //获取爆破图 if(index==Images.bees.length) { //到最后一张了 state = REMOVE; //将当前状态修改为REMOVE删除状态 } return img; //返回爆破图 } return null; //删除状态不返回图片 } public int getAwardType() { return awardType; //返回奖励类型 } }
BigAirplane:
package cn.tedu.cn; import java.awt.image.BufferedImage; public class BigAirplane extends FlyingObject implements EnemyScore{ private int speed; public BigAirplane(){ super(66,89); speed = 2; } public void step() { y+=speed; //y+向下 } private int index = 1; //爆破图的下标 /*重写getImage()获取图片*/ public BufferedImage getImage() { //每十毫秒走一次 if(isLive()) { return Images.bairs[0]; }else if(isDead()) { BufferedImage img = Images.bairs[index++]; //获取爆破图 if(index==Images.bairs.length) { //到最后一张了 state = REMOVE; //将当前状态修改为REMOVE删除状态 } return img; //返回爆破图 } return null; //删除状态不返回图片 } /*重写getScore()*/ public int getScore() { return 3; //打掉大敌机,玩家得3分 } }
Bullet:
package cn.tedu.cn; import java.awt.image.BufferedImage; public class Bullet extends FlyingObject{ private int speed; public Bullet(int x,int y){ //子弹有许多个,每个子弹的初始坐标都不同 super(8,20,x,y); speed = 3; } public void step() { y-=speed; //y+向上 } /*重写getImage()获取图片*/ public BufferedImage getImage() { if(isLive()) { return Images.bullet; //直接返回图片 }else if(isDead()){ //若死了的 state = REMOVE; //将状态修改为REMOVE删除状态 } return null; //死了的和删除的,都不反图片 /* //若活着的,返回bullet 图片 //若死了的,状态改为删除,同时不返回图片 //若删除的不返回图片 */ } /*重写isOutOfBounds()判断子弹是否越界*/ public boolean isOutOfBounds() { return y<=-height; //敌人的y>=窗口的高,即为越界了 } }
EnemyAward接口:
package cn.tedu.cn; /*奖励接口*/ public interface EnemyAward { public int FIRE = 0; //火力 public int LIFE = 1; //命 /*获取奖励类型*/ public int getAwardType(); }
EnemyScore接口:
package cn.tedu.cn; /*得分接口*/ public interface EnemyScore { public int getScore(); //得分 }
FlyingObject超类:
package cn.tedu.cn; import java.util.Random; import java.awt.image.BufferedImage; /*飞行物*/ public abstract class FlyingObject { public static final int LIVE = 0; //活着的 public static final int DEAD = 1; //死了的 public static final int REMOVE = 2; //删除的 protected int state = LIVE; //当前状态默认为活着的 protected int width; //宽 protected int height; //高 protected int x; //x坐标 protected int y; //y坐标 //专门给小敌机,大敌机,小蜜蜂提供的 //因为三种敌人的宽高不同,所以数据得写活,自然传参 //因为三种敌人的x和y坐标相同,所以直接写死,不需要传参 public FlyingObject(int width,int height){ this.width=width; this.height=height; Random rand = new Random(); //随机数对象 x = rand.nextInt(World.WIDTH-width); //0到(窗口宽-小敌机宽)之间是随机数 y = -height; //y:负的敌人的高 } /*专门给英雄机、天空、子弹提供的*/ //因为英雄机,天空,子弹的宽高xy都不同,所以数据都得写活,都得传参过来 public FlyingObject(int width,int height,int x,int y){ this.width=width; this.height=height; this.x=x; this.y=y; } public abstract void step(); /*获取对象的图片*/ public abstract BufferedImage getImage(); /*判断是否活着的*/ public boolean isLive() { return state==LIVE; //当前状态为LIVE则表示为活着的,返回true,否则返回flase } /*判断是死了着的*/ public boolean isDead() { //当前状态为DEAD则表示为活着的,返回true,否则返回flase return state==DEAD; } /*判断是否删除的*/ public boolean isRemove() { //当前状态为REMOVE则表示为活着的,返回true,否则返回flase return state==REMOVE; } /*判断敌人是否越界*/ public boolean isOutOfBounds() { return y>=World.HEIGHT; //敌人的y>=窗口的高,即为越界了 } /*检测敌人与子弹/英雄机的碰撞 this:敌人 other:子弹/英雄机*/ public boolean isHit(FlyingObject other) { int x1 = this.x-other.width; //x1:敌人的x-子弹/英雄机的宽 int x2 = this.x+this.width; //x2:敌人的x+敌人的宽 int y1 = this.y-other.height; //y1:敌人的y-子弹/英雄机的高 int y2 = this.y+this.height; //y2:敌人的y+敌人的高 int x = other.x; //x:子弹/英雄机的x int y = other.y; //y:子弹/英雄机的y return x>=x1 && x<=x2 && y>=y1 && y<=y2; } /*飞行物去死*/ public void goDead() { state = DEAD; //将当前状态修改为DEAD死了的 } }
Hero:
package cn.tedu.cn; import java.awt.image.BufferedImage; public class Hero extends FlyingObject { private int life; private int fire; public Hero() { super(97, 139, 140, 400); life = 3; fire = 0; } public void step() { } int index = 0; //下标 /*重写getImage()获取图片*/ public BufferedImage getImage() { //每十个毫毛走一次 return Images.heros[index++ % Images.heros.length]; //在0到1之间来回切换 /* index=0; 10M 返 回hero[0] index=1; 20M 返 回hero[1] index=2; 30M 返 回hero[0] index=3; 40M 返 回hero[1] index=4; */ } /*英雄机发射子弹(生成子弹对象)*/ public Bullet[] shoot() { int xStep = this.width / 4; //1/4英雄机的宽 int yStep = 2; if (fire > 0) { //双倍火力 Bullet[] bs = new Bullet[2]; //2发子弹 bs[0] = new Bullet(this.x + 1 * xStep, this.y - yStep); //x:英雄机的x+1/4英雄机的宽 y:英雄机的y-固定的20 bs[1] = new Bullet(this.x + 3 * xStep, this.y - yStep); //x:英雄机的x+3/4英雄机的宽 y:英雄机的y-固定的20 fire -= 2; //发射一次双倍火力,则火力值减2 return bs; } else { //单倍 Bullet[] bs = new Bullet[1]; //1发子弹 bs[0] = new Bullet(this.x + 2 * xStep, this.y - yStep); //x:英雄机的x+2/4英雄机的宽 y:英雄机的y-固定的20 return bs; } } /*英雄机随着鼠标移动*/ public void moveTo(int x, int y) { this.x = x - this.width / 2; //英雄机的x=鼠标的x-1/2英雄机的宽 this.y = y - this.height / 2; //英雄机的y=鼠标的y-1/2英雄机的高 } /*英雄机增命*/ public void addLife() { life++; //命数加1 } /*获取英雄机的命*/ public int getLife() { return life; //返回命数 } /*英雄机减命*/ public void subtractLife() { life--;//命数-1 } /*清空火力值*/ public void clearFire() { fire = 0; //火力值为零 } /*英雄机增火力*/ public void addFire() { fire += 40; //火力值增40 } } Images:
package cn.tedu.cn; //图片工具类 import java.awt.image.BufferedImage; import javax.imageio.ImageIO; public class Images { // 公开的 静态的 数据类型 变量名 public static BufferedImage sky; public static BufferedImage bullet; public static BufferedImage[] heros; public static BufferedImage[] airs; public static BufferedImage[] bairs; public static BufferedImage[] bees; public static BufferedImage start; public static BufferedImage pause; public static BufferedImage gameover; static { start = readImage("img/start.png"); pause = readImage("img/pause.png"); gameover = readImage("img/gameover.png"); sky = readImage("img/background.png"); bullet = readImage("img/bullet.png"); heros = new BufferedImage[2]; heros[0] = readImage("img/hero0.png"); heros[1] = readImage("img/hero1.png"); airs = new BufferedImage[5]; airs[0] = readImage("img/airplane.png"); bairs = new BufferedImage[5]; bairs[0] = readImage("img/bigairplane.png"); bees = new BufferedImage[5]; bees[0] = readImage("img/bee.png"); for(int i=1;i<airs.length;i++) { //赋值爆破图 airs[i] = readImage("img/bom"+i+".png"); bairs[i] = readImage("img/bom"+i+".png"); bees[i] = readImage("img/bom"+i+".png"); } } public static BufferedImage readImage(String fileName){ try{ BufferedImage img = ImageIO.read(FlyingObject.class.getResource(fileName)); return img; }catch(Exception e){ e.printStackTrace(); throw new RuntimeException(); } } } Sky:
package cn.tedu.cn; import java.awt.image.BufferedImage; /*天空:是飞行物*/ public class Sky extends FlyingObject{ private int speed;;//移动速度 private int y1; //第二张图的y坐标 /*构造方法*/ public Sky(){ super(World.WIDTH,World.HEIGHT,0,0); speed = 1; y1 = -World.HEIGHT; } public void step() { y += speed; //y+(向下) y1+= speed; //y+(向下) if(y>=World.HEIGHT) { //若y>=窗口的高,意味着y移出去了 y=-World.HEIGHT; //则修改y的值为负的窗口的高(挪到最上面去了) } if(y1>World.HEIGHT) { //若y1>=窗口的高,意味着y1一出去了 y1=-World.HEIGHT; //则修改y1的值为负的窗口的高(挪到最上面去了) } } /*重写getImage()获取图片*/ public BufferedImage getImage() { return Images.sky; //直接返回sky图片即可 } /*获取y1坐标*/ public int getY1() { return y1; } }
World主程序:
package cn.tedu.cn; import javax.swing.*; import java.awt.*; import java.util.Timer; import java.util.TimerTask; import java.util.Random; import java.util.Arrays; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; public class World extends JPanel { public static final int WIDTH = 400; // 窗口的宽 public static final int HEIGHT = 700; // 窗口的高 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 Sky sky = new Sky(); // 天空对象 private Hero hero = new Hero(); // 英雄机 private FlyingObject[] enemies = {}; // 敌人组 private Bullet[] bullets = {}; // 子弹数组 /* 敌人生成(小敌机,大敌机,小蜜蜂)对象 */ public FlyingObject nextOne() { Random rand = new Random(); int type = rand.nextInt(20); // 0到19之间的随机数 if (type < 5) { // 0到4返回小蜜蜂对象 return new Bee(); } else if (type < 13) { // 5到12返回小蜜蜂对象 return new Airplane(); } else { // 13到19返回大敌机对象 return new BigAirplane(); } } private int enterIndex = 0; /* 敌人(小敌机,大敌机,小蜜蜂)入场 */ public void enterAction() { // 每10毫秒做一次 enterIndex++; // 每10毫秒增1 if (enterIndex % 40 == 0) { // 每400毫秒走一次 FlyingObject obj = nextOne(); // 获取敌人对象 enemies = Arrays.copyOf(enemies, enemies.length + 1); // 扩容 enemies[enemies.length - 1] = obj; // 将obj添加到最后一个元素上 } } private int shootIndex = 0; // 子弹入场计数 /* 子弹入场 */ public void shootAction() { // 每10毫秒走一次 shootIndex++; // 每10毫秒走一次 if (shootIndex % 30 == 0) { // 每300毫秒走一次 Bullet[] bs = hero.shoot(); // 获取子弹数组对象 bullets = Arrays.copyOf(bullets, bullets.length + bs.length); // 扩容(bs有几个元素就扩大几个元素) System.arraycopy(bs, 0, bullets, bullets.length - bs.length, bs.length); // 数组的追加 } } /*飞行物移动*/ public void stepAction() { sky.step(); //天空动 for (int i = 0; i < enemies.length; i++) { //遍历所有敌人 enemies[i].step(); //敌人动 } for (int i = 0; i < bullets.length; i++) { //遍历所有子弹 bullets[i].step(); //子弹动 } } /*删除越界的敌人和子弹*/ public void outOfBoundsAction() { //每10毫秒走一次 for (int i = 0; i < enemies.length; i++) { //遍历所有敌人 if (enemies[i].isOutOfBounds() || enemies[i].isRemove()) { //判断是否出界或爆破 enemies[i] = enemies[enemies.length - 1]; //把最后一个敌人放在出界敌人的位置 enemies = Arrays.copyOf(enemies, enemies.length - 1); //缩容 } } for (int i = 0; i < bullets.length; i++) { //遍历所有子弹 if (bullets[i].isOutOfBounds() || bullets[i].isRemove()) { //判断是否出界或爆破 bullets[i] = bullets[bullets.length - 1]; //把最后一个子弹放在出界子弹的位置 bullets = Arrays.copyOf(bullets, bullets.length - 1); //缩容 } } } private int score = 0; //玩家得分 /*子弹与敌人的碰撞*/ public void bulletBangAction() { for (int i = 0; i < bullets.length; i++) { //遍历所有子弹 Bullet b = bullets[i]; //获取每个子弹 for (int j = 0; j < enemies.length; j++) { //遍历所有敌人 FlyingObject f = enemies[j]; //获取每个敌人 if (b.isLive() && f.isLive() && f.isHit(b)) { //若都活着并且还撞上了 b.goDead(); //子弹去死 f.goDead(); //敌人去死 if (f instanceof EnemyScore) { //若被撞对象能得分--所有实现EnemyScore的类 EnemyScore es = (EnemyScore) f; //将被撞敌人强转为得分接口 score += es.getScore(); //玩家得分 } if (f instanceof EnemyAward) { //若被撞敌人为奖励--所有实现EnemyAward的类 EnemyAward ea = (EnemyAward) f; //将被撞敌人强转为奖励接口 int type = ea.getAwardType(); //获取奖励类型 switch (type) { //根据奖励类型来获取不同的奖励 case EnemyAward.FIRE: //若奖励类型为火力 hero.addFire(); //则英雄机增火力 break; case EnemyAward.LIFE: //若奖励类型为命 hero.addLife(); //则英雄机增命 break; } } } } } } /*英雄机与敌人撞*/ public void heroBangAction() { //每10毫秒走一次 for (int i = 0; i < enemies.length; i++) { //遍历所有敌人 FlyingObject f = enemies[i]; //获取每个敌人 if (hero.isLive() && f.isLive() && f.isHit(hero)) { f.goDead(); //敌人去死 hero.subtractLife(); //英雄机减命 hero.clearFire(); //英雄机清空火力 } } } public void checkGameOverAction() { if (hero.getLife() <= 0) { //表示游戏结束了 state = GAME_OVER; //将当前状态修改为游戏结束状态 } } /* 启动程序的执行 */ public void action() { MouseAdapter m = new MouseAdapter() { public void mouseMoved(MouseEvent e) { if (state == RUNNING) { int x = e.getX(); //获取鼠标的x坐标 int y = e.getY(); //获取鼠标的y坐标 hero.moveTo(x, y); //英雄机随着鼠标移动 } } public void mouseClicked(MouseEvent e) { switch (state) { //根据当前状态做不同的处理 case START: //启动状态时修改为运行状态 state = RUNNING; break; case GAME_OVER: //游戏结束状态时修改为启动状态 score = 0; //先清理现场,在修改为启动状态 sky = new Sky(); hero = new Hero(); enemies = new FlyingObject[0]; bullets = new Bullet[0]; state = START;//修改为启动状态 break; } } /*重写mouseExited()鼠标移出事件*/ public void mouseExited(MouseEvent e) { if (state == RUNNING) { //运行状态时修改为暂停状态 state = PAUSE; } } /* 重写mouseEntered()鼠标移入事件*/ public void mouseEntered(MouseEvent e) { if (state == PAUSE) { //暂停状态时修改为运行状态 state = RUNNING; } } }; this.addMouseListener(m); this.addMouseMotionListener(m); Timer timer = new Timer(); // 定时器对象 int intervel = 10; // 定时间隔(以毫秒为单位) timer.schedule(new TimerTask() { public void run() { // 定时器干的事(每十毫秒走一次) // 敌人入场 子弹入场 飞行物移动 子弹与敌人碰撞 英雄机与敌人碰撞 if (state == RUNNING) { //仅在运行状态下执行 enterAction(); //敌人(小敌机,大敌机,小蜜蜂)入场 shootAction(); //子弹入场 stepAction(); //飞行物移动 outOfBoundsAction(); //删除越界敌人 bulletBangAction(); //子弹与敌人碰撞 heroBangAction(); //英雄机与敌人的碰撞 checkGameOverAction(); //检测游戏结束 } repaint(); // 重画 调用repaint() 画笔 } }, intervel, intervel); //定时计划表 } /* 重写paint()画 */ public void paint(Graphics g) { // 每10毫秒走一次 g.drawImage(sky.getImage(), sky.x, sky.y, null); // 画天空1 g.drawImage(sky.getImage(), sky.x, sky.getY1(), null); // 画天空2 g.drawImage(hero.getImage(), hero.x, hero.y, null); // 画英雄机 for (int i = 0; i < enemies.length; i++) { // 遍历所有敌人 FlyingObject f = enemies[i]; // 获取每个敌人 g.drawImage(f.getImage(), f.x, f.y, null); // 画敌人 } for (int i = 0; i < bullets.length; i++) { // 遍历所有子弹 Bullet b = bullets[i]; // 获取每个子弹 g.drawImage(b.getImage(), b.x, b.y, null); // 画子弹 } g.drawString("分数:" + score, 10, 25); //画分 g.drawString("生命:" + hero.getLife(), 10, 45); //画命 /*画启动图,暂停图,结束图*/ switch (state) { case START: g.drawImage(Images.start, 0, 0, null); break; case PAUSE: g.drawImage(Images.pause, 0, 0, null); break; case GAME_OVER: g.drawImage(Images.gameover, 0, 0, null); } } public static void main(String[] args) { JFrame frame = new JFrame("飞机大战"); World world = new World(); frame.add(world); Image icon = Toolkit.getDefaultToolkit().getImage("C:\\Users\\才哥\\Desktop\\Shoot\\src\\cn\\tedu\\cn\\img\\1.png"); frame.setIconImage(icon); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(WIDTH, HEIGHT); frame.setLocationRelativeTo(null); frame.setVisible(true); // 设置窗口可见 尽快调用 world.action(); }
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
已为社区贡献1条内容
所有评论(0)