实现可以继续上局

该博客详细介绍了如何在坦克游戏中实现记录和重开功能。通过定义Recorder类来保存游戏状态,包括击毁的坦克数量和剩余坦克的位置信息。使用IO流读写文件来存储和加载这些数据。同时,展示了游戏面板的优化,包括敌我坦克和子弹的绘制、碰撞检测以及游戏循环的处理。此外,还实现了键盘监听以控制坦克移动和射击。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

🌲实现记录

要实现记录,这里就用用到IO流相关的知识了

🌲定义记录类

package com.Cx_330.TankGame4;

import java.io.*;
import java.util.Vector;

public class Recorder {
    private static int totalTankNums; //记录击中敌人坦克的数量
    private static BufferedWriter bw;//字符输出流
    private static BufferedReader br;//字符输入流
    private static String recordFile="src\\myRecord.txt";//定义要存放的地址
     private static Vector<EnemyTank> enemyTanks=new Vector<>();//结束时记录剩余坦克的位置/方向

    //如果想继续上局的话,就需先设计一个Vector容器去接收Node对象
    private static Vector<Node> nodes=new Vector<>();

    public static String getRecordFile() {
        return recordFile;
    }

    //若要继续游戏,从E盘取出上一次结束时坦克的位置方向信息
    public static Vector<Node> getTankInfo(){
        try {
            br=new BufferedReader(new FileReader(recordFile));
            String begin=br.readLine();
            String[] split = begin.split(":");
            totalTankNums=Integer.parseInt(split[1]);
            String line="";
            while ((line=br.readLine())!=null){
                String[] s = line.split(" ");
                int x=Integer.parseInt(s[0]);
                int y=Integer.parseInt(s[1]);
                int direct=Integer.parseInt(s[2]);
                Node node = new Node(x, y, direct);
                nodes.add(node);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            try {
                br.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return nodes;
    }


    //当退出游戏时,将剩余坦克坐标存放E盘根目录下
    public static void keepRecord(){
        try {
            bw=new BufferedWriter(new FileWriter(recordFile));
            bw.write("您击毁敌人坦克数量为:"+totalTankNums);
            bw.newLine();
            for (int i = 0; i < enemyTanks.size(); i++) {
                EnemyTank enemyTank = enemyTanks.get(i);
                if(enemyTank.leap){
                    String s=enemyTank.getX()+" "+enemyTank.getY()+" "+enemyTank.getDirect();
                    bw.write(s+"\r\n");
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            if(bw!=null){
                try {
                    bw.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    //每当击中一个敌坦克,totalTankNums加1
    public static void countTankNums(){
      totalTankNums++;
    }
    public static int getTotalTankNums() {
        return totalTankNums;
    }

    public void setTotalTankNums(int totalTankNums) {
        totalTankNums = totalTankNums;
    }

    public static void setEnemyTanks(Vector<EnemyTank> enemyTanks) {
        Recorder.enemyTanks = enemyTanks;
    }
}

🌲定义NODE类

package com.Cx_330.TankGame4;

public class Node {
    private int x;
    private int y;
    private int direct;

    public Node(int x, int y, int direct) {
        this.x = x;
        this.y = y;
        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 int getDirect() {
        return direct;
    }

    public void setDirect(int direct) {
        this.direct = direct;
    }
}

🌲画板优化最终方案

package com.Cx_330.TankGame4;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.util.Vector;

public class Mypanel extends JPanel implements KeyListener,Runnable {

    //定义一个接收输入流的Vector容器
    Vector<Node>nodes=new Vector<>();
    //定义我的坦克
    Hero hero=null;
    //定义敌人坦克
    Vector<EnemyTank> enemyTanks=new Vector<>();
    //初始化敌人的坦克个数
    int enemySize=5;
    //定义炸弹集合 当子弹击中坦克存放炸弹
    Vector<Boom> booms=new Vector<>();
    //定义爆炸的图片
    Image image1=null;
    Image image2=null;
    Image image3=null;

    public Mypanel(String choice){

        File file = new File(Recorder.getRecordFile());
        if(file.exists()){
            //接收Vector<Node>容器
            nodes = Recorder.getTankInfo();
        }else {
            System.out.println("该文件不存在,游戏将重新开始");
            choice="1";
        }
        //在最开始的时候就把EnemyTanks集合给Recorder类去记录
        Recorder.setEnemyTanks(enemyTanks);
        hero = new Hero(800,300);//初始化自己的坦克
        hero.setSpeed(10);//设置速度

        //做判断 1重开 还是0继续
        switch (choice){
            case "1":
                //初始化敌人坦克  并放入子弹  并开启线程
                for (int i = 0; i < enemySize; i++) {
                    //定义一个坦克
                    EnemyTank enemyTank=new EnemyTank(100*(i+1),0);
                    //设置坦克方向
                    enemyTank.setDirect(2);
                    //设置敌人坦克速度
                    enemyTank.setSpeed(1);
                    //定义一个子弹
                    Shot shot = new Shot(enemyTank.getX()+20,enemyTank.getY()+60,2);
                    //开启坦克线程
                    new Thread(enemyTank).start();
                    //添加子弹到敌人坦克集合中
                    enemyTank.shots.add(shot);
                    //开启子弹线程
                    new Thread(shot).start();
                    //添加坦克到敌人坦克集合中
                    enemyTanks.add(enemyTank);
                }
                break;
            case "0":

                //初始化敌人坦克  并放入子弹  并开启线程
                for (int i = 0; i < nodes.size(); i++) {
                    Node node = nodes.get(i);
                    //定义一个坦克
                    EnemyTank enemyTank=new EnemyTank(node.getX(),node.getY());
                    //设置坦克方向
                    enemyTank.setDirect(node.getDirect());
                    //设置敌人坦克速度
                    enemyTank.setSpeed(1);
                    //定义一个子弹
                    Shot shot = new Shot(enemyTank.getX()+20,enemyTank.getY()+60,2);
                    //开启坦克线程
                    new Thread(enemyTank).start();
                    //添加子弹到敌人坦克集合中
                    enemyTank.shots.add(shot);
                    //开启子弹线程
                    new Thread(shot).start();
                    //添加坦克到敌人坦克集合中
                    enemyTanks.add(enemyTank);
                }
                break;
            default:
                System.out.println("选择有误");
                System.exit(0);
                break;
        }

        //初始化图片
        image1=Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/b1.jpg"));
        image2=Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/b3.jpg"));
        image3=Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/b3.jpg"));

        //指定播放音乐的路径
            new AePlayWave("src\\x.wav").start();
    }

    //绘制简单的界面
    public void showInfo(Graphics g){

        g.setColor(Color.red);
        Font font = new Font("宋体", Font.BOLD, 35);
        g.setFont(font);
        g.drawString("您累击敌方坦克数目",1024,50);
        this.drawTank(1024,90,g,0,1);
        //重置颜色  因为在画坦克时画笔颜色改变了
        g.setColor(Color.black);
        g.drawString(Recorder.getTotalTankNums()+"",1200,130);
    }
    @Override
    public void paint(Graphics g) {
        super.paint(g);
        //画游戏界面大小
        g.fillRect(0,0,1000,750);
        //画界面信息
        showInfo(g);
        //画自己坦克
        if(hero.leap){
            drawTank(hero.getX(),hero.getY(),g,hero.getDirect(),0);
        }

        //画出爆炸效果
        for (int i = 0; i < booms.size(); i++) {
            Boom boom=booms.get(i);
            if(boom.life>6){
                g.drawImage(image2,boom.x,boom.y,80,80,this);
            }
            else if (boom.life>3){
                g.drawImage(image1,boom.x,boom.y,80,80,this);
            }
            else {
                g.drawImage(image3,boom.x,boom.y,80,80,this);
            }
            //让炸弹生命值减少  配合动态爆炸效果
            boom.lifeTime();
            //如果某个炸弹生命值为0  从booms删除
            if(boom.life<=0){
                booms.remove(boom);
            }
        }


        //画敌人坦克
        for (int i = 0; i < enemyTanks.size(); i++) {
            EnemyTank enemyTank = enemyTanks.get(i);
            enemyTank.setEnemyTanks(enemyTanks);
            if(enemyTank.leap){
                //画敌人坦克
                drawTank(enemyTank.getX(),enemyTank.getY(),g,enemyTank.getDirect(),1);
                //画敌人子弹
                for (int j = 0; j < enemyTank.shots.size(); j++) {
                    //先取子弹
                    Shot shot=enemyTank.shots.get(j);
                    //绘制子弹 先判断坐标是否越界 若越界则从shots集合里面去除 否则绘制
                    if(!shot.isLive){
                        enemyTank.shots.remove(j);
                     } else{
                        g.setColor(Color.green);
                        g.draw3DRect(shot.x,shot.y,3,3,false);
                    }
                }
            }
        }
        //画己方子弹
        for (int i = 0; i < hero.shots.size(); i++) {
            Shot shot = hero.shots.get(i);
            if(shot!=null&&shot.isLive==true){
                g.setColor(Color.cyan);
                g.draw3DRect(shot.x,shot.y,3,3,false);
            }else {
                hero.shots.remove(shot);
            }
        }
    }

    /**
     *
     * @param x 坦克左上角x坐标
     * @param y 坦克左上角y坐标
     * @param g 画笔
     * @param direct  方向
     * @param type   坦克类型(自己/敌人)
     */
    public void drawTank(int x,int y,Graphics g,int direct,int type){

        //0我的坦克  1敌人坦克
        switch (type){
            case 0:
                g.setColor(Color.cyan);
                break;
            case 1:
                g.setColor(Color.green);
                break;
        }

        //方向 (w 0上 1d 2右 s 3下 a左)
        switch (direct){
            case 0://👆
                g.fill3DRect(x,y,10,60,false);//左轮
                g.fill3DRect(x+30,y,10,60,false);//右轮
                g.fill3DRect(x+10,y+10,20,40,false);//身体架子
                g.fillOval(x+10,y+20,20,20);//盖子
                g.drawLine(x+20,y,x+20,y+20);//炮筒
                break;
            case 1://👉
                g.fill3DRect(x,y,60,10,false);//左轮
                g.fill3DRect(x,y+30,60,10,false);//右轮
                g.fill3DRect(x+10,y+10,40,20,false);//身体架子
                g.fillOval(x+20,y+10,20,20);//盖子
                g.drawLine(x+60,y+20,x+20,y+20);//炮筒
                break;
            case 2://👇
                g.fill3DRect(x,y,10,60,false);//左轮
                g.fill3DRect(x+30,y,10,60,false);//右轮
                g.fill3DRect(x+10,y+10,20,40,false);//身体架子
                g.fillOval(x+10,y+20,20,20);//盖子
                g.drawLine(x+20,y+20,x+20,y+60);//炮筒
                break;
            case 3://👈
                g.fill3DRect(x,y,60,10,false);//左轮
                g.fill3DRect(x,y+30,60,10,false);//右轮
                g.fill3DRect(x+10,y+10,40,20,false);//身体架子
                g.fillOval(x+20,y+10,20,20);//盖子
                g.drawLine(x,y+20,x+20,y+20);//炮筒
                break;
        }
    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    @Override
    public void keyPressed(KeyEvent e) {
        if(e.getKeyCode()==KeyEvent.VK_W){
           if(hero.getY()>0){
               hero.moveUp();
           }
            hero.setDirect(0);
        } else if (e.getKeyCode()==KeyEvent.VK_D) {
            if(hero.getX()+60<1000){
                hero.moveRight();
            }
            hero.setDirect(1);
        }
        else if (e.getKeyCode()==KeyEvent.VK_S) {
            if (hero.getY()+60<750){
                hero.moveDown();
            }
            hero.setDirect(2);
        }else if (e.getKeyCode()==KeyEvent.VK_A) {
            if (hero.getX()>0){
                hero.moveLeft();
            }
            hero.setDirect(3);
        }

        if (e.getKeyCode()==KeyEvent.VK_J){
            hero.shotEnemyTank();
        }

        this.repaint();
    }

    @Override
    public void keyReleased(KeyEvent e) {

    }

    public void EnemyHitMyTank(Shot shot,Hero hero){
        switch (hero.getDirect()){
            case 0:
            case 2:
                if(shot.x>hero.getX()&&shot.x<hero.getX()+40
                        &&shot.y>hero.getY()&&shot.y<hero.getY()+60){
                    shot.isLive=false;

                    Boom boom=new Boom(hero.getX(),hero.getY());
                    if(hero.leap){
                        booms.add(boom);
                        hero.leap=false;
                    }
                }
                break;
            case 1:
            case 3:
                if(shot.x>hero.getX()&&shot.x<hero.getX()+60
                        &&shot.y>hero.getY()&&shot.y<hero.getY()+40){
                    shot.isLive=false;

                    Boom boom=new Boom(hero.getX(),hero.getY());
                    if(hero.leap){
                        booms.add(boom);
                        hero.leap=false;
                    }
                }
                break;
        }
    }
    //判断子弹是否击中坦克
        public void hitEnemyTank(Shot shot, EnemyTank enemyTank){
        switch (enemyTank.getDirect()){
            case 0:
            case 2:
                if(shot.x>enemyTank.getX()&&shot.x<enemyTank.getX()+40
                &&shot.y>enemyTank.getY()&&shot.y<enemyTank.getY()+60){
                    shot.isLive=false;
                    enemyTank.leap=false;
                    enemyTanks.remove(enemyTank);
                    hero.shots.remove(shot);
                    Recorder.countTankNums();
                    Boom boom=new Boom(enemyTank.getX(),enemyTank.getY());
                    booms.add(boom);
                }
                break;
            case 1:
            case 3:
                if(shot.x>enemyTank.getX()&&shot.x<enemyTank.getX()+60
                        &&shot.y>enemyTank.getY()&&shot.y<enemyTank.getY()+40){
                    shot.isLive=false;
                    enemyTank.leap=false;
                    enemyTanks.remove(enemyTank);
                    hero.shots.remove(shot);
                    Recorder.countTankNums();
                    Boom boom=new Boom(enemyTank.getX(),enemyTank.getY());
                    booms.add(boom);
                }
                break;
        }
    }

    @Override
    public void run() {
        while (true){
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            
            //判断自己的子弹集合是否击中敌人坦克
            for (int i = 0; i < hero.shots.size(); i++) {
                Shot shot = hero.shots.get(i);
                if(shot!=null && shot.isLive){
                    for (int j = 0; j < enemyTanks.size(); j++) {
                        EnemyTank enemyTank=enemyTanks.get(j);
                        hitEnemyTank(shot,enemyTank);
                    }
                }
            }

            //判断敌人的子弹集合是否击中己方坦克
            for (int i = 0; i < enemyTanks.size(); i++) {
                    EnemyTank enemyTank = enemyTanks.get(i);
                    for (int j = 0; j < enemyTank.shots.size(); j++) {
                        Shot shot = enemyTank.shots.get(j);
                        if(shot!=null && shot.isLive){
                            EnemyHitMyTank(shot,hero);
                        }
                    }
                }

            this.repaint();
        }
    }
}


🌲框架的最终优化

package com.Cx_330.TankGame4;

import sun.awt.WindowClosingListener;

import javax.swing.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Scanner;

public class TankGame03 extends JFrame {
    private Mypanel mp=null;
    public static void main(String[] args) {
        TankGame03 tankGame01 = new TankGame03();
    }
    Scanner scanner=new Scanner(System.in);

    public TankGame03() {
        System.out.println("请做出你的选择 1--重开 0--继续上局");
        String choice=scanner.next();
        //启动画板线程
        mp=new Mypanel(choice);
        Thread thread = new Thread(mp);
        thread.start();
        //在框架中添加画板
        this.add(mp);
        //在框架中添加键盘监听事件
        this.addKeyListener(mp);
        //初始化框架的大小
        this.setSize(1500,810);
        //设置在关闭的时候自动结束JVM虚拟机
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //使画板画出来的图形可视化
        this.setVisible(true);
        //添加关闭窗口的处理
        this.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                Recorder.keepRecord();
                System.exit(0);
            }
        });
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

C_x_330

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值