源码具体详情请点击 https://download.csdn.net/download/qq_40803710/11011232 进行下载。
1.第一个任务:做6个子类
Sky: y1;step step();
Hero: life;doubleFire move(int x,int y){}
Airplane: step step();
BigAirplane: step step();
Bee: xstep; ystep; awardType//0表示带命;1表示带分 step();
Bullet: step step();
2.第二个任务:使用构造方法,初始化数据
1)Sky:无参构造
public Sky() {
super(400,700,0,0);
y1=-700;
step = 1;
}
2) Hero:无参构造
public Hero() {
super(97,124,400/2-97/2,400);
life = 3;
doubleFire = 0;//0表示单倍火力 >0表示双倍火力
}
3)敌人对象(Airplane,BigAirplane,Bee)无参构造
public Airplane() {
super(49,36);
step = 2;
}
public BigAirplane() {
super(69,99);
step = 2;
}
public Bee() {
super(60,50);
xstep = 1;
ystep = 2;
awardType = new Random().nextInt(2); //0:火力值 1:命
}
4)Bullet
public Bullet(int x,int y) {
super(8,14,x,y);
step = 3;
state = LIFE;
}
3. 第三个任务:定义FlyingObject(实现代码重用)
1)定义FlyingObject,定义通用的变量和方法
2)设计两个构造方法:
对Airplane,Bee ,BigAirplane对象的初始化方法
//给敌人对象初始化Airplane,BigAirplane,Bee
public FlyingObject(int width,int height){
this.width = width;
this.height = height;
x = new Random().nextInt(400-this.width);
y = -height;
},在子类中调用
对Hero,Sky,Bullet对象的初始化方法
//给Sky,Hero,Bullet三个类实例化的方法
public FlyingObject(int width,int height,int x,int y){
this.width = width;
this.height = height;
this.x = x;
this.y = y;
},在子类中调用
3)调整成员变量的修饰符
父类中可以被访问的成员访问修饰符:protected
子类中的成员不被外界访问修饰符:private
4.第四个任务:画页面
1)定义World类,继承JPanel
2)定义窗口,显示窗口
import javax.swing.JPanel;
import java.awt.Graphics;
import javax.swing.JFrame;
public class world extends JPanel{
Sky sky = new Sky();
public static void main(String args[]) {
JFrame frame = new JFrame();
world world = new world();
frame.add(world);
frame.setTitle("飞机大战"); //设置窗口标题
frame.setSize(400,700); //设置窗口大小
frame.setLocationRelativeTo(null); //设置窗口居中显示
frame.setVisible(true); //设置窗口可视化
}
//实现画的功能
public void paint(Graphics g) {
sky.paintObject(g);
}
}
3)把图片拷贝到工程包下
4)加载图片
4.1)天空
//存放图片对象
private static BufferedImage image;
static{
try {
//使用ImageIO读取图片
image = ImageIO.read(Sky.class.getResource("background.png"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
4.2)小敌机
//加载图片到数组中
private static BufferedImage[] images = new BufferedImage[5];
static{
for(int i = 0;i try { images[i]=ImageIO.read(Airplane.class.getResource("airplane"+i+".png")); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } 4.3)大敌机 //加载图片到数组中 private static BufferedImage[] images = new BufferedImage[5]; static{ for(int i = 0;i try { images[i]=ImageIO.read(Airplane.class.getResource("bigplane"+i+".png")); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } 5)获取图片 //类中有一个抽象方法时类不能定义为对象 要想让当前类创建对象 //要将父类抽象且方法抽象(父类中声明)才可以实现 public abstract BufferedImage getImage(); //子类中具体实现 5.1)天空@Override public BufferedImage getImage() { return image; } (1)小敌机 /* * 1、如果当前状态为活着,加载数组的第一张图片 * 2、如果当前状态为死亡,加载数组中剩余的四张图片,把state=REMOVE */ int deadIndex = 1; @Override public BufferedImage getImage() { if(this.isLife()) { return images[0]; }else if(this.isDead()) { //解决怎样加载剩余四张图片 可以多次调用返回 BufferedImage image = images[deadIndex++]; if(deadIndex==images.length) { state = REMOVE; } return image; } return null; } (2)大敌机 /* * 1、如果当前状态为活着,加载数组的第一张图片 * 2、如果当前状态为死亡,加载数组中剩余的四张图片,把state=REMOVE */ int deadIndex = 1; @Override public BufferedImage getImage() { if(this.isLife()) { return images[0]; }else if(this.isDead()) { BufferedImage image = images[deadIndex++]; if(deadIndex==images.length) { state = REMOVE; } return image; } return null; } (3)蜜蜂 /* * 1、如果当前状态为活着,加载数组的第一张图片 * 2、如果当前状态为死亡,加载数组中剩余的四张图片,把state=REMOVE */ int deadIndex = 1; @Override public BufferedImage getImage() { if(this.isLife()) { return images[0]; }else if(this.isDead()) { //解决怎样加载剩余四张图片 可以多次调用返回 BufferedImage image = images[deadIndex++]; if(deadIndex==images.length) { state = REMOVE; } return image; } return null; } (4)子弹 public Bullet[] getBullet() { if(doubleFire == 0) { Bullet[] b = new Bullet[1]; int b_x = this.x + this.width/2; int b_y = this.y - 20; Bullet b1 = new Bullet(b_x,b_y); b[0] = b1; return b; }else { Bullet[] b = new Bullet[2]; int b_x = this.x + this.width/4; int b_y = this.y - 20; Bullet b1 = new Bullet(b_x,b_y); b[0] = b1; int b_x2 = this.x + this.width/4*3; Bullet b2 = new Bullet(b_x2,b_y); b[0] = b1; b[1] = b2; return b; } } /* * 1、如果当前状态为活着,加载数组的第一张图片 * 2、如果当前状态为死亡,把state=REMOVE */ @Override public BufferedImage getImage() { if(this.isLife()) { return image; }else if(this.isDead()) { state = REMOVE; } return null; } 6)画图片 public void paintObject(Graphics g) { g.drawImage(getImage(), x, y, null); g.drawImage(getImage(), x, y, null); } 在World类中画图片 定义方法objectAction FlyingObject object [] = {}; //敌人入场 public void objectAction(){ //小敌机的初始化 object = new FlyingObject[6]; object[0] = new Airplane(); object[1] = new Airplane(); object[2] = new Airplane(); object[3] = new BigAirplane(); object[4] = new BigAirplane(); object[5] = new BigAirplane(); } //实现画的功能 public void paint(Graphics g){ sky.paintObject(g); //画小敌机 for(int i = 0;i object[i].paintObject(g); } } 5.第五个任务:让画面动起来 (1)动起来 //天空向下移动 public void step() { y += step; y1 += step; if(y >= 700) { y = -700; } if(y1 >= 700) { y1 = -700; } } //敌人对象动起来 public void step() { y += step; } //小蜜蜂的step方法 public void step() { x += xstep; y += ystep; if(x>=400-this.width) { xstep *= -1; } } //子弹动起来 public void step() { y -= step; } (2)在world中定义方法 //让飞行物动起来 public void stepAction() { //天空 sky.step(); //让敌人(小敌机、大敌机、蜜蜂)动起来 for(int i = 0;i object[i].step(); } //让子弹动起来 for(int i = 0;i bullets[i].step(); } } 在run方法中调用 public void action() { //使用定时器 Timer timer = new Timer(); timer.schedule(new TimerTask() { public void run() { objectAction(); //生成敌人对象 stepAction(); //让画面动起来 bulletAction(); //run()功能:调用paint()方法 repaint(); } }, 10, 10); //delay延迟 period } (3)随机产生敌人对象 3.1)//随机产生一个敌人对象 public FlyingObject nextOne() { //20以内随机数 分成三个范围 定义其类型 int Random = new Random().nextInt(20); if(Random<4) { return new Bee(); }else if(Random>=4 && Random<12) { return new BigAirplane(); }else { return new Airplane(); } } //控制生成敌人数量 int flyIndex = 0; //敌人入场 public void objectAction() { flyIndex++; if(flyIndex % 40 == 0) { //敌人的初始化 FlyingObject obj = nextOne(); object = Arrays.copyOf(object, object.length+1); object[object.length-1] = obj; } } //控制生成子弹数量 int bulletIndex = 0; public void bulletAction() { bulletIndex++; if(bulletIndex % 40 == 0) { //子弹的初始化 Bullet b1[] = hero.getBullet(); //数组扩容:原来数组回收,新建数组拷贝扩容,第二参数为数组总大小 //Arrays.copyOf(original, newLength) bullets = Arrays.copyOf(bullets, bullets.length + b1.length); //对原数组数据拷贝第一个:从哪里开始拷;第四个:从哪里开始拷贝;第五个:拷贝多少个 System.arraycopy(b1, 0, bullets, bullets.length - b1.length, b1.length); } } 3.2)把随机对象放到数组中 int index = 0; //敌人入场 public void objectAction(){ index++; if(index%40==0){ //小敌机的初始化 FlyingObject ob = nextOne(); object = Arrays.copyOf(object,object.length+1); object[object.length-1]=ob; } } 4)子弹的产生 4.1)在Hero类中定义方法 public Bullet[] getBullet(){ if(doubleFire==0){ Bullet[] b = new Bullet[1]; int b_x = this.x + this.width/2; int b_y = this.y - 20; Bullet bl = new Bullet(b_x,b_y); b[0] = bl; return b; }else{ Bullet[] b = new Bullet[2]; int b_x = this.x + this.width/4; int b_y = this.y - 20; Bullet b1 = new Bullet(b_x,b_y); int b_x2 = this.x + this.width/4*3; Bullet b2 = new Bullet(b_x2,b_y); b[0] = b1; b[1] = b2; return b; } } 4.2)把子弹对象放到数组中 int bulletIndex=0; //子弹入场 public void bulletAction(){ bulletIndex++; if(bulletIndex%30==0){ Bullet bl[] = hero.getBullet(); //数组扩容 bullets = Arrays.copyOf(bullets, bullets.length+bl.length); //数组拷贝 System.arraycopy(bl, 0, bullets, bullets.length-bl.length, bl.length); } } 5)英雄机随鼠标移动(Hero类中) 5.1)//x,y表示鼠标的坐标 (Hero类中) public void move(int x,int y){ this.x = x - this.width/2; this.y = y - this.height/2; } 5.2)添加事件监视器 (World类中) //定义鼠标的移动事件处理方法(内部类:(匿名类)) MouseAdapter l = new MouseAdapter(){ public void mouseMoved(MouseEvent e){ //获取鼠标点的坐标 int x = e.getX(); int y = e.getY(); hero.move(x, y); } }; //给Jpanel添加事件监视器的对象 this.addMouseMotionListener(l); 6.第六个任务:删除越界的对象 public abstract boolean outOfBounds(); public boolean outOfBounds() { return this.y>700; } public boolean outOfBounds() { return this.y<0; } public boolean outOfBounds() { return false; } //回收越界的对象:(敌人,子弹) public void outOfBoundsAction() { //装活着的敌人的对象的数组 FlyingObject[] fo = new FlyingObject[object.length]; //活着的敌人对象数目 int lifeIndex = 0; //遍历数组 for(int i = 0;i //从数组中获取敌人的对象 FlyingObject f = object[i]; //找出没有越界的敌人 if(!f.outOfBounds()&&!f.isRemove()) { fo[lifeIndex] = f; lifeIndex++; } } //数组的拷贝 object = Arrays.copyOf(fo, lifeIndex); //子弹的越界对象的删除 //定义数组,装没有越界的子弹 Bullet[] bo = new Bullet[bullets.length]; //活着的子弹对象数目 int bulletsIndex = 0; //遍历数组 for(int i = 0;i //从数组中获取子弹的对象 Bullet b = bullets[i]; //找出没有越界的子弹 if(!b.outOfBounds()&&!b.isRemove()) { bo[bulletsIndex] = b; bulletsIndex++; } } //数组的拷贝 bullets = Arrays.copyOf(bo, bulletsIndex); } 7.第七个任务:定义敌人和子弹(英雄机)发生碰撞的方法 public boolean hit(FlyingObject other) { /* x轴的范围:this.x-other.width(左x) this.x+this.width(右x) y轴的范围:this.y+this.height(上y) this.y-other.height(下y) 如果子弹的x,y坐标在以上范围内,说明撞上了,返回true,否则返回false */ 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; } (2)定义接口,定义得分的方法 public interface Enemy { public int getScore(); } 需要大敌机和小敌机实现接口,重写方法 public int getScore() { return 1; } (3)定义接口,定义福利 public interface Award {//接口中都是公有静态常量,不用写属性,只需类型名字 int DOUBLEFIRE = 0;//带火力值 int LIFE = 1;//带名 int getType(); } 需要小蜜蜂实现接口 public int getType() { return awardType; } (4)定义功能方法 //让敌人去死的方法(在FlyingObject类中实现) public void goDead() { state = DEAD; } //加命(在Hero类中实现) public void addLife(){ life++; } //获取命(在Hero类中实现) public int getLife(){ return life; } //增加火力值(在Hero类中实现) public void addDoubleFire(){ doubleFire+=40; } 8.第八个任务:当子弹和敌人碰撞之后的得分和福利的设置,并在页面画分和命 //子弹和敌人发生碰撞 int score = 0; public void bulletHitAction(){ //遍历子弹集合, for(int i = 0;i //拿到一个子弹对象 Bullet b = bullets[i]; for(int j = 0;j FlyingObject f = object[j];//获取一个敌人对象 if(b.isLife()&&f.isLife()&&f.hit(b)){//子弹对象和所有的敌人碰撞的匹配 f.goDead();//敌人去死 b.goDead();//子弹去死 if(f instanceof Enemy){//如果是(大敌机或者是小敌机) score += ((Enemy) f).getScore();//得分 } if(f instanceof Award){//如果是小蜜蜂 switch(((Award) f).getType()){ case Award.DOUBLEFIRE://带火力值得小蜜蜂 hero.addDoubleFire();//火力值增加 case Award.LIFE://带命的小蜜蜂 hero.addLife();//命增加 } } } } } } g.drawString("Scoure:"+score, 10, 40); g.drawString("Life:"+hero.getLife(), 10, 60); 9.第九个任务:英雄机和敌人发生碰撞:如果碰到的是大(小)敌机,命-1; 如果碰到的是小蜜蜂:火力清0 (1)在Hero类中定义方法:subLife(); clearFire(); //减命 public void subLife(){ life--; } //清空火力值 public void clearFire(){ doubleFire = 0; } (2)heroHitAction(); //英雄机和敌人碰撞 public void heroHitAction() { for(int i = 0;i { FlyingObject f = object[i]; //获取一个敌人对象 if(f.isLife()&&f.hit(hero)) { f.goDead(); //敌人去死 if(f instanceof Enemy) { hero.subLife(); } if(f instanceof Award) { hero.clearFire(); } } } } 10.第10个任务:画窗口的状态 public static final int START = 0; public static final int RUNNING = 1; public static final int PAUSE = 2; public static final int GAMEOVER = 3; private int state = START; public void checkGameOverAction() { if(hero.getLife()==0&&hero.isRemove()) { state = GAMEOVER; } if(hero.getLife()==0) { hero.goDead(); } } //存放图片对象 private static BufferedImage startImage; private static BufferedImage pauseImage; private static BufferedImage gameOverImage; static { try { //以读取流的方式加载图片 startImage = ImageIO.read(Sky.class.getResource("start.png")); pauseImage = ImageIO.read(Sky.class.getResource("pause.png")); gameOverImage = ImageIO.read(Sky.class.getResource("gameover.png")); } catch(IOException e) { e.printStackTrace(); } } switch(state) { case START: g.drawImage(startImage, 0, 0, null); break; case PAUSE: g.drawImage(pauseImage, 0, 0, null); break; case GAMEOVER: g.drawImage(gameOverImage, 0, 0, null); break; } MouseAdapter l = new MouseAdapter() { public void mouseMoved(MouseEvent e) { if(state == RUNNING) { int x = e.getX(); int y = e.getY(); hero.move(x, y); } } public void mouseEntered(MouseEvent e) { if(state == PAUSE) { state = RUNNING; } } public void mouseExited(MouseEvent e) { if(state == RUNNING) { state = PAUSE; } } public void mouseClicked(MouseEvent e) { if(state == START) { state = RUNNING; } if(state == GAMEOVER) { //初始化操作 object = new FlyingObject[0]; bullets = new Bullet[0]; score = 0; hero = new Hero(); state = START; } } };