PointRider / open-java

483 stars 32 forks source link

dogfightZ img

Featured|HelloGitHub

基于

Java Swing

以及

自主研发的基于小孔成像原理与图形光栅化的字符3D画面框架 graphic_Z

构建的 3D空战游戏

注:dogfight 为军事用语,是指战机近距离接战缠斗,可直接译为“狗斗”。

项目构建:Maven
运行环境:Java 8

DogfightZ 游戏说明

启动游戏

  1. 使用 “dogfight启动游戏.bat” 或 双击target目录下的jar包 启动游戏,来到菜单界面

    1640329895417

  2. 点击Start ! 按钮即可开始游戏,开始游戏后请关闭输入法,使用 [ 和 ](缩放) 、IJKL(显示尺寸)和MN(字体)键调整画面以适配屏幕

    1640330552519

    游戏试玩预览视频https://www.bilibili.com/video/BV1XU4y1T794

操作说明:

战机基本操控(战机起飞前不具有机动能力)
战机战斗操控(刚进入游戏时要等待航炮 CN 和导弹 MS 装弹完成)
其他键位

武器系统说明

屏幕颜色闪烁说明

项目源代码介绍

这是Eclipse-Maven Java工程,使用JDK1.8

编码工作完成后可使用mavenPackage.bat进行maven打包,目标位于target/dogfightZ-jar-with-dependencies.jar

dogfightZ-jar-with-dependencies.jar是独立的可执行游戏本体,在正确安装配置Java环境的计算机上可以直接双击运行。

项目结构预览

项目源代码总体分为4个大包,如图所示

1640331259439

我将重点介绍 graphic_Z 包和dogfight_Z 内的内容。

graphic_Z包

graphic_Z 是自主研发的基于小孔成像原理与图形光栅化的字符3D画面框架

1640331356171

dogfight_Z包内容

1640331619902

1640331760931

1640331794348

算法过程与部分实现代码

小孔成像算法

3D游戏与2D游戏最大的不同点在于多了一个纵深的空间轴向,同样大小的物体在距离视角不同距离的位置上会形成大小不同的像,小孔成像原理反应了这种纵深距离与尺寸的对应关系,如下图所示

img

小孔之所以能成像是因为光屏上的每一点都只能通过小孔接收到一个方向传来的光,所以光屏上每一点都是外部某个确定点的映射。相反如果开孔过大,物体上的一个点发出的光会在光屏上的一片区域形成光斑,如下如所示,如果有多个这样的光斑叠加在一起,必定会是模糊一片,所以只有小孔能够成像

img

由于小孔成像成的是倒像,于是我们将光屏以小孔为中心作对称,让物体发出的光都会会聚到光屏后的一点,这样就简化了计算如图所示

img

X0、Y0、Z0在通过算法前分别为物体上每个点与镜头形成的相对位置,通过算法后,X0和Y0就是这个点在屏幕上的坐标

/src/graphic_Z/Cameras/CharFrapsCamera.java

img

由于游戏世界中每个物体可以自由移动、转动,而玩家的视野也会跟随玩家自由移动、转动,故,故每个角色元素都有自己在游戏世界中的坐标位置、旋转角度,而每个物体上的每个点都有相对于自己中心的旋转角度和旋转后的位置,再者,玩家镜头也有自己在世界中的坐标和自由转动的角度,要实现小孔程序,就要在这几个不同的坐标系之间进行转换,才能得到每个点相对于镜头的坐标。算法如下(这些代码位于小孔成像之前)

/src/graphic_Z/Cameras/CharFrapsCamera.java

img

有了以上基础,我们计算出了物体每一个点在屏幕上的位置坐标,我们需要有一个“感光底片”来接收“小孔”所成的像。我们使用了一个二维字符数组,首先将所有位置设为空格,然后将有光照到的坐标上设置为白色的字符,这样就形成了一帧的图像,这个数组称为帧缓冲(fraps_buffer),这属于图形光栅化。代码如图所示:

/src/graphic_Z/Cameras/CharFrapsCamera.java

img

img

img

为了加速性能,我们知道三维物体经过小孔成像透视变换后,直线仍为直线,所以我们可以采用2维直线绘制算法去绘制物体模型,如图所示:

/src/graphic_Z/Cameras/CharFrapsCamera.java

img

最后,对于远处的物体,在屏幕上很小,如果绘制每一个顶点,就很浪费性能,所以在以点为基本图形元素绘制物体的过程中,我们采取根据距离不同,跳过绘制部分点的策略,如图(i是物体点的下标,rge为点到镜头的相对距离,visibility为最大能见度):

/src/graphic_Z/Cameras/CharFrapsCamera.java

img

每次刷新,VisualManager会让所有注册的镜头在帧缓冲上对每个物体列表中的每个物体进行曝光(多镜头设计是为了以后进行双眼视差真3D视觉输出(类似于VR设备),左边输出左眼看到的图像,右边输出右眼看到的图像),每个物体曝光后形成的3D画面还需要叠加2D的HUD图形,如下图所示

/src/graphic_Z/Managers/CharVisualManager.java

img

最后VisualManager将帧缓冲的字符拼接为字符串,刷新到文本框(mainScr)(tmpThread的任务是sleep几十毫秒,来控制屏幕帧率)

/src/graphic_Z/Managers/CharVisualManager.java

img

游戏内采用的坐标系

img

静态缓冲加速近似计算数学函数算法

主要思想:将常用的有限定义域数学函数(如三角函数、反三角函数、随机函数等)进行计算静态缓冲,调用函数时,只需要直接去对应的静态数组中取即可,如图是静态表生成的算法,boot为设定的精度值,为65536(即函数定义域划为65536份)

/src/graphic_Z/utils/GraphicUtils.java

img

以下是对应的几个函数值获取方法:

/src/graphic_Z/utils/GraphicUtils.java

img

飞行器飞行算法

在游戏的每一帧中,Game类的主循环调用刷新方法时,会协调ManagerObject去更新每个物体的状态,再让VisualManager去构建新一帧的画面:

/src/graphic_Z/Worlds/CharTimeSpace.java (Game类的基类)

img

下图是ObjectsManager的printNew()

/src/graphic_Z/Manager/CharObjectsManager.java

img

VisualManager的printNew()就是介绍小孔成像算法最后的那段代码。

ObjectsManager调用每个物体的go()方法,对于飞行器类:

/src/dogfight_Z/Aircraft.java

img

WeaponSystemRun是武器系统的运行方法,而doMotion()为飞行运动的核心代码,如下图所示

/src/dogfight_Z/Aircraft.java

img

在执行doMotion算法之前,Game类中主循环接收到用户的击键后,会调用类似于以下方法的代码去改变几个运动状态向量(velocity_roll、roll_angle等):

/src/dogfight_Z/Aircraft.java

img

img

导弹跟踪算法

核心思想:赋予导弹一只眼睛,以导弹的视角计算目标在其“眼睛”中的位置(CharFrapsCamera.getXY_onCamera),如果偏离中心,就以飞行器基类的方法操控转向,直至飞向目标

/src/dogfight_Z/Ammo/Missile.java

img

NPC算法

NPC主要有两种状态:1.巡航状态,2.追踪并攻击以及逃离攻击

巡航算法就是随机地选取方向,每次选取方向后保持随机的时间飞行。如下图:

/src/dogfight_Z/NPC.java

img

NPC追踪玩家攻击的算法与导弹追踪目标的算法很类似,在其基础上增加了火控锁定和武器控制,代码比较冗长,暂不张贴于此,详见NPC类中的trace()和pursuit(float range_to_me)算法。

项目打包说明

请运行 mavenPackage.bat,打包后位于 target/dogfightZ-jar-with-dependencies.jar,包含依赖项,可在JRE1.8环境下独立运行,若正确配置JAVA_HOME,双击该jar包即可启动游戏。