我们的旅程从你开始,我们的英雄,希望能够开始并完成一个角色扮演游戏而冒险进入该未知领域。我们将讨论角色扮演游戏的历史,我们将通过本书开发游戏的功能,以及评估以帮助您开发游戏的工具时的一些考虑因素。我们将学习游戏架构的简要历史,以及它如何与LibGDX的架构相关并与其不同。最后,我们将看看LibGDX项目结构并运行默认的应用程序,以便我们在下一章中开展工作。
本章将涉及以下主题
- 了解角色扮演游戏的基本原理
- 开发角色扮演游戏时使用的技术
- 了解游戏体系架构的基本知识
- 了解LibGDX的高级组件布局
- 了解LibGDX的应用程序生命周期
- 设置你的开发环境
- 了解项目结构及其构建环境
- 运行默认的示例程序
1.了解角色扮演游戏的基本原理
关于角色扮演游戏历史的论述超出了本书的范围,但是多年来通过角色扮演游戏(RPG)的起源引发了基于计算机的角色扮演游戏(CRPG)的发展。这是完全解释本书所涵盖的游戏类型所必需的。 Neal Hallford所著的 《Swords & Circuitry:计算机角色扮演游戏设计师指南》详细介绍了这一历史。
1.1 历史
略
1.2 RPG 特征
一般来说,要求人们定义什么是RPG角色扮演游戏,将会引发无尽的争论,而不会得到满意的答案。为了清楚起见,以角色扮演游戏为核心的游戏可以定义为一个系统,其中规则是主要根据故事在各种目标的设定中扮演角色。
首先,例如,children's make believe(孩子门的假扮成(某角色)),被认为是扮演角色,但没有规则,所以它不能被认为是RPG。一旦添加了规则,我们现在有一个系统可以让人们进行角色扮演,这被认为是角色扮演游戏,且是实时角色扮演(LARP)。
第二个RPG的例子是玩家假定英雄角色在微型物理战场上玩著名战役,这被认为是桌面角色扮演,它是从《Wills‘s Little Wars》开始的战争游戏的自然延伸。
角色扮演游戏的第三个例子将是D&D开始的笔和纸系统,并为Tolkien-inpired的带有魔法和龙的幻想系统奠定基础。
略 ...
本书将覆盖以下特征
- 用统计属性开发人物
- 开发一个平衡系统,让你的角色在整个游戏中持续增长,相比比角色的升级,前期的遭遇变得更加容易。
- 开发玩家的运动,动画,物理和碰撞检测
- 使用语音窗口创建交互式NPC角色,并通过对话树进行沉浸
- 用战斗机制,重生点和AI寻路创造有趣的敌人
- 通过场景门户与地图上不同区域之间的过渡与世界进行互动。
- 为物品拾取和装备构建库存管理系统
- 开发用于保存和加载游戏的配置文件
- 创建脚本过场动画以添加故事和戏剧元素
- 开发一个任务系统来扩大游戏的内容
- 利用可定制的皮肤构建库存和抬头显示(HUD)布局,并为更新健康和魔法构建逻辑。
- 使用物品和金钱创建一个商店交易界面(UI)
- 创造特殊效果,让游戏更加“多汁”和抛光,并帮助营造氛围。
2 开发角色扮演游戏时使用的技术
了解创建游戏时可用的不同技术可能会令人沮丧,尤其是当您认为对一组工具的承诺将您锁定到解决方案时。有时候,拿出各种引擎或框架进行试驾,会让你的硬盘散落着未完成的成熟游戏项目。其他时候,当您在线搜索帮助时,您在论坛中获得的唯一回应是标准自鸣得意看源代码答案。这些经历可能令人筋疲力尽,尤其是没有计划。首先,为了正确评估任何解决方案,我们需要用某些有针对性的问题来恰当地制定项目目标。
2.1商业游戏与技术展示
2.2目标平台
2.3游戏框架与游戏引擎
2.4预算
3 了解游戏架构的基本知识
为了更好的理解典型的高级游戏架构的基本知识,我们可以从第一个基于文本的冒险游戏Adventure开始
3.1Adventure的高级游戏循环
下图描述了Adventure类型基于文本的游戏的高级游戏循环,其中游戏将阻止其生命周期的所有更新,直到它在命令行上接收到基于用户的文本输入为止:略...
3.2高级的基于事件的循环
下图(图2)引用了一个事件循环,例如,Windows处理其图形用户界面事件的方式。这个数字甚至可以在大多数平台上推广,包括Java如何在Java虚拟机(JVM)中处理自己的事件循环:略...
3.3基于图形的高级游戏循环
下图(图3)高水平地展示了一个基于图形的视频游戏循环在其核心上的实际功能:略...
4掌握LibGDX高级组件布局
我们现在要回顾一下LibGDX背后的架构
4.1LibGDX后端模块
下图(图4)是说明LibGDX的核心接口的图。这些是可用的最高级别抽象,提供创建游戏时所需的大部分功能(包括其关联的模块库):这些接口是针对当前支持的每个目标平台实现的,允许您使用这些API开发您的游戏一次,而不必担心特定于平台的问题。每个接口包含的功能(一旦为每个支持平台实现)的概述如下:
- Application.java:这个接口成为平台OS用来加载你的游戏的入口点。每个实现都将负责设置窗口,处理调整大小事件,渲染界面以及在其生命周期中管理应用程序。具体来说,Application.java将提供绘图,音频,输入,文件IO处理以及日志系统,内存占用信息和扩展库的钩子等模块
- Graphics.java:该界面包含许多与平台图形处理器通信的辅助方法,例如渲染到屏幕并查询可用的显示模式,如图形分辨率和颜色深度。还有生成像素图和纹理的便捷方法。有趣的一点是,为了实现跨平台支持,通过将OpenGL ES函数映射到桌面OpenGL函数,为桌面模拟了底层图形API(OpenGL ES 2.0或OpenGL ES 3.0)。
- Audio.java:该接口包含许多用于创建和管理各种音频资源的辅助方法。此接口有助于创建声音效果,播放音乐流并直接访问PCM音频输入和输出的音频硬件。
- Files.java:在管理游戏资产(如读取和写入文件)时,此接口包含许多用于访问平台文件系统的辅助方法。这种对不同类型文件位置的抽象包括内部文件(位于您的游戏工作目录中)和外部文件(外部存储器,如SD卡)。
- Input.java:这个接口包含许多帮助方法,用于轮询(或处理事件)用户输入,不仅来自标准输入,例如键盘按键和鼠标按键点击,还包括移动设备输入,例如触摸屏和加速度传感器变化,其他辅助方法包括处理振动,指南针访问,屏幕键盘输入和光标捕获。
- Net.java:该接口包含许多用于执行特定网络相关操作的辅助方法,例如管理HTTP / HTTPS GET和POST请求以及创建TCP服务器/客户端套接字连接。
- Preferences.java:该界面包含许多辅助方法,用于存储和访问应用程序游戏设置值,作为轻量级设置存储机制。
4.2LibGDX的核心模块
上图(图5)中左侧列中的模块(音频,文件,图形,输入和网络)已在前面的图4中讨论过。其他模块如下:
- Maps:该模块包含用于处理不同级别映射实现的类,例如从Tiled(一种名为TMX的基于XML的格式)和Tide生成的映射。便捷方法包括处理地图和引用资产的加载,渲染地图,访问属性,和选择不同图层
- Math:该模块包含具有方便实用方法的类,用于处理各种数学计算,如三角函数,线性代数和概率。这些方法也被优化为效率更高。其他类包括处理形状,面积和体积的几何类,交叉和重叠等碰撞检测测试以及插值算法。
- Assets:此模块包含用于管理资源(如纹理,位图字体,粒子效果,像素图,UI皮肤,瓷砖地图,声音和音乐)的加载和存储的类。这些类还将处理不同的缓存策略,以优化游戏资产的存储和使用。
- Scenes:该模块包含用于构建用于创建UI的2D场景图形的类,例如游戏菜单和HUD叠加层。此模块还提供了用于管理布局,绘制和处理不同UI的输入的类。
- Utils:这个模块更多地适用于其他各种不适用的各种各样的实用方法。此模块支持以XML和JSON(具有序列化支持)进行读写,具有原始类型支持(这有助于避免自动装箱类型时的性能命中),定时器和对象池的自定义集合。
LibGDX还有其他库,但通常由第三方维护。这些将落在扩展文件夹下。 LibGDX扩展文件夹包含以下内容: - gdx-box2d:这是2D刚体的物理引擎
- gdx-bullet:这是一个实时物理模拟库
- gdx-controllers:这是用于游戏手柄和游戏手柄控制器的支持
- gdx-freetype:这将生成位图字体一个TrueType字体(TTF)文件
- gdx-jnigen:这允许C / C ++代码与Java源代码内联写入
- gdx-setup:这是用于使用Gradle构建系统管理LibGDX安装的UI项目设置应用程序
- gdx-tools:这是各种工具的集合,以帮助您开发游戏,如粒子效果编辑器,纹理打包器应用程序和位图字体创建器实用程序
5了解LibGDX的应用程序生命周期
为了对LibGDX包含的核心模块有更好理解,我们现在可以查看LibGDX为桌面编写的典型游戏的应用生命周期,如下图所示(图6):这张图表示你的游戏循环的循环,其中一个循环通过逻辑代表一个帧。以下步骤概述了此图中通过游戏循环的各种路径:
- LwjglApplication类将使用您的起始类实例和传入其构造函数的配置来引导自己。 LwjglApplication构造函数将实例化LibGDX中使用的各种子系统模块,使用前面图4中描述的应用程序,图形,音频,输入,文件和网络模块的静态实例填充Gdx(com.badlogic.gdx)环境类。然后LwjglApplication构造函数会产生一个线程,我们称之为主循环,这个线程将运行直到游戏退出。这个主循环线程代表了游戏的生命周期,实例化由游戏开始注释为活动图中初始节点引用。现在,我们可以移动到第2步。
- 初始启动后图中的下一个节点是一个指定为create()的动作节点。 create()方法是一种接口方法,您必须在创建游戏时执行该方法,以便连接到LibGDX的生命周期。在游戏循环线程开始时,create()只会被调用一次。这将成为游戏的初始化代码的位置,包括预加载资源,实例化游戏屏幕以及初始化游戏子系统。
- 这一步表示我们在循环中的第一个决策节点,它在每个循环的开始处通过游戏循环检查,或每帧一次。测试是游戏是否仍在运行,并允许我们在游戏状态更改为不运行时退出。作为一个方面说明,为了保证你正常退出你的游戏,它允许执行清理代码以正确的顺序进行,建议你遵循退出游戏的LibGDX约定,退出时使用以下语句:Gdx.app.exit();这个调用到应用程序对象的静态实例中会将游戏循环的运行状态设置为false,随后进入下一步,允许优雅地退出你的游戏。所以,如果游戏正在运行,那么我们可以转到第7步。如果游戏没有运行,跳转到第4步。
- 活动图中由pause()指定的动作节点是创建游戏时必须实现的接口方法之一。这种方法保证了游戏的正确处理,比如保存游戏的当前状态。完成后,我们转到下一步。
- 在活动图中由dispose()指定的动作节点是一种接口方法,用于在游戏处于被销毁的过程中保证游戏资源的正确清理,并且是释放这些资源的适当位置。 为了澄清,由于这是一个Java环境,所以实现Disposable接口的所有对象(com.badlogic.gdx.utils)都应该在这里调用其适当的dispose()方法。 例如,对于非托管Texture对象的dispose()方法调用,将从静态OpenGL实例中删除纹理并使其句柄无效。 现在,我们进入第6步。
- 在dispose()完成其工作后,绘图曲面会与任何仍在使用的音频硬件手柄一起销毁,然后运行System.exit()。在前面的图中,该步骤由活动图中最后节点的游戏停止注释引用。
- 图中的下一步将我们带到决策节点,在这个节点中,游戏循环会计算出我们是否正在从绘制表面状态的先前更改过渡。当游戏循环开始时,绘图曲面的前一个状态被设置为主动作为初始占位符,然后检查当前绘图曲面以查看我们是否处于活动状态。绘图表面的活动状态(用于桌面)指示绘图表面是否处于对焦状态(不在另一个窗口后面)或最大化。如果确定我们已经转换到绘图曲面的新状态,那么我们在步骤8中移动到下一个决策节点。如果没有转换到新状态,那么我们可以继续到步骤11。
- 在确定自从最后一帧(循环的最后一个循环)以来已经发生了一些状态变化之后,游戏循环图中的下一步将确定我们是否已经从先前的聚焦状态转换为当前状态 没有集中的状态,反之亦然。如果绘制表面聚焦在最后一帧但现在不是,那么我们将被最小化,所以我们将转到步骤9中由pause()指定的动作节点。如果绘制表面未聚焦在最后一帧中,但现在集中,然后我们被最大化,所以我们将转到步骤10中由resume()指定的动作节点。
- 在游戏循环中的一个循环中,如果绘图表面状态从最大化或焦点变为最小化或未聚焦,则游戏循环会调用暂停()。完成后,我们转到步骤11。
- 在游戏循环中的一个循环中,如果绘图表面状态从最小化或未聚焦变为最大化或聚焦,则resume()将被游戏循环调用。活动图中由resume()指定的动作节点是另一种必须由您的游戏实现的接口方法。此方法将保证从以前暂停的状态进行正确处理,例如从磁盘重新加载保存的状态信息。在基于Android的设备上,这也将是您重新加载非托管纹理的位置,但这不是桌面的问题。完成后,我们转到步骤11。
- 图中的下一个节点表示关于自上次帧更新以来当前绘图表面的尺寸是否已经改变的决定。 如果尺寸已经改变,那么我们转到步骤12.如果尺寸没有改变,那么我们转到步骤13。
- 自上次帧更新以来,绘图表面的大小发生了变化,因此会触发调整大小事件。活动图中由resize()指定的动作节点是必须由您的游戏实现的接口方法。此方法的参数列表表示游戏屏幕的新尺寸,宽度和高度(以像素为单位)。这些维度通常会传递到屏幕或绘图表面以在下一个渲染调用中更新。一旦这一步完成,我们进入第13步。
- 这个动作节点处理从输入设备获取状态信息。这包括更新当前帧的增量时间间隔,更新鼠标光标位置和鼠标按钮按下事件,并更新键盘按键事件。完成此步骤后,我们转到步骤14。
- 这个动作节点处理来自输入设备的状态信息。这主要包括传递鼠标光标位置,鼠标按键和键盘按键直到输入事件处理程序类InputProcessor。您的游戏通常会实例化此类并将其设置在环境类Gdx中,以便您可以每帧访问输入事件。当这一步完成时,我们可以进入步骤15。
- 此动作节点处理更新当前帧的音频资源。 对于桌面,这主要用于更新音乐,因为音乐将跨帧播放。 当这一步完成时,我们进入步骤16。
- 这个决策节点专门处理我们是否应该绘制绘制表面的测试。如果我们需要渲染(比如游戏对象的位置已经改变了这个框架,或者鼠标光标已经移动),那么我们进入第17步。否则,如果我们不需要渲染,那么我们已经完成了一个这样的循环游戏循环,我们将在第3步开始下一帧。
-
活动图中由render()指定的动作节点是必须由您的游戏实现的接口方法。这种方法将成为游戏生命周期中最重要的方法。将游戏场景渲染到屏幕上的命令将与这些处理UI组件,物理计算更新,AI例程和游戏对象更新一起存在。一旦这一步完成并且我们已经完成了当前帧的更新,我们将回到步骤3来开始一个新的。
总之,在上图中,指定为create(),resize(),render(),pause(),resume()和dispose()的操作都是ApplicationListener接口中的所有方法,如下图所示(图7):
这些接口方法所代表的职责的简要回顾如下:
- create():在游戏的生命周期中,这只在开始时被调用一次。通常,这是初始化代码(准备开始游戏)生存的适当位置。
- resize(int width,int height):每当游戏画面的大小发生变化时调用它。参数都表示游戏屏幕的新宽度和高度(以像素为单位)。
- render():每次需要渲染游戏画面时调用此方法,例如调整大小事件或更改游戏画面。将游戏场景渲染到屏幕的命令应该在这里。
- pause():在桌面上,当游戏屏幕最小化,用户按下键或游戏退出时调用此方法。通常,这是保存游戏状态的好地方。
- resume():在桌面上,当游戏屏幕被最大化时,这个方法被调用,从以前的状态被最小化。
- dispose():这个方法在游戏被销毁时被调用。这将是清理和释放所有仍在使用的资源的适当位置。
现在我们已经对LibGDX的软件包和生命周期进行了概述,现在我们可以生成一个启动器项目,我们将在本书的剩余部分中进行开发。
6设置你的开发环境
6.1必备工具安装
开发工具:android studio
开发语言:java
代码托管工具:git
项目生成工具:gdx-setup(下载地址:https://libgdx.badlogicgames.com/nightlies/dist/gdx-setup.jar)
略...
6.2运行gdx-setup工具
运行gdx-setup之后将出现以下界面:- Name:游戏名
- Package:游戏的包名
- Game class:游戏入口类
- Destination:项目输出目录
- Android SDK:SDK安装目录
- LibGDX Version:
- Sub Projects:可选平台OS
- Extensions:第三方支持库
- Bullet:这是一个实时的物理模拟库
- Freetype:它通过一个TrueType字体文件实时生成位图字体
- Tools:这是一个用于帮助开发游戏的杂项工具集合,例如粒子效果编辑器,一个纹理打包应用程序和一个位图字体创建器实用程序
- Controllers:这是游戏手柄和游戏杆控制器支持
- Box2D:这是2D刚体物理引擎
- Box2DLights:这是一个用于2D游戏的动态照明库
- Ashley:这是一个游戏实体基于框架
- Show Third Party Extensions:包含如下两个扩展
- Overlap2D:这是一个游戏级别的创作工具和用户界面编辑器
- VisUI:这是一个UI工具包库,包括平面皮肤和小部件,如颜色选择器和文件选择器
- Advanced:
- Generate:生成项目
7理解构建环境和项目结构
7.1构建环境:Gradle
略...
7.2项目结构
略...
7.3版本控制系统
略...
8运行默认的示例程序
略