Java-Java基础07之坦克大战保存玩家记录及加音效

主要内容有:Java对文件的读写操作、文件输入/输出流的应用、图片的拷贝、文件字符流、缓冲字符流、记事本界面与功能的完善、播放声音、坦克大战v4.0添加保存玩家记录、添加游戏音效。

File类的基本用法_Demo12_1.java

/*
* 功能 :File类的基本用法
*/
package com.test1;
import java.io.*;
public class Demo12_1 {
    /**
     * @param args
     */
    public static void main(String[] args) {
        //创建一个文件对象
        File f=new File("d:\\aa.txt");
        //得到文件的路径
        System.out.println("文件路径:"+f.getAbsolutePath());
        //得到文件的大小,字节数
        System.out.println("文件大小:"+f.length());
        System.out.println("可读:"+f.canRead()+" 可写:"+
                f.canWrite()+" 可执行:"+f.canExecute());
        //创建文件和创建文件夹
        File f1=new File("d:\\ff\\bb.txt");
        if(!f1.exists())
        {
        //可以创建新文件
            try {
                f1.createNewFile();
            } catch (IOException e) {
        // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        else
        {
            System.out.println("文件存在不能创建!");
        }
        //创建文件夹
        File f2=new File("d:\\ff");
        if(f2.isDirectory())
        {
            System.out.println("文件夹已存在!");
        }
        else
        {
        //创建
            f2.mkdir();
        }
        //文件与文件夹都是文件,文件夹是一种特殊的文件
        //列出一个文件夹下的所有文件
        File f3=new File("d:\\ff");
        if(f3.isDirectory())
        {
            File lists[]=f3.listFiles();
            for(int i=0;i<lists.length;i++)
            {
                System.out.println("文件名:"+lists[i].getName());
            }
        }
    }
}

FileInputStream类的使用_Demo12_2.java

/*
* 演示FileInputStream类的使用
*/
package com.test2;
import java.io.*;
public class Demo12_2 {
    /**
     * @param args
     */
    public static void main(String[] args) {
        //得到一个文件对象
        File f=new File("d:/test.txt");
        //因为File没有读写的能力,所以要使用InputStream流。
        FileInputStream fis=null;
        try {
            //文件输入流
            fis=new FileInputStream(f);
            byte []bytes=new byte[1024];        //定义一个字节数组,相当于缓存
            int n=0;         //用于存放实际读取到的字节数
            //循环读取
            while((n=fis.read(bytes))!=-1)
            //如果文件流中的字节数大于数组长度(1024),循环一次,就从输入文件流中
            //读取等于数组长度(1024)的字节存到字节数组bytes中,第二次再读取剩余的,
            //如果文件流中的字节数大于数组长度(1024),则一次循环就能文件流中的字节全都存入bytes数组中
            {
            //把字节转成String
                String s=new String(bytes,0,n);
                System.out.println(s);
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{
            //关闭文件流必须放在finally块里
            try {
                fis.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

FileOutputStream的使用_Demo12_3.java

/*
* 演示FileOutputStream的使用
*/
package com.test3;
import java.io.*;
public class Demo12_3 {
    /**
     * @param args
     */
    public static void main(String[] args) {
        //定义文件对象
        File f=new File("d:\\ss.txt");
        //字节输出流
        FileOutputStream fos=null;
        try {
            fos=new FileOutputStream(f);
            String s="维唯为为 OK,HelloWorld";
            String s1="中国好!";
            //定义字节数组
            //byte []bytes=new byte[1024];
            //如何把String->bytes数组
            try {
                fos.write(s.getBytes("UTF-8"));
                fos.write(s1.getBytes("UTF-8"));
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally
        {
            try {
                fos.close();         //关闭文件流
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

图片拷贝Demo12_4.java

/*
* 图片拷贝
*/
package com.test4;
import java.io.*;
public class Demo12_4 {
    /**
     * @param args
     */
    public static void main(String[] args) {
        //思路 先把图片读入到内存-->写入到某个文件
        //因为是二进制文件,因此只能用字节流完成
        FileInputStream fis=null;        //定义输入流
        FileOutputStream fos=null;        //定义输出流
        try {
            fis=new FileInputStream("d:/ff/a.jpg");        //输入流
            fos=new FileOutputStream("d:/a.jpg");        //输出流
            byte buf[]=new byte[512];
            int n=0;
            //循环读取
            while((n=fis.read(buf))!=-1)
            {
                //输出到指定文件
                fos.write(buf);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            try {
                fis.close();        //关闭输入流
                fos.close();        //关闭输出流
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

文件字符流_Demo12_5.java

/*
* 演示文件字符流的案例
*/
package com.test5;
import java.io.*;
public class Demo12_5 {
    /**
     * @param args
     */
    public static void main(String[] args) {
        //文件读取出字符流对象(输入流)
        FileReader fr=null;
        //写入到文件(输出流)
        FileWriter fw=null;
        try{
        //创建fr输入对象
            fr=new FileReader("d:        //test.txt");
        //创建fw输出对象
            fw=new FileWriter("d:/vvvv.txt");
            int n=0;        //记录实际读取的字符数
        //读入内存
            char c[]=new char[1024];
            while((n=fr.read(c))!=-1)        //循环读出
            {
                String s=new String(c,0,n);
        //将c中有效字符存到s中
                System.out.println(s);
                fw.write(c, 0, n);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally{
            try {
                fr.close();
                fw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

缓冲字符流_Demo12_6.java

/*
* 演示缓冲字符流案例
*/
package com.test6;
import java.io.*;
public class Demo12_6 {
    /**
     * @param args
     */
    public static void main(String[] args) {
        //
        BufferedReader br=null;        //Buf输入流
        BufferedWriter bw=null;        //Buf输出流
        try {
            //先创建FileReader对象
            FileReader fr=new FileReader("d:/test.txt");
            br=new BufferedReader(fr);
            //创建FileWriter对象
            FileWriter fw=new FileWriter("d:/赵云.txt");
            bw=new BufferedWriter(fw);
            //循环读取文件
            String s="";
            while((s=br.readLine())!=null)         //从buf流中读取
            {
                System.out.println(s);
                //输出到磁盘
                bw.write(s+"\r\n");
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{
            try {
                br.close();
                bw.close();
            } catch (Exception e2) {
                // TODO: handle exception
            }
        }
    }
}

记事本_Demo12_7.java

/*
* 我的记事本(界面+功能)
*/
package com.test7;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Notepad extends JFrame implements ActionListener{
    //定义需要的组件
    JTextArea jta=null;             //文本域
    JMenuBar jmb=null;             //菜单条
    JMenu jml=null;             //第一JMenu
    JMenuItem jmi1=null;            //菜单项
    JMenuItem jmi2=null;            //菜单项
    public static void main(String[] args) {
            //
        Notepad notepad=new Notepad();
    }
            //构造函数
    public Notepad()
    {
        //创建jta
        jta=new JTextArea();
        jmb=new JMenuBar();
        jml=new JMenu("文件");
        //设置助记符
        jml.setMnemonic('F');
        jmi1=new JMenuItem("打开(o)",new ImageIcon("./src/new.jpg"));
        //注册监听
        jmi1.addActionListener(this);
        jmi1.setActionCommand("open");
        jmi2=new JMenuItem("保存(s)",new ImageIcon("./src/save.jpg"));
        jmi2.addActionListener(this);
        jmi2.setActionCommand("save");
        //加入菜单条
        this.setJMenuBar(jmb);
        //把菜单jml放入菜单条jmb
        jmb.add(jml);
        //把菜单项(jmi1)放入菜单(jml)
        jml.add(jmi1);
        jml.add(jmi2);
        //放入到JFrame
        this.add(jta);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setSize(400,500);
        this.setVisible(true);
    }
    @Override
    public void actionPerformed(ActionEvent e) {
        //判断是哪个菜单被选中
        if(e.getActionCommand().equals("open"))            //打开菜单
        {
            System.out.println("点击了打开菜单项!");
            //隆重推荐JFileChooser
            //文件选择组件
            JFileChooser jfc1=new JFileChooser();
            //设置名字
            jfc1.setDialogTitle("请选择文件....");
            //按默认方式显示打开文件对话框
            jfc1.showOpenDialog(null);
            //显示
            jfc1.setVisible(true);
            //得到用户选择的文件全路径
            String filename=jfc1.getSelectedFile().getAbsolutePath();
            //读取文件中的内容
            FileReader fr=null;
            BufferedReader br=null;
            try {
                fr=new FileReader(filename);
                br=new BufferedReader(fr);
            //从文件中读取信息并显示到jta
                String s="";
                String allCon="";
                while((s=br.readLine())!=null)
                {
                    allCon+=s+"\r\n";
                }
            //放置到jta
                jta.setText(allCon);
            } catch (Exception e2) {
                e2.printStackTrace();
            }finally{
                try {
                    fr.close();
                    br.close();
                } catch (Exception e3) {
                    e3.printStackTrace();
                }
            }
        }
        else if(e.getActionCommand().equals("save"))
        {
            System.out.println("点击了保存菜单项!");
            //隆重推荐JFileChooser
            //出现保存对话框
            JFileChooser jfc1=new JFileChooser();
            //设置名字
            jfc1.setDialogTitle("另存为....");
            //按默认方式显示保存文件对话框
            jfc1.showSaveDialog(null);
            //显示
            jfc1.setVisible(true);
            //得到用户选择的文件全路径
            String filename=jfc1.getSelectedFile().getAbsolutePath();
            //把内容写入到指定的文件
            FileWriter fw=null;
            BufferedWriter bw=null;
            try {
                fw=new FileWriter(filename);
                bw=new BufferedWriter(fw);
            //写入
                bw.write(this.jta.getText());
            } catch (Exception e2) {
                e2.printStackTrace();
            }finally{
                try {
                    bw.close();
                    fw.close();
                } catch (Exception e3) {
                    e3.printStackTrace();
                }
            }
        }
    }
}

测试声音_ TestAudio.java

/*
* 测试声音
*/
package com.test2;
import java.io.*;
import javax.sound.sampled.*;
public class TestAudio {
    /**
     * @param args
     */
    public static void main(String[] args) {
         //1.创建建一个AePlayWave对象实例
        AePlayWave apw=new AePlayWave("./src/声音.wav");
         //2.启动该线程播放
        apw.start();
    }
}
         //播放声音的类
class AePlayWave extends Thread {
    private String filename;
    public AePlayWave(String wavfile) {
        filename = wavfile;
    }
    public void run() {
        File soundFile = new File(filename);
        AudioInputStream audioInputStream = null;
        try {
            audioInputStream = AudioSystem.getAudioInputStream(soundFile);
        } catch (Exception e1) {
            e1.printStackTrace();
            return;
        }
        AudioFormat format = audioInputStream.getFormat();
        SourceDataLine auline = null;
        DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
        try {
            auline = (SourceDataLine) AudioSystem.getLine(info);
            auline.open(format);
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }
        auline.start();
        int nBytesRead = 0;
         //这是缓冲
        byte[] abData = new byte[512];
        try {
            while (nBytesRead != -1) {
                nBytesRead = audioInputStream.read(abData, 0, abData.length);
                if (nBytesRead >= 0)
                    auline.write(abData, 0, nBytesRead);
            }
        } catch (IOException e) {
            e.printStackTrace();
            return;
        } finally {
            auline.drain();
            auline.close();
        }
    }
}

坦克大战v4.0_ MyTankGame3.java

/*
* 功能:坦克大战v4.0
* 1.画出坦克
* 2.我的坦克可以上下左右移动
* 3.可以发射子弹,子弹连发(最多5颗)
* 4.当子弹击中敌人坦克时,敌人坦克消失(爆炸效果)
* 5.我被击中时,显示爆炸效果
* 6.防止敌人坦克重叠运动
* 6.1决定把判断是否碰撞的函数写到EnemyTank类中去
* 7.可以分关
* 7.1做一个开始的Panel,它是一个空的
* 7.2字体闪烁效果
* 8.可以在玩游戏的时候暂停和继续
* 8.1当用户点暂停时,子弹的速度和坦克 速度设为0,并让坦克的方向不变化
* 9.可以记录玩家的成绩
* 9.1用文件流
* 9.2单写一个记录类,完成对玩家的记录
* 9.3先完成保存共击毁了多少敌人坦克的功能
* 9.4存盘退出游戏,可以记录当时敌人坦克的坐标,并可以恢复
* 10.java如何操作声音文件
* 10.1对声音文件的操作
* 11.网络对决....
*/
package com.test1;
import java.awt.*;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
public class MyTankGame3 extends JFrame implements ActionListener
{
    MyPanel mp=null;         //游戏面板
    MyStartPanel msp=null;         //开始面板
        //需要的菜单
    JMenuBar jmb=null;
        //开始游戏
    JMenu jm1=null;         //菜单
    JMenuItem jmi1=null;        //菜单项
    JMenuItem jmi2=null;        //退出
    JMenuItem jmi3=null;        //存盘退出
    JMenuItem jmi4=null;        //续上局
        //构造函数
    public MyTankGame3()
    {
        //创建菜单及菜单项
        jmb=new JMenuBar();
        jm1=new JMenu("游戏(G)");
        jm1.setMnemonic('G');        //设置快捷方式
        jmi1=new JMenuItem("开始新游戏(N)");
        jmi1.setMnemonic('N');        //设置快捷方式
        jmi2=new JMenuItem("退出游戏(E)");
        jmi2.setMnemonic('E');        //设置快捷方式
        jmi3=new JMenuItem("存盘退出游戏(E)");
        jmi3.setMnemonic('C');        //设置快捷方式
        jmi4=new JMenuItem("继续上局游戏(R)");
        jmi4.setMnemonic('R');        //设置快捷方式
        jm1.add(jmi1);        //将菜单项(jmi1)加入菜单(jm1)
        jm1.add(jmi2);
        jm1.add(jmi3);
        jm1.add(jmi4);
        jmb.add(jm1);        //将菜单(jm1)加入菜单栏
        //对jmi1i添加事件响应
        jmi1.addActionListener(this);
        jmi1.setActionCommand("newGame");
        jmi2.addActionListener(this);
        jmi2.setActionCommand("exit");
        jmi3.addActionListener(this);
        jmi3.setActionCommand("saveExit");
        jmi4.addActionListener(this);
        jmi4.setActionCommand("conGame");
        //加入提示面板
        msp=new MyStartPanel();
        this.add(msp);
        Thread t=new Thread(msp);
        t.start();
        this.setJMenuBar(jmb);        //加入菜单栏
        this.setSize(600,500);
        this.setLocation(200,200);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
    }
    public static void main(String[] args) {
        MyTankGame3 mtg=new MyTankGame3();
    }
    @Override
    public void actionPerformed(ActionEvent e) {
        //开始新的游戏
        if(e.getActionCommand().equals("newGame"))
        {
        //创建游戏战场面板
            mp=new MyPanel("newGame");
        //启动mp线程
            Thread t=new Thread(mp);
            t.start();
            this.remove(msp);        //先删除旧的开始面板
            this.add(mp);         //然后加入新的游戏面板
        //注册监听
            this.addKeyListener(mp);
        //显示、刷新JFrame
            this.setVisible(true);
        }
        else if(e.getActionCommand().equals("exit"))
        {
        //用户点击了退出系统的菜单
        //保存击毁敌人数量
            Recorder.keepRecording();
            System.exit(0);        //退出,0代表正常退出,-1代表异常退出
        }
        //对存盘退出处理
        else if(e.getActionCommand().equals("saveExit"))
        {
        //工作
            Recorder rd=new Recorder();
            rd.setEts(mp.ets);
        //保存击毁敌人的数量和坐标
            rd.keeyRecAndEnemyTank();
            System.exit(0);        //退出
        }
        else if(e.getActionCommand().equals("conGame"))        //续上局
        {
        //创建游戏战场面板
            mp=new MyPanel("conGame");
        //mp.flag="con";
        //启动mp线程
            Thread t=new Thread(mp);
            t.start();
            this.remove(msp);        //先删除旧的开始面板
            this.add(mp);         //然后加入新的游戏面板
        //注册监听
            this.addKeyListener(mp);
        //显示、刷新JFrame
            this.setVisible(true);
        }
    }
}
        //开始提示面板
class MyStartPanel 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,30);
            g.setFont(myFont);
            g.drawString("stage:1", 130, 150);
        }
    }
    @Override
    public void run() {
        //
        while(true)
        {
        //休眠
            try {
                Thread.sleep(100);
            } catch (Exception e) {
                e.printStackTrace();
            }
            times++;
        //重画
            this.repaint();
        }
    }
}
        //我的面板
class MyPanel extends JPanel implements KeyListener,Runnable
{
        //定义一个我的坦克
    Hero hero=null;
        //判断是续上局,还是新游戏
        //String flag="newGame";
        //定义敌人的坦克组
    Vector<EnemyTank>ets=new Vector<EnemyTank>();
    Vector<Node>nodes=new Vector<Node>();
        //定义炸弹集合
    Vector<Bomb>bombs=new Vector<Bomb>();
        //初始化敌人坦克数量
    int enSize=6;
        //定义三张图片,组成成一颗炸弹
    Image image1=null;
    Image image2=null;
    Image image3=null;
        //构造函数
    public MyPanel(String flag)
        //构造函数中的参数,用于判断是续上局,还是新游戏
    {
        Recorder.getRecording();        //恢复记录
        hero=new Hero(100,200);
        if(flag.equals("newGame"))        //如果是新游戏
        {
        //初始化敌人的坦克
            for(int i=0;i<enSize;i++)
            {
        //创建一个辆敌人的坦克对象
                EnemyTank et=new EnemyTank((i+1)*50,0);
                et.setColor(0);        //设置颜色
                et.setDirect(2);        //设置方向
        //将MyPanel的敌人坦克向量交给敌人坦克
                et.setEts(ets);
        //启动敌人的坦克
                Thread t=new Thread(et);
                t.start();
        //给敌人坦克添加一颗子弹
                Shot s=new Shot(et.x+10,et.y+30,2);
        //把子弹加入给敌人
                et.ss.add(s);
        //启动子弹敌人的子弹线程
                Thread t2=new Thread(s);
                t2.start();
        //加入
                ets.add(et);
            }
        }
        else         //如果不新游戏
        {
            nodes=new Recorder().getNodesAndEnNums();        //恢复敌人坦克
        //初始化敌人的坦克
            for(int i=0;i<nodes.size();i++)
            {
                Node node=nodes.get(i);
        //创建一个辆敌人的坦克对象
                EnemyTank et=new EnemyTank(node.x,node.y);
                et.setColor(0);        //设置颜色
                et.setDirect(node.direct);        //设置方向
        //将MyPanel的敌人坦克向量交给敌人坦克
                et.setEts(ets);
        //启动敌人的坦克
                Thread t=new Thread(et);
                t.start();
        //给敌人坦克添加一颗子弹
                Shot s=new Shot(et.x+10,et.y+30,2);
        //把子弹加入给敌人
                et.ss.add(s);
        //启动子弹敌人的子弹线程
                Thread t2=new Thread(s);
                t2.start();
        //加入
                ets.add(et);
            }
        }
        try{
            image1=ImageIO.read(new File("./src/bomb_1.gif"));
            image2=ImageIO.read(new File("./src/bomb_2.gif"));
            image3=ImageIO.read(new File("./src/bomb_3.gif"));
        }catch (Exception e)
        {
            e.printStackTrace();
        }
        //播放开战声音
        AePlayWave apw=new AePlayWave("./src/声音.wav");
        apw.start();
        //初始化图片
        //image1=Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_1.gif"));
        //image2=Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_2.gif"));
        //image3=Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_3.gif"));
    }
        //画出提示信息坦克(该坦克不参与战斗)
    public void showInfo(Graphics g)
    {
        //敌人的坦克提示信息
        this.drawTank(60, 330, g, 3, 0);
        g.setColor(Color.black);
        g.drawString(Recorder.getEnNum()+"", 85, 350);
        //我的坦克提示信息
        this.drawTank(130, 330, g, 3, 1);
        g.setColor(Color.black);
        g.drawString(Recorder.getMyLife()+"", 155, 350);
        //画出玩家的总成绩
        g.setColor(Color.black);
        Font f=new Font("宋体",Font.BOLD,20);
        g.setFont(f);
        g.drawString("您的总成绩:", 420, 30);
        this.drawTank(430, 60, g, 3, 0);        //敌人坦克
        g.setColor(Color.black);
        g.drawString(Recorder.getAllEnNum()+"", 460, 80);
    }
        //重写paint函数
    public void paint(Graphics g)
    {
        super.paint(g);         //这句不能少
        g.fillRect(0,0,400,300);        //设置游戏面板背景
        //画出提示信息
        this.showInfo(g);
        //画出自己的坦克
        if(hero.isLive)
        {
            this.drawTank(hero.getX(), hero.getY(), g, this.hero.direct, 1);
        }
        //从ss中取出每一颗子弹,并画出
        for(int i=0;i<this.hero.ss.size();i++)         //设置子弹连发
        {
        //取出一颗子弹
            Shot myShot=hero.ss.get(i);
        //画出一颗子弹
            if(hero.s!=null&&hero.s.isLive==true)
            {
                g.setColor(Color.WHITE);        //设置子弹颜色
                g.fill3DRect(myShot.x, myShot.y, 3, 3, true);
            }
            if(myShot.isLive==false)        //如果子弹已经死亡
            {
        //从ss中删除掉该子弹
                hero.ss.remove(myShot);
            }
        }
        //画出炸弹
        for(int i=0;i<bombs.size();i++)
        {
        //System.out.println("bombs.size()="+bombs.size());
        //取出炸弹
            Bomb b=bombs.get(i);
            if(b.life>6)
            {
                g.drawImage(image1, b.x, b.y, 30, 30, this);
            }
            else if(b.life>4)
            {
                g.drawImage(image2, b.x, b.y, 30, 30, this);
            }
            else
            {
                g.drawImage(image3, b.x, b.y, 30, 30, this);
            }
        //让b的生命值减小
            b.lifeDown();
            if(b.life==0)        //如果炸弹生命值为0时,就把炸弹从集合中去掉
            {
                bombs.remove(b);
            }
        }
        //画出敌人的坦克
        for(int i=0;i<ets.size();i++)
        {
            EnemyTank et=ets.get(i);
            if(et.isLive)         //画出还是活的坦克
            {
                this.drawTank(et.getX(), et.getY(), g, et.getDirect(), 0);
        //再画出敌人的子弹
                for(int j=0;j<et.ss.size();j++)
                {
        //取出子弹
                    Shot enemyShot=et.ss.get(j);
                    if(enemyShot.isLive)
                    {
                        g.setColor(Color.PINK);        //设置子弹颜色
                        g.fill3DRect(enemyShot.x, enemyShot.y, 3, 3, true);        //画子弹
                    }
                    else         //如果敌人的坦克死亡了就从Vector去掉
                    {
                        et.ss.remove(enemyShot);
                    }
                }
            }
        }
    }
        //判断我的子弹是否击中敌人的坦克
    public void hitEnemyTank()
    {
        //在这run函数里判断子弹是否击中敌人坦克
        for(int i=0;i<hero.ss.size();i++)
        {
        //取出子弹
            Shot myShot=hero.ss.get(i);
            if(myShot.isLive)        //判断子弹是否还是活的或有效
            {
        //取出每个坦克,与它判断
                for(int j=0;j<ets.size();j++)
                {
        //取出坦克
                    EnemyTank et=ets.get(j);
                    if(et.isLive)
                    {
                        if(this.hitTank(myShot,et))
                        {
        //减少一个敌人坦克
                            Recorder.redurceEnNum();
        //增加我的记录(战绩)
                            Recorder.addEnNumRec();
                        }
                    }
                }
            }
        }
    }
        //敌人的子弹是否击中我
    public void hitMe()
    {
        //取出每一个敌人的坦克
        for(int i=0;i<this.ets.size();i++)
        {
        //取出坦克
            EnemyTank et=ets.get(i);
        //取出每一颗子弹
            for(int j=0;j<et.ss.size();j++)
            {
        //取出子弹
                Shot enemyShot=et.ss.get(j);
                if(hero.isLive)
                {
                    this.hitTank(enemyShot, hero);
                }
            }
        }
    }
        //1.写一个专门判断子弹是否击中敌人坦克的函数
    public boolean hitTank(Shot s,Tank et)
    {
        boolean bool=false;         //判断坦克是否被击中
        //判断该坦克的方向
        switch(et.direct)
        {
        //如果敌人坦克的方向是右或者是左
            case 0:
            case 1:
                if(s.x>et.x&&s.x<et.x+30&&s.y>et.y&&s.y<et.y+20)
                {
        //击中
                    s.isLive=false;         //子弹死亡
                    et.isLive=false;        //敌人坦克死亡
                    bool=true;
        //创建一颗炸弹
                    Bomb b=new Bomb(et.x,et.y);
        //把炸弹放入到Vector
                    bombs.add(b);
                }
                break;
        //如果敌人坦克的方向是上或者是下
            case 2:
            case 3:
                if(s.x>et.x&&s.x<et.x+20&&s.y>et.y&&s.y<et.y+30)
                {
        //击中
                    s.isLive=false;         //子弹死亡
                    et.isLive=false;        //敌人坦克死亡
                    bool=false;
        //创建一颗炸弹
                    Bomb b=new Bomb(et.x,et.y);
        //把炸弹放入到Vector
                    bombs.add(b);
                }
                break;
        }
        return bool;
    }
        //画出坦克的函数(扩展)
    public void drawTank(int x,int y,Graphics g,int direct,int type)
    {
        //判断坦克的类型
        switch(type)
        {
            case 0:
                g.setColor(Color.cyan);
                break;
            case 1:
                g.setColor(Color.yellow);
                break;
        }
        //判断方向
        switch(direct)
        {
            case 0:         //向右
        //画出上面的矩形
                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+30, y+10);
        //画齿轮
                g.setColor(Color.darkGray);
                g.drawLine(x+2, y+1, x+2, y+4);
                g.drawLine(x+5, y+1, x+5, y+4);
                g.drawLine(x+8, y+1, x+8, y+4);
                g.drawLine(x+11, y+1, x+11, y+4);
                g.drawLine(x+14, y+1, x+14, y+4);
                g.drawLine(x+17, y+1, x+17, y+4);
                g.drawLine(x+20, y+1, x+20, y+4);
                g.drawLine(x+23, y+1, x+23, y+4);
                g.drawLine(x+26, y+1, x+26, y+4);
                g.drawLine(x+2, y+16, x+2, y+19);
                g.drawLine(x+5, y+16, x+5, y+19);
                g.drawLine(x+8, y+16, x+8, y+19);
                g.drawLine(x+11, y+16, x+11, y+19);
                g.drawLine(x+14, y+16, x+14, y+19);
                g.drawLine(x+17, y+16, x+17, y+19);
                g.drawLine(x+20, y+16, x+20, y+19);
                g.drawLine(x+23, y+16, x+23, y+19);
                g.drawLine(x+26, y+16, x+27, y+19);
                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, y+10);
        //画齿轮
                g.setColor(Color.darkGray);
                g.drawLine(x+2, y+1, x+2, y+4);
                g.drawLine(x+5, y+1, x+5, y+4);
                g.drawLine(x+8, y+1, x+8, y+4);
                g.drawLine(x+11, y+1, x+11, y+4);
                g.drawLine(x+14, y+1, x+14, y+4);
                g.drawLine(x+17, y+1, x+17, y+4);
                g.drawLine(x+20, y+1, x+20, y+4);
                g.drawLine(x+23, y+1, x+23, y+4);
                g.drawLine(x+26, y+1, x+26, y+4);
                g.drawLine(x+2, y+16, x+2, y+19);
                g.drawLine(x+5, y+16, x+5, y+19);
                g.drawLine(x+8, y+16, x+8, y+19);
                g.drawLine(x+11, y+16, x+11, y+19);
                g.drawLine(x+14, y+16, x+14, y+19);
                g.drawLine(x+17, y+16, x+17, y+19);
                g.drawLine(x+20, y+16, x+20, y+19);
                g.drawLine(x+23, y+16, x+23, y+19);
                g.drawLine(x+26, y+16, x+27, y+19);
                break;
            case 2:         //向下
        //画出我的坦克(到时封装成一个函数)
        //1.画出左边的矩形
                g.fill3DRect(x, y, 5, 30,false);
        //2.画出右边的矩形
                g.fill3DRect(x+15, y, 5, 30,false);
        //3.画出中间矩形
                g.fill3DRect(x+5, y+5, 10, 20,false);
        //4.画出中间的圆形
                g.fillOval(x+5, y+10, 10, 10);
        //5.画出线
                g.drawLine(x+10, y+15, x+10, y+30);
        //画齿轮
                g.setColor(Color.darkGray);
                g.drawLine(x+1, y+2, x+4, y+2);
                g.drawLine(x+1, y+5, x+4, y+5);
                g.drawLine(x+1, y+8, x+4, y+8);
                g.drawLine(x+1, y+11, x+4, y+11);
                g.drawLine(x+1, y+14, x+4, y+14);
                g.drawLine(x+1, y+17, x+4, y+17);
                g.drawLine(x+1, y+20, x+4, y+20);
                g.drawLine(x+1, y+23, x+4, y+23);
                g.drawLine(x+1, y+27, x+4, y+27);
                g.drawLine(x+16, y+2, x+19, y+2);
                g.drawLine(x+16, y+5, x+19, y+5);
                g.drawLine(x+16, y+8, x+19, y+8);
                g.drawLine(x+16, y+11, x+19, y+11);
                g.drawLine(x+16, y+14, x+19, y+14);
                g.drawLine(x+16, y+17, x+19, y+17);
                g.drawLine(x+16, y+20, x+19, y+20);
                g.drawLine(x+16, y+23, x+19, y+23);
                g.drawLine(x+16, y+27, x+19, y+27);
                break;
            case 3:         //向上
        //画出我的坦克(到时封装成一个函数)
        //1.画出左边的矩形
                g.fill3DRect(x, y, 5, 30,false);
        //2.画出右边的矩形
                g.fill3DRect(x+15, y, 5, 30,false);
        //3.画出中间矩形
                g.fill3DRect(x+5, y+5, 10, 20,false);
        //4.画出中间的圆形
                g.fillOval(x+5, y+10, 10, 10);
        //5.画出线
                g.drawLine(x+10, y+15, x+10, y);
        //画齿轮
                g.setColor(Color.darkGray);
                g.drawLine(x+1, y+2, x+4, y+2);
                g.drawLine(x+1, y+5, x+4, y+5);
                g.drawLine(x+1, y+8, x+4, y+8);
                g.drawLine(x+1, y+11, x+4, y+11);
                g.drawLine(x+1, y+14, x+4, y+14);
                g.drawLine(x+1, y+17, x+4, y+17);
                g.drawLine(x+1, y+20, x+4, y+20);
                g.drawLine(x+1, y+23, x+4, y+23);
                g.drawLine(x+1, y+27, x+4, y+27);
                g.drawLine(x+16, y+2, x+19, y+2);
                g.drawLine(x+16, y+5, x+19, y+5);
                g.drawLine(x+16, y+8, x+19, y+8);
                g.drawLine(x+16, y+11, x+19, y+11);
                g.drawLine(x+16, y+14, x+19, y+14);
                g.drawLine(x+16, y+17, x+19, y+17);
                g.drawLine(x+16, y+20, x+19, y+20);
                g.drawLine(x+16, y+23, x+19, y+23);
                g.drawLine(x+16, y+27, x+19, y+27);
                break;
        }
    }
    @Override
    public void keyPressed(KeyEvent e)         //键按下处理
    {
        //a表示向左,s表示向上,w表示向上,d表示向右
        if(e.getKeyCode()==KeyEvent.VK_D)
        {
            this.hero.setDirect(0);        //设置我的坦克的方向,向右
            this.hero.moveRight();
        }
        else if(e.getKeyCode()==KeyEvent.VK_A)
        {
            this.hero.setDirect(1);        //向左
            this.hero.moveLeft();
        }
        else if(e.getKeyCode()==KeyEvent.VK_S)
        {
            this.hero.setDirect(2);        //向下
            this.hero.moveDown();
        }
        else if(e.getKeyCode()==KeyEvent.VK_W)
        {
            this.hero.setDirect(3);        //向上
            this.hero.moveUp();
        }
        if(e.getKeyCode()==KeyEvent.VK_J)
        {
        //判断玩家是否按下j
        //发射子弹
            if(this.hero.ss.size()<=4)        //连发子弹小于5
            {
                this.hero.shotEnemy();
            }
        }
        //重绘Panel
        this.repaint();
    }
    @Override
    public void keyReleased(KeyEvent e)
    {
    }
    @Override
    public void keyTyped(KeyEvent e)
    {
    }
    @Override
    public void run() {
        //每隔100毫秒去重绘
        while(true)
        {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
        // TODO Auto-generated catch block
                e.printStackTrace();
            }
        //2.什么地方调用-判断子弹是否击中敌人坦克的函数
            this.hitEnemyTank();        //子弹是否击中敌人坦克
            this.hitMe();        //敌人的坦克是否击中我了
        //重绘
            this.repaint();
        }
    }
}

Members.java

package com.test1;
import java.util.*;
import java.io.*;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.SourceDataLine;
                //播放声音的类
class AePlayWave extends Thread {
    private String filename;
    public AePlayWave(String wavfile) {
        filename = wavfile;
    }
    public void run() {
        File soundFile = new File(filename);
        AudioInputStream audioInputStream = null;
        try {
            audioInputStream = AudioSystem.getAudioInputStream(soundFile);
        } catch (Exception e1) {
            e1.printStackTrace();
            return;
        }
        AudioFormat format = audioInputStream.getFormat();
        SourceDataLine auline = null;
        DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
        try {
            auline = (SourceDataLine) AudioSystem.getLine(info);
            auline.open(format);
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }
        auline.start();
        int nBytesRead = 0;
                //这是缓冲
        byte[] abData = new byte[512];
        try {
            while (nBytesRead != -1) {
                nBytesRead = audioInputStream.read(abData, 0, abData.length);
                if (nBytesRead >= 0)
                    auline.write(abData, 0, nBytesRead);
            }
        } catch (IOException e) {
            e.printStackTrace();
            return;
        } finally {
            auline.drain();
            auline.close();
        }
    }
}
                //坦克恢复点
class Node
{
    int x,y,direct;
    public Node(int x,int y,int z)
    {
        this.x=x;
        this.y=y;
        this.direct=direct;
    }
}
                //记录类,同时也可以保存玩家的设置
class Recorder
{
                //记录每关有多少敌人
    private static int enNum=20;
                //设置我有多少可以用的坦克
    private static int myLife=3;
                //记录总共消灭了多少敌人
    private static int allEnNum=0;
    private static FileWriter fw=null;                //文件流
    private static BufferedWriter bw=null;                //buf流
    private static FileReader fr=null;
    private static BufferedReader br=null;
                //定义一个集合用于保存敌人的坦克
    private Vector<EnemyTank>ets=new Vector<EnemyTank>();
                //从文件中恢复记录点
    static Vector<Node> nodes=new Vector<Node>();
    public Vector<EnemyTank> getEts() {
        return ets;
    }
    public void setEts(Vector<EnemyTank> ets) {
        this.ets = ets;
    }
    public static int getAllEnNum() {
        return allEnNum;
    }
    public static void setAllEnNum(int allEnNum) {
        Recorder.allEnNum = allEnNum;
    }
    public static int getEnNum() {
        return enNum;
    }
    public static void setEnNum(int enNum) {
        Recorder.enNum = enNum;
    }
    public static int getMyLife() {
        return myLife;
    }
    public static void setMyLife(int myLife) {
        Recorder.myLife = myLife;
    }
                //减少敌人数
    public static void redurceEnNum()
    {
        enNum--;
    }
                //消灭敌人
    public static void addEnNumRec()
    {
        allEnNum++;
    }
                //保存击毁敌人坦克的数量、坐标和方向
    public void keeyRecAndEnemyTank()
    {
        try {
                //创建
            fw=new FileWriter("./myRecording.txt");
            bw=new BufferedWriter(fw);
            bw.write(allEnNum+"\r\n");
                //System.out.println("size="+ets.size());
                //保存当前活的敌人坦克的坐标和方向
            for(int i=0;i<ets.size();i++)
            {
                //取出第一个坦克
                EnemyTank et=ets.get(i);
                if(et.isLive)
                {
                //活的就保存,坐标与方向
                    String recorde=et.x+" "+et.y+" "+et.direct;
                //写入
                    bw.write(recorde+"\r\n");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
                //关闭流
            try {
                //后开先关闭
                bw.close();
                fw.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
                //把玩家击毁敌人坦克数量保存到文件中
    public static void keepRecording()
    {
        try {
                //创建
            fw=new FileWriter("./myRecording.txt");
            bw=new BufferedWriter(fw);
            bw.write(allEnNum+"\r\n");
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            try {
                bw.close();
                fw.close();                //关闭流
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
                //完成恢复退出时的记录
    public Vector<Node> getNodesAndEnNums()
    {
        try {
            fr=new FileReader("./myRecording.txt");
            br=new BufferedReader(fr);                 //读取记录
            String n="";
            n=br.readLine();                //先读取一行
            allEnNum=Integer.parseInt(n);
            while((n=br.readLine())!=null)
            {
                String []xyz=n.split(" ");                //读取以空格分隔的字符
                Node node=new Node(Integer.parseInt(xyz[0]),
                        Integer.parseInt(xyz[1]),Integer.parseInt(xyz[2]));
                nodes.add(node);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            try {
                br.close();
                fr.close();                //关闭流
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return nodes;
    }
                //从文件中读取记录
    public static void getRecording()
    {
        try {
            fr=new FileReader("./myRecording.txt");
            br=new BufferedReader(fr);                 //读取记录
            String n=br.readLine();                 //将读取的记录存到string中
            allEnNum=Integer.parseInt(n);
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            try {
                br.close();
                fr.close();                //关闭流
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}
                //炸弹类
class Bomb
{
                //定义炸弹的坐标
    int x,y;
                //炸弹的生命
    int life=9;
                //炸弹是否还是活的
    boolean isLive=true;
    public Bomb(int x,int y)
    {
        this.x=x;
        this.y=y;
    }
                //减少炸弹生命值
    public void lifeDown()
    {
        if(life>0)
        {
            life--;
        }
        else
        {
            this.isLive=false;
        }
    }
}
                //子弹类
class Shot implements Runnable
{
    int x,y,direct;
    int speed=3;
                //是否还活着
    boolean isLive=true;
    public Shot(int x,int y,int direct)
    {
        this.x=x;
        this.y=y;
        this.direct=direct;
    }
    @Override
    public void run() {
                //子弹向前跑动
        while(true)
        {
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            switch(direct)
            {
                case 0:                 //子弹向右
                    x+=speed;
                    break;
                case 1:                 //子弹向左
                    x-=speed;
                    break;
                case 2:                 //子弹向下
                    y+=speed;
                    break;
                case 3:                 //子弹向上
                    y-=speed;
                    break;
            }
                //System.out.println("子弹坐标x="+x+" y="+y);
                //子弹何时死亡
                //判断该子弹是否碰到边缘
            if(x<0||x>400||y<0||y>300)
            {
                this.isLive=false;
                break;
            }
        }
    }
}
                //坦克类
class Tank
{
                //表示坦克的横坐标
    int x=0;
                //坦克纵坐标
    int y=0;
                //坦克方向
    int direct=3;                //0表示右,1表示左,2表示下,3表示上
                //坦克的速度
    int speed=1;
                //坦克的颜色
    int color;
    boolean isLive=true;
    public int getColor() {
        return color;
    }
    public void setColor(int color) {
        this.color = color;
    }
    public int getSpeed() {
        return speed;
    }
    public void setSpeed(int speed) {
        this.speed = speed;
    }
    public int getDirect() {
        return direct;
    }
    public void setDirect(int direct) {
        this.direct = direct;
    }
    public int getX() {
        return x;
    }
    public void setX(int x) {
        this.x = x;
    }
    public int getY() {
        return y;
    }
    public void setY(int y) {
        this.y = y;
    }
    public Tank(int x,int y)
    {
        this.x=x;
        this.y=y;
    }
}
                //敌人的坦克,把敌人坦克做成线程类
class EnemyTank extends Tank implements Runnable
{
                //boolean isLive=true;//是否死亡
    int times=0;
                //定义一个集合向量可以访问到MyPanel上所有敌人的坦克
    Vector<EnemyTank>ets=new Vector<EnemyTank>();
                //定义一个集合向量,可以存放敌人的子弹
    Vector<Shot>ss=new Vector<Shot>();
                //敌人添加子弹,应当在刚刚创建坦克和敌人的坦克子弹是死亡之后
    public EnemyTank(int x,int y)
    {
        super(x,y);
    }
                //得到MyPanel的敌人坦克向量
    public void setEts(Vector<EnemyTank> ets) {
        this.ets = ets;
    }
    public Vector<EnemyTank> getEts() {
        return ets;
    }
                //判断是否碰到了别的敌人坦克
    public boolean isTouchOtherEnemy()
    {
        boolean b=false;
        switch(this.direct)
        {
            case 0:                 //坦克向右
                //取出所有的敌人坦克
                for(int i=0;i<ets.size();i++)
                {
                //取出第一个坦克
                    EnemyTank et=ets.get(i);
                    if(et!=this)                //如果不是自己
                    {
                //如果敌人的方向是向上或向下
                        if(et.direct==3||et.direct==2)
                        {
                //如果此坦克的右上角点在其它坦克矩形区域内
                            if(this.x+30>=et.x&&this.x+30<=et.x+20
                                    &&this.y>=et.y&&this.y<=et.y+30)
                            {
                                return true;
                            }
                //如果此坦克的右下角点在其它坦克矩形区域内
                            if(this.x+30>=et.x&&this.x+30<=et.x+20
                                    &&this.y+20>=et.y&&this.y+20<=et.y+30)
                            {
                                return true;
                            }
                        }
                //如果敌人的方向是向左或向右
                        if(et.direct==1||et.direct==0)
                        {
                //如果此坦克的右上角点在其它坦克矩形区域内
                            if(this.x+30>=et.x&&this.x+30<=et.x+30
                                    &&this.y>=et.y&&this.y<=et.y+20)
                            {
                                return true;
                            }
                //如果此坦克的右下角点在其它坦克矩形区域内
                            if(this.x+30>=et.x&&this.x+30<=et.x+30
                                    &&this.y+20>=et.y&&this.y+20<=et.y+20)
                            {
                                return true;
                            }
                        }
                    }
                }
                break;
            case 1:                 //坦克向左
                //取出所有的敌人坦克
                for(int i=0;i<ets.size();i++)
                {
                //取出第一个坦克
                    EnemyTank et=ets.get(i);
                    if(et!=this)                //如果不是自己
                    {
                //如果敌人的方向是向上或向下
                        if(et.direct==3||et.direct==2)
                        {
                //如果此坦克的左上角点在其它坦克矩形区域内
                            if(this.x>=et.x&&this.x<=et.x+20
                                    &&this.y>=et.y&&this.y<=et.y+30)
                            {
                                return true;
                            }
                //如果此坦克的左下角点在其它坦克矩形区域内
                            if(this.x>=et.x&&this.x<=et.x+20
                                    &&this.y+20>=et.y&&this.y+20<=et.y+30)
                            {
                                return true;
                            }
                        }
                //如果敌人的方向是向左或向右
                        if(et.direct==1||et.direct==0)
                        {
                //如果此坦克的左上角点在其它坦克矩形区域内
                            if(this.x>=et.x&&this.x<=et.x+30
                                    &&this.y>=et.y&&this.y<=et.y+20)
                            {
                                return true;
                            }
                //如果此坦克的左下角点在其它坦克矩形区域内
                            if(this.x>=et.x&&this.x<=et.x+30
                                    &&this.y+20>=et.y&&this.y+20<=et.y+20)
                            {
                                return true;
                            }
                        }
                    }
                }
                break;
            case 2:                 //我的坦克向下
                //取出所有的敌人坦克
                for(int i=0;i<ets.size();i++)
                {
                //取出第一个坦克
                    EnemyTank et=ets.get(i);
                    if(et!=this)                //如果不是自己
                    {
                //如果敌人的方向是向上或向下
                        if(et.direct==3||et.direct==2)
                        {
                //如果此坦克的左下角点在其它坦克矩形区域内
                            if(this.x>=et.x&&this.x<=et.x+20
                                    &&this.y+30>=et.y&&this.y+30<=et.y+30)
                            {
                                return true;
                            }
                //如果此坦克的右下角点在其它坦克矩形区域内
                            if(this.x+20>=et.x&&this.x+20<=et.x+20
                                    &&this.y+30>=et.y&&this.y+30<=et.y+30)
                            {
                                return true;
                            }
                        }
                //如果敌人的方向是向左或向右
                        if(et.direct==1||et.direct==0)
                        {
                //如果此坦克的左下角点在其它坦克矩形区域内
                            if(this.x>=et.x&&this.x<=et.x+30
                                    &&this.y+30>=et.y&&this.y+30<=et.y+20)
                            {
                                return true;
                            }
                //如果此坦克的右下角点在其它坦克矩形区域内
                            if(this.x+20>=et.x&&this.x+20<=et.x+30
                                    &&this.y+30>=et

版权所有,转载请注明出处 luowei.github.io.