Java Swing手搓童年坦克大战游戏(II)

文章目录

  • 0.初衷
  • 1.创建游戏窗口
  • 2.创建坦克
  • 3.实现坦克移动和发射炮弹
  • 4.创建地图
    • 4.1关于地图瓦片的尺寸遇到的问题
  • 5.坦克与障碍物的碰撞处理
    • 5.1碰撞检测
    • 5.2坦克与地图中的瓦片碰撞
    • 5.3坦克相互碰撞
    • 5.4坦克碰见炮弹
    • 5.5坦克拐弯
  • 6.道具
    • 6.1星星
    • 6.2炸弹
    • 6.3钟表
    • 6.4城堡
    • 6.5坦克
    • 6.6无敌圈
  • 7.炮弹命中目标的处理
  • 8.连续发射炮弹
  • 9.游戏结束game over逻辑处理
  • 10.炮弹突破游戏窗口
  • 11.思路理顺
    • 11.1碰撞检测:
    • ~~11.2道具功能逻辑~~
    • 11.3待解决问题
    • 11.4代码仓库
  • 12.吐槽

0.初衷

  自从若干年前研究了古老的Java Swing,就决定要用Swing做点有意思的东西出来,一方面自娱自乐,另一方面也锻炼锻炼编码技术。

  这个坦克大战游戏的立项看了一下记录是2021.12.25,应该是圣诞节那天确定的,然而比较尴尬的是时间过去了一年半多了,当时吹下的牛(立下的flag),至今还没有实现,作为一名码农(程序员or爱码士),实在惭愧,是时候兑现了,2023年8月份我就把当时实现的项目重新熟悉了起来,可怜巴巴的几个类,只实现了游戏主体循环,内容还要一点点的来。

  这个项目的框架依然和之前开发打砖块游戏Java Swing制作古老的打砖块游戏所用框架一模一样,没有区别,是在JFrame基础上实现双缓冲绘制和交互,其实这样比较麻烦,不如直接使用JPanel类,系统已经实现了双缓冲,不用自己再实现一遍了。自己当时还自己琢磨了一个非常简单的爆炸效果,[破涕为笑]。

  争取尽快实现并发布到某hub上吧。至于游戏原理大致是怎么回事儿,打砖块那篇文章有说,下面就直接进入正题了

1.创建游戏窗口

创建一个JFrame即可,先上个效果图吧。
在这里插入图片描述

2.创建坦克

玩家坦克和敌军坦克,一开始代码手绘了坦克,矩形+圆形+矩形,非常简陋,先表示这么个意思,后续再优化,看能不能找人做个坦克图片啥的。顺便实现了圆形炮弹发射。

后来从游戏视频中截图,然后使用gimp软件抠图,实现了敌军坦克的美化,顺带练习了抠图。

3.实现坦克移动和发射炮弹

  1. 玩家坦克,按方向键进行控制,实现坦克4个方向的移动,按ctrl键发射炮弹。

  2. 敌军坦克,在游戏循环中自主移动、发射炮弹,遇到障碍物或墙拐弯。

4.创建地图

地图是用瓦片拼接实现的,瓦片是最小,不可分割的地图单位,共5种,砖块、草地、铁块、雪地、河流。目前缺少雪地,取色并绘制矩形实现,草地略复杂。
在这里插入图片描述

  • 在坦克大战的游戏地图上,宽有19个方块,高有15个方块,后来证明这个数量有问题。
  • 地图创建成功了,看来大家是一样的使用二维int数组,整个窗口是一个由若干行和列tile瓦片大小网格组成的规整的背景,每个网格可以存放不同数字来表示不同的瓦片,如砖块、草地、铁块、雪地、河流。

4.1关于地图瓦片的尺寸遇到的问题

  (1)刚开始,tile瓦片尺寸50*50,后来经过对游戏的仔细观察和开发实践,发现这样不好实现只有一半瓦片、混合瓦片的情况,比如一半砖头,一半砖头加一半钢铁。

  (2)再有游戏中砖块按5050情况,如果只剩下5025,那么坦克是可以走到空白的50*25的,可是也不太好实现。

  (3)豪华版的游戏中玩家坦克三颗星发射炮弹消除钢铁的1/4的小块钢铁也是有的,才发现自己这思路是不能满足这个需求的,于是决定重新修改地图的实现逻辑,瓦片的大小需要改称4块钢铁中一块钢铁大小尺寸才是合适的,这样即可满足需求。

看了b站一个大佬的坦克大战开发视频讲解(Windows平台使用C语言调用系统绘图API进行的实现),感觉这么做确实不妥,如上一些需求实现起来很麻烦,于是改为25*25。

另外由于Java Swing Graphics对float支持不是太方便,后续可能改为24*24。

5.坦克与障碍物的碰撞处理

5.1碰撞检测

  • 在坦克与瓦片的碰撞判断上面遇到了很大的困难,自己思考一直解决不掉,使用矩形碰撞检测算法倒是可以检测出来然而砖块多了计算量很大、后来想了想可以将坦克行进方向一行或一列进行检测减少计算量,跨越砖块行进还得多一行或列,可是还是没能解决复杂的逻辑。
  • 后来查阅资料明白可以使用网格里面是否有瓦片阻挡,没有的话可以直接通过,否则就是无法通过除非用炮弹打碎才能通过。后来了解到有射线检测法解决这个问题。
  • 经过1天的尝试发现确实可以实现坦克和瓦片的碰撞检测逻辑,然而又出现了新的问题,在坦克跨网格进行移动的时候会出现bug,坦克会跑到瓦片tile上面去,很不合理。
  • 跨网格和不跨网格的逻辑都加上,坦克在地图上与障碍物位置关系就没有问题了,主要是考虑坦克所跨的网格下一批网格是否有障碍物,只要有一个存在障碍物,坦克就不能前进,这样才是合理的,这样就解决了上一条bug。不过又出现了新的问题,就是坦克在只有一个仅仅容纳自己通过的路口,很难对准入口,这个需要处理一下。
  • 这里瓦片尺寸的坑一直存在,直到后面不得不解决。

5.2坦克与地图中的瓦片碰撞

  • 坦克一边前进,一边检测前方的障碍物,如砖块、钢铁、河流,如果有,坦克不能继续前进。

5.3坦克相互碰撞

敌军坦克之间,相互碰撞和拐弯掉头已经实现

5.4坦克碰见炮弹

坦克被消灭,敌军坦克有一些需要多枚炮弹才能消灭。

5.5坦克拐弯

  • 问题:坦克在只能容纳一个坦克通过的路口,很难对准。
  • 尺寸变小以后,在坦克移动的过程中,判断坦克的左右转弯,改进思路,当坦克位于一个网格内,左右转向要快速直接转过去。
  • 当按下方向键,如果按键时间非常短,小于某个阈值,坦克移动速度修改,这样更方便的对准单个通道。
    坦克在通过一个刚好容纳一个坦克的身位的时候,如下图,坦克向上行走,需要左右转向,坦克必须可丁可卯的对准这个有空的通道,否则只差一个px,由于碰撞检测,坦克都无法通过。
    在这里插入图片描述
    思考良久,最终决定在坦克停止移动后,将坦克强制对齐到下一个网格线,这样就解决了难对准的问题。

一直找不到好的解决办法。已经解决,在坦克停止移动后,将坦克强制对齐到下一个网格线。

  • 终极解决方法:在拐弯的时候,对坦克坐标进行合理的调整,校准,坦克中心点,始终要对准一条网格线前进。

6.道具

道具功能,由于时间的仓促和功能的取舍,目测要放到二期工程了。

6.1星星

道具对坦克外观的影响,道具对炮弹火力的影响

6.2炸弹

6.3钟表

6.4城堡

6.5坦克

6.6无敌圈

7.炮弹命中目标的处理

初级坦克发射一发炮弹,只能消除1/4的方块层级,每个砖头方块有4层,当炮弹升级到某个级别一发可以消除2层,铁块的话,一共2层,一发消除1层。

  1. 炮弹消除砖块;已经实现。地图被击中的处理,这个处理感觉略显复杂,尤其砖头方块,被击中后,需要考虑强弱火力,击中后还剩多少,处理起来略复杂一些。

  2. 炮弹消除铁块,铁块消除,玩家已经吃了3个星星,这时候火力很猛,可以消除铁块了;
    另外当玩家吃了2个星星或2个以上,这时候炮弹可以消除2层砖块。目前缺少星星道具,目测二期实现。

  3. 炮弹击中坦克:消灭坦克。已经实现。

  4. 炮弹击中炮弹,相互抵消已经实现。(玩家和敌军的炮弹,敌军炮弹相互是不抵消的)

  5. 炮弹击中基地,或玩家生命为0,game over

  6. 目前觉得在方块tile被击中后应该记录状态,根据状态进行重绘,状态改变和绘制的过程可能有些复杂。后来发现不用记录也行,直接在图形上表现出来即可,不过还是记录状态更好,通过状态值可以了解瓦片的形状。

8.连续发射炮弹

有一个问题,音效播放数量错误,每一个音效播放不完整,只有最后面的音效完整。Mac上面音效却是完整的。在间隔时间很短,连续消灭2辆敌军坦克的时候,敌军坦克爆炸音效第二声没播放出来,这是一个问题。

9.游戏结束game over逻辑处理

基地老家被消灭或玩家坦克全被消灭,游戏结束。

10.炮弹突破游戏窗口

后续再说吧

11.思路理顺

11.1碰撞检测:

  1. 坦克移动中,撞墙,坦克互相碰撞、坦克碰到地图块(砖头、钢铁、河流)、碰到道具、被炮弹击中
  2. 炮弹击中坦克、地图块(砖头、钢铁)、大本营、玩家炮弹和敌军炮弹

11.2道具功能逻辑

二期工程再说,暂时不做。

  1. 星星增强火力,改变玩家坦克外观
  2. 城堡保护基地,砖块变为一圈钢铁,有时间长度限制
  3. 无敌圈可以无视发来的炮弹,有时间长度限制
  4. 坦克可以增加一条命
  5. 炸弹可以消灭地图中已出现的所有坦克
  6. 钟表可以一定时间长度内使敌军坦克静止

11.3待解决问题

  1. 当瓦片被消除一半的时候,坦克无法开过去,只能全部瓦片50*50被消除后坦克才能走过去。
  2. 转弯不好对齐的问题。
  3. 坦克每次移动瓦片1/4距离,这样方便坦克炮弹沿着分割线前进,可以保证消除和坦克同样宽度的瓦片
    随着后来瓦片尺寸的调整,拐弯的校准,这3个问题都解决了。

11.4代码仓库

代码都在这里了,大家根据需要自取吧。
https://github.com/ximen502/WarOfTank
https://gitee.com/ximen502/WarOfTank

12.吐槽

  学习了Java Swing知识后,就开发了打砖块游戏,也叫弹球游戏,详情请看Java Swing制作古老的打砖块游戏,自己觉得效果还行[敝帚自珍/doge],不过看过这篇文章的人却不多,不过某一天我在文章底部推荐里面看到一篇文章JAVA 实现《JAVA打砖块》游戏,相似度不高,不过看代码相似度贼高,目测99.9%,人家的阅读人数突破了4万,我的源码被传到下载里面明码标价30¥,暑期还搞了一波促销活动11.9¥,我简直不能相信,[捂脸]。为啥差距有几十倍。也不知道代码是否有人下载,他赚了多少钱……

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/298853.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

React 实现拖放功能

介绍 本篇文章将会使用react实现简单拖放功能。 样例 布局拖放 LayoutResize.js import React, {useState} from "react"; import { Button } from "antd"; import "./LayoutResize.css";export const LayoutResize () > {const [state,…

canvas 实心文字设置(含最大宽度)的示例

查看专栏目录 canvas示例教程100专栏,提供canvas的基础知识,高级动画,相关应用扩展等信息。canvas作为html的一部分,是图像图标地图可视化的一个重要的基础,学好了canvas,在其他的一些应用上将会起到非常重…

【Docker】docker 服务相关命令

目录 1. 启动docker 服务 2.查看docker 服务的状态 3. 停止docker 服务 4.重启 docker 服务 5.开机自启动命令 1. 启动docker 服务 systemctl start docker 2.查看docker 服务的状态 systemctl status docker 3. 停止docker 服务 systemctl stop docker 此时再使用 syst…

RDD入门——RDD 代码

创建RDD 程序入口 SparkContext val conf new SparkConf().setMaster("local[2]").setAppName(spark_context") val sc: SparkContext new SparkContext(conf) SparkContext 是 spark-core 的入口组件,是一个 Spark 程序的入口,在 Sp…

BRF文件数据结构

一.BRF-文件头数据结构 type_mesh "mesh" 网格 type_material "material" 材质struct brf_header{int type_length; //4个字节, type字符串对应长度char* type_name; //根据type_length获取int type_content_num; //4个字节,对应类型所含个数,例如含有模…

数据分析——火车信息

任务目标 任务 1、整理火车发车信息数据,结果的表格形式为: 2、并输出最终的发车信息表 难点 1、多文件 一个文件夹,多个月的发车信息,一个excel,放一天的发车情况 2、数据表的格式特殊 如何分析表是一个难点 数…

UnityVR入门之六 如何让3DUI层级在场景模型之上

一、问题来源 根据 UnityVR入门之五 射线检测交互-CSDN博客 这一章节我们了解到VR要与UI交互需要将Canvas设置为World Space属性,然后使用碰撞盒的方式进行射线交互。 正常我们ui是始终叠加在3d场景之上的,如此设置当ui与场景模型相交就会遮挡穿模 二、解…

git常用命令及概念对比

查看日志 git config --list 查看git的配置 git status 查看暂存区和工作区的变化内容(查看工作区和暂存区有哪些修改) git log 查看当前分支的commit 记录 git log -p commitID详细查看commitID的具体内容 git log -L :funcName:fileName 查看file…

el-form点击提交后把验证失败的数据传给了后端

问题&#xff1a;版本号需要根据后端返回的结果查看是否可用&#xff0c;在这里1.0.0是不可用的&#xff0c;如果点击其他地方则会报红&#xff0c;可是直接点击提交&#xff0c;则会把1.0.0这个错误的数据也提交给后端。 解决方案&#xff1a; html代码&#xff1a; <el…

Flume基础知识(十):Flume 聚合实战

1&#xff09;案例需求&#xff1a; hadoop100上的 Flume-1 监控文件/opt/module/group.log&#xff0c; hadoop101上的 Flume-2 监控某一个端口的数据流&#xff0c; Flume-1 与 Flume-2 将数据发送给 hadoop102 上的 Flume-3&#xff0c;Flume-3 将最终数据打印 到控制台。…

【Pytorch】学习记录分享11——GAN对抗生成网络

PyTorch GAN对抗生成网络 0. 工程实现1. GAN对抗生成网络结构2. GAN 构造损失函数&#xff08;LOSS&#xff09;3. GAN对抗生成网络核心逻辑3.1 参数加载&#xff1a;3.2 生成器&#xff1a;3.3 判别器&#xff1a; 0. 工程实现 原理解析&#xff1a; 论文解析&#xff1a;GAN…

综合跨平台全端ui自动化测试框架Airtest——AirtestIDE录制微信小程序脚本教学

前言 有在自动化测试领域的小伙伴应该都知道&#xff0c;app和小程序自动化这一类的自动化测试在实际操作中有时候很棘手让人心烦&#xff0c;动不动就是用appium写代码脚本维护什么的&#xff0c;不仅步骤繁琐&#xff0c;环境配置方面也是繁琐无比&#xff0c;动不动就与客户…

云计算:OpenStack 分布式架构管理VXLAN网络(单控制节点与多计算节点)

目录 一、实验 1.环境 2.各节点新增网卡准备VXLAN网络 3.控制节点配置私有网络 4.计算节点1配置私有网络 5.计算节点2配置私有网络 6.重启服务 7.修改Dashboard 8.新建项目&#xff08;租户&#xff09;及用户 9.新建网络与子网 10.新建实例 11.新建路由 12.新增浮…

【机器学习】循环神经网络(二)-LSTM示例(keras)国际航空乘客问题的回归问题...

使用 Keras 在 Python 中使用 LSTM 循环神经网络进行时间序列预测 国际航空乘客问题的回归问题 这个文件是一个CSV格式的数据集&#xff0c;它包含了从1949年1月到1960年12月的每个月的国际航空乘客的总数&#xff08;以千为单位&#xff09;。第一行是列名&#xff0c;分别是&…

贯穿设计模式-享元模式思考

写享元模式的时候&#xff0c;会想使用ConcurrentHashMap来保证并发&#xff0c;没有使用双重锁会不会有问题&#xff1f;但是在synchronize代码块里面需要尽量避免throw异常&#xff0c;希望有经验的同学能够给出解答&#xff1f; 1月6号补充&#xff1a;没有使用双重锁会有问…

Robot Operating System 2: Design, Architecture, and Uses In The Wild

Robot Operating System 2: Design, Architecture, and Uses In The Wild (机器人操作系统 2&#xff1a;设计、架构和实际应用) 摘要&#xff1a;随着机器人在广泛的商业用例中的部署&#xff0c;机器人革命的下一章正在顺利进行。即使在无数的应用程序和环境中&#xff0c;也…

Python爬虫-大麦网演出数据和票价数据

前言 本文是该专栏的第14篇,后面会持续分享python爬虫干货知识,记得关注。 本文以大麦网为例,获取大麦网全部的演出数据以及对应的票价数据。示例图如下所示: 如上图所示,笔者将在本文详细介绍通过python爬虫去获取全国的“演唱会,话剧歌剧,体育比赛,儿童亲子”等等以…

Odoo | Module | 统计系统周期使用人数/当前在线人数

文内材料 GITHUB地址 前言介绍 Odoo作为开源ERP系统的No.01,近年愈发的得到国内很多公司的关注。 虽然它的定位是中小型企业的ERP管理系统&#xff0c;但是在几年的Odoo开发实施过程中&#xff0c;有不足50人的小型企业&#xff0c;也有上万人的中大型企业。功能快速落地和…

即时设计:设计流程图,让您的设计稿更具条理和逻辑

流程图小助手 在设计工作中&#xff0c;流程图是一种重要的工具&#xff0c;它可以帮助设计师清晰地展示设计思路和流程&#xff0c;提升设计的条理性和逻辑性。今天&#xff0c;我们要向您推荐一款强大的设计工具&#xff0c;它可以帮助您轻松为设计稿设计流程图&#xff0c;让…

c#调试程序一次启动两个工程(多个工程)

概述 c# - Visual Studio : debug multiple projects at the same time? 以在解决方案中设置多个启动项目(右键单击解决方案&#xff0c;转到设置启动项目&#xff0c;选择多个启动项目)&#xff0c;并为包含在解决方案(无、开始、不调试就开始)。如果您将多个项目设置为开始…