面向对象经典案例坦克大战


package Tank;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.*;
import javax.swing.*;

/**
 * @author Administrator
 *包含主方法, MyPanel面板绘制我的坦克
 *2.画黄色坦克
 *lession3.画四个方向的坦克
 *4.坦克动起来+绘制3个敌人坦克
 *5.绘制子弹,子弹做成线程类
 *6.子弹连发,安排子弹只在画布中活动
 *7.限制子弹连发数在 KeyEvent.VK_J,子弹打中坦克方法 2层for循环
 *8.放入爆炸类图片 myPanel()新建图片对象,在原材料里新建爆炸类,在paint()里画爆炸效果,图片是和包同一级目录
 *9.敌人坦克动起来 做成线程类,难点自动调用重绘
 *10.敌人坦克围着屏幕转,敌人坦克发射子弹 在画坦克时 画敌人子弹
 *11.敌人坦克不能互相碰撞
 *12.制作开始游戏时的关卡显示面板
 *13.绘制新游戏菜单 开始我的面板    在原材料类新建Jilu类 定义静态方法敌人数量减少,然后在击中双方方法里调用
 *MyPanel里有tjsl()画出来 敌我坦克数量减少 显示在面板
 *14.每次开启游戏时,自动获得上次打死坦克数量  在右上面板显示
 *15.存盘退出 在记录类新建2个方法 MyPanel()里调用读取记录方法
 *16.新建存盘退出方法  新建位置类
 *17.Jilu类新建读盘方法  MyPanel()修改构造方法 增加if else判断
 *18.加上出场声音
 */
public class Tank1 extends JFrame implements ActionListener{
    private MyPanel mp=null;
    private GuangkaPanel gkmp=null;
    private JMenuBar jmenuBar;
    private JMenu cd1;
    private JMenuItem cdx1,cdx2,cdx3,cdx4;
    public Tank1() {
        jmenuBar=new JMenuBar();
        cd1=new JMenu("游戏(G)");
        cd1.setMnemonic('G');
        cdx1=new JMenuItem("新游戏(N)");
        cdx2=new JMenuItem("退出游戏(E)");
        cdx3=new JMenuItem("存盘退出(C)");
        cdx4=new JMenuItem("继续游戏(S)");
        cdx1.addActionListener(this);cdx2.addActionListener(this);
        cdx3.addActionListener(this);cdx4.addActionListener(this);
        cdx1.setActionCommand("newGame");cdx2.setActionCommand("exit");
        cdx3.setActionCommand("saveExit");cdx4.setActionCommand("goonGame");
        cd1.add(cdx1);cd1.add(cdx2);cd1.add(cdx3);cd1.add(cdx4);
        jmenuBar.add(cd1);
        this.setJMenuBar(jmenuBar);
        this.setIconImage((new ImageIcon("tank.jpg")).getImage());
        
        gkmp=new GuangkaPanel();    
        Thread t=new Thread(gkmp);
        t.start();
        this.add(gkmp);        
        
        this.setSize(600, 500);
        this.setLocation(300, 280);
        this.setResizable(false);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
        this.setTitle("坦克大战");
    }
    public static void main(String[] args) {
        Tank1 t1=new Tank1();
    }
    @Override
    public void actionPerformed(ActionEvent e) {
        if(e.getActionCommand().equals("newGame"))//新游戏事件
        {
            mp=new MyPanel("newGame");
            this.remove(gkmp);
            this.add(mp);
            this.addKeyListener(mp);
            Thread t=new Thread(mp);
            t.start();
            this.setVisible(true);
        }
        else if(e.getActionCommand().equals("goonGame"))//继续游戏
        {
            //封装
            mp=new MyPanel("goonGame");        
            Thread t=new Thread(mp);
            t.start();
            this.remove(gkmp);
            this.add(mp);        
            this.addKeyListener(mp);
            this.setVisible(true);
        }
        else if(e.getActionCommand().equals("saveExit"))//保存退出
        {
            Jilu jl=new Jilu();
            jl.setDtk(mp.dtk);//设置下敌人坦克的面板
            jl.cunpan();
            System.exit(0);
        }
        else if(e.getActionCommand().equals("exit"))//直接退出游戏
        {
            Jilu.bcjl();
            System.exit(0);
        }
    }
}
class GuangkaPanel extends JPanel implements Runnable{
    int times=0;
public void paint(Graphics g) {        
        super.paint(g);
        g.fillRect(0, 0, 400, 300);
        if(times%2==0) {//画关卡面板,时间出现闪烁的效果
            g.setColor(Color.yellow);
            Font myFont=new Font("华文行楷",Font.BOLD,38);
            g.setFont(myFont);
            g.drawString("第1关", 140, 140);
        }
}
    @Override
    public void run() {
        while(true) {
            try {
                Thread.sleep(600);//间隔多少出现闪烁
            } catch (Exception e) {e.printStackTrace();}
            times++;
            this.repaint();
        }
    }    
}
/**
 * @author Administrator
 *面板绘制坦克
 */
class MyPanel extends JPanel implements KeyListener, Runnable{

     MyTank mt=null;
     DiTank dt=null;
    //敌人坦克多线程 使用vector集合  坦克组 向量
    Vector<DiTank> dtk=new Vector<DiTank>();
    Vector<Baozha> bzjh=new Vector<Baozha>();    
    static Vector<Weizhi> wzjh=new Vector<Weizhi>();

    int tksl=3;
    //爆炸也需要做向量,有3张图片
    Image tp1=null;
    Image tp2=null;
    Image tp3=null;
    
    public MyPanel(String ss) {
        //第一个读取硬盘数据
        Jilu.dqjl();
        mt=new MyTank(140,232);
        if(ss=="newGame") {            
            for(int i=0;i<tksl;i++) {
                 dt=new DiTank((i)*180+5, 0);
                dt.setFangxiang(2);
                Thread t2=new Thread(dt);
                t2.start();//敌人坦克启动线程
                Zidan zd=new Zidan(dt.x+10,dt.y+30,2);
                dt.dzd.add(zd);
                Thread t3=new Thread(zd);//敌人发射子弹线程
                t3.start();
                dtk.add(dt);
                dt.dtkxl(dtk);//?
            }
        }else if(ss.equals("goonGame")) {
            wzjh=Jilu.dupan();
            for(int i=0;i<wzjh.size();i++) {
                Weizhi wz=wzjh.get(i);
                DiTank dt=new DiTank(wz.x,wz.y);
                dt.setFangxiang(wz.fangxiang);
                dt.dtkxl(dtk);
                Thread t2=new Thread(dt);
                t2.start();//敌人坦克启动线程
                Zidan zd=new Zidan(dt.x+10,dt.y+30,2);
                dt.dzd.add(zd);
                Thread t3=new Thread(zd);//敌人发射子弹线程
                t3.start();
                dtk.add(dt);            
            }
        }
        Shengyin sy=new Shengyin("./tank.wav");
        sy.start();
        tp1=Toolkit.getDefaultToolkit().getImage(("src/bzxg1.gif"));
        tp2=Toolkit.getDefaultToolkit().getImage(("src/bzxg2.gif"));
        tp3=Toolkit.getDefaultToolkit().getImage(("src/bzxg3.gif"));

    }
    //画敌我坦克数量减少方法
    public void tjsl(Graphics g) {
        this.drawTank(80, 330, g, 0, 0);
        g.setColor(Color.black);
        g.drawString(Jilu.getMtsl()+"", 116, 350);
        this.drawTank(150, 330, g, 0, 1);
        g.setColor(Color.black);
        g.drawString(Jilu.getDtsl()+"", 186, 350);
        
        this.drawTank(450, 86, g, 0, 1);
        g.setColor(Color.black);
        g.drawString(Jilu.getSdtj()+"", 486, 107);
        g.setColor(Color.BLACK);
        Font f=new Font("华文彩云",Font.BOLD,20);
        g.setFont(f);
        g.drawString("你消灭的坦克总数", 410, 40);
    }
    public void paint(Graphics g) {
        
        super.paint(g);
        g.fillRect(0, 0, 400, 300);
        this.tjsl(g);
        //画我的坦克
        if(mt.shengming) {
            this.drawTank(mt.getX(),mt.getY(),g,mt.fangxiang,0);
        }
        //画敌人的坦克 3辆
        for(int i=0;i<dtk.size();i++) {
            DiTank dt=dtk.get(i);
            if(dt.shengming) {
                this.drawTank(dtk.get(i).getX(),dtk.get(i).getY(),g,dt.fangxiang,1);
                for(int j=0;j<dt.dzd.size();j++) {        
                    
                    Zidan dtzd=dt.dzd.get(j);//每次往里装一颗子弹
                    if(dtzd!=null && dtzd.shengming==true) {
                        g.setColor(Color.white);
                        g.fill3DRect(dtzd.x, dtzd.y, 3, 3, false);
                    }
                    if(dtzd.shengming==false) {//子弹碰墙 后进行删除
                        dt.dzd.remove(dtzd);    
                    }
                }
            }
        }
        //画我的坦克子弹
        for(int i=0;i<mt.aa.size();i++) {
            Zidan zd=mt.aa.get(i);//每次往里装一颗子弹
            if(mt.zd!=null && mt.zd.shengming==true) {
                g.setColor(Color.white);
                g.fill3DRect(zd.x, zd.y, 3, 3, false);
            }
            if(zd.shengming==false) {//子弹碰墙 后进行删除
                mt.aa.remove(zd);    
            }
        }
/*        //画敌人坦克子弹  已经放到画敌人坦克循环里了
        for(int i=0;i<dt.dzd.size();i++) {        
            //DiTank dt=dtk.get(i);
            Zidan dtzd=dt.dzd.get(i);//每次往里装一颗子弹
            if(dtzd!=null && dtzd.shengming==true) {
                g.setColor(Color.white);
                g.fill3DRect(dtzd.x, dtzd.y, 3, 3, false);
            }
            if(dtzd.shengming==false) {//子弹碰墙 后进行删除
                dt.dzd.remove(dtzd);    
            }
        }*/
        //画爆炸类
    for(int i=0;i<bzjh.size();i++) {
        
        Baozha bz=bzjh.get(i);
        if(bz.shengcunqi>6) {
            g.drawImage(tp1, bz.x, bz.y, 30, 30, this);            
        }else if(bz.shengcunqi>3) {
            g.drawImage(tp2, bz.x, bz.y, 30, 30, this);
        }else {
            g.drawImage(tp3, bz.x, bz.y, 30, 30, this);
        }
        bz.suqsd();
        if(bz.shengcunqi==0) {
            bzjh.remove(bz);
        }
    }
    
}
    //击中我方坦克的方法
    public void jzwf() {
        for(int i=0;i<this.dtk.size();i++) {//将敌人坦克一个个取出来
            DiTank dt=dtk.get(i);
            for(int j=0;j<dt.dzd.size();j++) {//将敌人子弹一个个取出来,2者进行比较
                Zidan zd=dt.dzd.get(j);
                if(mt.shengming) {
                    this.jzdf(zd, mt);
                }
            }
            this.repaint();
        }
    }
    //击中敌人坦克方法
    public void jzdf1() {
        for(int i=0;i<mt.aa.size();i++) {//每取出一颗子弹
            Zidan zd=mt.aa.get(i);
            if(zd.shengming) {
                for(int j=0;j<dtk.size();j++) {//每取出一个敌人坦克
                    DiTank dt=dtk.get(i);
                    if(dt.shengming) {
                        if(this.jzdf(zd, dt)) {//b2值为真
                            Jilu.dtjs();
                            Jilu.sdsl();
                        }
                    }                    
                }    
            }
            this.repaint();
        }
    }
    //子弹击中敌人坦克方 法 升级为击中双方坦克的方法
        public boolean jzdf(Zidan zd,Tank dt) {//多态 父类引用指向子类对象
            //子弹不分敌我的 这里
            DiTank dt1;
            boolean b2=false;
            switch(dt.fangxiang) {
            case 0:
            case 2:
                if(zd.x>dt.x && zd.x<dt.x+20 && zd.y>dt.y && zd.y<dt.y+30)
                {
                    Baozha bz=new Baozha(dt.x,dt.y);//需要给爆炸图传入x,y坐标值
                    bzjh.add(bz);
                    zd.shengming=false;
                    dt.shengming=false;
                    b2=true;
                /*if(dt instanceof DiTank) {//判断当前传入的对象是属于哪个类的,然后执行操作
                    Jilu.dtjs();
                    Jilu.sdsl();
                    }*/                    
                }
                break;
            case 1:
            case 3:
                if(zd.x>dt.x && zd.x<dt.x+30 && zd.y>dt.y && zd.y<dt.y+20)
                {
                    Baozha bz=new Baozha(dt.x,dt.y);
                    bzjh.add(bz);
                    zd.shengming=false;
                    dt.shengming=false;    
                    b2=true;
                    //if(dt instanceof DiTank) {Jilu.dtjs();Jilu.sdsl();}
                }            
            }
            return b2;
        }
    

    public void drawTank(int x, int y, Graphics g, int fangxiang, int leixing) {
        switch(leixing) {
        case 0://我的坦克 黄色
            g.setColor(Color.yellow);
            break;
        case 1://敌人的坦克 绿色
            g.setColor(Color.green);
        }
        switch(fangxiang) {
        case 0://上
            g.fill3DRect(x, y, 5, 30, false);//左边的矩形
            g.fill3DRect(x+15, y, 5, 30, false);//右边的矩形
            g.fill3DRect(x+5, y+5, 10, 20, false);//中间的矩形
            g.fillOval(x+5, y+10, 10, 10);
            g.drawLine(x+10, y+15, x+10, y-3);
            break;
        case 1://左
            g.fill3DRect(x, y, 30, 5, false);//左边的矩形
            g.fill3DRect(x, y+15, 30, 5, false);//右边的矩形
            g.fill3DRect(x+5, y+5, 20, 10, false);//中间的矩形
            g.fillOval(x+10, y+5, 10, 10);
            g.drawLine(x+15, y+10, x-3, y+10);
            break;
        case 2://下
            g.fill3DRect(x, y, 5, 30, false);//左边的矩形
            g.fill3DRect(x+15, y, 5, 30, false);//右边的矩形
            g.fill3DRect(x+5, y+5, 10, 20, false);//中间的矩形
            g.fillOval(x+5, y+10, 10, 10);
            g.drawLine(x+10, y+15, x+10, y+33);
            break;
        case 3://右
            g.fill3DRect(x, y, 30, 5, false);//左边的矩形
            g.fill3DRect(x, y+15, 30, 5, false);//右边的矩形
            g.fill3DRect(x+5, y+5, 20, 10, false);//中间的矩形
            g.fillOval(x+10, y+5, 10, 10);
            g.drawLine(x+15, y+10, x+33, y+10);
            break;
        }
    }
    @Override
    public void keyTyped(KeyEvent e) {}
    public void keyReleased(KeyEvent e) {}
    public void keyPressed(KeyEvent e) {
        if(e.getKeyCode()==KeyEvent.VK_W) {
            this.mt.setFangxiang(0);
            mt.xiangshang();
        }else if(e.getKeyCode()==KeyEvent.VK_A){
            this.mt.setFangxiang(1);
            mt.xiangzuo();
        }else if(e.getKeyCode()==KeyEvent.VK_S){
            this.mt.setFangxiang(2);
            mt.xiangxia();
        }else if(e.getKeyCode()==KeyEvent.VK_D){
            this.mt.setFangxiang(3);
            mt.xiangyou();
        }
        if(e.getKeyCode()==KeyEvent.VK_J) {
            if(mt.aa.size()<3) {//限制子弹数为8个
                this.mt.fszd();
            }            
        }
        this.repaint();
    }
    
    @Override
/*    public void run() {
        while(true) {
            try {
                Thread.sleep(100);//合理利用资源 隔100ms重绘制
            } catch (Exception e) {}
            //子弹和坦克在面板碰撞
            for(int i=0;i<mt.aa.size();i++) {
                //二层循环的目的每发子弹和每量敌人坦克碰撞
                Zidan zd=mt.aa.get(i);
                if(zd.shengming) {
                    for(int j=0;j<dtk.size();j++) {
                        DiTank dt=dtk.get(j);
                        if(dt.shengming) {                            
                            this.jzdf(zd,dt);                                
                        }
                    }
                }
                this.repaint();
            }
    // 因为敌方坦克没有线程来自动调用重绘,
//你可以在Mypanel的run方法判断子弹和坦克的那个线程this.repaint()再外面一个循环再加一个this.repaint()
            this.repaint();
        }
    
    }//run()
*/
    public void run() {//第10课后直接在MyPanel线程类调用方法
        while(true) {
            try {
                Thread.sleep(100);//合理利用资源 隔100ms重绘制
            } catch (Exception e) {}
            this.jzdf1();
            this.jzwf();
            this.repaint();
        }
    }
}

原文地址:https://www.cnblogs.com/smartwen666/p/7859693.html