首页 > 编程语言 >韩顺平Java坦克大战项目分析与实现

韩顺平Java坦克大战项目分析与实现

时间:2024-11-17 17:45:46浏览次数:3  
标签:10 20 子弹 项目分析 Java 坦克 敌人 enemyTank 顺平

JAVA坦克大战项目

文章目录

界面

在这里插入图片描述
在这里插入图片描述

技术栈

import java.util.Vector;
import java.util.HashMap;
import java.util.Map;
import javax.swing.*;
import java.awt.
*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.BufferedReader;
import java.util.Scanner;
import java.io.File;
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;
Math.random()
多线程
面向对象
异常处理
流程控制
循环
数据类型与运算符
IO流

项目结构

Tank 坦克父类

属性方法
x,y 坐标moveLeft 向左移动
direct 方向moveRight 向右移动
speed 速度,默认1moveDown 向下移动
isLive 是否存活moveUp 向上移动
(x、y、direct、speed)的Getter和Setter

EnemyTank 敌人坦克类

属性方法
isLive 敌方坦克是否存活,默认truerun 坦克随机移动
shots 子弹集合setEnemyTanks 可以将MyPanel 的成员 Vector enemyTanks = new Vector<>(); 设置到 EnemyTank
enemyTanks 可以得到敌人坦克的VectorisTouchEnemyTank 判断当前的这个敌人坦克,是否和enemyTanks中的其他坦克发生的重叠或者碰撞
directionParams 定义一个映射来存储方向和Shot构造参数
SLEEP_TIME 休眠时间
MOVE_STEPS 移动步数

Hero 己方坦克类

属性方法
shot 表示一个射击(线程)shotEnemyTank 射击
shots 可以发射多颗子弹

Bomb 爆炸类

属性方法
x,y 坐标lifeDown 减少生命值
isLive 是否存活,默认true
life 生命值,默认9

Shot 子弹类

在这里插入图片描述

属性方法
x,y 坐标run
让子弹移动
子弹移动到面板的边界时退出,就应该销毁(把启动的子弹的线程销毁)
当子弹碰到敌人坦克时,也应该结束
speed 速度
direct 方向
isLive 是否存活

MyPanel 面板类

在这里插入图片描述

属性方法
Hero hero = null; // 己方坦克initEnemyTanks 初始化敌人坦克
Vector enemyTanks = new Vector<>(3); // 敌方坦克集合,默认3个paint 绘制
黑色矩形游戏活动范围
记录板
画出自己坦克和子弹
画出敌人的坦克和子弹
爆炸效果
// 存放炸弹
Vector bombs = new Vector<>();
drawTank 画坦克
根据不同类型坦克,设置不同颜色
根据坦克方向,来绘制对应形状坦克
int enemyTankSize = 3; // 敌方坦克默认3个run 每隔100毫秒,重绘区域,刷新绘图区
// 3个爆炸图片对象
Image image1 = null;
Image image2 = null;
Image image3 = null;
hitTank 判断我方子弹是否击中坦克
directionMap 定义方向映射keyPressed 监听键盘按下
WSAD改变坦克方向
如果用户按下的是J,就发射
执行重绘
nodes 用来存储恢复游戏记录的敌方坦克数据initImages 初始化图片对象
showInfo 显示我方击毁敌方坦克的信息
drawHeroAndShots 画己方坦克和子弹
enemyTanksAndShots 画出敌人的坦克和子弹
explosionEffect 爆炸效果
hitHero 判断敌人坦克是否击中我的坦克
canMoveInDirection 检查坦克是否可以在指定方向上移动
moveHeroInDirection 根据方向移动坦克

AePlayWave 坦克大战音乐类

在这里插入图片描述

Node 类

在这里插入图片描述

用来恢复上次游戏记录

Recorder 记录类

该类用于记录相关信息的和文件交互

程序入口 类

在这里插入图片描述


功能

子弹移动(线程)

子弹移动到面板的边界时退出,就应该销毁(把启动的子弹的线程销毁)
当子弹碰到敌人坦克时,也应该结束

坦克移动(线程)

让坦克保持一个方向走30步,防止每走一步就改变方向乱动

防止坦克穿墙

随机改变坦克方向

如果坦克死亡(被击中)退出线程

每隔100毫秒,重绘区域,刷新绘图区(线程)

绘制黑色矩形游戏活动范围、画出自己坦克和子弹、画出敌人的坦克和子弹、爆炸效果

根据不同类型坦克,设置不同颜色; 根据坦克方向,来绘制对应形状坦克

/**
 * 画坦克
 *
 * @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) {
    // 根据不同类型坦克,设置不同颜色
    switch (type) {
        case 0:
            g.setColor(Color.cyan);
            break;
        case 1:
            g.setColor(Color.yellow);
            break;
    }
    // 根据坦克方向,来绘制对应形状坦克
    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 + 30, x + 20, y);
            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 + 30, y + 20, x + 60, 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 + 30, 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 + 30, y + 20, x, y + 20);
            break;
        default:
            System.out.println("暂时没有处理");
    }
}

解决坦克按下J键射击后原先射击的子弹消失了

让敌人的坦克发射的子弹消亡后,可以再发射子弹

可以发射多颗子弹

创建一个shots集合,把新创建的shot子弹放到集合中,每颗子弹都要启动一个线程

在绘制子弹时,需要遍历该集合取出绘制,如果该shot对象已经无效,就从shots集合中拿掉

限制子弹发射数量

防止敌人坦克重叠

判断当前的这个敌人坦克,是否和enemyTanks中的其他坦克发送的重叠或者碰撞

根据方向射击

爆炸效果

爆炸类使用一个数组存放炸弹

让爆炸类生命值减少

每隔10毫秒根据爆炸类的生命值绘制爆炸图片(3张其中一张),如果爆炸类的生命值等于0就移除这个炸弹

try {
    Thread.sleep(10);
} catch (InterruptedException e) {
    throw new RuntimeException(e);
}
for (int i = 0; i < bombs.size(); i++) {
    Bomb bomb = bombs.get(i);
    if (bomb.life > 6) {
        g.drawImage(image1, bomb.x, bomb.y, 60, 60, this);
    } else if (bomb.life > 3) {
        g.drawImage(image2, bomb.x, bomb.y, 60, 60, this);
    } else {
        g.drawImage(image3, bomb.x, bomb.y, 60, 60, this);
    }
    bomb.lifeDown();
    if (bomb.life == 0) {
        bombs.remove(bomb);
    }
}

判断我方子弹是否击中坦克

子弹击中后子弹和坦克就不显示了、防止子弹击中不显示的坦克也会爆炸、防止画敌人坦克的的时候数组越界、击中坦克创建Bomb对象,加入到bombs

/**
 * 判断我方子弹是否击中坦克
 *
 * @param s
 * @param enemyTank
 */
public void hitTank(Shot s, EnemyTank enemyTank) {
    switch (enemyTank.getDirect()) {
        case 0: // 上
        case 2: // 下
            if (s.x > enemyTank.getX() && s.x < enemyTank.getX() + 40
                    && s.y > enemyTank.getY() && s.y < enemyTank.getY() + 60) {
                s.isLive = false;
                // 子弹击中后坦克就不显示了
                enemyTank.isLive = false;
                // 防止子弹击中不显示的坦克也会爆炸
                enemyTanks.remove(enemyTank);
                // 防止画敌人坦克的的时候数组越界
                enemyTankSize--;
                // 创建Bomb对象,加入到bombs
                Bomb bomb = new Bomb(enemyTank.getX(), enemyTank.getY());
                bombs.add(bomb);
            }
            break;
        case 1: // 右
        case 3: // 左
            if (s.x > enemyTank.getX() && s.x < enemyTank.getX() + 60
                    && s.y > enemyTank.getY() && s.y < enemyTank.getY() + 40) {
                s.isLive = false;
                enemyTank.isLive = false;
                // 防止子弹击中不显示的坦克也会爆炸
                enemyTanks.remove(enemyTank);
                // 防止画敌人坦克的的时候数组越界
                enemyTankSize--;
                Bomb bomb = new Bomb(enemyTank.getX(), enemyTank.getY());
                bombs.add(bomb);
            }
            break;
    }
}

监听键盘按下事件

改变坦克方向位置、解决坦克穿墙、如果用户按下的是J就发射、需要重绘面板才能生效

发射一颗子弹

1.在按下J键,我们判断当前hero对象的子弹,是否已经销毁
2.如果没有销毁,就不去触发shotEnemyTank
3.如果已经销毁,才去触发shotEnemyTank

所有的子弹都取出和敌人所有的坦克进行判断

判断敌人坦克是否击中我方坦克

遍历所有敌人坦克,取出敌人坦克,遍历敌人坦克对象的所有子弹,取出子弹,如果我们的坦克还活着并且敌人的坦克也活着,判断我方子弹是否击中坦克

当敌人的坦克击中我方坦克时,我方坦克消失,并出现爆炸效果

退出游戏时记录玩家的总成绩(累计击毁敌方坦克数),敌人坦克坐标/方向,存盘退出【io流】

在这里插入图片描述

玩游戏时,可以选择是开新游戏还是继续上局游戏

游戏开始时,播放经典的坦克大战音乐

使用一个播放音乐的类

修正下文存储位置

处理文件相关异常

shotEnemyTank

所有的子弹都取出和敌人所有的坦克进行判断

判断敌人坦克是否击中我方坦克

遍历所有敌人坦克,取出敌人坦克,遍历敌人坦克对象的所有子弹,取出子弹,如果我们的坦克还活着并且敌人的坦克也活着,判断我方子弹是否击中坦克

当敌人的坦克击中我方坦克时,我方坦克消失,并出现爆炸效果

退出游戏时记录玩家的总成绩(累计击毁敌方坦克数),敌人坦克坐标/方向,存盘退出【io流】

[外链图片转存中…(img-GUFNYxBZ-1731835156330)]

玩游戏时,可以选择是开新游戏还是继续上局游戏

游戏开始时,播放经典的坦克大战音乐

使用一个播放音乐的类

修正下文存储位置

处理文件相关异常

标签:10,20,子弹,项目分析,Java,坦克,敌人,enemyTank,顺平
From: https://blog.csdn.net/QQ2861104332/article/details/143835172

相关文章

  • java初步与IDEA的安装
    为什么选择JavaJava用途广泛:Java是目前使用最为广泛的网络编程语言之一,在服务器端占比90%以上.Java可以用来做什么:1.企业级应用,特别是金融服务与电子商务领域.2.Android应用开发,是Android移动应用的主要开发语言之一.3.Web开发.4.桌面应用.5.大数据技术,hadoop及......
  • Java集合框架高频面试问题精粹(下篇)
    书接上回,上一篇文章介绍了Java集合常见面试题全解(上),反响不错,也有很多同学发表了自己的观点,这次又来了,这次是Java集合常见面试题总结(下)了,主要讲解了Map集合原理,它的使用频率也是很高。那么它的存储结构和实现原理是怎么样的呢一、Collections工具类(不重要)Collections 工......
  • 基于java+springboot的社区心理健康服务平台系统
    前言基于java+springboot的社区心理健康服务平台系统是守护社区居民心理健康的重要依托。系统为居民提供心理测评功能,涵盖情绪、压力、人际关系等多方面的专业量表,居民可自行测试,系统会即时给出结果和相应建议。同时,设有心理咨询预约模块,居民能查看心理咨询师的资料,......
  • 【华为OD技术面试手撕真题】84、前 K 个高频元素 | 手撕真题+思路参考+代码解析(C & C+
    文章目录一、题目......
  • Java面试之多线程&并发篇(5)
    前言本来想着给自己放松一下,刷刷博客,突然被几道面试题难倒!常用的线程池有哪些?简述一下你对线程池的理解?Java程序是如何执行的?锁的优化机制了解吗?说说进程和线程的区别?似乎有点模糊了,那就大概看一下面试题吧。好记性不如烂键盘***12万字的java面试题整理******java核心面试知......
  • 【Java】继承和多态
    继承1继承1.1为什么需要继承1.2继承概念1.3继承的语法1.4父类成员访问1.4.1子类中访问父类的成员变量1.4.2子类中访问父类的成员方法1.5super关键字1.6子类构造方法1.7super和this1.8再谈初始化1.9protected关键字1.10继承方式1.11final关键字1.12继承......
  • 35.校园网上订餐系统(基于SSM的Java项目)
    目录1.系统的受众说明2.系统需求分析2.1 开发环境2.2 需求分析2.3 可行性研究分析3. 系统概要设计3.1 系统设计概述3.2 系统功能分析3.3 系统用例图3.4 系统流程图4.数据库设计与实现4.1 数据库的结构设计4.1.1概念结构设计4.1.2 表概要说......
  • 华为OD机试 - 挑7 (Java 2024 E卷 100分)
    华为OD机试2024E卷题库疯狂收录中,刷题点这里。实战项目访问:http://javapub.net.cn/专栏导读本专栏收录于《华为OD机试(JAVA)真题(E卷+D卷+A卷+B卷+C卷)》。刷的越多,抽中的概率越大,私信javapub,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注......
  • (赠源码)基于Java Web+springboot+MySQL的Unishare闲置物品共享系统研究22945-计算机毕
    摘 要随着科技的快速迭代和人们环保意识的提高,共享经济逐渐成为社会发展的重要趋势。然而,在现实生活中,人们的消费水平大大提高,存在很多闲置物品无人问津,造成了一定的资源浪费和环境污染。与此同时,许多人需要使用这些闲置物品,却不知道如何获取。这种情况下,基于JavaWeb的Uni......
  • java+SSM+MySQL非遗传承背景下甘肃人文宣传网站051441-计算机毕设 原创(赠源码)
    摘 要信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于站在的角度存在偏差,人们经常能够获得不同类型信息,这也是技术最为难以攻克的课题。针对非遗传承背景下甘肃人文宣传网站等问题,对非遗传承背景下甘肃人文宣传网站进行研究分析,然后开......