韩顺平--Java坦克大战

Posted 闲言博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了韩顺平--Java坦克大战相关的知识,希望对你有一定的参考价值。

1、说明

  写了14个版本,终于完成了,项目结构如下

2、游戏效果


(1)击中敌人

(2)被敌人击中

3、代码如下

(1)TankGame 主方法

package cn.bloghut;

import cn.bloghut.component.MyPanel;
import cn.bloghut.service.Recorder;

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

/**
 * @Classname TankGame
 * @Description TODO
 * @Date 2022/5/8 8:25
 * @Created by 闲言
 */
public class TankGame extends JFrame 

    private MyPanel panel;

    public static void main(String[] args) 

        new TankGame();
    

    public TankGame()
        System.out.println("请输入选择: 1 表示新游戏,2是继续上局");
        Scanner scanner = new Scanner(System.in);
        //将panel放入到thread中
        this.panel = new MyPanel(scanner.next());
        scanner.close();

        new Thread(panel).start();
        //设置绑定监听器
        this.addKeyListener(panel);
        this.add(panel);
        //设置窗体关闭
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setTitle("闲言-坦克大战");
        //获取当前屏幕分辨率
        int width = Toolkit.getDefaultToolkit().getScreenSize().width;
        int height = Toolkit.getDefaultToolkit().getScreenSize().height;
        //设置窗体大小不可变
        this.setResizable(false);
        //设置窗体位置
        width = (width - 1300) / 2;
        height = (height - 750) / 2;
        this.setBounds(width,height,1300,750);
        this.setBackground(Color.black);
        //设置窗体显示
        this.setVisible(true);

        //在JFrame 中增加相关关闭窗口的处理
        this.addWindowListener(new WindowAdapter() 
            @Override
            public void windowClosing(WindowEvent e) 
                Recorder.keepRecord();
                System.exit(0);
            
        );

    


(2)MyPanel 视图

package cn.bloghut.component;

import cn.bloghut.pojo.*;
import cn.bloghut.service.PlayAudio;
import cn.bloghut.service.Recorder;
import cn.bloghut.service.Shot;

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

/**
 * @Classname MyPanel
 * @Description 坦克大战绘图区域
 * 为了让panel 不停的重绘子弹,需要将MyPanel
 * @Date 2022/5/8 8:44
 * @Created by 闲言
 */
public class MyPanel extends JPanel implements KeyListener, Runnable 
    //定义我的坦克
    Hero hero = null;
    //定义敌人坦克
    Vector<EnemyTank> enemyTanks = new Vector<>();
    //用于存放炸弹
    //当子弹击中坦克时,就加入一个bomb 对象
    Vector<Bomb> bombs = new Vector<>();
    //定义三种图片,用于显示炸弹
    Image img1 = null;
    Image img2 = null;
    Image img3 = null;

    //定义一个存放Node 对象的Vector,用于恢复敌人坦克的坐标和放向
    Vector<Node> nodes = null;
    //敌人坦克数量
    int enemyTankSize = 3;
    public MyPanel(String type) 
        //判断记录文件是否存在
        //如果存在就正常执行,如果文件不存在,提示只能开启新的游戏
        File file = new File(Recorder.getRecordFile());
        if (!file.exists())
            type = "1";
            System.out.println("文件不存在只能开启新游戏");
        else 
            nodes = Recorder.getNodesAndTanks();
        

        //初始化我的坦克
        hero = new Hero(150, 150);
        //设置坦克速度
        hero.setSpeed(5);
        switch (type) 
            case "1":
                //初始化敌人坦克
                for (int i = 0; i < enemyTankSize; i++) 
                    EnemyTank enemyTank = new EnemyTank(100 * (i + 1), 0);
                    enemyTank.setDirection(2);
                    //启动敌人坦克线程
                    new Thread(enemyTank).start();
                    //给该enemyTank 加入一颗子弹
                    Shot shot = new Shot(enemyTank.getX() + 20, enemyTank.getY() + 60, enemyTank.getDirection());
                    //加入到
                    enemyTank.getShots().add(shot);
                    //为每个坦克,放入所有的敌人对象
                    enemyTank.setEnemyTanks(enemyTanks);
                    //启动shot
                    new Thread(shot).start();
                    enemyTanks.add(enemyTank);
                
                break;
            case "2": //继续上局游戏
                //初始化敌人坦克
                for (int i = 0;i < nodes.size();i++)
                    Node node = nodes.get(i);
                    EnemyTank enemyTank = new EnemyTank(node.getX(),node.getY());
                    enemyTank.setDirection(node.getDirection());
                    //启动敌人坦克线程
                    new Thread(enemyTank).start();
                    //给该enemyTank 加入一颗子弹
                    Shot shot = new Shot(enemyTank.getX() + 20, enemyTank.getY() + 60, enemyTank.getDirection());
                    //加入到
                    enemyTank.getShots().add(shot);
                    //为每个坦克,放入所有的敌人对象
                    enemyTank.setEnemyTanks(enemyTanks);
                    //启动shot
                    new Thread(shot).start();
                    enemyTanks.add(enemyTank);
                
                break;
            default:
                System.out.println("你的输入有误");
        
        //获取项目路径
        //1.获取图片资源
        String parent = System.getProperty("user.dir");
        parent += "\\\\";
        //2.初始化图片
        img1 = Toolkit.getDefaultToolkit().getImage(parent + "bomb_1.gif");
        img2 = Toolkit.getDefaultToolkit().getImage(parent + "bomb_2.gif");
        img3 = Toolkit.getDefaultToolkit().getImage(parent + "bomb_3.gif");
        //存放敌人坦克信息
        Recorder.setEnemyTanks(enemyTanks);
        //播放指定的音乐
        new PlayAudio("bg.wav").start();
    

    @Override
    public void paint(Graphics g) 
        super.paint(g);
        //填充矩形,默认黑色
        g.fillRect(0, 0, 1000, 750);
        //画出游戏信息
        showInfo(g);
        //画自己坦克
        if (hero != null && hero.isLive()) 
            drawTank(hero.getX(), hero.getY(), g, hero.getDirection(), 1);
        
        //画出自己射击的子弹
        //不为空,且处于发射状态
        if (hero.getShot() != null && hero.getShot().isLive()) 
            g.draw3DRect(hero.getShot().getX(), hero.getShot().getY(), 2, 2, false);
        
        if (hero.getShots().size() > 0) 
            for (int i = 0; i < hero.getShots().size(); i++) 
                Shot shot = hero.getShots().get(i);
                if (shot != null && shot.isLive()) 
                    g.draw3DRect(shot.getX(), shot.getY(), 2, 2, false);
                 else 
                    //如果shot对象已经无效,就从子弹集合中移除
                    hero.getShots().remove(shot);
                
            
        

        //画敌人坦克
        for (int i = 0; i < enemyTanks.size(); i++) 
            EnemyTank enemyTank = enemyTanks.get(i);
            //判断当前坦克是否还存活,只有存活的时候才去画
            if (enemyTank.isLive()) 
                drawTank(enemyTank.getX(), enemyTank.getY(), g, enemyTank.getDirection(), 0);
                //绘制敌人坦克子弹
                Vector<Shot> shots = enemyTank.getShots();
                for (int j = 0; j < shots.size(); j++) 
                    Shot shot = shots.get(j);
                    //子弹存活的时候才绘制
                    if (shot.isLive()) 
                        g.draw3DRect(shot.getX(), shot.getY(), 1, 1, false);
                     else 
                        //子弹出边界了,移除子弹
                        enemyTank.getShots().remove(shot);
                    
                
            
        
        //如果bombs 集合中有对象,就画出
        for (int i = 0; i < bombs.size(); i++) 
            Bomb bomb = bombs.get(i);
            //根据当前炸弹的life值画出对应的图片
            if (bomb.getLife() > 6) 
                g.drawImage(img1, bomb.getX(), bomb.getY(), 60, 60, this);
             else if (bomb.getLife() > 3) 
                g.drawImage(img1, bomb.getX(), bomb.getY(), 60, 60, this);
             else 
                g.drawImage(img1, bomb.getX(), bomb.getY(), 60, 60, this);
            
            //让这个炸弹的生命值减少
            bomb.lifeDown();
            //如果bomb 生命值为0,就从集合中删除
            if (bomb.getLife() == 0) 
                bombs.remove(bomb);
            
        
    

    /**
     * 显示 击毁敌方的坦克信息
     *
     * @param g 画图
     */
    public void showInfo(Graphics g) 
        g.setColor(Color.BLACK);
        Font font = new Font("宋体", Font.BOLD, 25);
        g.setFont(font);
        g.drawString("您累计击毁敌方坦克", 1020, 30);
        drawTank(1020, 60, g, 0, 0);
        g.setColor(Color.BLACK);
        g.drawString(Recorder.getAllEnemyTankTotal() + "", 1080, 100);
    

    /**
     * 绘制坦克
     *
     * @param x         坦克的左上角x坐标
     * @param y         坦克的左上角y坐标
     * @param g         画笔
     * @param direction 坦克方向(上下左右)
     * @param type      坦克类型
     */
    public void drawTank(int x, int y, Graphics g, int direction, int type) 
        //根据不同类型的坦克设置不同颜色
        switch (type) 
            case 0://0 敌人的坦克
                g.setColor(Color.cyan);
                break;
            //
            case 1://1 我们的坦克
                g.setColor(Color.yellow);
                break;
        
        //根据坦克的方向来绘制坦克
        //direction 0-向上,1-向右,2-向下,3-向左
        switch (direction) 
            case 0:
                //左右

以上是关于韩顺平--Java坦克大战的主要内容,如果未能解决你的问题,请参考以下文章

韩顺平--Java坦克大战

韩顺平--Java坦克大战

第18章 坦克大战2

第20章 坦克大战3

Java坦克大战 跟学韩顺平老师视频开发

第16章 坦克大战1