day09 1.子弹与敌人的碰撞 1)在超类中FlyingObject设计hit()实现敌人与子弹/英雄机得碰撞 /** 成员方法:检测敌人与子弹/英雄机的碰撞 * this:敌人 other:子弹 */ public boolean hit(FlyingObject other) { int x1 = this.x - other.width; int x2 = this.x + this.width; int y1 = this.y - other.height; int y2 = this.y + this.height; int x = other.x; int y = other.y; return x>=x1 && x<=x2 && y>=y1 && y<=y2; } 在超类中FlyingObject设计goDead()实现飞行物去死的 /** 成员方法:飞行物去死 */ public void goDead() { state = DEAD; //将当前状态修改为DEAD }
import java.util.Random; import java.awt.image.BufferedImage; import javax.imageio.ImageIO; import java.awt.Graphics; /** * 飞行物--超类 * @author soft01 */ public abstract class FlyingObject { /** 常量: 三种状态(活着的、死了的、删除的) */ public static final int LIFE = 0; public static final int DEAD = 1; public static final int REMOVE = 2; /** 成员变量:当前状态(默认为活着的) */ protected int state = LIFE; /** 成员变量:宽、高、x轴、y轴 */ protected int width; protected int height; protected int x; protected int y; /** 构造方法:专门给英雄机、天空、子弹用 */ public FlyingObject(int width,int height,int x,int y) { this.width = width; this.height = height; this.x = x; this.y = y; } /** 构造方法:专门给小敌机、大敌机、小蜜蜂用 */ public FlyingObject(int width,int height) { this.width = width; this.height = height; Random rand = new Random(); x = rand.nextInt(World.WIDTH-width); y = -height; } /** 抽象方法:飞行物移动 */ public abstract void step(); /** 抽象方法:获取图片 */ public abstract BufferedImage getImage(); /** 抽象方法:检查飞行物是否越界 */ public abstract boolean outOfBounds(); /** 静态方法:读取图片 */ public static BufferedImage loadImage(String fileName) { try { BufferedImage img = ImageIO.read(FlyingObject.class.getResource(fileName)); //同包中读图片 return img; } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(); } } /** 成员方法:判断状态(活着的、死了的、删除的) */ public boolean isLife() { return state == LIFE; } public boolean isDead() { return state == DEAD; } public boolean isRemove() { return state == REMOVE; } /** 成员方法:画对象的 g:画笔 */ public void paintObject(Graphics g) { g.drawImage(getImage(),x,y,null); } /** 成员方法:检测敌人与子弹/英雄机的碰撞 * this:敌人 other:子弹 */ public boolean hit(FlyingObject other) { int x1 = this.x - other.width; //敌人的x - 子弹/英雄机的宽 int x2 = this.x + this.width; //敌人的x + 敌人的宽 int y1 = this.y - other.height; //敌人的y - 子弹/英雄机的高 int y2 = this.y + this.height; //敌人的y + 敌人的高 int x = other.x; //子弹/英雄机的x int y = other.y; //子弹/英雄机的y return x>=x1 && x<=x2 && y>=y1 && y<=y2; //x在x1和x2之间,y在y1和y2之间 } /** 成员方法:飞行物去死 */ public void goDead() { state = DEAD; //将当前状态修改为DEAD } }
在Hero类中设计addLife()增命、addDoubleFire()增火力 /** 成员方法:命数增加 */ public void addLife() { life++; //命数增1 } /** 成员方法:火力值增加 */ public void addDoubleFire() { doubleFire += 40; //火力值增40 }
import java.awt.image.BufferedImage; /** * 英雄机 * @author soft01 */ public class Hero extends FlyingObject{ /** 静态变量:英雄机图片 */ private static BufferedImage[] images; static { images = new BufferedImage[2]; for (int i = 0; i < images.length; i++) { images[i] = loadImage("hero" + i + ".png"); } } /** 成员变量:生命、火力值 */ private int life; //生命 private int doubleFire; //火力值 /** 构造方法 */ public Hero(){ super(97,124,140,400); life = 3; doubleFire = 0; } /** 成员方法:命数增加 */ public void addLife() { life++; //命数增1 } /** 成员方法:获取命数 */ public int getLife() { return life; //返回命 } /** 成员方法:火力值增加 */ public void addDoubleFire() { doubleFire += 40; //火力值增40 } /** 成员方法:英雄机移动 */ public void step() {} /** 成员方法:英雄机随鼠标移动x,y */ 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英雄机的高 } /** 成员方法:获取图片 */ int index = 0; @Override public BufferedImage getImage() { if(isLife()) { return images[index++%2]; //(index++%2)余数为0或1 } return null; } /** 成员方法:英雄机发射子弹(创建子弹对象) */ public Bullet[] shoot() { int xStep = this.width/4; //xStep:1/4英雄机的宽 int yStep = 20; //yStep:固定的20 if (doubleFire > 0) { //双 Bullet[] bs = new Bullet[2]; //2发子弹 //英雄机的x坐标加1/4英雄机的宽 bs[0] = new Bullet(this.x + 1 * xStep,y-yStep); //英雄机的x坐标加3/4英雄机的宽 bs[1] = new Bullet(this.x + 3 * xStep, y-yStep); doubleFire -= 2; //发射一次双倍火力,火力值减2 return bs; } else { //单 Bullet[] bs = new Bullet[1]; //1发子弹 //英雄机的x坐标加2/4英雄机的宽 bs[0] = new Bullet(this.x + 2 * xStep, y-yStep); return bs; } } /** 成员方法:英雄机永不越界 */ @Override public boolean outOfBounds() { return false; } }
2)子弹与敌人的碰撞为定时发生的,所以在run()中调用BulletBangAction()方法 在BulletBangAction()中: 遍历所有子弹,获取每一个子弹,遍历所有敌人,获取每个敌人 判断是否撞上了,若撞上了: 1)子弹去死,敌人去死 2)小敌机和大敌机 ----------得分 小蜜蜂 ----------------英雄机得命或双倍火力 /** 成员方法:子弹与敌人的碰撞 */ int score = 0; public void bulletBangAction() { //每10个毫秒走一次 //遍历子弹数组 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.isLife() && f.isLife() && f.hit(b)) { b.goDead(); //子弹去死 f.goDead(); //敌人去死 if (f instanceof Enemy) {//若被撞对象是敌人 Enemy e = (Enemy)f;//强转为得分接口 score += e.getScore();//玩家得分 } if (f instanceof Award) {//若被撞对象是奖励 Award a = (Award)f;// 强转为奖励接口 int type = a.getType();//获取奖励类型 //基于不同的类型来得到不同的奖励 switch (type) { //若奖励为火力值 case Award.DOUBLE_FIRE: hero.addDoubleFire(); //则增加火力值 break; case Award.LIFE: //若奖励为命 hero.addLife(); //则增加命 break; } } } } } } 2.画分和画命 1)在Hero类中设计getLife()获取命 /** 成员方法:获取命数 */ public int getLife() { return life; //返回命 } 2)在paint()方法中,画分和画命 g.drawString("SCORE:" + score,10,25); g.drawString("LIFE:" + hero.getLife(), 10, 45);
import java.awt.Graphics; import javax.swing.JFrame; import javax.swing.JPanel; 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;; /** * 整个世界 * @author soft01 */ public class World extends JPanel{ /** 常量:窗口宽、窗口高 */ public static final int WIDTH = 400; public static final int HEIGHT = 700; /** 成员变量:天空、英雄机、飞行物敌人数组、子弹数组 */ private Sky sky = new Sky(); private Hero hero = new Hero(); private FlyingObject[] enemies = {}; private Bullet[] bullets = {}; /** 启动程序的执行 */ public void action() { Timer timer = new Timer(); //创建定时器对象 int interval = 10; //定时间隔(以毫秒为单位) timer.schedule(new TimerTask() { //匿名内部类 @Override public void run() { //定时干的事(每10个毫秒走一次) enterAction(); //敌人入场,子弹入场,飞行物移动 shootAction(); //子弹入场,英雄机发射子弹 stepAction(); //飞行物入场 outOfBoundsAction(); //删除越界 bulletBangAction(); //子弹与敌人的碰撞 repaint(); //重画(重新调用paint()方法) } },interval,interval); //定时计划 /** 鼠标侦听器 */ MouseAdapter l = new MouseAdapter() { /** 重写mouseMoved()鼠标移动 */ public void mouseMoved(MouseEvent e) { int x = e.getX(); //获取鼠标的x坐标 int y = e.getY(); //获取鼠标的y坐标 hero.moveTo(x, y); //英雄机随着鼠标移动 } }; this.addMouseListener(l); //处理鼠标操作事件 this.addMouseMotionListener(l); //处理鼠标滑动事件 } /** 成员方法:生成敌人(小敌机、大敌机、小蜜蜂)对象 */ public FlyingObject nextOne() { Random rand = new Random(); //随机数对象 int type = rand.nextInt(20); //0~19之间的数 if (type < 11) { //0~7返回小敌机 return new Airplane(); } else if(type < 17){ //8~15返回小敌机 return new BigAirplane(); } else { //16~19返回小敌机 return new Bee(); } } /** 成员方法:敌人(小敌机、大敌机、小蜜蜂)入场 */ int enterIndex = 0; //敌人入场计数 public void enterAction() { //每10个毫秒走一次 enterIndex++; //每10毫秒增1 if(enterIndex%40 == 0) { //每400(10*40)毫秒走一次 FlyingObject obj = nextOne(); enemies = Arrays.copyOf(enemies, enemies.length+1); //数组扩容 enemies[enemies.length-1] = obj; //将敌人对象填充到enemies数组的最后一个元素上 } } /** 成员方法:子弹入场,英雄机发射子弹 */ int shootIndex = 0; //子弹入场计数 public void shootAction() { //每10个毫秒走一次 shootIndex++; //每10毫秒增1 if(shootIndex%20 == 0) { //每300(10*30)毫秒走一次 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个毫秒走一次 int index = 0; //1)不越界敌人下标 2)不越界敌人个数 FlyingObject[] enemyLives = new FlyingObject[enemies.length]; //不越界敌人数组 for (int i = 0; i < enemies.length; i++) { //获取敌人数组 FlyingObject f = enemies[i]; //获取每一个敌人 if(!f.outOfBounds()) { //不越界 enemyLives[index] = f; //将不越界敌人放到不越界数组中 index++; //1)不越界敌人数组下标增一 2)不越界敌人个数增1 } } enemies = Arrays.copyOf(enemyLives, index); //将不越界数组中的元素复制到敌人数组之中,数组的长度为index index = 0; Bullet[] bulletLives = new Bullet[bullets.length]; for (int i = 0; i < bullets.length; i++) { Bullet b = bullets[i]; if(!b.outOfBounds()) { bulletLives[index] = b; index++; } } bullets = Arrays.copyOf(bulletLives, index); } /** 成员方法:子弹与敌人的碰撞 */ int score = 0; public void bulletBangAction() { //每10个毫秒走一次 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.isLife() && f.isLife() && f.hit(b)) { //如果活着的子弹和活着的敌人撞上了 b.goDead(); //子弹去死 f.goDead(); //敌人去死 if (f instanceof Enemy) { //若被撞对象是敌人 Enemy e = (Enemy)f; //强转为得分接口 score += e.getScore(); //玩家得分 } if (f instanceof Award) { // 若被撞对象是奖励 Award a = (Award)f; // 强转为奖励接口 int type = a.getType(); //获取奖励类型 switch (type) { //基于不同的类型来得到不同的奖励 case Award.DOUBLE_FIRE: //若奖励为火力值 hero.addDoubleFire(); //则增加火力值 break; case Award.LIFE: //若奖励为命 hero.addLife(); //则增加命 break; } } } } } } /** 成员方法:paint()方法 */ @Override public void paint(Graphics g) { sky.paintObject(g); //画天空 hero.paintObject(g); //画英雄机 for (int i = 0; i < enemies.length; i++) { //遍历所有敌人 enemies[i].paintObject(g); //画敌对飞行物 } for (int i = 0; i < bullets.length; i++) { //遍历子弹 bullets[i].paintObject(g); //画子弹 } g.drawString("SCORE:" + score,10,25); g.drawString("LIFE:" + hero.getLife(), 10, 45); } /** main主方法 */ public static void main(String[] args) { JFrame frame = new JFrame(); //创建窗口 World world = new World(); //创建面板 frame.add(world); //将面板添加到窗口 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //设置关闭窗口即停止运行程序 frame.setSize(WIDTH,HEIGHT); //设置窗口大小 frame.setLocationRelativeTo(null); //设置窗口居中显示 frame.setVisible(true); //1)设置窗口可见 2)尽快调用paint()方法 world.action(); //启动程序 } }
原文地址:https://www.cnblogs.com/lj-6112/p/8666539.html
时间: 2024-10-29 05:42:50