JAVA基础小项目 - 坦克大战(下)

简介: JAVA基础小项目 - 坦克大战(下)

第四个版本:



从这一个版本开始,一个游戏的简单雏形已经有了,这一个版本实现了让敌人移动的同时发射子弹的功能,同时我方的坦克射击敌人的时候,可以让敌人消失


怎么样让敌人可以边移动边发射子弹:


我们需要在敌人的多线程run代码里面,然敌人进行间歇性的走动:


@Override
    //我们发现坦克在原地抽搐,我们要实现坦克的平稳运行
    //实现坦克运动不会越界
    public void run() {
        do {
            switch (this.direct) {
                case 0:
                    for (int i = 0; i < 30; i++) {
                        if (y > 0)
                            y -= sreed;
                        try {
                            Thread.sleep(50);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    break;
                case 1:
                    for (int i = 0; i < 30; i++) {
                        if (x < 500)
                            x += sreed;
                        try {
                            // 短暂的停顿
                            Thread.sleep(50);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    break;
                case 2:
                    for (int i = 0; i < 30; i++) {
                        if (y < 400)
                            y += sreed;
                        try {
                            Thread.sleep(50);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    break;
                case 3:
                    for (int i = 0; i < 30; i++) {
                        if (x > 0)
                            x -= sreed;
                        try {
                            Thread.sleep(50);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    break;
            }
            //不同的方向移动的方向不同
            this.direct = (int) (Math.random() * 4);
        } while (this.isLive);
    }
复制代码


至于生成子弹,需要定时去轮询所有的坦克,检查坦克中组合的子弹集合是否存在子弹,如果小于一定的数量,需要生成对应的子弹对象同时加入到敌人的坦克当中。由于子弹创建就会开始执行线程进行


@Override
    public void run() {
        //限定一段时间重新绘制
        while (true) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //判断是否击中
            for (int x = 0; x < mytank.vecs.size(); x++) {
                //每一颗子弹和每一个坦克匹配
                //取出一颗子弹之前判断是否有子弹
                buts = mytank.vecs.get(x);
                //判断子弹是否有效
                if (buts.isOut()) {
                    continue;
                }
                //取出每一个坦克与它判断
                for (int y = 0; y < vec.size(); y++) {
                    //判断敌方坦克是否死亡
                    if (vec.get(y).isLive) {
                        en = vec.get(y);
                        //记性判断是否击中操作
                        hitTank(en, buts);
                    }
                }
            }
            //如果子弹数小于一定数目
            for (int x = 0; x < vec.size(); x++) {
                EnemyTank et = vec.get(x);
                //遍历每一辆坦克的子弹集合
                if (!et.isLive()) {
                    continue;
                }
                if (et.vecs.size() < 1) {
                    //对于不同的坦克方向生成子弹的方向也不同
                    Bullet enybut = null;
                    switch (et.getDirect()) {
                        case 0:
                            enybut = new Bullet(et.getX() + 10, et.getY(), 0);
                            //将创建的子弹加入到集合当中
                            et.vecs.addElement(enybut);
                            break;
                        case 1:
                            enybut = new Bullet(et.getX() + 30, et.getY() + 10, 1);
                            et.vecs.addElement(enybut);
                            break;
                        case 2:
                            enybut = new Bullet(et.getX() + 10, et.getY() + 30, 2);
                            et.vecs.addElement(enybut);
                            break;
                        case 3:
                            enybut = new Bullet(et.getX(), et.getY() + 10, 3);
                            et.vecs.addElement(enybut);
                            break;
                    }
                    new Thread(enybut).start();
                }
            }
            //重绘
            this.repaint();
        }
    }
复制代码


在子弹类当中进行不断的数值改变:

下面的内容表示子弹的类


public class Bullet implements Runnable {
    //隐藏一大段代码:
public void run() {
        while (true) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            switch (this.direct) {
                case 0:
                    this.y -= screed;
                    break;
                case 1:
                    this.x += screed;
                    break;
                case 2:
                    this.y += screed;
                    break;
                case 3:
                    this.x -= screed;
                    break;
            }
            //碰到边缘消失
            if (x < 0 || x > outx || y < 0 || y > outy) {
                isOut = true;
                break;
            }
        }
    }
}
复制代码


第五个版本:


在第五个版本当中,我们实现了开始菜单的界面,同时视线菜单的不断显示:

界面会不断的闪烁

接着,敌人增加了子弹可以摧毁我们的方法


网络异常,图片无法展示
|


网络异常,图片无法展示
|


接着,我们可以实现爆炸的效果:


由于爆炸的效果不好截图,请看源代码

网络异常,图片无法展示
|


/**
 * 实现闪烁功能
 * 重构坦克 - 第五版
 * @author zxd
 * @version 1.0
 * @date 2021/1/29 23:54
 */
class SelectIsSallup extends JPanel implements Runnable {
  /**
   * 时间属性
   */
  int times = 0;
    public void paint(Graphics g) {
        super.paint(g);
        g.fillRect(0, 0, 600, 400);
        if (times % 2 == 0) {
            //画出文字
            Font font1 = new Font("华文新魏", Font.BOLD, 20);
            //设置字体的颜色
            g.setColor(Color.yellow);
            g.setFont(font1);
            g.drawString("stage 1", 200, 150);
        }
    }
    @Override
    public void run() {
        while (true) {
            try {
                Thread.sleep(750);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (times > 500)
                times = 0;
            times++;
            this.repaint();
        }
    }
}
复制代码


如何让敌人的子弹对我们造成伤害:


/**
   * 建立一个方法,判断是否产生碰撞
   * 是否攻击了其他的坦克
   * @return
   */
  private boolean isTouchOther() {
        // 根据自己的方向进行选择判断
        switch (this.direct) {
            // 坦克向上走的时候
            case 0:
                // 取出所有的坦克对象
                for (int x = 0; x < enevec.size(); x++) {
                    EnemyTank et = enevec.get(x);
                    //如果不是自己的坦克
                    if (et != this) {
                        //如果敌人的坦克朝上或者朝下的时候
                        if (et.direct == 0 || 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 + 20 >= et.x && this.x + 20 <= et.x + 20
                                    && this.y >= et.y && this.y <= et.y + 30) {
                                return true;
                            }
                        }
                        //如果敌人是朝左边或者右边的时候
                        if (et.direct == 1 || et.direct == 3) {
                            //判断边界
                            //对于第一个点进行判断
                            if (this.x >= et.x && this.x <= et.x + 30
                                    && this.y >= et.y && this.y <= et.y + 20) {
                                return true;
                            }
                            //对于第二个点进行判断
                            if (this.x + 20 >= et.x && this.x + 20 <= et.x + 30
                                    && this.y >= et.y && this.y <= et.y + 20) {
                                return true;
                            }
                        }
                    }
                }
                break;
            //  坦克想右边走的时候
            case 1:
                // 取出所有的坦克对象
                for (int x = 0; x < enevec.size(); x++) {
                    EnemyTank et = enevec.get(x);
                    //如果不是自己的坦克
                    if (et != this) {
                        //如果敌人的坦克朝上或者朝下的时候
                        if (et.direct == 0 || 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 >= et.y && this.y <= et.y + 30) {
                                return true;
                            }
                        }
                        //如果敌人是朝左边或者右边的时候
                        if (et.direct == 1 || et.direct == 3) {
                            //判断边界
                            //对于第一个点进行判断
                            if (this.x + 30 >= et.x && this.x + 30 <= et.x + 30
                                    && this.y + 20 >= 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 <= et.y + 20) {
                                return true;
                            }
                        }
                    }
                }
                // 坦克想下的时候
            case 2:
                // 取出所有的坦克对象
                for (int x = 0; x < enevec.size(); x++) {
                    EnemyTank et = enevec.get(x);
                    //如果不是自己的坦克
                    if (et != this) {
                        //如果敌人的坦克朝上或者朝下的时候
                        if (et.direct == 0 || 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 == 3) {
                            //判断边界
                            //对于第一个点进行判断
                            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.y && this.y + 30 <= et.y + 20) {
                                return true;
                            }
                        }
                    }
                }
                break;
            // 坦克向左移动的时候
            case 3:
                // 取出所有的坦克对象
                for (int x = 0; x < enevec.size(); x++) {
                    EnemyTank et = enevec.get(x);
                    //如果不是自己的坦克
                    if (et != this) {
                        //如果敌人的坦克朝上或者朝下的时候
                        if (et.direct == 0 || 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 == 3) {
                            //判断边界
                            //对于第一个点进行判断
                            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;
                            }
                        }
                    }
                }
        }
        return false;
    }
复制代码


最终版本:


在最终的版本当中,一个坦克大战的基本游戏算是完成

了,当然还有很多需要完成点。这里主要提示一下暂停这一个功能点:


暂停的主要思想是为坦克加一个状态去控制坦克的所有行为。让暂停的flag为false的时候,线程不在执行,绘画每次都是绘制在同一个位置。这样就造成了“暂停”的假象。


//暂停功能
if(e.getKeyCode()==KeyEvent.VK_P)
{
    if(this.clickcount%2 == 0)
        mytank.setSuspend(false);
    else
        mytank.setSuspend(true);
    //利用循环将坦克类中的子弹速度变成0
    for(int x=0; x<vec.size(); x++)
    {
        en = vec.get(x);
        //敌方坦克移动速度归于0
        //坦克不允许移动
        if(this.clickcount%2 == 0)
            en.setSuspend(false);
        else
            en.setSuspend(true);
        for(int y=0; y<en.vecs.size(); y++)
        {
            //子弹的速度变成0
            if(this.clickcount%2 == 0)
                en.vecs.get(y).setSuspend(false);
            else
                en.vecs.get(y).setSuspend(true);
        }
    }
    this.clickcount++;
}
复制代码


总结:


这个文档不是最终版本,如果有不懂的欢迎提issue,承诺给予答复但是不会再改动代码了。

相关文章
|
3月前
|
关系型数据库 MySQL Java
【MySQL+java+jpa】MySQL数据返回项目的感悟
【MySQL+java+jpa】MySQL数据返回项目的感悟
55 1
|
3月前
|
编解码 Oracle Java
java9到java17的新特性学习--github新项目
本文宣布了一个名为"JavaLearnNote"的新GitHub项目,该项目旨在帮助Java开发者深入理解和掌握从Java 9到Java 17的每个版本的关键新特性,并通过实战演示、社区支持和持续更新来促进学习。
104 3
|
12天前
|
Java Maven
java项目中jar启动执行日志报错:no main manifest attribute, in /www/wwwroot/snow-server/z-server.jar-jar打包的大小明显小于正常大小如何解决
在Java项目中,启动jar包时遇到“no main manifest attribute”错误,且打包大小明显偏小。常见原因包括:1) Maven配置中跳过主程序打包;2) 缺少Manifest文件或Main-Class属性。解决方案如下:
java项目中jar启动执行日志报错:no main manifest attribute, in /www/wwwroot/snow-server/z-server.jar-jar打包的大小明显小于正常大小如何解决
|
8天前
|
存储 Java BI
java怎么统计每个项目下的每个类别的数据
通过本文,我们详细介绍了如何在Java中统计每个项目下的每个类别的数据,包括数据模型设计、数据存储和统计方法。通过定义 `Category`和 `Project`类,并使用 `ProjectManager`类进行管理,可以轻松实现项目和类别的数据统计。希望本文能够帮助您理解和实现类似的统计需求。
47 17
|
30天前
|
NoSQL Java 关系型数据库
Liunx部署java项目Tomcat、Redis、Mysql教程
本文详细介绍了如何在 Linux 服务器上安装和配置 Tomcat、MySQL 和 Redis,并部署 Java 项目。通过这些步骤,您可以搭建一个高效稳定的 Java 应用运行环境。希望本文能为您在实际操作中提供有价值的参考。
135 26
|
2月前
|
XML Java 测试技术
从零开始学 Maven:简化 Java 项目的构建与管理
Maven 是一个由 Apache 软件基金会开发的项目管理和构建自动化工具。它主要用在 Java 项目中,但也可以用于其他类型的项目。
68 1
从零开始学 Maven:简化 Java 项目的构建与管理
|
2月前
|
Java
Java项目中高精度数值计算:为何BigDecimal优于Double
在Java项目开发中,涉及金额计算、面积计算等高精度数值操作时,应选择 `BigDecimal` 而非 `Double`。`BigDecimal` 提供任意精度的小数运算、多种舍入模式和良好的可读性,确保计算结果的准确性和可靠性。例如,在金额计算中,`BigDecimal` 可以精确到小数点后两位,而 `Double` 可能因精度问题导致结果不准确。
|
2月前
|
Java Android开发
Eclipse 创建 Java 项目
Eclipse 创建 Java 项目
52 4
|
2月前
|
SQL Java 数据库连接
从理论到实践:Hibernate与JPA在Java项目中的实际应用
本文介绍了Java持久层框架Hibernate和JPA的基本概念及其在具体项目中的应用。通过一个在线书店系统的实例,展示了如何使用@Entity注解定义实体类、通过Spring Data JPA定义仓库接口、在服务层调用方法进行数据库操作,以及使用JPQL编写自定义查询和管理事务。这些技术不仅简化了数据库操作,还显著提升了开发效率。
59 3
|
3月前
|
JavaScript 前端开发 Java
解决跨域问题大集合:vue-cli项目 和 java/springboot(6种方式) 两端解决(完美解决)
这篇文章详细介绍了如何在前端Vue项目和后端Spring Boot项目中通过多种方式解决跨域问题。
423 1
解决跨域问题大集合:vue-cli项目 和 java/springboot(6种方式) 两端解决(完美解决)