飞机大战 (递归版)

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.image.BufferedImage;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;


public class Fight extends JPanel {
    public static final int H= 1000;
    public static final int W=(int)(1.618*H);
  
    public static BufferedImage beeImg;
    public static BufferedImage devilImg;
    public static BufferedImage bossImg;
    public static BufferedImage bulletImg;
    public static BufferedImage hero0Img;
    public static BufferedImage hero1Img;
    public static BufferedImage startImg;
    public static BufferedImage stopImg;
    public static BufferedImage dieImg;
    static {
        try{
            devilImg   =ImageIO.read(Fight.class.getResourceAsStream("Image/devil.jpg"));
            bossImg   =ImageIO.read(Fight.class.getResourceAsStream("Image/boss.jpg"));
            bulletImg     =ImageIO.read(Fight.class.getResourceAsStream("Image/bullet.jpg"));
            beeImg        =ImageIO.read(Fight.class.getResourceAsStream("Image/bee.png"));
            hero0Img      =ImageIO.read(Fight.class.getResourceAsStream("Image/hero0.png"));
            hero1Img      =ImageIO.read(Fight.class.getResourceAsStream("Image/hero1.png"));
            startImg      =ImageIO.read(Fight.class.getResourceAsStream("Image/start.jpg"));
            stopImg      =ImageIO.read(Fight.class.getResourceAsStream("Image/stop.jpg"));
            dieImg      =ImageIO.read(Fight.class.getResourceAsStream("Image/die.jpg"));
        } catch (IOException e){
            e.printStackTrace();
        }
    }
      
    int scroe=0;
    int state=0;     // 0开始界面, 1暂停, 2运行游戏
    int level=1;    // 等级
    Flies hero;        // 英雄   + 子弹
    Flies boss;        // boss + 敌机
    Flies beeK;        // 蜂王   + 工蜂
    
    Fight(){
        new FightThread().start();//启动线程
        this.addMouseMotionListener(l);
        this.addMouseListener(l);
    }
    MouseAdapter l=new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e){
            if(state==0 || hero.life==0  ) { 
                state=2;
                hero =new Flies(W/2-32, H-64,  128, 128, 0, 0, -1, 1, 1, 0, 10);
                boss  =new Flies(-1 ,      0,  128, 128, 0, 0,  1, 1, 1, 0, 30);
                beeK  =new Flies(-1 ,      0,  128, 128, 0, 0,  1, 1, 1, 0, 50);
                beeK.vis=boss.vis=false;
                scroe=100;
            }
        }
        public void mouseMoved(MouseEvent e) {
            if(state==2){
                hero.x=e.getX()- hero.w/2;
                hero.y=e.getY()- hero.h/2;
            }
        }
        @Override
        public void mouseEntered(MouseEvent e) {
            if(state==1) state=2;
        }
        @Override
        public void mouseExited(MouseEvent e) {
            if(state==2) state=1;  
        }
    };
    

    public void paint(Graphics g){
        super.paint(g);
        if(state==0){
            g.drawImage(startImg, 0,0,W,H, null);
            paintStr(g, "Play", Color.gray, 40, 60, H/2+30);
        }
        else if(state==1) {
            g.drawImage(stopImg, 0,0,W,H, null);
            paintStr(g, "暂停", Color.gray, 40, W-140, H/2);
        }
        else if(state==2){
            paintStr(g, "得分:"+scroe, Color.black, 20, 5, H-20);
            paintStr(g, "life:"+hero.life, Color.black, 20, W-150, H-20);
            if(boss.vis) paintStr(g, "Bosslife:"+boss.life, Color.gray, 20, 10, 20);
            if(hero.life==0){
                g.drawImage(dieImg, 0,0,W,H, null);
                paintStr(g, "HEROES NEVER DIE", Color.black, 60, 0,300);
                paintStr(g, "Click replay", Color.black, 60,   230, 350);
                
            }
            else {
                paintFlies(g, hero, hero0Img, bulletImg);
                paintFlies(g, boss, bossImg, devilImg);
                paintFlies(g, beeK, beeImg, beeImg);
            }
        }else if(state==3){
            paintStr(g, "Win", Color.red, 100, W/2-80, H/2);
        }
    }
   
    public void paintStr(Graphics g, String str, Color col, int siz, int x, int y){
        Font font=new Font("宋体", Font.BOLD , siz);
        g.setFont(font);
        g.setColor(col);
        g.drawString(str, x, y);
   }
    //递归输出
    public void paintFlies(Graphics g, Flies x, BufferedImage FatherImg, BufferedImage SonImg){
           if(x.vis && x.life>0){
                if(x.depth==0) g.drawImage(SonImg , x.x, x.y, x.w, x.h, null);
                else g.drawImage(FatherImg , x.x, x.y, x.w, x.h, null);
           }
           for(Flies y : x.SonList)
               paintFlies(g, y, FatherImg, SonImg);
   }
    class FightThread extends Thread{
        public void run(){
            while(true){
                //改变坐标
                if(state==2 && hero.life>0){
                    hero.Split();
                    boss.Split();
                    beeK.Split();
                    Shot(beeK, hero, 1);
                    Shot(boss, hero, -1);
                    if(level==28){
                        boss.vis=true;
                    }
                    if(boss.life<=0) state=3;
                }
                //重绘
                repaint();
                //休眠
                try{
                    Thread.sleep(10);
                }catch(InterruptedException e){
                    e.printStackTrace();
                }    
            }
        }
        void Shot(Flies a, Flies b,int t){
            //a与b是否碰撞
            if(a.vis && b.vis && a.life>0 && b.life>0)
            if(a.x+a.w/2>=b.x && a.x+a.w/2<=b.x+b.w)
                if(a.y<=b.y+b.h && a.y >= b.y){
                    if(a.life>=b.life) { a.life=a.life-b.life; b.life=0; }
                    else { b.life=b.life-a.life; a.life=0; }
                    //题为标志变量,-1为杀死敌机,非-1为杀死工蜂
                    if(t==-1) { 
                        scroe++; 
                        if(scroe>=level*4 &&level<29) {
                            boss.upgrade(++level); 
                            hero.upgrade(level); 
                        }
                    } 
                    else {
                        hero.Switch();
                    }
                }
            //b与a的孩子是否碰撞
            for(Flies c : a.SonList)
                Shot(c, b, t);
            //a与b的孩子是否碰撞
            for(Flies c : b.SonList)
                Shot(c, a, t);
        }
    }
    
    public static void main(String[] args) {
        JFrame jfr =new JFrame("打飞机");
        jfr.setSize(W+15, H+38);
        Fight jpa=new Fight();
        jfr.add(jpa);
        jfr.setAlwaysOnTop(true);
        jfr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jfr.setLocationRelativeTo(null);
        jfr.setVisible(true);
    }
}
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class Flies{
    protected boolean vis=true;     // 是否可绘标志
    protected boolean RandX=false;  // 出生时 横坐标是否随机标志
    protected int x, y, bornX;        // 坐标 , bornX是出生是的x坐(为了按照给定的函数运动,初始点会参与计算)
    protected int w, h;                // 大小
    protected int Vx, Vy;            // 横,纵坐标轴飞行速度
    protected int dir;                // 方向:向上或向下
    protected int way=0;            // 子弹运动方式
    
    protected int time=0;            // 计时器
        //    根据等级改变的量
        protected int life;            // 生命
        protected int breadth,depth;// Son广度 ,Son深度
        protected int Tshot=30;        // 如果有Son, 其生成时间间隔
        
    protected List<Flies> SonList=new ArrayList<Flies>();;  // Son表单
    //构造函数初始化新生飞机
    Flies(int x, int y, int w, int h, int Vx,int Vy, int dir, int depth,int breadth, int way, int Tshot){
        Random rand=new Random();
        if(x==-1) { this.x=rand.nextInt(Fight.W-10)+10; RandX=true; }
        else this.x=x;
        this.bornX=this.x;
        this.y=y;
        this.w=w;
        this.h=h;
        this.Vx=Vx;
        this.Vy=Vy;
        this.dir=dir;
        this.depth=depth;
        this.life=w*h;
        this.breadth=breadth;
        this.way = way;
        this.Tshot=Tshot;
    }
    
    void Split(){
        int maxV=1000;        //速度上限
                time++;
                // 1.先运动。运动方式可以随心所欲,这里假设Vy受加速度为1,速度上限maxV
                y=y+Vy;
        x=x+Vx;
                if(depth==0 && Vy<=maxV && Vy>=-maxV) Vy=Vy+(Vy<0?-1:1);
                //2.判断是否出界,出界及死亡,然后删除生命值0且孙子飞行物个数为0 的子飞行物
                if(vis && (y+h<0 || y>Fight.H)) life = 0;
                for(int i=0;i<SonList.size();i++)
                if(SonList.get(i).life==0 && SonList.get(i).SonList.size()==0)
                    SonList.remove(i--);
                    
                //3.生成子飞行物
                if(time>=Tshot && life > 0 && depth > 0){
                    time=0;
                    for(int i=1;i<=breadth;i++){                
                        SonList.add(new Flies(
                            RandX ? -1 : (x+w/2-w/8),  y,    //纵坐标固定
                            w/4, h/4,                             //假设子大小为父大小16分之一
                            Vx+(breadth/2-i+(breadth%2==1?1:(breadth/2>=i?1:0))),
                            Vy+dir, dir, depth-1, breadth, way, Tshot ));
                    }
                }
                
        //4.递归:子飞行物生成孙子飞行物
                for(Flies x: SonList)
                    if(x.life>0) x.Split();
    }
    // 升级函数
    void upgrade(int level){
        life=life+1000;
        Tshot=30-level/2;
        depth=level/29+1;
        if(level==29) breadth=5;
        else breadth=level/5+1;
    }
    void Switch(){
        way++;
        way=way%2;
    }
    
    // 横坐标运动函数
     int fun(int way){
         if(way==1) return (int)(Math.sin(3.14*2/(400/breadth)*y)*(breadth-1)*4)+Vx+x;
         return x+Vx;
     }
}

 

点赞