Java9 游戏开发高级教程(二)

协议:CC BY-NC-SA 4.0

六、设置 Java 9 IDE:NetBeans 9 简介

让我们从第六章开始,了解 NetBeans 9 集成开发环境(IDE)的重要特性和特征,因为它是您将用来创建专业 Java 9 游戏和物联网应用的主要软件。尽管 Java 9 JDK 是您的专业 Java 9 游戏以及 NetBeans 9 IDE 的基础,但我们将从学习 NetBeans 开始我们的 Java 游戏编码之旅,NetBeans 是您的 Java 游戏项目的“前端”(或窗口,通过它您可以查看和工作)。

NetBeans 9 是 Java 9 JDK 的官方 IDE,因此,它将是您在本书中使用的。这并不是说你不能使用另一个 IDE,比如 Eclipse 或 IntelliJ,它们分别是 32 位 Android 4.4 和 64 位 Android Studio 3.0 的官方 IDE。我更喜欢将 NetBeans 9 用于我的新媒体应用,将游戏开发用于我的 Java 9 和 JavaFX 游戏以及物联网应用软件开发编程范例。

这不仅是因为 NetBeans 9 可以集成第三方插件,如 Gluon 的 JavaFX Scene Builder,还因为它是一个 HTML5+CSS4+JS IDE,我通常使用 Java 9、JavaFX、Android 4.4 和 Android 8.0 为我的客户创建我设计的所有东西,也使用 HTML5。我这样做是为了让内容可以在封闭的、专有的操作系统和平台上运行,这些操作系统和平台到目前为止还没有命名。正如你们大多数人所知,我更喜欢开放(源代码)软件和平台,正如你们可能在第一章中观察到的那样,因为它们“天生”是开放的,可免费用于商业用途,广泛可用,受到 99%的主要制造商的支持,并且不需要批准过程。或者我只为一个特定的硬件平台或一个操作系统发布应用。

值得注意的是,NetBeans 9 支持许多其他流行的编程语言,例如 C、C++、Groovy 和 PHP。我使用 NetBeans 9 进行 HTML、CSS 和 JavaScript 网站和应用开发,因为 NetBeans 正在迅速成为一流的 Java、JavaFX 和 HTML5 应用开发环境。

我们要做的第一件事是看一下 NetBeans 版本 9 中的新增功能。NetBeans 8.2 于 2016 年第四季度发布,大约在 Java 8 发布一年半之后。这种版本号同步并非巧合,因为 NetBeans 8.0 是在 Java 8 之后发布的,而 NetBeans 9 很可能会在 2017 年第四季度 Java 9 之后发布。在本章中,我们将了解为什么您希望使用 NetBeans 9,而不是旧版本的 NetBeans。

我们接下来要做的事情是了解 NetBeans 9 IDE 的各种属性,这些属性使它成为 Pro Java 9 游戏开发的宝贵工具。在这本书的过程中,我们将会看到它为你提供的所有令人惊奇的特性;在本章中,您将无法获得其中一些功能的实际操作经验,因为我们还需要开始创建您的游戏,并因此将引导代码库或应用基础结构放置到位,以便您可以真正体验这些 NetBeans 9 IDE 功能。

因此,在本章的后半部分,您将学习如何使用 NetBeans 9 创建 Java 9 和 JavaFX 9 项目。这样,您就可以通过创建一个真实世界的 i3D 棋盘游戏,开始稳步前进,并使您的 Pro Java 9 游戏开发成为现实,您将在本书的过程中开发该游戏。

NetBeans 9 的新特性:Java 9 模块集成

NetBeans 9 是该软件在稳定版 8.2 之后的下一个主要修订版,现在集成了 Java 9 模块系统、Java 9 运行时版(JRE)和 JUnit Java 测试套件,因此这些不必单独下载。如果您正在下载 NetBeans 9 for HTML5+CSS+JS、PHP 或 C++,您不再需要下载 JDK 或 JRE。这可以在 NetBeans IDE 下载包页面上看到,如图 6-1 所示,这也是为什么有针对 HTML5/JS、PHP 和 C/C++的 32 位(x86)或 64 位(x64)预编译 NetBeans 9 版本的原因。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-1。

The Java SE Edition NetBeans download bundle contains the NetBeans platform, Java SE, and JavaFX SDKs

也就是说,如果您使用任何其他版本(Java SE、Java EE 或 All ),就像本书一样,JRE 不包括在内。这是因为您将下载 JDK,正如您在第一章中所做的那样,以便能够使用这些 Java SE(或 EE,对于大公司而言)版本,正如您已经看到的,JRE 包含在下载和安装过程中。NetBeans 9 还支持 Apache Ant 和 Maven 存储库的最新版本。在本章的剩余部分,我将介绍自 2014 年第一季度 NetBeans 版发布以来的一些新功能。我将使用子部分对它们进行分类,并根据相关主题为读者进行组织。

Java 9 支持:模块、Ant、Java Shell、多版本

NetBeans 9 将与 Java 9 同时发布,因此它的主要目标是支持 Java SE 9 版本的所有特性和功能。这将包括新的 Java 9 模块特性,这将提高安全性,并使开发者能够优化他们的 Java 9 游戏发行版的数据足迹。这将包括基于 Ant 和基于 Maven 的 Java 9 项目,因此 Ant 和 Maven 构建系统将被升级以支持 Java 9 模块。

Java 9 SE 应用项目最初将支持单模块开发(包括所有模块)以及支持多模块开发的新项目类型,因此您可以挑选 Java 9 模块。我们最终将只使用几个核心 JavaFX 模块(base、graphics 和 media ),这样我们的发行版数据占用空间将会显著减少,但我们将在本书的最后完成,因为这是一个更高级的主题。

Apache Ant 正在更新,以获得对 JDK 9 的支持,涵盖基本的 Ant 任务,并且当 NetBeans 9 在 JDK 9 上运行或 JDK 9 被设置为您项目的 Java 平台时,Java 9 SE 发行版中的所有工具都将正确工作。NetBeans Profiler 现在可以与 JDK 9 应用协同工作,Java shell 支持以及与 NetBeans 9 IDE 的集成已经添加到 NetBeans 9 项目的每个级别。NetBeans 9 及其集成的 Java 9 支持现在可以正确处理多版本 JAR 文件。

最后,NetBeans 9 项目将很快转移到 Apache 上。该提案可在 https://wiki.apache.org/incubator/NetBeansProposal 进行审核。该提案涵盖了这一变化将如何影响 NetBeans 9 版本。在 NetBeans 9.0 和 9.0.1 版本中,将会迁移源代码、错误、构建作业和相关服务。

IDE 用户体验:更多信息和智能编码

NetBeans 8.1 引入了一个改进的代码导航窗格,它现在可以区分游戏的 Java 方法所包含的超类或接口,以及方法名及其返回类型。代码补全(我们将在本章的下一个主要部分中介绍)在 NetBeans 8.1(以及 8.2 和 9 等更高版本)的几乎所有方面都得到了显著改进,包括改进了最相关的 Java 代码插入项的预选、改进了前缀自动补全、改进了子词自动补全以及改进了 Java 枚举值的自动补全。

Java 代码分析:完全重新设计的 Java 分析套件

NetBeans 在 8.1 版中对其 Java 代码分析套件进行了全面的检查,包括简化的分析器设置、无需预先设置的新的单击式 Java 代码分析,以及只需选中代码分析结果旁边的复选框即可选择方法或类进行详细分析的能力。附加到正在运行的进程的能力有所提高,并且选定的 PID 会被记住以供后续会话使用。新特性包括监控 CPU 利用率、从分析的应用中转储线程的能力、在 CPU 分析视图中显示所选线程的合并结果的能力,以及改进的实时应用分析视图。

其他新的评测器功能包括 CPU 评测结果中的实时正向和实时反向调用树、系统内存评测结果中的实时分配树,以及在评测会话期间简化的设置调整。

该 NetBeans 分析引擎是 8.1(及更高版本)ide 中改进最多的,包括连接到正在运行的进程时显著加快的连接速度,对当前分析方法的传出调用的限制,以及为某些预选类分析系统内存性能的能力。所有这些都将有助于优化 Pro Java 9 游戏开发,因为游戏需要最高性能。

profiler 用户界面(UI)现在变得更加完美和专业,具有一个统一的分析窗口,在一个可定制的托管视图中包含所有操作、设置和结果。有一个单独的快照窗口窗格,您可以使用它来管理持久性分析数据。

还有一个全新的、100%重新实现的 profiler 表和树表区域,它提供了具有本机外观的分析外观,允许开发人员无缝集成代码开发和优化。

与 NetBeans IDE 的其余部分的分析器集成也有了很大的改进;此外,还有一个更加完美的 profile 菜单,添加了一个名为 Attach to Project 的新操作,并且在代码导航器中添加了 Profile 类和 Profile 方法操作。在本书的后面,当我们需要在 Java 9 游戏中实现系统内存和 CPU 优化时,我们将会看到 NetBeans 9 Profiler。

NetBeans 9 的主要属性:智能 IDE

在本节中,我将向您全面介绍 NetBeans 9 的所有强大功能,以便您了解安装在开发工作站上的这个 IDE 工具有多强大,以及掌握它的所有功能有多重要,这样您就可以作为一名专业的 Java 9 游戏或物联网应用开发人员来运用所有这些功能。IDE 是您使用 JavaFX APIs 编写的 Java 9 代码和您的计算机之间的接口;它允许您可视化您的代码,将其组织成逻辑方法,在您的计算机上测试它,分析它相对于您的系统内存和处理器周期的最佳运行情况,并将其打包以便通过网站在互联网上分发,或者作为 Windows、OS/X、Linux 或 OpenSolaris 的独立应用用于桌面计算机,甚至作为 Android OS 或 Tizen OS 的嵌入式设备应用。理想情况下,iOS、Opera OS 和 Chrome OS 也将在 2018 年前支持 Java 9 应用,因为 Android 和 Tizen 已经在 Linux 内核之上的 Java(Android OS)和 Linux 内核之上的 html 5(ti Zen OS)平台上占据了最大的市场份额。

NetBeans 9 是智能的:将您的代码编辑放在 Hyperdrive 中

虽然 IDE 确实非常类似于文字处理器,只是针对创建模块化代码结构而不是编写业务文档进行了优化,但是 NetBeans 9 这样的集成开发环境在开发人员的编程工作过程中提供的帮助要比文字处理器在作者的写作和文档创作工作过程中提供的帮助大得多。文字处理器主要用于使用桌面出版功能格式化文本以使其看起来像样,纠正拼写错误,以及纠正语法和句子结构。

例如,您的文字处理器不会对您为业务编写的内容提出实时建议,而 NetBeans 9 IDE 会在您实时编写代码时查看您正在编写的内容,并在您创建代码时帮助您完成 Java 代码语句和 Java 代码结构的编写。因此,NetBeans 9.0 可以说比工作处理器具有更高的人工智能商数,如 Microsoft Office、Corel WordPerfect、Apache Open Office 或 Ubuntu Libre Office current feature。

NetBeans 要做的事情之一是为您完成 Java 代码行,以及对代码语句应用颜色以突出不同类型的构造(类、方法、变量、常量、数组、引用),如图 6-2 所示。NetBeans 将应用行业标准代码缩进,使 Java 代码更易于阅读,无论是对您自己还是对您的 Pro Java 9 游戏和物联网应用开发团队的其他成员。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-2。

NetBeans includes Files, Services, Projects, Navigator, and Output Panes (left top to bottom) as well as a Java editor

NetBeans 还将提供匹配或缺失的代码结构元素,如括号、冒号和分号,以便您在创建复杂、深度嵌套或异常密集的编程结构时不会迷路。当我把你从 Java Game Developer 带到 Pro Java 9 Game Developer 时,你将创建具有这些特征的高级 Java 构造,随着你在本书中 Java 代码复杂性的进步,我将肯定指出当我们在你的游戏中实现它时,密集、复杂或深度嵌套的 Java 8 和 Java 9 代码。

NetBeans 还可以提供引导代码,例如我们将在本章稍后创建的 JavaFX 游戏应用引导代码,因为我知道您急于开始创建您的 Pro Java 9 游戏。NetBeans 9 提供了您可以填写和自定义的代码模板、编码提示和技巧以及代码重构工具。随着您的 Java 9 代码变得越来越复杂,它成为代码重构的逻辑候选者,这可以使代码更容易理解,更容易升级,并且更高效。NetBeans 还可以自动重构您的代码。

如果您想知道什么是代码重构,它是改变现有计算机代码的结构,使其更有效或更具可伸缩性,而不改变其外部行为(即,它完成了什么)。例如,NetBeans 可以采用传统的 Java 7 代码,并通过实现 Java 8 中引入的 Lambda 表达式来提高效率。

NetBeans 9 还将提供一种或另一种类型的弹出帮助器对话框,其中包含方法、常量、资源引用(在本书中编写 Pro Java 9 游戏时,您将了解所有这些内容),甚至是关于如何构造 Java 语句的建议。例如,NetBeans 9 会建议何时使用 Java 8 Lambda 表达式来简化代码并兼容多线程。

NetBeans 9 是可扩展的:用多种语言编辑代码

你的文字处理器不能做的另一件事是允许你给它增加功能,NetBeans 9 可以用它的插件架构做到这一点。描述这种类型的体系结构的术语是可扩展的,这意味着,如果需要,它可以扩展以包括附加的特性。例如,如果您想扩展 NetBeans 9 以允许您用 Python 编程,您可以这样做。NetBeans 9 也可以以这种方式支持 COBOL 或 BASIC 等较老的语言,尽管由于目前大多数流行的消费电子设备都使用 Java、XML、JavaScript、SVG 和 HTML5,我不太确定为什么有人愿意花时间这样做。我谷歌了一下,发现有人在 NetBeans 中用 Python 和 COBOL 编程,所以有现实证明这个 IDE 确实是可扩展的。

可能是因为其可扩展性,NetBeans 9 IDE 支持许多流行的编程语言,包括客户端的 C、C++、Java SE、Javadoc、JavaScript、XML、HTML5 和 CSS,以及服务器端的 PHP、Groovy、Java EE 和 Java Server Pages (JSP)。客户端软件在终端用户持有或使用的设备上运行(在 iTV 机的情况下),而服务器端软件在某处的服务器上远程运行,并且当软件在服务器上运行时,通过因特网或类似网络与终端用户对话。

客户端软件将更高效,因为它位于运行它的硬件设备的本地,并且因此它更具可伸缩性,因为不涉及经历任何过载的服务器。随着越来越多的人在任何给定的时间点使用服务器端软件,服务器过载总是会发生。您创建的 Java SE 9 和 JavaFX 游戏或物联网交付物往往位于客户端,在网站中交付并使用网站,但也可以通过 JNLP 下载在客户端使用,或者下载 JAR 或针对给定操作系统平台编译的可执行文件。

NetBeans 9 是高效的:有组织的项目管理工具

显然,项目管理功能在任何主流 IDE 中都必须非常强大,NetBeans 9 包含了大量的项目管理功能,这些功能允许您以多种不同的分析方式查看您的专业 Java 游戏开发项目及其相应的文件以及这些文件之间的相互关系。有六种主要的项目管理视图或窗格,可以用来观察项目中各种类型的相互关系。图 6-2 显示了 bootstrap pro Java 9 游戏开发 JavaFX 项目,我们将在本章稍后创建该项目。

图 6-2 显示了为这个新项目打开的六个主要项目管理窗格或窗口,这样你就可以准确地看到它们将向你展示什么。一个优秀的编程 IDE 需要能够管理可以变得非常庞大的项目,包括超过一百万行代码,并且包含在项目文件夹层次结构中的数百个文件夹中。这可能涉及数千个文本(Java 9 代码)文件,以及数百个文件形式的新媒体素材,有些是基于文本的(SVG、XML),有些是二进制数据格式的(JPEG、MPEG)。

“项目”窗格显示构成 Java 9 游戏项目的 Java 源代码包、库和模块。这可以在图 6-2 的左下方看到。顶部的窗格是文件窗格,显示硬盘上的项目文件夹及其文件层次结构。

下面的服务窗格显示了数据库、服务器、存储库、Docker 和构建主机,以便在项目中使用它们。这些主要是服务器端技术,这些技术通常用于大型开发团队,所以我们不打算详细讨论这些,因为这是一本为单人游戏设计者编写的书。

项目窗格应该始终保持打开,在 ide 的左侧,从图 6-7 开始,您将在本章的所有图中看到。“项目”窗格或窗口为您提供了 Java 9 游戏项目中所有项目源代码和资源(内容)的主要访问点。文件窗格不仅显示项目文件夹和文件层次结构,还显示每个文件中的数据、JavaFX 新媒体素材和 Java 9 代码层次结构。

“导航”窗格显示在 NetBeans IDE 底部的“文件”、“项目”和“服务”窗格下面,它显示了 Java 代码结构中存在的关系。在本例中,这是 JavaFXGame 类。start()方法,而。main()方法,我们将在第七章中学习,在我们学习了所有关于 NetBeans 9 IDE 的知识以及如何使用它来创建一个名为 JavaFXGame 的 Java 9 游戏项目之后,我们将很快完成这个项目。

NetBeans 9 是 UI 设计友好的:用户界面设计工具

NetBeans 9 的可扩展插件功能支持许多平台的 design-your-UI 拖放设计工具,包括 Java SE、Java EE、Java ME、JavaFX 和 Swing,以及 C、C++、PHP、HTML5 和 CSS4。NetBeans 9 支持为您编写应用 UI 代码的可视编辑器,因此您所要做的就是使屏幕上的可视内容看起来像您希望它在游戏应用中的样子。由于游戏使用 JavaFX 新媒体游戏引擎,NetBeans 支持 Gluon JavaFX Scene Builder Kit,这是一种高级 JavaFX 用户界面设计可视化(拖放)编辑器。

由于 JavaFX 具有 PRISM 游戏引擎以及 3D(使用 OpenGL ES 或嵌入式系统)支持,因此我们将主要关注本书的 i3D,因为我在《Java 8 游戏开发入门》(Apress,2014)中已经介绍过 i2D。这本书的假设是,读者将希望构建最先进的专业 Java 游戏,这将等同于利用 JavaFX 引擎的 3D 和 i3D,Java FX 引擎现在是 Java 8 和 9 的一部分(以及 Lambda 表达式)。最有效的方法是使用 Java 代码,而不是拖放式代码生成器。

开发 pro Java 9 游戏的最快方法是利用 Java 和 JavaFX 环境慷慨提供的高级代码和编程结构,供您在创建尖端应用时使用。在这种情况下,这将是 pro Java 游戏,其中包含强大的新媒体元素,如 2D 矢量、3D 矢量、数字音频、视频和数字图像,这些元素组合在一起成为一个统一的 2D 和 3D 混合内容创建管道。

NetBeans 9 对 Bug 不友好:用调试器消除 Bug

每一种计算机编程语言都有一个普遍的假设,即一个“bug”,或者没有完全按照您的要求运行的代码,其对编程项目的负面影响会随着问题得不到解决的时间越长而越大。正因如此,可以说这些虫子一“出生”就需要被“压扁”。NetBeans 9 有大量的错误查找代码分析工具,可以使用集成的 NetBeans 调试器来访问这些工具。NetBeans 9 还支持与第三方 Find Bugs 3.0.1 项目的集成,该项目可以在 SourceForge.net 上找到,如果你想下载单机版,可以在findbugs.sourceforge.net找到。

这些工具将我们在本章本节开始时讨论的实时“键入时”代码纠正和编码效率工具提升到高级调试的下一个级别。

您的 Java 代码不会变得那么复杂,直到本书的稍后部分,所以当我们需要在后面的章节中使用这些高级工具时,当您的知识库更高级时,我们将会介绍它们是如何工作的。

NetBeans 9 是一个速度狂:用分析器优化你的代码

NetBeans 还有一个称为 Profiler 的东西,这是 NetBeans IDE 在 8.1 版中彻底改进的领域之一,正如我在前面的“NetBeans 代码分析”一节中指出的那样。NetBeans Profiler 工具会在 Java 8 或 Java 9 代码实际运行时查看这些代码,并告诉您它使用内存和 CPU 周期的效率。这种剖析分析将允许您优化代码,并使其更有效地使用关键系统资源,如线程、系统内存和处理周期。这对于 Pro Java 9 游戏开发来说非常重要,因为分析复杂的游戏可以帮助您在嵌入式系统上优化游戏的“流畅度”,与普通的六核和八核 CPU 相比,嵌入式系统不是很强大(例如,在单核或双核 CPU 上),或者在使用双核或四核 CPU 的不太强大的计算机系统上。

这个分析器是一个动态的软件分析工具,因为它在 Java 代码运行时查看您的代码,而 FindBugs 代码分析工具可以说是一个静态的软件分析工具,因为它只是在编辑器中查看您的代码,而不是“编译”并运行在系统内存中。因为我已经在第四章中讨论了静态和动态的重要性,所以你知道动态处理对于你的职业 Java 游戏开发工作过程来说是多么强大和 CPU 密集型。同样的考虑也适用于实时调试。NetBeans 调试器还允许您在代码运行时逐句通过代码,因此该工具可以被视为“混合体”,它跨越了静态(编辑)和动态(执行)代码分析模式之间的鸿沟。

为 Pro Java 9 游戏及其 JavaFX PRISM 引擎创建项目基础后,在本章的下一节中,如果您喜欢使用 IDE 顶部的 Profile 菜单,可以运行 Profiler。然而,如果你这样做,你根本看不到什么,因为 Hello World bootstrap 应用实际上什么都不做。

因此,在添加实时渲染的 3D 素材等内容时,我们将进入 NetBeans Profiler。在本章中,我将尽量让您“提前”了解 NetBeans 9 的这些关键功能,而不需要使用很多页面,这样您就可以轻松使用该软件,并且在本书的过程中,当 IDE 相关的任何内容(有时是字面意思)出现时,您不会感到惊讶或“措手不及”。

事不宜迟,让我们启动 NetBeans 9 并创建您的基于引导 JavaFX API 的 pro Java 9 游戏项目,这样我们就可以在本章中对您的 Pro Java 9 游戏进行一些 Java 9 和 JavaFX 编程。

创建 Pro Java 9 游戏项目:JavaFXGame

让我们言归正传,为您将在本书的课程中创建的 pro Java 9 游戏创建一个项目基础,以便您在本书的每一章中都朝着您的最终目标前进。我将在本书的过程中向您展示如何创建一个原创游戏,以便您看到创建一个不存在的游戏所涉及的过程,而不是大多数游戏编程书籍复制市场上已经存在的游戏或将素材拖放到预建的游戏引擎中。为了开始 Java 8 游戏开发(Apress,2014),我得到了我的客户的许可,允许读者在这本书的过程中看到创建 i2D InvinciBagel 游戏的过程。对于这本书,我将创建 i3D 棋盘游戏引擎,用于我自己的iTVboardgame.com网站。

单击任务栏上的快速启动图标,或者双击桌面上的图标以启动 NetBeans 9,您将看到 NetBeans 9 启动屏幕。此屏幕会显示一个进度条,告诉您如何配置 NetBeans 9 IDE 以供使用。这包括将 IDE 的各种组件加载到计算机的系统内存中,以便在 pro Java 9 游戏开发过程中可以流畅地实时使用 IDE。

将 NetBeans 9 IDE 加载到系统内存后,初始 NetBeans 9 起始页将显示在您的显示屏上,如图 6-3 所示。单击“起始页”选项卡右侧的 x。这将关闭此介绍页(选项卡),并显示 NetBeans 9 IDE,如图 6-4 左侧所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-3。

Close the Start Page tab (upper left) by clicking the x on the right side of the tab to reveal NetBeans 9 IDE

这将显示我称之为“原始”的 IDE,IDE 中没有活动的项目。现在好好享受吧,我们很快就会为你的项目组件在这个 IDE 中填充窗口(我称之为浮动调色板窗格,因为整个 IDE 都在我称之为窗口的地方)。你可以在图 6-4 中看到这个空 IDE 的一部分,没有太多可看的,因为目前只有顶部菜单和快捷图标,也在 IDE 的顶部,目前没有太多其他可见的。

如果您想知道,您退出的起始页仅在您第一次启动 NetBeans IDE 时显示,但是如果您希望以后打开此起始页选项卡,以便您可以浏览演示和教程部分,您可以这样做!要随时打开此起始页,您可以使用 NetBeans 9.x 帮助菜单,然后选择起始页子菜单。我通常会表示一个菜单序列,如帮助➤开始菜单,只是为了你将来的参考。如果你在本书后面看到这样的结构,它是嵌套子菜单的级联菜单序列。

在 NetBeans 9.0 IDE 中,您要做的第一件事是创建一个新的 JavaFXGame Java 项目。为此,我们将使用 NetBeans 9.0 新项目系列对话框。这是我在上一节中谈到的一个有用的 Java 编程特性,它使用正确的 JavaFX 库创建您的引导项目。main()和。start()方法、java 语句和 import 语句,所有这些都将在下一章中学习。点击你的 NetBeans 9 IDE 左上角的文件菜单,如图 6-4 所示,然后选择新建项目菜单项,恰好是第一个菜单项。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-4。

Use the File ➤ New Project menu sequence (upper left) to open the NetBeans 9 New Project series of dialogs

请注意,在新项目菜单项的右侧,列出了一个 Ctrl+Shift+N 快捷键组合,以防您想记住它。

如果您想要使用此键盘快捷键来调用新的项目系列对话框,请按住键盘上的 Ctrl 和 Shift 键(同时按住),并在按住它们的同时,按下 N 键。这将做同样的事情选择文件➤新项目菜单序列用你的鼠标。

系列中的第一个对话框是选择项目对话框,显示在图 6-5 的右侧。因为您将在游戏中使用强大的 JavaFX 新媒体引擎,所以在左侧的类别选择器窗格中,从所有编程语言类别的列表中选择 JavaFX 类别,对于步骤 2,该类别标有红色数字 2。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-5。

Use the Choose Project dialog to specify a JavaFX Application for your Pro Java Game

接下来,从右侧标有红色数字 3 的项目选择器窗格中选择 JavaFX Application,执行步骤 3。我们选择这个是因为你的 pro Java 9 游戏将是一种 JavaFX API 应用。您可以在描述窗格(显示为红色数字 4)中阅读每个项目类型的描述,最后单击下一步按钮前进到下一个对话框,在图 6-5 中显示为红色数字 5。

请记住,Oracle 决定将 JavaFX API(当时是库,现在是模块)集成到 Java 7 和 Java 8 中,因此 JavaFX 游戏现在只是一个 Java 游戏,而在 Java 7 之前(在 Java 6 中),JavaFX 2.0 是它自己独立的编程语言!JavaFX 引擎(您将在下一章中了解更多)必须完全重新编码为 Java 7(和 Java 8) API 或库集合(现在在 Java 9 中它变成了模块),才能成为 Java 9 编程语言的无缝集成组件。

JavaFX API 将取代 Abstract Windowing Toolkit (AWT)和 Swing (UI 元素),尽管这些旧的 UI 设计库仍然可以在 Java 项目中使用,但它们通常只由遗留(旧的)Java 代码使用,因此这些项目仍然可以在 Java 1.02、2、3、4、5、6、7、8 和 9 下编译和运行。您将编译并运行这个新的基于 JavaFX API 的项目,该项目是您在本章的这一节中创建的,因此您将看到 JavaFX 正在 Java 9 下运行。JavaFX 的当前版本是 9,因为 Oracle 使版本号与 Java 9 相匹配,然而,这些类与我在 Java 8 游戏开发入门书中使用的是相同的。

请注意,在其他窗格下面有一个描述窗格,它会告诉您所选择的内容。在这种情况下,这将是一个启用了 JavaFX 特性的新 Java 应用,其中“enabled”意味着 JavaFX 9 API 库将通过一系列 import 语句包含(并启动)在 Java 应用项目的类和方法中,您将很快在代码中看到这一点。您将在第七章中了解所有这些 Java 9 和 JavaFX 9 代码的作用,这将涵盖 JavaFX 9 及其许多用户界面设计和多媒体相关特性。

点击 Next 按钮,进入新 Java 项目系列对话框中的下一个对话框,即名称和位置对话框,如图 6-6 所示。该对话框允许您使用项目位置和项目文件夹数据字段设置应用项目名称,该名称将用于创建类名和包名,以及您希望项目存储在硬盘上的位置,这些也在图 6-6 中显示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-6。

Name the project JavaFXGame, and leave all other naming conventions the way NetBeans set them

将项目命名为 JavaFXGame,保留默认的项目位置、项目文件夹、JavaFX 平台,并完全按照 NetBeans 为您配置的方式创建应用类设置,因为此 NetBeans 对话框将根据项目名称自动为您实现所有的类和包命名约定。

完成后,您可以单击“完成”按钮,这将告诉 NetBeans 9 为您创建 JavaFX 游戏应用,并在 NetBeans 9 IDE 中打开它,以便您可以开始使用它并了解 JavaFX API。

让 NetBeans 9.0 按照应该的方式为您做事情通常是一个好主意。如图 6-6 所示,NetBeans 使用该对话框中的项目位置和项目文件夹数据字段为用户文件夹和文档子文件夹创建逻辑C:\Users\Walls\Documents\NetBeansProjects\JavaFXGame文件夹。

对于项目文件夹数据字段,NetBeans 将(逻辑上)创建名为 JavaFXGame 的子文件夹。这将位于 NetBeansProjects 文件夹下,就像是您自己创建的一样,只有 NetBeans 9 为您完成了这项工作。

对于 JavaFX 平台选择下拉列表,NetBeans 9 默认为最新的 Java 9 JDK,也称为 JDK 1.9,具有最新的 JavaFX API(现在是 Java 7、8 和 9 语言的集成部分)。

在这一点上,我们不打算实现一个定制的预加载器项目,尽管如果我有时间和剩余的页数,我可能会在本书的后面部分重新讨论这个问题。因此,请不要选中此选项,这样您就可以学习自己创建这个预加载器 Java 9 项目代码,而不是让 NetBeans 9 为您完成。

因为您没有创建共享库的多个应用,所以不要选中使用专用文件夹存储库复选框,最后,确保正确配置了创建应用类。Java 9 类应该命名为 JavaFXGame,应该包含在 javafxgame 包中。

在这个配置中,包路径和类名将是javafxgame.JavaFXGame。这将跟在 PackageName 后面。ClassName Java 类和包名范例、camelCase 大小写和路径,使用点符号句点字符将包名连接到类名的头部,显示它保存的位置。

在第七章中,我将查看图 6-7 中所示的 Java 代码的一些基本组件,因为在本章中,我们将主要关注 NetBeans 9.0 IDE 及其特性,在第七章中,我们将完全专注于 JavaFX 编程语言,然后在第八章中,我们将讨论场景图。

如图 6-7 所示,NetBeans 已经写好了 package 语句,7 条 JavaFX API package import 语句,以及public class JavaFXGame extends Application声明;子类化你的 JavaFXGame 类,使用一个 JavaFX Application超类,创建一个启动public void start(Stage primaryStage)的方法,创建一个. main()方法来管理你的主 JavaFX 线程public static void main(String[] args)

如图 6-7 所示,NetBeans 9 将重要的 Java 编程语句关键字着色,将关键字用蓝色表示,字符串对象用橙色表示,内部 Java 和系统引用用绿色表示,注释用灰色表示。NetBeans 9 IDE 插入的有关 Java 9 代码的警告和建议用黄色标出,而阻止编译可执行文件(JAR)的 Java 9 编码错误用红色标出。

第 20 行还显示 NetBeans 提供了将按钮对象事件处理转换为 Lambda 表达式的功能,方法是给它加黄色下划线(警告:这可以转换为 Java 8 Lambda 表达式)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-7。

Examine the bootstrap JavaFX code NetBeans created for you, based on the Name and Location dialog

如果您愿意,也可以更改这些颜色,但是我建议您使用 Oracle NetBeans 9 和更早版本实现的行业标准编码颜色,因为这些颜色已经随着时间的推移变得标准化了。

在运行此引导代码以确保 NetBeans 9 为您编写的引导 Java 9 代码能够正常工作之前,您需要将此代码编译为可执行格式,以便使用系统内存运行。NetBeans 9 还为您管理编译和运行过程,即使这些操作实际上利用了 Java 开发工具包(JDK)提供的实用程序。

接下来,我们来看看如何使用 NetBeans 9 完成这一任务,使用 NetBeans 9 的“运行”菜单,其中包含运行、测试、构建、清理、编译、检查、验证、生成 JavaDoc 以及其他与运行相关的 Java 编译功能。

在 NetBeans 9 中编译一个 Pro Java 9 游戏项目

为了向您展示如何在运行和测试 Java 游戏代码之前编译它,我在这里向您展示了一步一步的工作过程,这样您就可以接触到编译/构建/运行/测试 Java 代码测试过程的每一步。点击 Run 菜单和 Run Project (JavaFXGame) (first)菜单项,构建、编译并运行您的 Java 9 和 JavaFX 代码,如图 6-8 所示。您也可以使用 F6 快捷键,如菜单项选择右侧所示。现在您的项目已经准备好进行测试了!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-8。

Use Run ➤ Run Project (JavaFXGame) to build and run the project to make sure the NetBeans IDE is working

图 6-9 显示了 NetBeans 9.0 构建/编译/运行进度条,该进度条在编译期间将始终出现在 NetBeans 9.0 IDE 的右下角。还显示了输出窗格,最大化以便我们可以看到 Ant 构建过程做了什么,我们将在本章的下一节中更详细地了解它。

这里需要注意的是,只要您使用文件➤保存菜单序列或 Ctrl-S 键盘快捷键,NetBeans 9.0 就会编译您的项目代码,因此,如果您在创建引导代码后立即使用了 NetBeans IDE 的保存功能,您就不需要执行此编译过程,我刚刚向您演示了如何手动执行此过程,因为此过程会在您每次保存 Java 游戏项目时自动完成。

图 6-9 中还显示了输出窗格或窗口正上方的。Java 代码编辑窗格或窗口中的 start()方法。左边是一个减号图标,周围有一个正方形。这应该用于折叠或隐藏该方法的内容。只需单击代码编辑窗口左侧的减号图标即可。

减号图标将变成加号图标,以便折叠的代码块可以“展开”(取消折叠)。现在,我们已经了解了如何在 NetBeans 9 中编译项目,以及如何在 JavaFXGame.java 项目的代码中折叠和展开逻辑方法代码块(Java 类的逻辑功能组件)的视图,是时候运行这些代码了,看看它是否有效。如果是这样的话,我们可以进入第七章,开始学习 JavaFX API 以及它给 Java 9 编程环境带来的新的媒体开发能力。

在 NetBeans 9 中运行您的专业 Java 游戏项目

既然您已经创建并编译了使用 JavaFX game 项目的引导 Java 9,那么是时候运行或执行引导代码了,看看它能做什么。正如您已经了解到的,您可以使用 NetBeans 顶部的“运行➤”“运行项目”菜单序列来访问“运行项目”菜单项,或者如图 6-9 左上角所示,您可以使用看起来像绿色视频传输播放按钮的快捷图标。如果你把鼠标放在上面,你会得到一个浅黄色的工具提示,显示一个运行项目(JavaFXGame) (F6)弹出帮助信息。在编写 Java 9 和 Android Studio 书籍时,我通常会使用较长的菜单序列,而不是快捷图标,这样做只是为了更彻底。这向读者显示了 IDE 菜单系统中所有东西的位置,所以所有东西都被包含了。如果还没有,现在就运行新的 JavaFXGame 应用。一旦运行了编译好的 Java 9 和 JavaFX 代码,就会在 NetBeans IDE 上打开一个窗口,在其中运行您的软件,如图 6-9 右侧所示。目前它使用流行的 Hello World 示例应用。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-9。

Drag up the separator bar to reveal the Output area of the IDE (running application seen at right)

在 Java 9 代码编辑窗格和代码编辑器窗格底部的输出选项卡之间的分隔线上方单击并按住鼠标左键,向上拖动分隔线,调整相对窗口空间的大小。该空间在 JavaFXGame.java 代码编辑窗格和输出 JavaFXGame 信息窗格之间共享。做这个调整大小的操作将会显示你的输出标签和它的编译信息内容,如图 6-9 所示。

这个 Output 选项卡将包含 NetBeans 9 的不同类型的输出,例如编译操作输出、运行操作输出(如图 6-9 所示)、探查器操作输出(我们将在本书后面的内容中对其进行分析),甚至是您的应用本身的输出(我们将在这里查看)。

你可能已经注意到,在图 6-7 中,你的 bootstrap Java 和 JavaFX 应用的代码在第 23 行使用了一个绿色的System. out .println("Hello World!"); Java 语句,所以如果你想看到你当前运行的应用打印到输出窗格(这就是 out 的意思,通常被称为输出控制台),你可以在你的 IDE 上当前运行的 Hello World 应用中点击“Hello World”按钮。

一旦你点击按钮,就会出现“你好,世界!”应该出现在 Output 选项卡中的红色文本下,表示它正在执行 JavaFXGame.jar 文件。JAR 文件是 Java 归档文件(J 代表 Java,AR 代表归档文件),是 Java 9 应用可用的可分发格式之一。

编译过程的一部分涉及到创建这个文件,所以如果编译后的版本可以工作,那么当所有的应用设计、编程、测试和优化完成后,您就可以准备好发布 JAR 文件了。

JAR 文件不包含您实际的 JavaFX 代码,而是一个压缩的、加密的“Java bytestream”版本的应用,JRE 可以执行和运行它(就像 NetBeans 9 现在所做的那样)。JavaFXGame.jar 文件前面的“路径”告诉您 NetBeans 9 将 jar 文件编译到硬盘上的哪个位置,以及它当前从哪个位置访问它以便能够运行它。在我的系统上,这个位置如下:

C:\Users\Walls\Documents\NetBeansProjects\JavaFXGame\dist\run1381287366\JavaFXGame.jar

让我们看看其他一些输出选项卡文本,以便了解 NetBeans 是如何运行项目的 JAR 文件的。首先使用ant -f source-path jfxsarun调用 Ant 构建系统,由于在 JDK 中找不到 Java 可执行文件,所以它会在运行时中找到一个。然后它初始化(init:),并在 JAR Dependencies (deps-jar:)部分创建一个\build目录并更新 build-JAR-properties 文件。然后创建\build\classes\build\empty\build\generated-sources\ap-source-output目录。然后,Ant 会将项目编译到\build\classes目录,如果构建(编译)成功(没有错误),Ant 会创建\dist发行文件夹,并将 JAR 文件存放在那里。

然后 Ant 使用 JavaFX Ant API 启动ant-javafx.jar并部署 JavaFX API,将 JavaFX JAR 文件复制到一个\dist\run1381287366文件夹中。最后,Ant 使用jfx-project-run:运行 JavaFX 项目,执行 Java 9 和 JavaFX 代码,这相当于运行(和测试)它,如 NetBeans 9 IDE 顶部所示。

Ant 是创建 JAR 文件的“构建引擎”或构建工具,如果您愿意,还可以在 NetBeans 中使用其他构建引擎,如 Maven 和 Gradle,因为正如您现在所知道的,NetBeans 是可扩展的。由于 Ant 可以追溯到最早,并且是“遗留”构建系统,我们将在本书的过程中使用它。

摘要

在第六章中,我们介绍了 NetBeans 9“官方”集成开发环境(IDE ),它将作为 Java 9 游戏开发工作流程的基础和主要工具。这是因为这个 IDE 是您编写、编译、运行、测试和调试 Java 9(和 JavaFX API)代码的地方,也是您的新媒体(图像、音频、视频、3D 几何、纹理、字体、形状等)的地方。)使用 NetBeansProject 文件夹及其子文件夹存储和引用素材。我们首先概括介绍了 NetBeans 9 及其新功能,如 Java 9 模块支持,以及 NetBeans 8、8.1 和 8.2 中添加的一些最新的传统功能。这些强大的特性使 NetBeans 9.0 成为 Java 9 的官方 IDE。这些特性将帮助程序员第一次快速、高效、有效地开发 Pro Java 9 游戏代码。在这个概述之后,我们使用新的项目系列对话框和 JavaFX 应用引导 Java 代码模板创建了一个 Pro Java 9 游戏项目。

我们浏览了新的➤ Java 应用系列对话框,并为我们的游戏创建了一个 JavaFX 框架,这将允许我们使用新的媒体素材。之后,我们了解了如何使用 NetBeans 9 编译(构建和运行)应用,以及如何使用 NetBeans 运行应用。我们查看了 Output 选项卡以及它如何用于编译器输出,并查看了 Ant 构建过程,以了解它如何将 Java 9 与其 JavaFX APIs 结合起来。

在下一章中,我们将浏览 JavaFX 编程语言,如果你愿意的话,可以称为“JavaFX 初级读本”,并检查 JavaFX 引导应用中的 JavaFX 代码(如图 6-7 所示),这样你就会知道这个 JavaFX 代码在做什么。我们还将研究全面的 JavaFX API 的模块化组件。

七、JavaFX 9 简介:JavaFX 新媒体引擎概述

在第七章中,让我们以您在前两章中复习的 Java 9 编程语言和 NetBeans 9 IDE 的知识为基础;我们将详细回顾构成 JavaFX 9 新媒体引擎的功能、组件和核心类。这个 JavaFX 9 新媒体 UI 和 UX API 是使用在第六章中看到的javafx包添加到 Java 中的,当时你创建了 bootstrap pro Java 9 游戏应用。之前的 JavaFX 8 API 是随 Java 8 发布的,也兼容 Java 7,以及 Android 和 iOS。JavaFX 软件包对游戏编程非常重要,因为它们包含了游戏编程需要使用的高级新媒体类,包括使用场景图将场景组件组织成层次结构的类、用户界面布局和设计的类、2D 数字插图(称为矢量图形)的类,以及数字图像(称为光栅图形)、2D 动画(矢量和光栅)、数字视频、数字音频、3D 渲染、网页渲染引擎(WebKit)等的类。我们将在这一章中触及所有这些,这样你就知道 JavaFX 已经作为一个 API 被添加到 Java 中,你可以为 Java 9 游戏做些什么了。

在本书的早期深入 API 细节概述的基本原理是激发您大脑的创造性,以便您可以开始思考 JavaFX 新媒体引擎功能如何支持您的专业 Java 游戏概念和设计。您不仅需要知道 JavaFX 可以为您的游戏开发做些什么,而且所有的 API 类都是相互关联的,因此您需要了解 JavaFX 新媒体引擎的各个组件是如何组合在一起的。JavaFX 使用一组复杂的 API 来实现令人难以置信的“前端”功能,我喜欢称之为引擎。这是因为它为实现用户界面(UI)和用户体验(UX)带来了内在的力量,使您的专业 Java 游戏和物联网应用“获胜”。因此,请耐心听我解释这些“基础”章节,它们涵盖了如何掌握您的 IDE (NetBeans 9)、您的基础编程语言(Java 9)和新的媒体引擎(JavaFX 8),后者现在是一个集成的 Java 平台 API,并且在浏览器支持、功能和受欢迎程度方面都在快速增长。

在本章中,您将回顾 JavaFX QUANTUM toolkit、PRISM 渲染技术、WebKit web 引擎、GLASS windowing 技术、JavaFX 媒体引擎、JavaFX 场景图和 JavaFX API。

一旦你看到 JavaFX 是如何在最高层次上组合在一起的,就像你在 Java 9 的第五章中所做的那样,你将会看到一些你将会用来构建专业 Java 游戏的关键类。其中包括节点,以及以下内容:组、场景、舞台、布局、控制、堆栈面板、形状、几何体、媒体、图像、摄像机、效果、画布、绘画和动画。我们已经在第六章中看过 JavaFX 应用类;我们将继续学习这个类,以及可用于构建复杂多媒体项目(如游戏)的各种类。

最后,您将深入查看您在第六章中生成的引导 JavaFX 应用代码,并了解 Java。main()方法和 JavaFX。start()方法使用 Stage()构造函数方法创建 primaryStage Stage 对象,并在其中使用 scene()构造函数方法创建一个名为 Scene 的场景对象。您将看到如何使用 Stage 类中的方法来设置场景、标题舞台和展示舞台。您将学习如何创建和使用 StackPane 和 Button 类对象,以及如何向按钮添加 EventHandler。

JavaFX 概述:从场景图到操作系统

正如我在涉及新媒体的第 2 和第三章中所做的那样,我想从 JavaFX 的最高层次开始,也就是场景图。这是在图 2-1 和图 3-7 中最顶层显示的新媒体素材类型的右下一层。JavaFX API 的场景图 Java 代码也可以通过使用 Gluon 拖放式 JavaFX 场景构建器来构建,该构建器可以集成到 NetBeans 9 中,正如您在第六章中所了解的那样,也可以作为独立使用。因为这是专业 Java 9 游戏开发,我们将会看到如何“临时编码”所有这些场景结构。

如图 7-1 所示,JavaFX 场景图架构位于 JavaFX API 之上,JavaFX API 是 JavaFX 包的集合,如 javafx.scene 或 javafx.application,它最终允许您构建场景图并设计 Java FX 新媒体作品。在这种情况下,它将是一个专业的 Java 游戏。请注意,JavaFX API 不仅连接(在此图中使用钢轴承来表示桥)到它上面的场景图架构,还连接到它下面的 Java API 及其 JavaFX Quantum 工具包。如您所见,Java JDK(和 API)将 JavaFX 新媒体引擎连接到 NetBeans 9 和 JVM。JVM 允许 Java 在 Java 当前支持的各种平台以及未来(原生支持)的平台(如 Android 8 和 iOS)上分发你的 Pro Java 游戏。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-1。

JavaFX Component Architecture from Scene Graph at the top down through Java, NetBeans, JVM, and OSs

连接到 JavaFX API 的 Quantum toolkit 将我接下来要谈到的所有强大的新媒体相关引擎捆绑在一起。Quantum toolkit 处理所有这些引擎的线程管理,以便您的游戏代码(位于 JavaFX 主线程上)和游戏的新媒体素材(音频、视频、3D 矢量、2D 矢量)位于自己的线程上(A/V 使用专用线程,WebKit、窗口或 3D 渲染也是如此),可以通过双核、四核、六核和八核 CPU 上的独立线程(或进程)使用独立的处理器,这些处理器在当今的计算机和嵌入式消费电子设备中非常常见。我已经展示了新媒体引擎,它们非常重要,足以在图 7-1 的第四层中拥有自己的线程。

Glass Windowing Toolkit 控制 JavaFX 的窗口管理。它负责控制显示中的任何离散区域,如舞台或弹出窗口,如对话框。Glass 还管理事件处理队列,并将事件传递给 JavaFX 进行处理,它还设置计时器,这一点您将在本书稍后进入游戏时了解,以及 pulse 毫秒如何控制游戏的计时。

在图 7-1 中间可以看到,还有一个 WebKit 引擎和一个媒体播放器引擎。这些也由 Quantum toolkit 管理。WebKit 引擎可以呈现 HTML5、CSS3/4 和 JavaScript 内容。这意味着您可以创建在 JavaFX 游戏中无缝运行的 web 内容。媒体播放器媒体播放引擎卸载(处理)数字音频和数字视频素材的播放、UI 控制和导航。

Quantum toolkit 下面最重要的新媒体引擎是 Prism 引擎,我喜欢称之为“PRISM 游戏引擎”,因为它使用 Java2D 渲染 2D 内容,如果用户使用 Windows 7、8 或 10 平台,则使用 OpenGL (Macintosh、Linux 或嵌入式操作系统)或 DirectX 渲染 3D 内容。我在一些生产工作站上使用 Windows 7.2 和 10。Windows XP 和 Vista 支持已停止,因为大多数计算机和消费电子设备现在都支持 64 位(Windows XP 是 32 位的,只能处理 3.24 GB 的内存)。

PRISM 所做的是“桥接”主要操作系统平台以及消费电子嵌入式设备上的强大游戏引擎(DirectX 和 OpenGL),以便 JavaFX 可以将复杂的渲染任务处理从 nVidia (GeForce)、AMD(镭龙)、ARM、高通或英特尔“卸载”到 GPU 硬件。这使得 JavaFX/Java 游戏速度更快,并允许游戏使用更少的 CPU 处理能力来将游戏资源渲染到屏幕上。这反过来允许更多的 CPU 处理能力用于游戏逻辑,如人工智能或碰撞检测。在我们掌握了 JavaFX 引擎的特性及其场景图层次和架构之后,我们将在本书的下两章,JavaFX 初级读本和关于场景图设计的第八章中进入游戏设计的这些领域。

值得注意的是,游戏开发人员不需要了解 Quantum(线程)、Glass(窗口)或 Prism(渲染)引擎的内部工作原理,就可以利用它们强大的新媒体功能。在本书中,您将重点关注顶层场景图架构,以及该图的 JavaFX 和 Java API 级别。您还将涉及 NetBeans 9 IDE 级别,我们刚刚在第六章中讨论了这一级别,但是我们还将在本书的剩余部分中更详细地探讨它的特性。

就图 7-1 中图表的较低层而言,NetBeans 9.0 将为每个操作系统平台生成一个 Java 字节码文件,该文件可由定制 JVM 或 Java 9 虚拟机读取。这个 JVM,如图 7-1 底部所示,可以通过下载 Java 9 Java 运行时引擎(JRE)为任何给定的操作系统平台安装,你已经在第一章中遇到过,当你把它作为你的 Java 9 JDK 安装的一部分安装时。

这个 JVM 层允许你的游戏作为应用安装在所有流行的操作系统平台上,也可以安装在嵌入式设备上,这些设备也将支持 JavaFX。您还应该将您的 pro Java 游戏生成为一个可以嵌入到网站中的 Java“applet ”,甚至有一个部署模型,可以将应用从网站拖到桌面上,然后安装为一个完整的 Java 游戏应用。

在 iOS 8 和 Android 8 上已经有一个用于运行 JavaFX 应用的工作进程,尽管这种支持还不是“原生的”,所以 JavaFX 应用还不能直接在这些操作系统中运行。如果你对这方面的最新信息感兴趣,只需谷歌“Android 上的 JavaFX”或“iOS 上的 JavaFX”,你可以打赌,到 2018 年,Android OS、iOS、黑莓和 Tizen OS 设备将“原生”运行 JavaFX 应用。这将允许您使用这个 Java 和 JavaFX 动态组合“一次编码,随处运行”!我所说的原生是指,有一天你将能够使用 JetBrains IntelliJ 2017 Android Studio 直接将 Java(和 JavaFX engine)应用导出到 Android 8,或者导出到 iOS 或 Tizen OS,甚至可能使用 NetBeans 9 直接导出到 Android 8。这将增加 NetBeans 9 目前对 Windows、Mac、Open Solaris 和 Linux 发行版的支持。

Note

JetBrains IntelliJ IDEA 现在是用于创建 64 位 Android 8 应用的官方 IDE。这个 IDE 在我的 Android Apps for Absolute 初学者(Apress,2017)中有所涉及,其中涉及使用 Java 8 使用 IntelliJ IDEA 开发 64 位 Android 5 到 8 应用。IntelliJ 也包含在我的 Pro Android 可穿戴设备中(Apress,2015)。我预计到 2018 年底,Java 9 还将支持可穿戴设备和设备。

让我们从图 7-1 所示的图的顶部开始,看看 JavaFX 场景图和 javafx.scene 包,它使用 16 个强大而有用的 Java 类在 JavaFX API 中实现场景图。

JavaFX 场景包:16 个 Java 场景类

在我们的高级概述之后,我想做的第一件事是看看最重要的 JavaFX 包之一,javafx.scene 包。正如你在第 2 和 3 章中看到的,JavaFX 包不止一个。正如你在图 6-7 顶部看到的,你的 JavaFXGame.java 应用已经在使用四个不同的 JavaFX 包了。javafx.scene 包包含 16 个强大的 Java 类(记住 javafx 是用原生 Java 重新编码的),包括 Camera、ParallelCamera 和 PerspectiveCamera、Cursor 和 ImageCursor、LightBase、PointLight 和 AmbientLight,以及场景图形类(节点、父节点、组、场景和子场景)和一些实用程序类,如图 7-2 所示。如您所见,我已经对这 16 个 javafx.scene 包类进行了逻辑分组。我在此图的场景图部分中使用了场景类,因为使用此场景类创建的场景对象将包含使用其他四个节点、父、组和子场景场景场景图相关类及其子类创建的场景图对象。在这一章的后面,我们将会详细介绍所有这些场景图类。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-2。

The Java javafx.scene package and 16 core Scene Graph, Scene Utility, Lighting, Camera, and Cursor classes

JavaFX 的场景图架构类从最高级别的节点超类开始,连同其父类、子场景子类和父类的组子类,我们将在本书的后面使用它们来创建我们的游戏场景图层次。这些核心节点类用于创建游戏的 JavaFX 场景图形层次,并用于组织和分组使用 JavaFX 媒体素材和图形设计包创建的对象,这些包包含在 javafx.media 和 javafx.graphics Java 9 模块中。

有三个场景工具类,正如我所说的,它们允许您在任何时候拍摄场景或其任何场景图形节点的快照(如截图),以及打开或关闭场景抗锯齿,如果您在场景中使用 3D 基本体(使用数学而不是网格定义的几何体)。javafx.scene 包中的另一半(八个)类用于场景照明、场景摄影机和场景的光标控制。

在我们创建游戏时,我们将在以后的章节中讨论这些 javafx.scene 类,在此之前,我们将了解用于创建、分组、管理和操纵 javafx 场景内容的场景图形类。因此,我将覆盖 javafx.scene 包的类,如图 7-2 所示,从图的左侧移动到图的右侧,按照您可能最经常使用的类到最不经常使用的类的顺序。也就是说,所有这些类(可能除了快照)对 i3D 游戏都非常重要。

JavaFX 场景类:定义维度和背景颜色

javafx.scene 包中的两个主要类是 scene 类和 Node 类。我们将在下一节中介绍 Node 类及其父类、组类和子场景子类,因为这些类及其子类(如 JavaFXGame 类中使用的 StackPane 类)可用于在 JavaFX 中实现场景图架构。此外,在某种意义上,在我的图 7-2 和 7-3 中,节点类及其子类可以被视为在场景类的“下面”,尽管节点类不是场景类的子类。事实上,节点(场景图)类及其子类,或者更确切地说,使用这些类创建的对象,实际上包含在场景对象本身内部,就像在现实生活的舞台作品中按场景分组一样。出于这个原因,我们将首先看看如何使用 Scene 类及其 Scene()构造函数方法为 JavaFX 应用创建场景对象。这一节将为你在第五章中学到的关于重载构造函数方法的内容提供一个很好的强化,因为创建一个场景对象需要几种不同的方法。

这个场景类用于创建场景对象,使用 Scene()构造函数方法。这需要一至五个参数,取决于您选择使用六个重载构造函数方法中的哪一个。其中包括以下构造函数方法,这些方法具有六种不同的重载参数列表数据字段配置:

Scene(Parent root)
Scene(Parent root, double width, double height)
Scene(Parent root, double width, double height, boolean depthBuffer)
Scene(Parent root, double width, double height, boolean depthBuffer, SceneAntialiasing aAlias)
Scene(Parent root, double width, double height, Paint fill)
Scene(Parent root, Paint fill)

图 6-7 和第 28 行的 Java 代码中所示的当前 bootstrap Java 和 JavaFX 代码中使用的构造函数是第二个构造函数,到目前为止,它的结构(调用)如下:

Scene scene = new Scene(root, 300, 250);

如果您想给场景添加黑色背景色,您可以使用第五个使用颜色的重载构造函数方法。Color 类中的 BLACK 常量(这是一个 Paint 对象,因为 Color 是 Paint 子类)作为填充数据,在本例中是 fillColor。这可以通过使用以下 Scene()对象构造函数方法调用来完成:

Scene scene = new Scene(root, 300, 250, Color.BLACK);

请注意,根对象是一个父子类,称为 StackPane 类,它是使用 StackPane()构造函数方法创建的,在 Scene()构造函数方法调用上面两行,使用了下面一行 Java 代码:

StackPane root = new StackPane(); // StackPane subclassed from Parent; so Parent root node type

正如您所看到的,任何类都可以在构造函数中使用,只要它是为该构造函数参数位置(数据)声明(必需)的对象(类)类型的子类。这就是为什么我们能够在我们的参数列表中使用 Color 和 StackPane 对象,因为它们分别具有来自 Paint 和 Parent 类的超类起源。

如果您想知道布尔 depthBuffer 参数是什么,它用于 i3D 场景组件。由于这些场景组件是 3D 的,并且具有深度(除了 2D 的“X”和“Y”组件之外,还有一个“Z”组件),因此如果要创建 3D 场景或组合 2D 和 3D 场景组件,则需要包含此参数并将其设置为 true 值。最后,如果您想知道第四个构造函数方法的参数列表中传递的 SceneAntialiasing 对象(和类)是什么,它为 3D 场景组件提供了实时平滑。因此,对于我们将需要的 3D 场景对象,构造函数方法调用将如下所示:

Scene 3Dscene = new Scene(root, 300, 250, true, true);

JavaFX 场景图:使用父节点组织场景

Scene Graph 并不是 JavaFX 独有的,现在可以在许多新媒体内容创建软件包中看到,例如 3D、数字音频、声音设计、数字视频和特效。场景图是内容数据结构的可视化表示,类似于倒置的树,根节点在顶部,分支节点和叶节点从根节点出来。我第一次看到场景图方法进行场景设计是在我使用芬兰 RealSoft OY 的一个名为 Real3D 的 Amiga 4000 软件包进行 3D 建模、渲染和动画制作的时候。从那时起,这种方法被大量的 3D、数字视频和特效软件包复制,现在是 JavaFX 组织场景内容的方式。出于这个原因,你们中的许多人可能对这种设计范例很熟悉,因此也很适应。场景图数据结构不仅允许您构建、组织和设计 JavaFX 场景及其内容,而且如果您正确设置了场景图,它还允许您将不透明度、状态、事件处理程序、变换和特殊效果应用于场景图层次的整个逻辑分支。图 7-3 显示了一个基本的场景图树,根节点在顶部,根节点下面是分支节点和叶子节点。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-3。

JavaFX Scene Graph hierarchy, starting with the root node and progressing to branch nodes and leaf nodes

根节点是最顶端的节点,这就是为什么它被称为根,即使它在顶部,而不是在底部,就像植物生命世界中的根一样。根节点没有父节点,也就是说,在场景图形层次中,它上面没有任何东西。根节点本身是其下的分支节点和叶节点的父节点。

场景图树中第二个最强大(也是最复杂)的结构称为分支节点,它使用 javafx.scene.Parent 类作为其超类,并且可以包含子类,这是合乎逻辑的,因为它扩展了一个名为 Parent 的类。分支节点可以包含其他分支节点,以及“叶”节点,因此它可以用于创建一些非常复杂和非常强大的场景图层次结构(或场景图架构)。

层次结构中的最后一级是“叶”节点,叶节点是分支的末端。因此,叶节点可以没有子节点。重要的是要注意叶节点可以直接脱离根节点,如图 7-3 所示。可以通过使用父类、组类或子场景类来创建分支节点,如图 7-2 所示,或者使用它们的任何子类,例如 WebView、Region、Pane 或 StackPane 类。

位于分支最末端的对象(即叶节点)的示例包括 JavaFX 类(实例化为对象),这些类可以使用参数进行配置。示例包括形状、文本或控件。这些是设计或内容组件,因此没有设计任何子组件(子对象),因此根据其类函数设计的性质,它们本质上必须位于树和分支的末端。

因此,叶节点将始终包含一个 JavaFX 类,该类没有从父类或从组、区域或子场景类中子类化(扩展),并且其本身也没有被专门设计为在 JavaFX 场景图层次结构中包含任何子元素(子对象)。

父类的三个子类可以用作分支节点。这些包括用于分组子(叶节点)对象的 Group 类,以便不透明度、变换和特殊效果可以同时应用于组节点;Region 类,用于对 2D 的子对象(叶节点)进行分组以形成屏幕布局,如果您愿意,可以使用 CSS3 对其进行样式化;WebView 类,用于管理 WebEngine 类,它在 WebView 中呈现 HTML5、JS 和 CSS 内容。

JavaFX 场景内容:灯光,摄像机,光标,动作!

接下来,让我们看看图 7-2 中间列出的八个类,它们提供了一些强大的多媒体工具来控制你的应用的光标,以及为你的 2D 和 3D JavaFX 应用提供定制的灯光特效和定制的相机功能。在这种情况下,这可能是游戏,但也可能是电子书或 iTV 节目或任何需要 JavaFX 为 Java 9 APIs 提供的强大新媒体功能的物联网。

图 7-2 中间部分列出的更一般化的类(光标、光源、相机)是父类,更专门化的类(图像光标、点光源、平行相机等。)后面列出的是这些父类的子类。除了 LightBase 类,这似乎是显而易见的!

正如您可能已经猜到的(正确),JavaFX Cursor 类可用于控制在任何给定时间使用的应用光标图形(箭头、手、闭合的手、张开的手、调整大小、移动、文本、等待、无)。ImageCursor 子类可用于定义和提供基于图像的自定义光标,使用自定义光标图像中的 X 和 Y 位置来定义其“单击点”(也称为光标的“热点”)的位置。

LightBase 类及其 PointLight 和 AmbientLight 子类可用于照亮场景。这些类主要用于 3D 场景,它们需要在游戏运行的任何平台上具有 3D 功能,这在当今并不是一个真正的问题,因为大多数主要的 CPU 制造商也制造(包括)GPU。此外,值得注意的是,如果渲染游戏的硬件平台上没有 GPU,Prism 游戏引擎将使用 3D 处理模拟来模拟 3D 环境(GPU)。这被称为软件渲染。

如果设置正确,您也可以在 2D 游戏中使用这些照明类,或者在“混合”2D 和 3D 游戏中使用照明,由于 JavaFX 支持它,我们也将在本书的稍后部分研究这一点。

Camera 类及其 ParallelCamera 和 PerspectiveCamera 子类可用于拍摄或录制场景,并可用于 3D、2D 和混合游戏应用。其中两个相机类 camera 和 ParallelCamera 不要求运行 JavaFX 应用(在本例中为游戏)的平台上具备 3D (GPU)功能。在 3D 软件中,平行相机视图有时称为正交投影。

Camera 类的子类提供了两种不同的专门类型的相机。ParallelCamera 类可用于渲染场景,无需任何深度透视校正,这在 3D 行业中称为正交投影。这意味着这个类非常适合用于 2D 场景(和 2D 游戏)。

PerspectiveCamera 类提供了一个用于 3D 场景的复杂得多的相机,它将支持 3D 查看量。与 LightBase 类及其子类一样,PerspectiveCamera 类将需要运行 pro Java 9 游戏(或物联网应用)的硬件平台(称为目标平台)的 3D 功能。

PerspectiveCamera 类具有 fieldOfView 属性(state 或 property)。这可以用来改变你的观看音量,就像一个真正的相机变焦镜头可以,当你从广角放大到变焦。fieldOfView 属性的默认设置是 30 度的锐角。如果你还记得高中的几何课,你可以通过向下看相机的 y 轴(上下方向)来想象这个视野。如你所料,确实有。getFieldOfView()和。setFieldOfView(double)方法调用来控制此摄像机类属性。

接下来,让我们仔细看看场景实用程序类。在此之后,我们将进一步了解九个 javafx.scene 子包中的一些,如 javafx.scene.text、javafx.scene.image、javafx.scene.shape 和 javafx.scene.layout。

JavaFX 场景工具:场景快照和反走样

最后,我们应该快速查看一下图 7-2 右侧显示的三个实用程序类,因为它们可以用来提高用户设备屏幕上的场景输出质量(使用抗锯齿),以及为用户(社交媒体共享)或游戏逻辑提供屏幕捕捉功能。

让我们先把 SceneAntialiasing 类解决掉。你在第二章中学习了抗锯齿,我向你展示了它如何使用一种算法来平滑两种不同颜色交汇处的锯齿边缘,通常是在图像合成的对角线或圆形区域。图像合成是将两个独立的图像分层放置,形成一个合成图像。有时,这两个(或更多)图像层中的图像分量之间的不同边缘需要被平滑。平滑(反走样)是需要的,这样最终的图像合成看起来就像一个无缝的图像,这是艺术家或游戏设计师的意图。有趣的是,我们已经使用 StackPane 类(窗格是层)在 JavaFXGame 应用中实现了 JavaFX“层引擎”。“层堆栈”图像合成方法在游戏以及 Photoshop 或 GIMP 等软件中很常见。

SceneAntialiasing 类的作用是为 3D 场景提供抗锯齿处理(算法),以便它们可以在场景的 2D 背景上合成,无论这是默认颜色。白色或任何其他颜色值,2D 图像(创建混合的 2D 和 3D 应用),或任何其他东西,如数字视频。scene anialiasing 类允许您将静态 scene anialiasing 数据字段设置为 DISABLED(关闭抗锯齿)或 BALANCED(打开抗锯齿)值。平衡选项提供了质量和性能的平衡,这意味着设备硬件提供的处理能力越强,处理的抗锯齿质量越高。

接下来让我们看看 SnapshotParameters 类(object),它用于设置(包含)一个渲染属性参数,该参数将由 SnapshotResult 类(object)使用。这些参数包括将使用哪种类型的相机(平行或透视)对象,用于 3D 的 depthBuffer 是打开的(对于 3D 为 true)还是关闭的(对于 2D 为 false),用于包含结果快照图像数据的 Paint 对象,用于包含任何变换数据的 Transform 对象,以及用于定义要渲染的视口区域的 Rectangle2D 对象。这将是快照尺寸和屏幕上快照结果左上角设置的 X,Y 位置。

这个 SnapshotResult 类(更重要的是使用这个类创建的对象)包含生成的快照图像数据、请求的参数和场景图中的源节点。因此,这个类支持的三个方法是显而易见的:一个. getImage()方法将获取快照图像,一个. getSource()方法将获取源节点,一个. getSnapshotParameters()方法将获取快照参数。

场景子包:九个与场景相关的包

你可能会想“咻!javafx.scene 包概述中包含了很多内容!”事实上,核心 javafx.scene 包中有许多类,涵盖场景创建、场景图形组织和场景实用程序,如照明、相机、光标、屏幕截图(“sceneshots”)和设置实用程序。javafx.scene 包中还有很多,我称之为“子包”,它们是 javafx.scene 包下面的包,使用另一个包名(描述)的另一个点来引用。事实上,还有 9 个 javafx.scene 包,正如你在表 7-1 中看到的,它们涵盖了画布绘制、纹理绘制、特效、UI 布局、数字成像、事件处理、文本和字体、形状(2D 和 3D 几何)、2D 和 3D 变换等内容。在本章中,我们将会看到所有这些 javafx.scene 子包类和概念,并且在本书的课程中会用到它们中的许多。本章的这一节将更详细地介绍 javafx.scene 子包,您将在游戏开发中使用的许多功能都可以在这些子包中找到。这就是为什么我给你一个 JavaFX 提供的概述,以便它在一个地方完成,我们可以使用 JavaFX 9 APIs 开始 Pro Java 9 游戏编码,并使用所有这些多媒体功能来创建游戏体验。

表 7-1。

The Nine Second-Level JavaFX Scene Subpackages with Primary Function and Description of the Functional Classes

包名功能包装内容和功能描述
javafx.scene .画布直接绘图为自定义绘图图面提供 Canvas 类(和 Canvas 对象)
javafx.scene.effect特技特殊效果类:发光,混合,开花,阴影,反射,运动模糊
javafx.scene.image数字成像数字图像类:图像、图像视图、可写图像、像素格式
javafx.scene.input事件处理提供与将用户输入获取到 JavaFX 应用相关的类
javafx.scene.layoutUI 布局用户界面布局容器类:TilePane、GridPane、FlowPane 等。
javafx.scene.paint纹理(油漆)油漆类:油漆,颜色,线性梯度,径向梯度,停止,材料等。
javafx.scene.shape几何学2D 和 3D 几何类:网格,形状,Shape3D,圆,线,路径,弧等。
javafx.scene.text文本和字体提供文本呈现和字体呈现类:textFlow、Text、font 等。
javafx.scene.transform转换提供变换类:变换,仿射,旋转,缩放,剪切,平移

让我们从包含最少类的包开始,先把它们去掉。尽管该表按字母顺序列出了子包,但第一个包 javafx.scene.canvas 包含两个类:一个用于创建 canvas 对象的 Canvas 类和一个用于控制在画布上绘图的调用的 GraphicsContext 类。

下一个子包 javafx.scene.effect 包含特殊效果类。这些对于 pro Java 9 游戏开发非常有用,所以这是我将在本节中详细介绍的子包之一。

javafx.scene.image 子包用于在 javafx 中实现数字影像,它包含 imageView、Image、WritableImage、PixelFormat 和 WritablePixelFormat 类。ImageView 类是您通常用来保存数字图像素材的类,如果您想进行更高级的(算法)基于像素的数字图像创建,更高级的 PixelFormat 类允许您逐个像素地创建数字图像。

javafx.scene.input 子包包含用于从 javafx 应用的用户获取输入的类,包括鼠标和键盘输入、手势、触摸屏、滚动、缩放或滑动输入、剪贴板内容以及其他类型的输入。使用事件处理功能处理输入和动作,在本书中将会详细介绍这些功能,并且您已经在您的 Pro JavaFX 9 应用中体验过这些功能,如您的 bootstrap Java 9 代码的第 20 行到第 25 行所示(如图 6-7 )。

javafx.scene.layout 子包包含用于创建用户界面设计布局的类,也可用于您的屏幕布局设计。这些布局类包括控制和管理背景、添加边框和设置边框样式的类,并提供 UI 窗格管理类,如 StackPane、GridPane、TilePane、FlowPane 和 AnchorPane。这些 Pane 子类为 JavaFX 中的 UI 控件提供了自动屏幕布局算法。Background 类提供了屏幕背景实用程序,Border 类提供了屏幕边框实用程序,可用于为用户界面屏幕添加图形。

javafx.scene.paint 子包包含一个 Stop 类;Paint 超类和 Color、ImagePattern、LinearGradient 和 RadialGradient 子类;以及 3D Material 超类及其 PhongMaterial 子类。熟悉 3D 内容制作的人会认识这种 Phong 着色器算法,它允许不同的表面外观(塑料、橡胶等)。)待模拟。这些 Material 和 PhongMaterial 类需要 i3D 功能才能在回放硬件上成功运行,就像 SceneAntialiasing、PerspectiveCamera 和 LightBase 类和子类一样。这些都需要 GPU 硬件加速或者软件渲染。

抽象 paint 类创建绘制对象的子类,Color 类为这些对象着色(用颜色填充它们),LinearGradient 和 RadialGradient 是用颜色渐变填充对象的 Paint 子类,Stop 类允许您定义渐变颜色在渐变内部的开始和停止位置,这就是它的名称的来源。最后,还有您的 ImagePattern 类,它可以用可平铺的图像模式填充 Shape 对象,这对游戏非常有用。

javafx.scene.shape 子包包含 2D 几何(通常称为形状)和 3D 几何(通常称为网格)的类。Mesh 超类及其 TriangleMesh 子类处理 3D 几何,Shape3D 超类及其 Box、Sphere、Cylinder 和 MeshView 子类也是如此。形状超类有更多的子类(12);这些是 2D 几何元素,包括圆弧、圆、三次曲线、四次曲线、椭圆、直线、路径、多边形、折线、矩形和 SVGPath 类。还有“路径”支持,这是由 PathElement 超类及其 ArcTo、ClosePath、CubicCurveTo、HLineTo、LineTo、MoveTo、QuadCurveTo 和 VLineTo 子类提供的被定义为“开放”形状的路径(我喜欢称它为“样条线”,因为我是 3D 建模师),这些子类允许您绘制样条曲线来创建自己的自定义可缩放矢量图形(SVG)形状。

javafx.scene.text 子包包含用于将文本形状和字体渲染到场景中的类。这包括 Font 类,用于使用除 JavaFX“系统”字体之外的任何字体,还包括 Text 类,用于创建一个文本节点,该节点将使用该字体显示文本值。还有一个专门的布局容器类,称为 TextFlow,用于“流动”文本,就像你在文字处理器中看到的那样。

javafx.scene.transform 子包包含用于渲染 2D 和 3D 空间变换的类,例如 transform 超类的 Scale、Rotate、Shear、Translate 和 Affine (3D rotation)子类。这些可以应用于场景图中的任何节点对象。这允许你的场景图中的任何东西(文本,用户界面控件,形状,网格,图像,媒体等。)以您喜欢的任何方式进行转换,这为 JavaFX 游戏开发人员在转换事物时提供了大量的创造力。如果你想知道,平移是整个物体的线性运动。剪切是 2D 平面上两个不同方向的线性运动,或者是 2D 平面的另一部分固定时的一个方向的运动。想象一下,移动一个平面的顶部,而底部保持不动,那么正方形就变成了平行四边形,或者向不同的方向移动同一平面(正方形)的顶部和底部。

既然我们已经查看了 javafx.scene 包及其相关子包中大量重要且有用的类(对象),那么让我们看看其他 18 个顶级 javafx 包,了解 JavaFX 为应用开发提供的其他关键功能,当然,我们将重点关注那些可用于游戏开发的功能,这是我们在本章中一直在做的,并将在整本书中继续做的。

javafx.graphics 模块:18 个多媒体包

有 18 个顶级 javafx.graphics 模块包是最常用的包(除了核心 javafx.base 模块包)。它们遵循 javafx.packagename 名称格式(不是 javafx.graphics.packagename)。其中一些,比如 scene 和 css,也有子包级别。我们在前面的九个 javafx.scene 包及其子包中看到了这一点,所以我们在这里就不看了。javafx.graphics 模块是创建 Pro Java 9 游戏的三个关键模块之一,另外两个是 javafx.base 和 javafx.media。由于表 7-2 中包含了九个 javafx.graphics 模块包,这实质上意味着从 JavaFX API 模块的角度来看,javafx.graphics 模块总共有 18 个包类别,如表 7-1 中列出的九个。从 JavaFX 8 开始,Oracle 的 JavaFX 9 开发团队对这些模块包进行了重组,以实现更好的模块化(功能优化)。例如,如果你的 3D 游戏不需要音频或视频,你可以只使用基本和图形模块。由于我们需要音频,我们将使用基本、图形和媒体模块,或者七个 JavaFX API 模块中的三个(JavaFX API 包代码立即减少了 57%)。我想给你一个 javafx.graphics 模块包中这 18 个功能区域的概述,如表 7-1 和 7-2 所示,并仔细看看每个图形区域(矢量、光栅、动画、CSS)将做什么。

表 7-2。

javafx.graphics Module Top-Level (Nonscene) Packages, with Primary Functions and Description of Function

包名功能包装内容描述
javafx.animation动画类:动画计时器、时间轴、过渡、插值器、关键帧、键值
javafx .应用应用提供应用(初始化、启动、停止方法)、预加载程序、参数、平台
javafx.concurrent穿线提供线程类:Task、Service、ScheduledService、WorkerStateEvent
javafx.css半铸钢ˌ钢性铸铁(Cast Semi-Steel)提供与在 JavaFX 中实现级联样式表(CSS)相关的类
javafx.css.converter半铸钢ˌ钢性铸铁(Cast Semi-Steel)提供与在 JavaFX 中实现 CSS 相关的类
javafx.geometry3D 几何图形提供 3D 几何图形
javafx.print印刷提供打印
javafx.scene场景控制与场景创建、组织和控制相关的类(见表 7-1
javafx.stage舞台创作提供舞台创作

其中一些我们已经介绍过了,比如 javafx.application 包,我们在第六章中已经了解过了,还有 javafx.scene 包及其子包,我们在上一节中已经介绍过了。

表 7-2 中的第一个包是 javafx.animation 包。因为动画对 Java 游戏很重要,所以让我们在本章的下一节讨论它。我还将介绍 javafx.geometry 和 javafx.stage,因为 Java 9 游戏所需的表 7-2 中的核心包是动画、应用、几何、场景和 stage。

游戏的 JavaFX 动画:使用 javafx.animation 类

javafx.animation 包包含 animation 超类和 Timeline、AnimationTimer、Interpolator、KeyFrame 和 KeyValue 类。它还包含了 transition 超类和十个 Transition 子类,所有这些我们都将在本章的这一节中介绍,因为动画是 pro Java 9 游戏开发的一个重要设计元素。由于 JavaFX 9 API 的存在,这些动画类已经为我们编写好了,所以我们所要做的就是正确地使用这些类来为游戏添加动画。您将在这些类上花费大量时间,所以我将详细介绍每一个类,以便您了解每个类是如何工作的,哪些类可以协同工作,以及您需要哪些类来实现您自己的 Java 9 游戏逻辑解决方案。

JavaFX Animation 类:JavaFX 中动画对象的基础

Animation 类(更准确地说是 Animation 对象)为 JavaFX 中的动画提供了核心功能。Animation 类包含两个(重载的)Animation()构造函数方法。它们包括Animation()Animation(double targetFramerate),它们将在内存中创建动画对象,该对象将从包含其他子对象的高级对象中控制您的动画及其回放特征和生命周期。

动画类包含。play()方法。playFrom(cuePoint)或。playFrom(持续时间)方法和. playFromStart()方法。这些方法用于开始播放动画对象。还有就是。pause()方法可以暂停动画播放,而. stop()方法可以停止动画播放。有。jumpTo(持续时间)和。跳转到动画中预定义位置的 jumpTo(cuePoint)方法。

您可以使用 rate 属性设置动画播放速度(有些人称之为帧速率或 FPS)。cycleCount 属性(变量)允许您指定动画循环的次数,delay 属性允许您指定动画开始前的延迟时间。如果动画正在循环,此延迟属性将指定循环之间使用的延迟时间,这可用于创建一些逼真的效果。

通过将 cycleCount 属性或特性(变量)设置为不确定,然后使用 autoReverse 属性(设置为 false)可以指定无缝动画循环,或者通过为 autoReverse 属性指定 true 值可以使用 pong(来回)动画循环。如果希望动画只播放一次,而不是无限循环,也可以将 cycleCount 设置为一个数值,如 1。

有一个用于设置动画播放速率属性的. setRate()方法,一个用于设置延迟属性的. setDelay()方法,以及。setCycleCount()和。用于控制循环特性的 setCycleDuration()方法。可以想象,也有类似的。get()方法来“获取”这些动画对象变量的当前设置值(或属性、特性、参数、特征;不过,你更喜欢看你的数据领域是好的)。

使用用 ActionEvent 对象加载的 onFinished 属性,可以指定动画完成回放时要执行的动作。这将在动画到达每个循环的结尾时执行,正如您可以想象的,在专业 Java 游戏中使用这一特殊功能可以触发一些非常强大的东西。

您可以随时“轮询”只读变量(属性),以查找每个动画对象的状态、当前时间、当前速率、周期更新和总持续时间。例如,可以使用 currentTime 属性查看动画播放周期中任何时间点的播放头(帧指针)位置。

JavaFX Timeline 类:JavaFX 属性时间轴管理的动画子类

JavaFX Timeline 类是 JavaFX Animation 超类的一个子类,因此它的继承层次结构如下所示,从 Java master class Java . lang . object 开始,向下一直到 Timeline 类:

> java.lang.Object
  > javafx.animation.Animation
    > javafx.animation.Timeline

时间轴对象可用于定义一种特殊的动画对象,它由对象类型为 WritableValue 的 JavaFX 值(属性)组成。所有 JavaFX 属性的类型都是 WritableValue,所以这个类可以用来制作 JavaFX 中任何东西的动画,这意味着您可以用它来做的事情仅限于您的想象。

时间轴动画是使用 KeyFrame 对象定义的,通过前面提到的 KeyFrame 类创建。毫不奇怪,这个关键帧类允许您创建和管理位于时间轴对象内部的关键帧对象。熟悉动画的人都知道,关键帧为对象或数据值的动画中的不同点设置不同的插值数据值,以创建平滑的移动。

关键帧对象将始终由时间轴对象根据时间变量(使用 KeyFrame.time 访问)和要设置动画的属性进行处理,这些属性使用关键帧对象的值进行定义,并使用 KeyFrame.values 变量进行访问。

请务必注意,您需要在开始运行时间轴对象之前设置关键帧对象,因为您不能在正在运行的时间轴对象中更改关键帧对象。这是因为一旦启动,它就被放入系统内存。如果您想以任何方式更改正在运行的时间轴对象中的关键帧对象,请先停止时间轴对象,然后对关键帧进行更改,然后重新启动时间轴对象。这将把时间轴对象及其修改后的关键帧对象以及它们的新值重新加载到内存中。

您将在本书中使用的插值器类根据时间轴方向在时间轴对象中插入这些关键帧对象。插值是根据开始值和结束值创建中间帧或“补间”帧的过程。如果您想知道方向是如何推断的,它保存在 Animation 超类的 rate 属性和只读 currentRate 属性中,Animation 超类是扩展 Timeline 子类的一部分。

反转 rate 属性的值(即使其为负值)将反转(切换)播放方向,读取 currentRate 属性时也适用相同的原则(负值表示反向或向后)。最后,KeyValue 类(对象)用于保存每个关键帧对象中的数据值。一个关键帧对象存储多个(根据需要)KeyValue 对象,每个数据值使用一个 KeyValue 对象。

JavaFX 过渡类:用于过渡和特效应用的动画子类

JavaFX Transition 类是 JavaFX Animation 超类的子类,因此其继承层次结构如下所示,从名为 java.lang.Object 的 Java 主类开始,向下发展到 Transition 类:

> java.lang.Object
  > javafx.animation.Animation
    > javafx.animation.Transition

transition 类是一个公共抽象类,因此,它只能用于(子类化或扩展)创建 Transition 子类。事实上,已经为你创建了十个这样的子类来创建你自己的过渡特效。其中包括 SequentialTransition、FadeTransition、FillTransition、PathTransition、PauseTransition、RotateTransition、ScaleTransition、TranslateTransition、ParallelTransition 和 StrokeTransition 类。这些子类的 Java 9 类继承层次结构如下所示:

> java.lang.Object
  > javafx.animation.Animation
    > javafx.animation.Transition
      > javafx.animation.PathTransition

作为动画的子类,过渡类包含了动画的所有功能。你可能最终会直接使用这十个自定义过渡类,因为它们提供了你可能想要使用的不同类型的过渡(淡入淡出、填充、基于路径、基于笔画、旋转、缩放、移动或平移等)。).随着本书的进展,我们将学习如何使用其中的一些,所以我将继续学习 AnimationTimer 类。

JavaFX AnimationTimer 类:帧处理、纳秒和脉冲

JavaFX AnimationTimer 类不是 JavaFX Animation 超类的子类,因此它的继承层次结构如下所示;它以名为 java.lang.Object 的 Java 主类开始,以 AnimationTimer 结束:

> java.lang.Object
  > javafx.animation.AnimationTimer

这意味着 AnimationTimer 类是专门为 JavaFX 提供 AnimationTimer 功能的临时代码,它与 Animation(或 Timeline 或 Transition)类或子类没有任何关系。因此,如果您想将该类与占用 javafx.animation 包的 Animation、Interpolator、KeyFrame 和 KeyValue 类组合在一起,则该类的名称可能会有些误导。它和这些类没有任何关系!这个类允许你实现自己的动画(或游戏引擎)定时器,并自己编写代码!在 Java 8 游戏开发入门中,我展示了如何为 i2D 游戏做这件事。

这个 AnimationTimer 类也被声明为公共抽象类,就像 Transition 类一样。因为它是一个抽象类,所以只能用来(子类化或扩展)创建 AnimationTimer 子类。与 Transition 类不同,它没有为您创建的子类;您必须从头开始创建自己的 AnimationTimer 子类。

AnimationTimer 类看似简单,因为它只有一个您必须“覆盖”或替换的方法,该方法包含在公共抽象类中。handle()方法。该方法包含您希望在 JavaFX 引擎的舞台和场景处理周期的每一帧上执行的编程逻辑,它被优化为以 60 FPS(每秒 60 帧)播放,这恰好非常适合游戏。JavaFX 使用脉冲系统,该系统基于新的 Java 纳秒时间单位(Java 7 之前的版本使用毫秒)。

JavaFX 脉冲同步:JavaFX 场景图形元素的异步处理

JavaFX 脉冲是一种定时或同步事件,它同步您为 Pro Java 9 游戏或物联网应用创建的任何给定场景图结构中包含的元素的状态。JavaFX 中的脉冲系统由 Glass Windowing Toolkit 管理。Pulse 使用高分辨率(纳秒)计时器,Java 程序员也可以使用从 Java 7 开始引入的 System.nanoTime()方法来使用这些计时器。

JavaFX 中的脉冲管理系统被“封顶”或“节流”到 60 FPS。这是一种优化,因此我们前面讨论的所有 JavaFX 线程都有足够的“处理空间”来做它们需要做的事情。根据您在 pro Java 9 游戏逻辑中所做的事情,JavaFX 应用将自动生成多达三个线程。一个基本的业务应用可能只使用主要的 JavaFX 线程,但是一个 i3D 游戏也会产生 Prism 渲染线程,如果 pro Java 9 游戏也使用音频和/或视频(通常会这样),它也会产生一个媒体播放线程,如果它还实现了一个社交媒体接口或元素,它也会产生 WebKit 渲染线程。因此,正如您将看到的,健壮的 Java 9 游戏将需要仔细的处理器时间管理。

在我们的游戏开发过程中,我们将使用音频、2D、3D,可能还有视频,所以我们的 JavaFX 游戏应用肯定会是多线程的!正如您将看到的,JavaFX 被设计为能够创建具有多线程和纳秒计时功能以及 i3D PRISM 渲染硬件支持的游戏。

当场景图中发生变化时,例如 UI 控件定位、CSS 样式定义或动画正在播放,会安排一个脉冲事件,并最终“触发”该事件以同步场景图中元素的状态。JavaFX 游戏设计的诀窍是优化脉冲事件,使它们专注于游戏逻辑(动画、碰撞检测)。出于这个原因,对于 pro Java 9 游戏,您会希望最小化脉冲引擎需要处理的非 ameplay 更改(UI 控制位置、样式更改)。您将通过为静态设计系统使用场景图来实现这一点,也就是说,设计固定的视觉元素(UI、背景图像等)。)不被脉冲引擎改变。这将保存“脉冲”用于动画或互动游戏的动态元素。

我的意思是,你将使用场景图来设计你的游戏结构,但不会使用动态编程逻辑通过场景图实时操纵静态设计节点(UI、背景、装饰),因为需要使用 pulse 系统来执行这些 UI 更新,我们很可能需要这些实时处理事件来用于我们的 Pro Java 9 游戏处理。又来了:静态对动态的游戏设计。

JavaFX pulse 系统允许开发人员异步或无序地处理事件,并在纳秒级上调度任务。接下来,我们将看看如何使用. handle()方法在脉冲中调度代码。

利用 JavaFX 脉冲引擎:扩展 AnimationTimer 超类以生成脉冲事件

扩展 AnimationTimer 类是让 JavaFX pulse 引擎在其处理的每个脉冲上处理 Java 代码的一个好方法。您的实时游戏编程逻辑将放在您的。handle(long now)方法,可以通过使用另外两个 AnimationTimer 方法随意启动和停止。开始()和。停止()。

那个。开始()和。stop()方法是从 AnimationTimer 超类调用的,尽管这两个方法也可以被覆盖;只需确保最终在被覆盖的代码方法中调用 super.start()和 super.stop()。如果将它作为内部类添加到当前 JavaFX public void 中,其代码结构可能如下所示。start()方法结构(可以参考图 6-7 ,提醒一下):

public void start(Stage primaryStage) {
    Button btn = new Button;
    btn.setText("Say 'Hello World'");
    btn.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent event) {
            System.out.println("Hello World!);
        }
    }
    new AnimationTimer() {
        @Override
        public void handle(long now) {
            // Program logic that gets processed on every pulse which JavaFX processes
        }
    }.start();

            // Rest of start() method code regarding Stage and Scene objects is in here
}

前面的编程逻辑展示了如何“动态地”构造 AnimationTimer 内部类,以及 Java 点链接是如何工作的,因为对 AnimationTimer 超类的. start()方法调用被附加到新的 AnimationTimer()构造函数的末尾。在一条语句中,有 AnimationTimer 创建(new 关键字)、声明(构造函数方法)和执行(链接到 AnimationTimer 对象构造的 start()方法调用)。

如果您想为游戏逻辑的核心部分(如碰撞检测)创建一个更复杂的 AnimationTimer 实现,将游戏计时逻辑放入它自己的(自定义)AnimationTimer 子类而不是内部类中会是一个更好的方法(也就是说,一个更好的 pro Java 9 游戏设计)。如果您要创建多个 AnimationTimer 子类,以便可以实现自定义脉冲事件处理,这一点尤其正确。您可以同时运行多个 AnimationTimer 子类,但是我建议您不要忘乎所以,不要使用太多的 AnimationTimer 子类,而是优化您的 Java 代码,只使用一个。

要使用 Java extends关键字结合 AnimationTimer 超类来创建您自己的名为BoardGamePulseEngine的 AnimationTimer 类,请实现此 AnimationTimer 类定义和这些必需的 AnimationTimer 超类方法来创建您的“空”JavaFX pulse board 游戏逻辑计时引擎。

public class BoardGamePulseEngine extends AnimationTimer {
    @Override
    public void handle(long now) {   // Program logic here that gets processed on every pulse
    }
    @Override
    public void start() {
        super.start();
    }
    @Override
    public void stop() {
        super.stop();
    }
}

在我们学习了 Java 9、NetBeans 9、JavaFX 9 和 SceneGraph 的基础知识之后,我们将在本书的后面创建动画代码(第章第 8 )。本章中的代码示例只是向您展示如何实现这些 JavaFX 动画的示例。接下来,让我们来看看 JavaFX Stage 类,在这里我将向您展示一些代码,以使您的 JavaFX 环境透明,这样您的游戏就可以悬浮在操作系统桌面上,这是 Windows 中一种称为“无窗口 ActiveX 控件”的效果,它允许您创建虚拟的 i3D 对象。

JavaFX 屏幕和窗口控件:使用 javafx.stage 类

javafx.stage 包包含可被视为“顶级”的类,javafx 应用使用这些类的显示。在你的用例中,这是 pro Java 9 游戏。这个阶段是游戏的“顶层”,因为它向应用的最终用户展示了游戏的场景。在 Stage 对象中有 Scene 对象,在这些对象中有 SceneGraph 节点对象,它们包含组成 Java 9 游戏或 Java 9 IoT 应用的元素。因此,JavaFX Stage 对象是您将在 Java 9 游戏中使用的最高级对象。

另一方面,从操作系统的角度来看,这个包中的类可以被认为是提供低级服务的。这些选项包括 Stage、Screen、Window、WindowEvent、PopupWindow、Popup、DirectoryChooser 和 FileChooser,以及 FileChooser。ExtensionFilter 嵌套类。这些类将用于连接设备显示硬件、操作系统窗口管理、文件管理和目录(文件夹)管理功能。这是因为 Stage 类(对象)向 OS 请求这些功能,而不是使用 Java 或 JavaFX APIs 来实际实现它们,所以 OS 实际上是在您的 Java 9 游戏或 Java 9 IoT 应用请求 OS 提供这些 OS 前端实用程序时产生这些服务。

如果您想获得运行 JavaFX 应用的硬件设备所使用的显示硬件的描述,您将需要使用 Screen 类。该类通过提供一个. getScreens()方法来支持多屏幕(第二个屏幕是常见的行业术语)方案,该方法可以访问 ObservableList 对象(一个允许侦听器跟踪发生的更改的列表对象),该对象将包含一个包含所有当前可用屏幕的列表数组。有一个“主”屏幕,可以使用。getPrimary()方法调用。您可以通过使用. getDpi()方法调用来获取当前屏幕硬件的物理分辨率。也有。getBounds()和。getVisualBounds()方法调用可用的分辨率。

JavaFX 最终用户可以使用 Window 超类及其 Stage 和 PopupWindow 子类与您的应用进行交互。这是使用名为 primaryStage 的 Stage 对象完成的,该对象被传递到。start()方法(见图 5-2 )或使用弹出窗口(对话框、工具提示、上下文菜单、通知等)。)子类,如 Popup 或 PopupControl 对象。

您可以使用 Stage 类在 JavaFX 应用编程逻辑中创建辅助阶段。主 Stage 对象始终由 JavaFX 平台使用公共 void start(Stage primaryStage)方法调用来构造(正如您已经在 NetBeans 9 创建的引导 JavaFX 9 应用的第六章中看到的)。所有 JavaFX Stage 对象都必须使用主 JavaFX 应用线程来构造,并在其中进行修改,这一点我在前面讨论脉冲事件处理时已经讨论过。由于阶段相当于运行它的操作系统平台上的一个窗口,因此某些属性是只读的,需要在操作系统级别进行控制。这些是布尔属性(变量),它们包括 alwaysOnTop、全屏、图标化和最大化。

所有 Stage 对象都有一个 StageStyle 属性和一个 Modality 属性,可以使用常量进行设置。stageStyle 常量包括 StageStyle。装饰,舞台风格。无装饰,舞台风格。透明,舞台风格。统一的舞台风格。实用常数。设备常量包括设备。无,模态。应用模态和模态。WINDOW_MODAL 常量。在我们讨论完 javafx.stage 包之后,在下一节中,我将向您展示如何使用这个 StageStyle 属性和透明常数来做一些真正令人印象深刻的事情,这些属性和常数将使您的基于 javafx 的 Java 9 游戏和物联网应用与市场上的其他应用区别开来。

Popup 类可用于从头开始创建自定义弹出通知,甚至自定义游戏组件。或者,您可以使用 PopupControl 类及其 ContextMenu 和 Tooltip 子类来提供预定义的(即针对您自己的实现预编码的)JavaFX 图形用户界面(GUI)控件。

DirectoryChooser 和 FileChooser 类支持将标准 OS 文件选择和目录导航对话框传递到 JavaFX 应用中。文件选择器。ExtensionFilter 嵌套类提供了一个实用程序,用于根据文件类型(文件扩展名)过滤将出现在 FileChooser 对话框中的文件。

接下来,让我们将您当前的 JavaFXGame 应用的 Stage 对象提升一个层次,并向您展示如何使您的 Java 9 (JavaFX 9)游戏成为无窗口(浮动)应用!这是 JavaFX 9 众多令人印象深刻的特性之一,您可以在您的 Pro Java 9 游戏开发管道中加以利用。

使用 JavaFX Stage 对象:创建浮动的无窗口应用

让我们将 JavaFXGame 应用的 primaryStage Stage 对象(由我们的.start(Stage primaryStage)方法构造函数创建)设置为透明的,这样 HelloWorld 按钮(UI 控件)就可以浮动在您的操作系统桌面上(或者在本例中,浮动在 NetBeans 9 的顶部)。这是 JavaFX 可以做的事情,你很少看到利用,它将允许你创建 i3D 游戏,看起来“浮动”在你的用户的操作系统桌面上。对于 i3D 虚拟对象,至少在 Windows 7、8 和 10 操作系统上,这将被称为“无窗口 ActiveX 控件”移除窗口“chrome”或装饰在其他高级操作系统(如 Linux 和 Mac)中也应该得到支持,并且有一个程序调用来确定这种“使用 alpha 通道(透明)移除除我的内容之外的所有内容”功能是否到位,因此您可以实现纯色或背景图像的后备计划。这个很酷的小技巧(我想我会在书的开头向你展示一些很酷很强大的东西)部分是通过使用 StageStyle 实现的。透明常数,您刚刚了解了它与。Stage 类中的 initStyle()方法。StageStyle 是一个“helper”类,填充了 stage(或 OS 窗口,最终)装饰常数,其中一个是透明的。我们将使用的后备是未修饰的(一个正常的操作系统窗口)。

添加 StageStyle 常量:使用。initStyle(StageStyle style)方法调用

如图 7-4 所示,我在 Java 9 代码中添加了新的第 26 行(用浅蓝色突出显示),并键入 primaryStage 阶段对象名;然后我点击句点键,将一个 Java 点链插入到我想要使用的方法中。此时,NetBeans 9 将打开一个弹出的方法选择器帮助器对话框(实际上更像是一个选择器 UI);寻找。initStyle(StageStyle style)方法,如图 7-4 所示。单击该方法会以蓝色选中它,双击它会将其插入到您的代码中。接下来,我们将对方法的参数做同样的事情,使用相同的工作过程,允许(或诱使)NetBeans 9 为您进行 Java 编码工作。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-4。

Call an .initStyle() method off of the primaryStage Stage object, using dot notation to invoke a helper menu

正如您在图 7-4 中看到的,我在 NetBeans 9 helper 中单击了 initStyle(StageStyle style)选项,这将在您正在编写的代码行上方显示一个 Javadoc 窗口,其中包含有关该方法的文档。您可以使用这种方法来了解一个对象支持哪些方法,方法是键入对象名,按句点键,然后选择每个方法来查看它的作用。

如图 7-5 所示,Stage 对象是使用.start(Stage primaryStage)方法调用声明创建的,并使用。setTitle(),。initStyle(),。setScene(),最后是。中的 show()方法调用。start()方法结构。

现在,我将在 Java 9 代码中保留一个. setTitle()方法调用,但是请记住,一旦这个无窗口的应用处理开始工作,这个标题就是窗口 chrome(标题栏 UI 元素)的一部分。一旦这些都消失了(包括标题栏),标题属性的设置将成为一个争论点。

如果您在应用开发工作流程的这个阶段关注内存优化,那么您应该删除它。setTitle()方法调用,因为 Title 属性会占用内存空间,而且由于使用了 StageStyle,甚至看不到它。StageStyle(实际上是窗口样式)属性的透明常数。

在里面。initStyle()方法类型,键入所需的 StageStyle 类(对象)和句点,以调出下一个帮助器选择器。这次是常量选择器,如图 7-5 所示。选择透明选项,读取上面的 Javadoc 信息,然后双击它以完成代码语句,该语句应如下所示:

primaryStage.initStyle(StageStyle.TRANSPARENT); // Insert StageStyle Class TRANSPARENT Constant

正如您在 Javadoc 信息弹出窗口的图 7-5 中所看到的,将自动为要取消装饰的透明窗口(舞台)装饰样式编码一个回退(降级)方法。它的特点是背景颜色为白色,并且仍然移除了标准的操作系统窗口镶边(标题栏、最小化、最大化、关闭、调整大小等)。).接下来,让我们测试我们的代码,看看按钮现在是否悬浮在它后面的任何东西上(在这种情况下,这是 NetBeans)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-5。

Type StageStyle and a period in the method parameter area to pop up a constant selector NetBeans helper

接下来使用运行图标(或运行菜单)并运行应用。正如您在图 7-6 中看到的,我们试图实现的并没有成功,窗口的 chrome 元素消失了,但是透明度值并不明显。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-6。

Run Project to see if the Stage object is transparent; clearly there is an object set to off-white background color

正如您所看到的,有一个灰白色值(用于 iTV set 应用,因为一些 iTV set 不支持 255,255,255 白色)与 NetBeans 9 用于其代码编辑器窗格的 255,255,255 白色形成鲜明对比。

在您的处理管道中,一定还有其他东西尚未使用透明度值定义您的舞台背景。透明度使用十六进制值 0x00000000 来定义,这表示所有 aarggbb(Alpha、红色、绿色、蓝色)透明度和颜色值都被关闭。您需要开始将应用中的 JavaFX 组件视为层(目前有 Stage、Scene、StackPane、Button)。

在本书的第二章中,您学习了数字成像概念,如色深、alpha 通道、图层、混合、抖动,以及所有与处理 2D 平面中的像素相关的有趣技术信息。

接下来,我们应该尝试设置这个透明值的是从 Stage 开始的 JavaFX 场景图层次中的下一级,它包含场景图本身。下一个最顶层的组件,正如你在本章中学到的,是场景对象,它也有一个背景颜色值参数或属性。

因此,下一步是尝试使用十六进制值 0x00000000 或 Java 9 Color 类常量将该属性设置为零不透明度和颜色,这将实现完全相同的目标。

您的场景类(对象)不像 Stage 类(对象)那样具有透明的样式常量,因此您必须使用不同的方法和常量,以不同的方式将场景对象的背景设置为透明值。您应该意识到的一件事是,JavaFX 中所有将自身写入屏幕的东西都会以某种方式支持透明性。这允许 JavaFX 应用中的多层合成。

如果您查看 Scene 类文档,您会注意到有一个. setFill(颜色值)方法接受一个颜色(类或对象)值,所以接下来让我们尝试一下。如图 7-7 所示,我调用了。使用一个scene.setFill();方法从名为 Scene 的场景对象中设置 Fill()方法,NetBeans 让我从下拉帮助器中选择该方法。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-7。

Add a new line of code and type in the scene’s Scene object and a period to invoke a method helper selector

选择并双击.setFill(Paint value)方法,然后在参数区域键入 Java 9 颜色类名(颜色是 Paint 的子类)。接下来,键入句点,调出 Java 9 Color helper 类中包含的常数,如图 7-8 所示,找到并选择一个透明常数。正如您在 Javadoc 帮助器窗格中看到的,ARGB 颜色值是期望的#00000000。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-8。

Type the Color class name and period in the parameter area, and find and select a TRANSPARENT constant

再次运行应用,查看透明度是否显示出来。如图 7-9 所示,它仍然不透明。由于我们使用 StackPane 对象来实现 BoardGame 应用中的层,这是我们需要尝试设置透明度值的下一个级别。JavaFX 使用 Color 类常量来确定其所有 UI 对象的默认背景颜色值。如果我是 JavaFX 9 团队的一员,我会主张将它改为彩色。透明常数,但当然,这可能会让新用户感到困惑,因为 alpha 通道和合成层是高级概念和主题,这就是为什么它们在本 pro Java 9 游戏开发书的第二章的开头,涵盖了数字图像合成和相关概念。请注意,在图 7-9 中,NetBeans 已经为您导入了 Java Color 类,因为您在scene.setFill(Color.TRANSPARENT); Java 语句中使用了它。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-9。

Set the Scene object fill color to TRANSPARENT, and notice that NetBeans codes a Color class import statement

javafx.scene.layout.StackPane 类是 javafx.scene.layout.Region 类的子类,该类有一个. setBackground()方法来设置背景(类或对象)值。同样,必须有一个透明的值常量可用,或类似的东西,如背景。空,因为您需要始终将背景值设置为透明,特别是对于 pro Java 9 游戏设计,您需要灵活性来实现高级 2D 和 3D 合成和渲染管道。这种对透明性的支持也适用于 Android UI 容器。

有趣的是,事情并不总是像我们在 Java 编程中希望的那样简单和一致,因为我们已经使用了三个不同的方法调用,传递了三个自定义对象类型,到目前为止,实现了完全相同的最终结果(为设计元素安装了透明的背景色/图像板):。initStyle(StageStyle 对象)。setFill(颜色对象),以及。setBackground(背景对象)。这一次,您将使用另一个名为 EMPTY 的背景类(对象)常量来调用. setBackground(背景值)方法。

一旦使用root.setBackground(Background.EMPTY); Java 语句调用名为 root 的 StackPane 对象的方法,NetBeans 9 将帮助您找到常数。这一次更容易作为背景。空常数恰好是。setBackground()方法调用。如果您想查看所有后台助手类常量,请键入 root.setBackground(Background。进入 NetBeans 9,并查看出现在“常量”弹出帮助器选择器窗格中的结果。

如图 7-10 所示,NetBeans 9 提供了一个方法选择器下拉菜单,一旦您选择并双击。setBackground(背景值)方法,NetBeans 9 将为您编写代码语句,自动插入默认的空常量,该常量使用点标记法从背景类中调用。正如您将在红色的图 7-11 中看到的,NetBeans 还会在 Java 类的顶部编写后台类的导入语句。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-11。

The transparency now goes through all objects (layers), and the button is now rendered on the OS directly

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-10。

Add a line of code after the root StackPane object, type root and a period, and select setBackground()

现在,您可以通过运行项目工作流程(通过“运行”菜单或 NetBeans IDE 左上角的绿色 play transport 图标)再次测试您的无窗口(透明)JavaFX 应用版本。

正如您在图 7-11 中所看到的,我们现在已经实现了我们的目标,在 NetBeans IDE Java 代码编辑窗格的顶部只显示了按钮对象,这是正在运行的 Java 代码窗口下的下一个应用。下面是操作系统桌面。

您还可以看到 NetBeans 添加了您的后台类导入语句以及九行 StackPane (root)和 Scene (scene)对象 Java 9 代码,我们添加这些代码是为了使最终结果出现在图 7-11 的第 25 至 33 行中。一定要理解这些物体的创造过程,以及它们是如何相互链接,或者“连接”的,正如我喜欢称之为的那样,成为不可阻挡的功能交织。理解 Java 9 编程语句的顺序几乎和 Java 9 语句本身的构造一样重要。

例如,在编写第 25 行代码之前,不能编写第 28 行代码,在第 25 行中,实例化了根 StackPane 对象,这样就可以用它来创建场景的 scene 对象。

我在 NetBeans 9 中单击了根对象,以告诉 IDE 向我显示该对象在类中的用法,正如您将在图 7-11 中看到的,在 Java 9 代码中使用黄色突出显示跟踪该对象。随着你的 pro Java 9 游戏代码变得越来越复杂,这个很酷的特性变得越来越重要。正如我在第六章中提到的,我们将在本书的许多章节中讨论方便的 NetBeans 9 特性。

最后一个测试是确保我们的 JavaFX 应用在操作系统桌面上是透明的。将 NetBeans 9 IDE 拖到一边,并在桌面背景图像的顶部看到您的按钮 UI 元素,您可以在图 7-12 中看到它现在工作正常。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-12。

The JavaFX application seamlessly composited on top of the Windows 7 OS desktop’s wallpaper

您还可以看到代码工作时的折叠和展开图标(代码左侧的加号和减号图标)。我已经关闭(折叠)了。start()方法并打开了。main()方法。单击减号将关闭。main()方法,单击加号图标将打开导入语句和。start()方法代码体。

我关闭了 import 语句块。start()方法代码块向您展示了该类的五个主要区域:javafxgame 包声明、导入语句块、JavaFXGame 应用子类声明以及任何 JavaFX 9 游戏(或 IoT)应用所需的两个主要方法,它们是。开始()和。main()。

使用 2D、3D 和 alpha 通道,可以使用这种 StageStyle 创建一些非常酷的应用。透明功能,所以我想我应该在本书的早期向您展示这一点,以便我可以在 JavaFX“概述”一章中获得一些关于增强您的 JavaFX IoT 应用和 pro Java games 编码体验的很酷的技巧和提示。定义一个游戏或 i3D 虚拟物体,让它悬浮在操作系统桌面上,这是一种罕见的视觉冲击效果。

现在,我们已经从回顾与 pro Java 9 游戏开发最直接相关的所有 JavaFX 9 APIs 中获得了一个有趣的编码休息,让我们回到您可能想要了解的关于交互性、UI 设计、图表、音频或视频媒体素材以及关于与互联网和社交媒体平台的接口的其他 JavaFX 模块、包和类产品。我们还将简要介绍一些您不会使用的 API!

现在我们已经看了 javafx.stage 包,接下来让我们看看 javafx.geometry 包。

JavaFX 边界和尺寸:使用 javafx.geometry 类

尽管术语“几何”在技术上适用于 2D 和 3D 素材,但它们包含在 javafx.scene.shape 包中,我们在本章前面已经介绍过。javafx.geometry 包更像是一个“实用程序”包,包含从头开始构建 2D 或 3D 构造的基础类。因此,该包包含 Bounds 超类及其 BoundingBox 子类等类,以及 Insets、Point2D、Point3D、Dimension2D 和 Rectangle2D 几何内容创建实用程序类。这个 javafx.geometry 包中的所有这些类,除了 BoundingBox 类,都是直接从 java.lang.Object master 类扩展而来的,这意味着它们都是为提供点(也称为顶点)、矩形、尺寸、边界和插入(内部边界)而开发的(从头开始编码),用作 Java 9 游戏的几何实用程序。

Point2D 和 Point3D 类(最终是对象)分别保存 2D 平面上 2D 点的 X,Y 坐标,或者 3D 空间中 3D 点的 X,Y,Z 坐标。这些点对象最终将用于构建更复杂的 2D 或 3D 结构,由点的集合组成,如 2D 路径或 3D 网格。Point2D 和 Point3D 构造函数方法调用没有重载,它们分别使用以下标准格式:

Point2D(double X, double Y)

Point3D(double X, double Y, double Z)

Rectangle2D 类(对象)可用于定义一个矩形 2D 区域,通常称为“平面”,并且在图形编程中有许多用途,正如您所想象的那样。

Rectangle2D 对象在矩形的左上角有一个起点,使用 X 和 Y 坐标位置以及尺寸(宽乘高)来指定。Rectangle2D 对象的构造函数方法具有以下标准格式,并且未被重载:

Rectangle2D(double minX, double minY, double width, double height)

还有一个 Dimension2D 类(object ),它只指定宽度和高度维度,并不使用 X,Y 位置在屏幕上放置维度(这会使它成为一个矩形)。其构造方法如下:

Dimension2D(double width, double height)

Insets 类(object)类似于 Dimension2D 类,因为它不提供插入的位置值,但提供基于上、下、左、右偏移距离的矩形插入区域的偏移。Insets 方法实际上是重载的,因此您可以使用以下代码指定等距插入或自定义插入:

Insets(double topRightBottomLeft)

Insets(double top, double right, double bottom, double left)

Bounds 类是一个公共抽象类,永远不会是一个对象,而是一个创建节点边界类的蓝图,比如它的 BoundingBox 子类。Bounds 超类也允许一个负值,用来表示一个边界区域是空的(可以认为它是空的,或者未使用的)。BoundingBox 类使用以下(重载)构造函数方法创建 2D(第一个构造函数)或 3D(第二个构造函数)BoundingBox 对象:

BoundingBox(double minX, double minY, double width, double height)

BoundingBox(double minX, double minY, double minZ, double width, double height, double depth)

接下来,让我们看看 JavaFX 中的事件和动作事件处理,因为这为您的游戏增加了交互性。

游戏的 JavaFX 输入控件:使用 javafx.event 类

由于游戏本质上是交互式的,接下来让我们看看 javafx.event 包,因为它为我们提供了事件超类及其 ActionEvent 子类,用于处理动作事件,例如 UI 元素使用或动画关键帧处理事件使用。因为您将在 pro Java 9 游戏(或物联网应用)中使用 ActionEvent,所以我将在这里查看它的跨包(Java 到 JavaFX)类继承层次结构,因为这也将向您展示 JavaFX Event 类的起源。这是可能的,因为 JavaFX API 是 Java API 的一部分(在 Java API 之下)。

Java.lang.Object
  > java.util.EventObject
    > javafx.event.Event

      > javafx.event.ActionEvent

JavaFXGame 应用已经通过 EventHandler 接口及其。handle()方法,您将实现该方法来告诉 Java 应用如何处理该事件,该事件一旦发生就是一个 ActionEvent(编程术语被触发)。这个。然后,handle()方法“捕捉”被触发的事件,并根据这个“主体”内部的 Java 9 编程逻辑对其进行处理。handle()方法。

正如你从第五章中所知道的,Java 接口是一种提供空方法的类型,这些方法被声明使用,但是还不包含任何 Java 构造。未实现的方法在使用时需要由 Java 程序员来实现。这个 Java 接口只定义了需要实现哪些方法;在这种情况下,它是一个“处理”ActionEvent 的方法,以便以某种方式处理该事件。

值得注意的是,Java 接口定义了一个需要编码的方法,但并没有为您编写方法代码,因此它是一个“路线图”,指示您必须做些什么来完成现有的编程结构,或者与现有的编程结构进行交互。在这种情况下,这是一个用于处理 ActionEvent 对象的 Java 编程结构,或者更准确地说,是一个用于在 action event 被触发后处理它们的编程结构。

与本 JavaFX 新媒体引擎概述章节中涵盖的所有内容一样,在应用这些 JavaFX 9 编程结构、JavaFX 场景图构造和新媒体素材设计概念的过程中,您将很快深入了解如何使用这些包、类、嵌套类、接口、方法、常量和数据字段(变量)的细节。

JavaFX UI 元素:使用 javafx.scene.control 类

javafx.scene.control 包和 javafx.scene.chart 包在 javafx.controls 模块中,我们接下来将介绍这两个包。这个包包含了所有的用户界面控件(在 Android 中它们被称为“widgets”,我喜欢称它们为 UI“elements”)类,比如 Alert、Button、Cell、CheckBox、ChoiceDialog、ContextMenu、control、DatePicker、ColorPicker、Label、ProgressBar、Slider、Label、RadioButton、ScrollBar 和 TextField。由于 javafx.scene.control 中有 100 多个类,我甚至不打算在这里一一介绍,因为关于这个 Java 9 模块可以写一整本书。如果您想回顾这些类,只需使用 Google 或在 Oracle Java 网站上参考 javafx.control 模块,您就可以连续几天仔细阅读这些类的功能。对于这个模块,“reference”是一个关键词,因为当你需要实现一个给定的 UI 元素时,你需要单独地引用这个包和它的类。我将尝试使用我自己的 3D UI 元素和代码来创建本书中的 i3D 游戏,这样我就不必在发行版中包含这个 javafx.controls 模块,从而节省了在发行版中包含 100 多个控件类(更不用说十几个图表类)的开销,这些控件类甚至都没有被利用。

JavaFX 业务图表:使用 javafx.scene.chart 类

javafx.scene.chart 包位于具有预定义 UI 控件(UI 元素)的 javafx.controls 模块中。这个包包含了业务图表类,比如 Chart、ScatterChart、StackedAreaChart、XYChart、PieChart、LineChart、BarChart、StackedBarChart、AreaChart、BubbleChart 等等,用于业务应用,这是完全不同的一本书,所以在本书中我们不会涉及图表。事实上,对于我的游戏,我将使用 3D UI 方法,这将意味着我根本不需要包括 javafx.controls 模块(大量的类),这意味着我的游戏模块将只需要包括 javafx.base、javafx.media 和 javafx.graphics,使发行版的下载量大大减少(base 只有 10 个包,media 有 9 个,而 graphics 有 18 个,正如您在本章中所看到的)。

JavaFX 媒体控件:使用 javafx.scene.media 类

javafx.scene.media 包包含在 javafx.media 模块中,其中包含用于播放音频和视频媒体资源的类,包括 media、MediaPlayer 和 MediaView 类,以及 AudioClip、AudioEqualizer、EqualizerBand、Track、VideoTrack 和 SubtitleTrack 类。媒体类(或对象)引用或包含音频或视频媒体素材,MediaPlayer 播放该素材,MediaView(尤其是在视频的情况下)显示数字音频或视频媒体素材以及用于媒体回放的传输。

我们将在本书稍后为您的 pro Java 9 游戏添加数字音频音效时使用 AudioClip 类,只要我们使用该模块的数字音频部分,如果我们必须将它包含在您的应用(模块)发行版中,我们也可以利用数字视频素材(视频类)功能。

JavaFX Web 渲染:使用 javafx.scene.web 类

javafx.scene.web 包包含在 javafx.web 模块中,其中包含用于在场景中渲染 web (Internet)资源的类。这个包包含一组类,包括 WebEngine、WebView、WebEvent、WebHistory 和 HTMLEditor。正如您可能想象的那样,WebEngine 类(嘿,有人称这些算法为引擎)执行在 JavaFX 场景中显示 HTML5、CSS3、CSS4 和 JavaScript 的处理,WebView 创建节点以在 JavaFX 场景图中显示 WebEngine 输出。WebHistory 类(最终是对象)保存从 web 引擎实例化到从内存中删除的互联网“会话”,这是访问过的网页的历史,而 WebEvent 类将 JavaScript web 事件处理与 JavaFX 9 事件处理“连接”起来。我们不会将 javafx.web 模块用于我们将在本书的课程中创建的 i3D 游戏,因为我将重点关注可用于提供视觉上最专业的 i3D 游戏效果的核心 API。

其他 JavaFX 包:Print、FXML、Beans 和 Swing

在阅读完 JavaFX 概述章节之前,您应该仔细看看其他几个 JavaFX 包,因为这些包包含您可能希望在专业 Java 游戏开发中使用的类,但它们提供了更专业的功能,如打印、使用第三方 Java 代码、使用 AWT 和 Swing 等较旧的 UI 范例,以及使用 XML(特别是 FXML)将 UI 设计卸载给非程序员。这些 API 包括 javafx.print 包(javafx.graphics 模块)、javafx.fxml 包(javafx.fxml 模块)、javafx.beans 包(javafx.base 模块)和 javafx.embed.swing 包(javafx.swing 模块)。除非您的项目有特殊的需求,否则您不太可能在您的 Java 游戏设计和开发工作过程中使用这些。其中最明显的是 javafx.print,用于允许打印机与您的 pro Java 9 游戏一起工作。如果您需要使用旧的 Swing UI 元素,有一个 javafx.swing 模块可以实现这一点,但会给 Java 9 游戏发行版增加更大的数据量。javafx.beans 包将允许您使用 Java Beans(第三方或附加类),javafx.fxml 模块将允许您使用 Java Fxml,这种 XML 语言允许用户界面和图形设计卸载到 XML,而不是 Java 编码。这使得不熟悉 Java 的设计者也可以参与游戏项目。Android 操作系统和 Android Studio IDE 也使用这种方法,它们使用 XML 来完成许多顶级设计任务,因此设计人员不必是程序员。

摘要

在第七章中,您了解了 JavaFX 9 API 中一些最重要的包、概念、组件、类、构造函数、常量和变量(属性、参数、数据字段)。这是一个令人印象深刻的包含 36 个包的 7 个 Java 9 模块的集合,我使用表格简洁地概述了其中的许多模块,然后逐一介绍了它们。我这样做是因为本章中概述的大多数(如果不是全部)包和类最终会以某种方式用于新媒体、2D、3D 和混合 2D+3D pro Java 9 游戏开发。当我说全面概述时,我的意思是让我们看看在 Java 9 下使用 JavaFX 9 开发游戏所需的一切。

当然,我无法在一章中涵盖 JavaFX 9 API 中的每个功能类,所以我首先概述了图 7-1 中的 JavaFX API 新媒体引擎,以及它如何与上面的 JavaFX 场景图以及这些 API 下面的 Java FX API、NetBeans 9 和目标操作系统集成。您的 Java 9 游戏发行版和操作系统是通过 Java 虚拟机(JVM)连接起来的。这为 JavaFX 提供了跨众多流行平台和消费电子设备的扩展操作系统支持,从智能手机到平板电脑到 iTV 电视机,以及所有基于流行 WebKit 引擎的主流 web 浏览器(Chrome、Firefox 和 Opera)。

通过查看构成 JavaFX 引擎的结构,包括 JavaFX 场景图、JavaFX APIs、Quantum、Prism、Glass、WebKit 和媒体播放器引擎,您对 JavaFX 有了一个高层次的技术了解。您了解了这些多线程、渲染、窗口、媒体和 web 引擎是如何与 Java 9 APIs 和 JDK 以及 NetBeans 9 及其生成的 JVM 字节码进行交互的,NetBeans 9 及其生成的 JVM 字节码受当前运行在从 96 英寸 UHD iTV 电视机到 4 英寸智能手机等十几种不同消费电子设备类型之上的各种操作系统平台的支持。

我讲述了 JavaFX 的核心概念,例如使用 JavaFX 场景图和 JavaFX 脉冲事件系统,我们将在本书的整个过程中利用它们来创建一个 pro Java 9 游戏,从下一章开始,我们将开始设计游戏,并讲述如何使用 JavaFX 场景图来开发处理层次结构。

我深入研究了一些用于 pro Java 9 游戏设计的关键 JavaFX 包、子包和类,如应用、场景、形状、效果、布局、控制、媒体、图像、舞台、动画、几何、事件、fxml 和 web,以及它们相关的 Java 9 模块、包、子包、类和子类。在某些情况下,我甚至讨论了它们的接口、嵌套(助手)类和数据常量。

您在这篇 JavaFX 9 API 评论中休息了一下,向 JavaFXGame 应用添加了一些代码,使它成为一个“无窗口”的应用,能够“漂浮”在任何流行的 OS 桌面上。您了解了如何通过使用十六进制设置为 0x00000000 的 alpha 通道或使用表示 100% alpha 透明度的等效常数(如 Color)来使 Stage、Scene 和 StackPane 对象的背景属性透明。透明,舞台风格。TRANSPARENT,或者 Background.EMPTY .你也看到了 Group (Node)类和 object 本来就有一个透明的背景;当您将场景图形的顶级节点从堆栈面板更改为组(更好的顶级节点)时,根本不需要设置组背景透明度。

我不得不在本章中使用 NetBeans 9 IDE、Java 9 编程语言和 JavaFX 9 API 进行一些工作,这样我们就可以开始逐渐添加越来越多的代码,直到(很快)剩余的章节完全编码,因为所有这些基础材料,包括新媒体素材设计、API、IDE、游戏概念、JVM、UI、UX、3D 渲染引擎、2D 回放引擎、WebKit、静态与动态、游戏优化等等。 已经在你们的头脑中牢牢地就位,因为在本书的整个过程中,你们需要建立在这些先进知识的基础上。

在下一章中,您将看到 JavaFX 9 场景图。您将开始构建您在本章中学到的场景图形结构,并开始构建游戏的基础,包括用于启动游戏的按钮元素的 UI“面板”。我还会解释你的游戏规则,显示高分,给出制作学分,并包括法律免责声明。我知道您急于开始构建您的 pro Java 9 游戏基础设施,您将在下一章开始认真地做这件事,创建自定义方法并使用 JavaFX APIs 添加新的 Java 代码,开始为您的 JavaFXGame 类创建顶层。实际上,通过学习如何在 JavaFX 9 场景图形层(应用到场景到组到堆栈面板到 VBox 到按钮)内部(并通过它们)实现透明性,您在本章中已经开始做了一些工作。

八、JavaFX 9 场景图层次结构:Java 9 游戏设计的基础

让我们从用户界面和用户体验的角度,以及“引擎盖下”游戏引擎、3D 精灵引擎、碰撞引擎和物理引擎的角度,开始设计我们的 i3D JavaFXGame 游戏的基础设施,从而建立我们在第八章的前几章中学到的 JavaFX、游戏设计、多媒体和 Java 的新知识。我们将牢记优化,正如我们在本书剩余部分必须做的那样,这样我们就不会得到一个如此广泛或复杂的场景图,以至于脉冲系统无法有效地更新一切。这意味着将主游戏 UI 屏幕(StackPane 节点)保持在最少(四个或五个),以便将大部分处理能力留给 3D 游戏渲染(组节点),并确保媒体播放器(数字音频或数字视频)使用自己的线程,如果使用这种类型的媒体的话。(音频(尤其是视频)数据量非常大,可能需要大量处理。)你还需要确保驱动游戏的功能“引擎”都是模块化和逻辑编码的,使用它们自己的类,并利用你在第五章学到的适当的 Java 编程约定、结构、方法、变量、常量和修饰语。这将是一项艰巨的任务,从本章开始,将需要数百页才能完成,现在我已经确保你们都掌握了 Java、JavaFX、NetBeans、2D 和 3D 新媒体概念的知识。

我要介绍的第一件事是顶级的、正面的用户界面屏幕设计,这是你的游戏在启动 Java 应用时提供给用户的。这将包括用户在启动应用时看到的棋盘游戏“品牌”闪屏。该屏幕的一侧有按钮控件,用于访问包含说明、致谢、法律免责声明等信息的屏幕。这些 UI 屏幕是 StackPane 节点层,我们希望尽量减少它们的数量。StackPane 对象旨在包含堆叠的图像(合成)层。这些游戏支持屏幕将包含用户为了有效地玩游戏而需要知道的信息。这包括基于文本的信息,如游戏说明、演职员表、法律免责声明和高分屏幕。我们将包括法律免责声明,以使法律部门满意,并将突出强调致力于创建游戏和游戏素材的程序员和新媒体工匠的贡献。

在本章中,我们将概念化的棋盘游戏设计基础的下一个层次是游戏引擎组件 Java 类设计方面。这些将不会被游戏用户看到,但仍然非常重要。它们可能包括一个使用 JavaFX pulse 控制游戏更新的游戏引擎,一个管理游戏 3D 游戏精灵的 3D 精灵引擎,一个在两个精灵之间发生任何碰撞时进行检测和响应的碰撞引擎,一个将力和类似物理模拟应用于游戏的物理引擎,以便 3D 精灵加速和真实反弹,最后是一个 3D 演员引擎,它将管理为 JavaFXGame 游戏实例化的单个演员的特征。您将修改现有的JavaFXGame.java类来实现一个 UI,用按钮控件访问提供顶级用户界面游戏信息特性所需的功能信息屏幕。您将了解几个用于组织和定位的新 JavaFX 类,包括 Group、VBox、Insets 和 Pos 类。

游戏设计基础:主要功能屏幕

你要为你的游戏设计的第一件事是顶级的,或者说是最高级别的用户界面屏幕,你的游戏用户将会与它交互。这定义了用户第一次打开你的游戏时的用户体验。这些屏幕将使用您的 JavaFXGame Splash(品牌)屏幕访问,包含在主要 JavaFXGame.java 类代码中。正如您已经看到的,此 Java 代码将扩展 javafx.application.Application 类,并将启动应用,显示一个闪屏,以及查看说明、玩游戏、查看高分或查看游戏法律免责声明和游戏创作者(程序员、艺术家、作家、作曲家、声音设计师等)的选项。).图 8-1 显示了游戏的高层图,从顶部的功能 UI 屏幕开始,向下发展到 JavaFXGame.java 代码,然后到 API、JVM 和 OS 级别。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-1。

JavaFXGame functional screens and how they’ll be implemented in Java 9 and JavaFX 9 by using the JVM

这将需要您向 StackPane 布局容器父分支节点添加另外四个按钮节点,并最终(在第九章)添加一个 ImageView 节点作为闪屏图像容器。这个 ImageView 节点必须添加到 StackPane“背板”中,以便成为 StackPane 中的第一个子节点(z-order=0),因为 ImageView 包含我所说的闪屏 UI 设计的背景板。因为它在背景中,所以图像需要在按钮 UI 控件节点(SceneGraph)元素之后,这些元素的 z 顺序值为 1 到 5。

这意味着最初您将只使用八个 JavaFX SceneGraph 节点对象:一个父根组节点、第二个 StackPane 布局“分支”节点和 VBox UI 容器节点中的五个“叶”按钮控件节点来创建您的 JavaFXGame(功能)信息屏幕。您的说明、法律免责声明和信用屏幕将利用 TextFlow 和 ImageView 节点,因此在第九章之后,我们将有十个节点对象。你可以使用 VBox 节点来包含 UI 按钮,我们将在本章中把游戏 UI 导航基础设施放到你的游戏应用中。这是在我们考虑添加一个组“分支”节点,以及在它下面的分支和叶节点对象来包含 3D 游戏画面之前。当然,这是您希望 Java 游戏获得最佳脉冲更新性能的地方。

如果你仔细想想,这真的没有那么糟糕,因为这些 UI 屏幕都是静态的,不需要更新。也就是说,包含在这些节点对象中的 UI 元素是固定的,不需要使用 pulse 系统进行任何更新,因此您应该还有 JavaFX pulse 引擎 99%的能力来处理我们将在本书中编写的 JavaFXGame 游戏引擎。你总是需要知道你要求 pulse 引擎处理多少 SceneGraph 节点对象,因为如果这个数字变得太大,它将开始影响游戏的 i3D 性能。如果 i3D 游戏性能受到影响,游戏将不会流畅,这将影响你的用户体验(UX)。我们保持静态的节点对象越多,每个脉冲上需要处理的就越少。

Java 类结构设计:游戏引擎支持

接下来让我们看看 JavaFXGame 代码需要如何“在引擎盖下”组装的功能结构。这将使用您的 Java 9 游戏编程代码来完成,我们将在本书中创建这些代码。正面 UI 屏幕的外观和你的底层编程逻辑的外观之间真的没有关联,因为你的游戏的大部分编程代码总是致力于在游戏屏幕上创造游戏体验。游戏说明、法律和信用屏幕将只是复合在背景图像(保存在 ImageView 对象中)上的文本(保存在 TextFlow 对象中)。记分牌和高分屏幕将需要更多一点的编程逻辑,我们将在本书的结尾进行,因为游戏逻辑需要为评分引擎创建(和播放)并能够生成高分。

图 8-2 显示了 JavaFXGame 完成所需的主要功能游戏组件。该图显示了层次结构顶部的一个JavaFXGame.java应用子类。这将在 JavaFXGame 应用的下面或内部创建顶级 JavaFXGame 场景对象及其包含的 SceneGraph。这些功能区域既可以实现为方法,也可以实现为类。在本书中,我们使用方法实现了一个 i3D 游戏。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-2。

Primary game engine functions, representing Java methods that you will need to code for your game

在 JavaFXGame 场景对象(在 JavaFXGame.java 应用子类中创建)的下面,是功能性 Java 9 类的更广泛的结构设计,您将需要在本书的剩余部分中对其进行编码。这些引擎(类),如图 8-2 所示,将创建你的游戏功能,如游戏引擎(游戏处理循环)、逻辑引擎(游戏逻辑)、精灵引擎(3D 几何管理)、演员引擎(角色的属性)、分数引擎(游戏分数逻辑)、渲染引擎(实时渲染)、碰撞检测、物理模拟。您将需要创建所有这些 Java 方法,以便为 i3D 棋盘游戏实现一个全面的游戏引擎。

游戏引擎类,我称之为 GamePulse.java,是创建 AnimationTimer 对象的主要类,该对象基于不断触发游戏循环的脉冲事件在高级别处理游戏逻辑。如您所知,该循环将调用 handle()方法,该方法又包含最终访问您将创建的其他类的方法调用,这些类用于管理 3D 几何图形(sprite 引擎)、在屏幕上移动 3D 对象(actor 引擎)、检测碰撞(碰撞引擎)、在检测到所有碰撞后应用游戏逻辑(逻辑引擎),以及应用物理力来为您的游戏提供逼真的效果,如摩擦、重力和风(物理引擎)。在本书的剩余部分,你将构建一些引擎,这些引擎将用于为你的玩家创造游戏体验。我们将根据每个引擎和它们需要处理的内容对章节主题进行逻辑分层,因此从学习和编码的角度来看,一切都是逻辑结构化的。

JavaFX 场景图设计:最小化 UI 节点

最小化场景图的技巧是使用尽可能少的节点来实现一个完整的 UI 设计,正如你在图 8-3 中看到的,我已经用一个组根节点对象、一个 StackPane 布局“分支”节点对象、一个 VBox 分支节点对象和八个叶(子)节点(一个 TableView、一个 ImageView、一个 TextFlow 和五个按钮 UI 控件)完成了这个。正如您将看到的,当我们接下来开始编码场景图时,我将只使用 12 个对象并只导入 12 个类来实现我们在上一节中设计的 JavaFXGame 类的整个顶级 UI。TableView 和 TextFlow 对象将覆盖在 ImageView 对象之上,ImageView 对象包含 UI 设计的背景图像。这个 TableView 对象将在本书的后面添加,并将使用来自评分引擎的代码进行更新,如图 8-2 所示,您将在未来的章节中对其进行编码。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-3。

Game Scene Graph Node hierarchy, objects that Nodes contain, and new media assets they reference

ImageView 背板将包含 BoardGame 插图,如果需要,您可以使用 ImageView 容器来保存不同的数字图像素材。这样,基于您的 ActionEvent 对象,处理按钮控件上的单击,您可以为每个信息屏幕使用不同的背景图像素材。VBox 父 UI 布局容器将控制五个按钮控件的布局(间距)。还有一个 Inset 对象,您将创建它来保存 UI 按钮填充值,以微调按钮对象相对于彼此的对齐方式。

由于按钮对象不能单独定位,我不得不使用 VBox 类和 Insets 类来专业地包含和定位按钮控件。在本章中,我们将讨论您将用来创建这个高级设计的类,以便您对要添加到 JavaFXGame 中的每个类有一个概述,以便为您的 JavaFXGame.java 应用子类创建这个顶级 UI 设计。

我们为需要匹配五个不同按钮的五个不同屏幕优化您的场景图形使用的方法是使用一个 ImageView 作为背板来包含游戏启动时的 BoardGame 闪屏插图。当用户单击您的 UI 按钮时,您可以使用 Java 代码让 ImageView 使用一个 ImageView 场景图节点对象引用不同的图像。您的 TextFlow 对象将覆盖 ImageView 上的文本资源。

最后,可能有一个 SceneGraph 节点,它将包含高分表的数据结构。这将通过一个分数引擎来创建,我们将在以后讨论游戏分数方法和技术时创建这个引擎。现在,我们将留下分数和游戏代码未实现。接下来让我们看看一些新的 JavaFX UI 设计类。

JavaFX 设计:使用 VBox、Pos、Insets 和 Group

在深入编码之前,让我们深入了解一些新的 JavaFX 类,我们将利用它们来完成这些顶级游戏应用 UI 和 SceneGraph 设计。其中包括 Pos 类(定位)、Insets 类(填充)、VBox 类(垂直 UI 布局容器)和 Group 类(场景图形节点分组)。在下一章中,我们将介绍 Image(图像素材持有者)、ImageView(图像背板显示)和 TextFlow(文本数据显示)类。我们将按照从最简单(Pos)到最复杂(Group)的顺序来看这些,然后您将对您的 bootstrap JavaFX 项目代码进行相当广泛的更改,这将把这些新的类(和对象)添加到您的 JavaFX 场景图层次结构中,并重新组织它以更好地适应您的游戏。

JavaFX Pos 类:使用常量的通用定位

Pos 类是 Enum 类,是 enumeration 的简称。它包含一个常量列表,这些常量实际上被转换成整数值,以便在您的代码中使用。常量值使程序员更容易在他们的代码中使用这些值。在这种情况下,它将定位常量前缀,例如顶部、中心或基线。

Pos 类的 Java 类扩展层次结构从 java.lang.Object 主类开始,经过 java.lang.Enum 类,以 javafx.geometry.Pos 类结束。您引用了图 8-10 中代码第 56 行的 Pos。Pos 位于 javafx.geometry 包中,使用下面的子类层次结构:

java.lang.Object
  > java.lang.Enum<Pos>
    > javafx.geometry.Pos

正如您将在下一节中看到的,您必须使用 Insets 类和对象来获得您想要的像素精确定位。因为这是一个 Enum 类,所以除了 Pos 类为您提供的用于 Java 游戏中的广义和相对定位的常量之外,本节没有太多要学习的。

因此,Pos 类非常适合一般的定位,使用上、下、左、右以及基线(主要用于相对于字体的定位)。其中的每一个都有一个居中选项,所以通过使用这个 helper 类中提供的十几个常量,您可以实现您需要的任何类型的通用定位。

对于一般位置的示例,请参考您的网站设计经验,您可以设计一个网页,以便它可以缩放以适应不同的窗口大小和形状。这与像素精确定位有很大不同,在像素精确定位中,从固定屏幕尺寸和形状的位置 0,0 开始,将元素精确地放置在您想要的位置!

游戏设计通常使用像素精确定位,但在本章中,我将向您展示如何将一组 UI 按钮定位在一般位置(例如用户屏幕的右上角或左下角),以便您可以尽可能多地使用 JavaFX API 实用程序类(这个类在 javafx.geometry 包中)。

你将使用 TOP_RIGHT 常量,如图 8-10 中的第 56 行所示,将你的按钮控制库定位在你的棋盘游戏用户界面设计的右上角,远离主要的中央 3D 视图。

Pos 类提供了一组常量,我将在表 8-1 中总结这些常量,用于提供“通用的”水平和垂直定位和对齐。

表 8-1。

The Pos Class Enum Constants That Can Be Used for Positioning and Alignment in JavaFX

Pos 类常数总体定位结果
基线 _ 中心将对象垂直放置在基线上,水平放置在中心
基线 _ 左侧将对象垂直放置在基线上,水平放置在左边
基线 _ 右侧将对象垂直放置在基线上,水平放置在右侧
底部中心将对象垂直放置在底部,水平放置在中央
左下角将对象垂直放置在底部,水平放置在左侧
右下将对象垂直放置在底部,水平放置在右侧
中心将对象垂直放置在中心,水平放置在中心
中央 _ 左侧将对象垂直放置在中央,水平放置在左侧
中间 _ 右侧将对象垂直放置在中央,水平放置在右侧
顶部 _ 中间将对象垂直放置在顶部,水平放置在中间
左上角将对象垂直放置在顶部,水平放置在左侧
右上方将对象垂直放置在顶部,水平放置在右侧

Pos 类提供广义定位;它可以与 Insets 类结合使用,以提供更精确的像素定位。接下来让我们看看 Insets 类,因为它也在 javafx.geometry 包中。

JavaFX Insets 类:为用户界面提供填充值

insets 类是一个公共类,它直接扩展了 java.lang.Object 主类,这意味着 Insets 类是“临时编码”的,以在矩形区域内提供 Insets 或 offsets。想象一个相框,在它的外面和里面的图片之间留有一个“无光泽”或吸引人的边框。这就是 Insets 类用两个构造函数方法做的事情;一个提供相等或均匀的插入,一个提供不相等或不均匀的插入。

我们将使用提供不相等的插入值的构造函数,如果我们正在构造一幅图片,这会看起来非常不专业!Insets 类的 Java 类层次结构从 java.lang.Object 主类开始,并使用该类创建 javafx.geometry.Insets 类。正如你将在本章后面的图 8-11 的代码行 58 中看到的,Insets 类被设置为在两边提供 0 个像素,在两边提供 10 个像素。这会将按钮组从用户显示屏的角落推开。JavaFX Insets 类包含在 javafx.scene.geometry 包中,就像 Pos 类一样,并使用以下 Java 9 类层次结构:

java.lang.Object
  > javafx.scene.geometry.Insets

Insets 类提供了一组四个双偏移值,指定矩形的上、右、下和左侧,并且应该在构造函数方法中按该顺序指定,正如您在编写代码时看到的那样。您将使用这个 Insets 类(对象)来“微调位置”您的按钮控件组,您将使用 VBox 布局容器(您将在下一节中学习)来创建它。将这些 Insets 对象视为在另一个框内绘制一个框的方法,这显示了您希望矩形内的对象围绕其边缘“尊重”的间距。这通常被称为填充,尤其是在 Android Studio 和 HTML5 编程中。

用于创建 Insets 对象的最简单的 Insets()构造函数将使用以下格式:

Insets(double topRightBottomLeft)

此构造函数对所有间距边使用单个值(topRightBottomLeft),重载的构造函数允许您分别指定每个值,如下所示:

Insets(double top, double right, double bottom, double left)

这些值需要按此顺序指定。记住这一点的一个好方法是想象一个模拟时钟。这个钟的顶部有 12,右侧有 3,底部有 6,左侧有 9。因此,只需记住从正午开始指定顺时针方向(对于西方电影类型的爱好者来说),当使用“不均匀值”构造方法时,您将有一个很好的方法来记住如何指定 Insets 值。

您正在使用 Insets 类来定位您的按钮控件库,它最初会“卡”在 BoardGame 用户界面设计的左下角。Insets 对象将允许您使用这四个 Insets 参数中的两个,将按钮控件推离屏幕的右侧和 VBox 的顶部。

JavaFX VBox 类:为您的设计使用布局容器

因为按钮对象不容易定位,所以我将把这五个按钮对象放入 javafx.scene.layout 包中的一个布局容器中,该包名为 VBox,代表垂直框。这个公共类将事物排列成一列,由于您希望按钮在 BoardGame 的边上对齐,所以它是您将用于五个按钮控件节点的父节点,这些节点将成为这个 VBox 分支节点的子叶节点。这将创建一个 UI 按钮控件的“银行”,可以作为 UI 和闪屏设计的一个单元一起定位(移动)。

VBox 类是一个公共类,它直接扩展 javafx.scene.layout.Pane 超类,后者又扩展 javafx.scene.layout.Region 超类,后者扩展 javafx.scene.parent 超类,后者扩展 javafx.scene.Node 超类,后者扩展 java.lang.Object 主类。正如你在第 55 行看到的,在图 8-10 中,你将使用 VBox 作为按钮控件定位用户界面布局容器。这个 VBox 类包含在 javafx.scene.layout 包中,就像 StackPane 类一样,它使用以下 Java 类层次结构:

java.lang.Object
  > javafx.scene.Node
    > javafx.scene.Parent
      > javafx.scene.layout.Region
        > javafx.scene.layout.Pane
          > javafx.scene.layout.VBox

如果 VBox 指定了边框或填充值,则 VBox 布局容器内的内容将“遵守”该边框和填充规范。填充值是使用 Insets 类指定的,我们在前面已经介绍过,您将在这个微调的用户界面控件按钮库应用中使用它。

您正在使用 VBox 类(object ),以及 Pos 类常量和 Insets 类(object ),以便将您的 UI 按钮对象组合在一起,并在以后将其微调为按钮控件库。因此,这个 VBox 布局容器将成为 UI 按钮控件(或叶节点)的父节点(以及分支节点)。

可以将 VBox 对象想象成一种使用列将子对象垂直排列在一起的方式。这可能是您的图像素材,排列在彼此的顶部,将使用基本的 VBox 构造函数(零像素间距)或 UI 控件,如按钮排列在彼此的顶部,间隔开,使用一个重载的构造函数。

创建 VBox 对象的最简单的构造函数将使用下面的空构造函数方法调用:

VBox()

您将用于创建 VBox 对象的重载构造函数将有一个间距值,用于在 VBox 内的子按钮对象之间留出一些空间。它使用以下构造函数方法调用格式:

VBox(double spacing)

还有另外两种重载构造函数方法调用格式。这将允许您在构造函数方法调用本身内部指定子节点对象(在我们的例子中,这些是按钮对象),如下所示:

VBox(double spacing, Nodes... children)  

此构造函数将在节点对象数组之间指定零像素的间距值:

VBox(Nodes... children)

我们将使用“简短形式”。getChildren()。addAll()方法链向您展示这是如何做到的,但我们也可以通过使用以下构造函数来声明我们的 VBox 及其按钮节点对象:

VBox uiContainer = new VBox(10, gameButton, helpButton, scoreButton, legalButton, creditButton);

如果子对象设置为可调整大小,VBox 布局容器将根据不同的屏幕大小、纵横比和物理分辨率来控制子元素的大小调整。如果 VBox 区域将容纳子对象的首选宽度,它们将被设置为该值。有一个 boolean fillWidth 属性(property),它被设置为 true 作为其默认值。这指定子对象是否应该填充(放大)VBox 宽度值。

VBox 的对齐方式由 alignment 属性(属性或变量)控制,该属性默认为 Pos 类(Pos)中的 TOP_LEFT 常量。TOP_LEFT)。如果 VBox fillWidth 属性为 false,并且 VBox 的大小超过其指定的宽度,则子对象使用其首选宽度值,多余的空间将无法利用。fillWidth 的默认设置为 true,子级宽度将被调整以适合 VBox 宽度。请务必注意,VBox UI 布局引擎将对托管子元素进行布局,而不考虑它们的可见性属性(也称为属性、特征或对象变量)设置。

你还会注意到,我们在这一章中添加的类本来就有透明或空的背景(我称之为背板),所以我们不必像在第七章中那样做任何额外的工作来保持 alpha。

现在我们已经花了几页讨论了 javafx.scene.layout 和 javafx.geometry 包中的一些类,您将使用它们来创建您的 UI(按钮对象库)设计,让我们仔细看看 javafx.scene 包中与 SceneGraph 分组相关的类。这些类将允许我们实现高级的 SceneGraph 层次结构,您需要将该层次结构放置在 VBox UI 布局容器对象中的五个 JavaFX 按钮控件 UI 元素(对象)旁边,VBox UI 布局容器对象位于 StackPane UI 层合成对象的内部。当我们在本书稍后进入 3D 和 i3D 时,这个组(节点)容器对象将保存你的 i3D 游戏对象层次。

JavaFX Group 类:高级场景图节点分组

Group 类是一个公共类,它直接扩展 javafx.scene.Parent 超类,后者扩展 javafx.scene.Node 类,后者扩展 java.lang.Object master 类。因此,组对象是 JavaFX 场景图中的一种父(分支)节点对象,用于对其他分支和叶节点对象进行分组。Group 类使用以下 Java 类继承层次结构:

java.lang.Object
  > javafx.scene.Node
    > javafx.scene.Parent
      > javafx.scene.Group

组父节点对象包含子节点对象的可观察列表,每当呈现该组父节点对象时,将按预定顺序呈现该列表。组节点对象将采用其子节点的集合(汇总)界限;但是,它不能直接调整大小。应用到组的任何变换、效果或状态都将应用到(传递到)该组节点的所有子节点,但不会应用到组本身。

这意味着这些应用的变换和效果将不包括在组父节点的布局边界中;但是,如果变换和效果是直接在该组内的子节点对象上设置的,则它们将包含在该组的布局边界中。因此,要影响组父节点的布局界限,您将通过转换组 ObservableList 的成员,而不是通过转换组对象本身,从内到外进行操作。

默认情况下,在布局过程中,组父节点将自动缩放其托管子对象集,使其大小可调整为首选大小。这确保了区域或控件子对象将随着其状态的改变而适当地缩放。如果应用需要禁用这种自动调整大小的行为,那么它应该将 autoSizeChildren 设置为 false。重要的是要注意,如果任何子对象的首选大小属性被更改,它们不会自动调整大小,因为 autoSizeChildren 已被设置为 false。这个Group()构造函数将创建一个空组。

Group()

重载的Group(Collection<Node>)构造函数方法将使用下面的构造函数方法构造一个由 Java 集合<节点>组成的组,该组包含给定的节点对象子对象的 Java 集合:

Group(Collection<Node> children)

第二个重载的Group(Node…)构造函数方法将构造一个由子节点对象的 Java 列表组成的组,在构造函数方法参数区域内构造为逗号分隔的列表。这可以通过使用以下构造函数方法格式来实现:

Group(Node... children)

既然您已经对本章中使用的各种类有了一个概述,那么让我们回到组织 JavaFXGame 类的代码上来,这样它就符合我们对游戏 SceneGraph 所做的事情。

场景图代码:优化 JavaFXGame 类

我知道您渴望开发 JavaFXGame 类代码,所以让我们清理、组织和优化现有的 Java 9 代码,以实现如图 8-3 所示的大部分顶级用户界面和场景图设计,以便您在本章创建顶级 Java 9 游戏框架的过程中取得一些进展。您要做的第一件事是将所有对象声明和命名语句放在 JavaFXGame 类的顶部,在导入块和 Java 类声明之后。这些对象声明将出现在所有方法之前。许多程序员习惯于在代码的顶部声明全局变量,也可以用同样的方式在 Java 代码的顶部声明一个空的对象声明。这种方法更有条理,这个类中的所有方法都能够“看到”(访问或引用)这些对象,而不需要使用任何 Java 修饰关键字。这是因为对象声明位于 JavaFXGame 类的顶部,而不在该类包含的任何方法内部,所以以这种方式完成的所有声明对于在它们“下面”声明的所有方法都是“可见的”。如图 8-4 所示,我正在添加一个新的组对象,我将其命名为 root,因为它将成为新的场景图根。注意 Group 下的红色波浪下划线错误,因为没有 import 语句告诉 Java 9 您想要使用 Group 类。使用 Alt+Enter 组合键弹出 NetBeans helper 弹出窗口,选择为 javafx.scene.Group 添加导入选项,如图 8-4 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-4。

Declare the scene Scene object and the root Group object at the top of the JavaFXGame class before .start()

正如你所看到的,我还将你现有的场景场景对象的声明移到了类的顶部,所以,代替Scene scene = new Scene();,我们现在有了下面的场景对象声明 Java 代码结构,如图 8-5 所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-5。

Organize the .start() method by creating createBoardGameNodes() and addNodesToSceneGraph() methods

public class JavaFXGame extends Application {
    Scene scene;
    public void start(Stage primaryStage) {
        scene = new Scene(root, 300, 250);
    }
}

接下来,我们将对 StackPane 对象做同样的事情,我将把它重命名为 uiLayout,因为根对象现在是一个组节点类对象。添加 StackPane uiLayout 声明,如图 8-5 所示,然后将图 8-5 中红框所示的 Java 代码改为使用 uiLayout 名称代替根名称,如下:

uiLayout = new StackPane;
uiLayout.setBackground(Background.EMPTY);
uiLayout.getChildren().add(btn);

我将 uiLayout StackPane 代码放在场景实例化之前。我们将移动对象实例化,除了 Stage 对象(它需要成为。start()方法),变成自己的。createBoardGameNodes()方法,之后我们在 JavaFXGame.java 类的顶部创建了对象声明和命名块。

请记住,如果您通过在类的顶部使用类名来声明任何对象,并且该对象下面出现红色波浪下划线,您只需使用 Alt+Enter 击键组合并选择 import Java FX . package name . class name 选项,就可以让 NetBeans 为您编写导入语句。

正如您在图 8-4 中看到的,在弹出的帮助器对话框中通常有不止一个可能的导入语句,因此请确保从 JavaFX API 中选择类,因为这是我们将用于富媒体、物联网和游戏开发的类;Java 9 APIs 中所有的多媒体制作特性都保存在那里。

在我们新的顶级 Group SceneGraph 节点子类中,还有 java.security.acl.Group 类和第二个 Java FX . swing . Group layout . Group helper 类。因为我们在这里没有使用 Swing UI 元素(Java 5)和 ACL 安全性,所以我们知道要选择的正确导入语句是 javafx.scene.Group 选项。

JavaFX 对象声明:方法的全局类访问

让我们添加 JavaFX 对象声明和我们已经讨论过的新类的名称,以及在下一章设计游戏的 UI 视觉效果和闪屏元素时需要的 ImageView 和 TextFlow 对象。添加一个名为 uiContainer 的 VBox 对象(按钮对齐)、一个名为 uiPadding 的 Insets 对象、一个名为 boardGameBackPlate 的 ImageView 对象、一个名为 infoOverlay 的 TextFlow 对象以及五个名为 splashScreen、helpLayer、legalLayer、creditLayer 和 scoreLayer 的 Image 对象。向名为 helpButton、legalButton、creditButton 和 scoreButton 的按钮声明中再添加四个按钮对象,并将引导代码生成的 btn 按钮对象改为名为 gameButton。在下面的 Java 9 代码中,以及在图 8-6 中,您可以看到九行声明代码块,其中一些将是具有一个类名和多个对象名的复合声明(例如下面的 Image 和 Button,很快,我们还将有多个名为 root 和 gameBoard 的组对象):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-6。

Declare five new object types at the top of the JavaFXGame class and rename the btn object gameButton

Scene scene;
Group root;
StackPane uiLayout;
VBox uiContainer;
Insets uiPadding;
ImageView boardGameBackPlate;
TextFlow infoOverlay;
Image splashScreen, helpLayer, legalLayer, creditLayer, scoreLayer;     //  Compound Declaration
Button gameButton, helpButton, legalButton, creditButton, scoreButton; // a Compound Declaration

正如您在图 8-6 中看到的红色轮廓,NetBeans 将为您编写五个新的导入语句,只要您在 JavaFXGame 类的顶部键入这些对象声明和命名语句时按 Alt+Enter。

正如你看到的用黄色突出显示的,我已经将 bootstrap btn 按钮重命名为 gameButton,并将它的.setText("Hello World")更改为.setText("Start Game"),以更直接地反映这个按钮 UI 元素最终将完成什么,因为我们在本书的整个过程中会继续完善这个 Java 9 类代码。

我还将uiLayout.getChildren().add(btn);改为uiLayout.getChildren().add(gameButton);,以反映这个类中当前影响这个按钮对象的所有 Java 9 代码的名称变化。所有这些都在图 8-6 中用红色方框、蓝色线条选择和黄色对象参考选择突出显示。

只要您使用 Alt+Enter 组合键,NetBeans 9 就会为您编写这五个新的导入语句。确保选择具有正确 javafx 包类路径的选项。接下来,让我们优化您的。start()方法,卸载游戏对象实例化(Stage 除外,它是您的.onCreate(Stage primaryStage)方法的一部分),以便所有非 Stage 对象创建都使用.createBoardGameNodes()方法完成。

场景图设计:优化棋盘游戏。start()方法

现在我们可以优化。start()方法,这样它使用的代码不到十几行(如果你想向前看,请参见图 8-16 )。我想做的第一件事是将场景图节点创建 Java 构造模块化到它们自己的 createBoardGameNodes()方法中,该方法将在。start()方法,如图 8-7 所示。在方法的顶部添加一行代码,键入createBoardGameNodes();,使用 Alt+Enter 组合键让 NetBeans 9 在类的底部为您创建这个方法基础结构。此外,确保添加了root = new Group();对象实例化,因为您重命名了 StackPane 对象 uiLayout(如图 8-5 所示)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-7。

Add a createBoardGameNodes() method call at the top of the .start() method and add root = new Group()

剪切并粘贴当前在。start()方法(您将在稍后添加到此)到 createBoardGameNodes()方法中,以替换 bootstrap 方法中的“尚不支持”错误代码行,如图 8-8 所示(选中)。新的。完成这个 Java 9 代码重新配置操作后,createBoardGameNodes()方法应该如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-8。

Select all non-Stage and non-event-handling code in the start() method and cut and paste it in new method

private void createBoardGameNodes() {
    root = new Group();
    scene = new Scene(root, 640, 400);
    scene.setFill(Color.TRANSPARENT);
    gameButton = new Button();
    gameButton.setText("Start Game");
    uiLayout = new StackPane();
    uiLayout.setBackground(Background.EMPTY);
    uiLayout.getChildren().add(gameButton);
}

请注意,我们将所有内容都从。start()方法,它不需要被“托管”在那里。因为 primaryStage Stage 对象是由。start()方法参数,我们将把所有 primaryStage 对象引用留在该方法中,以及所有事件处理结构,它们需要在应用启动时放置到位。其他的都将放在 createBoardGameNodes()和另一个 addNodesToSceneGraph()方法中,我们将在本章后面创建该方法来保存. getChildren.add()或。getChildren()。addAll()方法调用。

所以在。start()方法,我们将首先调用 createBoardGameNodes()来创建所有的 SceneGraph 节点对象(即 Node、Parent 或 Group 的所有子类),然后调用 addNodesToSceneGraph()方法来使用。getChildren()。add()方法链或。getChildren()。addAll()方法调用链。这种组织方法允许我们在构建 Java 9 游戏时向场景图中添加新节点。

接下来,让我们创建第二个 addNodesToSceneGraph()方法,我们可以用它来组织、重新配置和扩展 JavaFX 游戏应用开发工作流程的 SceneGraph 节点构建部分。

添加场景图节点:addNodesToSceneGraph()

接下来,您需要创建一个方法,将我们已经创建的 SceneGraph 节点对象以及我们将要使用 VBox 构造函数实例化的节点对象添加到场景图形根对象中,在本例中,它现在是一个组对象。这个新的更高级别的 SceneGraph 根组对象将保存您的高级游戏功能的 StackPane UI 面板,以及我们将创建的用于保存 SceneGraph 的 3D 游戏分支的另一个组对象。在某种意义上,我们已经在使用 JavaFX 9 来创建一个混合应用,因为游戏 UI (StackPane)分支将是 2D,而游戏本身(组)将是 3D 的。我们将使用。getChildren()。add()方法链或。getChildren()。addAll()方法链,用于将“子”节点(节点、父节点或组的子类)对象添加到名为 root 的“父”组对象,该对象现在是 JavaFX 场景图的“根”。

为了创建第二个方法,我们将遵循与创建第一个定制方法相同的工作流程。在第createBoardGameNodes();行代码后立即添加一行代码,然后键入 addNodesToSceneGraph();作为第二行代码。

NetBeans 9 用红色波浪错误下划线突出显示后,使用 Alt+Enter 组合键并选择创建方法“addNodesToSceneGraph”到 javafxgame。JavaFXGame 选项,如图 8-9 突出显示。我还用红色突出显示了当前在 createBoardGameNodes()方法体中的一个语句,它将被重新定位到这个新的 addNodesToSceneGraph()方法体中。这将替换原有的throw new UnsupportedOperationException() Java 语句,NetBeans 将该语句放入所有新创建的引导程序方法中,这些方法是使用这个特定的工作过程创建的,在这个过程中,您可以让 NetBeans 为您编写新的方法代码。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-9。

After creating addNodesToSceneGraph() method, copy the uiLayout.getChildren() method chain to new method

剪切 uiLayout.getrChildren()。添加(game button);语句,并将其粘贴到占位符上,抛出新的 UnsupportedOperationException()代码行,替换该代码。一旦我们在下一节实例化了这些新节点,我们将使用这个方法向场景图添加更多的节点。

向 createBoardGameNodes()添加新的 UI 场景图形节点

让我们将本章前面所学的那些新的 UI 设计和定位 JavaFX 类对象(VBox、Pos、Insets)添加到 JavaFXGame 类和我们创建的 createBoardGameNodes()方法中,该方法包含我们的 JavaFX 9 场景图节点对象创建(和配置)Java 9 语句。

使用以下 Java 对象实例化代码创建一个名为 uiContainer 的新 VBox,该代码将 Java new 关键字与 VBox()构造函数方法结合使用:

uiContainer = new VBox();  // Create a Vertical Box UI element container named "uiContainer"

设置 VBox 与位置的对齐。方法从 Pos 助手类中调用 TOP_RIGHT 常量。setAlignment()方法通过使用下面的 Java 语句,显示在图 8-10 的构造下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-10。

Inside of the .setAlignment() method parameter area, type Pos.TOP_RIGHT and hit Alt+Enter to import

uiContainer.setAlignment(Pos.TOP_RIGHT); // Set VBox Alignment to TOP_RIGHT via Pos helper class

使用 Alt+Enter 击键组合来消除红色波浪错误下划线,并确保选择问题的正确解决方案,在本例中是 javafx.geometry.Pos 选项的 Add import,它列在最前面(最有可能是正确的解决方案),并且它是允许在您的代码中使用 Pos 类的解决方案。

下一步,我们将使用uiPadding = new Insets(0,0,10,10); Java 实例化语句创建 uiPadding Insets 对象,如图 8-11 中的第 58 行所示。最后,我们将通过使用uiContainer.setPadding(uiPadding);方法调用将 uiPadding Insets 对象“连接”到 uiContainer VBox 对象。这种联系在图 8-11 中用黄色显示,显示了 Insets 声明、实例化和实现之间的联系。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-11。

Create a uiPadding Insets object and wire it to the uiContainer VBox object using .setPadding(uiPadding);

我们已经将我们的按钮对象重命名为 gameButton (was btn),所以我们现在有 6 行对象实例化代码和 5 行对象配置代码,如图 8-11 所示,使用下面的 Java 9 代码:

private void createBoardGameNodes()  {
    root = new Group();
    scene = new Scene(root, 300, 250);
    scene.setFill(Color.TRANSPARENT);
    gameButton = new Button();
    gameButton.setText("Start Game");
    uiLayout = new StackPane();
    uiLayout.setBackground(Background.EMPTY);
    uiContainer = new VBox();
    uiContainer.setAlignment(Pos.TOP_RIGHT);
    uiPadding = new Insets(0,0,10,10);
    uiContainer.setpadding(uiPadding);
}

重要的是要注意,因为在场景 scene 对象的构造函数方法调用中使用了根组对象,所以这一行代码需要首先出现,以便在使用它之前创建根组对象。

接下来,让我们使用方便的程序员的快捷方式,在uiContainer.setPadding(uiPadding);方法调用下剪切并粘贴你的两个游戏按钮实例化和配置代码行,然后在它自身下复制并粘贴代码四次,如图 8-12 底部突出显示的,使用在第六章中创建的修改的游戏按钮(btn)引导 UI 元素创建所有十个用户界面按钮元素。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-12。

Create 10 Button object instantiation and configuration statements at the end of createBoardGameNodes()

这将允许您将 gameButton 分别更改为 helpButton、scoreButton、legalButton 和 creditButton,以创建五个独特的 UI Button 对象。按钮的 Java 9 游戏代码应该如下所示:

gameButton = new Button();
gameButton.setText("Start Game");
helpButton = new Button();
helpButton.setText("Game Rules");
scoreButton = new Button();
scoreButton.setText("High Scores");
legalButton = new Button();
legalButton.setText("Disclaimers");
creditButton = new Button();
creditButton.setText("Game Credits");

在 addNodesToSceneGraph()中添加新的 UI 设计节点

正如你在图 8-13 中看到的,Java 代码是没有错误的,我现在已经声明并实例化了另一个名为 gameBoard 的组对象。这将包含 SceneGraph 的 3D game elements 分支,因此 Group 对象声明现在已经成为类顶部的复合语句。我在代码中单击了 gameBoard 对象,以创建该对象声明的高亮跟踪,在 createBoardGameNodes()中实例化,并在 addNodesToSceneGraph()中使用,这表明如果在类的顶部声明,就可以在任何需要的地方使用对象。这种单击要跟踪的对象名称的方法是 NetBeans 9 的一个有用的技巧,只要您想跟踪对象的使用情况,就可以使用这种方法。我将经常在截图中使用它来突出我在添加新的 Java 代码时正在做的事情(以及为什么)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-13。

Add gameBoard Group object and add Node objects to SceneGraph using .getChildren().add and .addAll()

接下来,让我们确保我们的节点被正确地添加到场景图中。在场景图形的根(顶部)之外,这是一个组对象,我们将有另一个 gameBoard 组对象来保存 i3D 游戏元素和素材,以及 uiLayout StackPane 对象。使用以下语句将它们添加到根组中:

root.getChildren().add(gameBoard);        // Add new i3D Game Group Node to root Group Node

root.getChildren().add(uiLayout);         // Add uiLayout StackPane Node to root Group Node

接下来,我们将 uiContainer VBox 布局容器分支节点添加到 uiLayout StackPane 分支节点,并将五个按钮 UI 元素叶节点添加到 uiContainer VBox。这是使用两行 Java 9 代码完成的,如下所示:

uiLayout.getChildren().add(uiContainer);      // Add VBox Vertical Layout Node to StackPane Node

uiContainer.getChildren().addAll(gameButton,  // Add All UI Button Nodes to the VBox Node
                                 helpButton,
                                 legalButton, creditButton, scoreButton);

图 8-13 显示了这个场景图构造代码。我在对象层次上使用了颜色填充,可视化地显示节点对象(更准确地说是节点子类对象),它们是场景、根或分支节点。(如果您想查看这些 JavaFX 根、分支和叶节点对象层次结构,如图 8-3 所示。)

这里要注意的重要事情是您将节点对象添加到组根场景图形对象的顺序。该顺序会影响 3D 元素之上的场景渲染合成以及 UI 元素合成的合成层顺序。添加到根组的第一个节点将位于场景合成(渲染)堆栈的底部。因此,这需要是游戏板组节点对象,它将保存 i3D 游戏,以便节点首先被添加到场景图形根,如果你向下看,它在底部,或者如果你向前看,它在场景合成和渲染堆栈的后面。你可以在图 8-13 中看到这一点。

下一个要添加的节点将是您的 uiLayout StackPane 节点对象,因为您的 2D 用户界面(浮动)面板将需要覆盖在您的 3D 游戏板的顶部。将这些顶级节点对象放入场景图形层次后,我们可以将 uiContainer VBox 节点对象添加到 StackPane 节点对象,该对象将包含所有按钮控件叶节点对象。请注意,我们使用的是。getChildren()。addAll()方法链将按钮控件对象添加到 VBox 中,因为我们可以在。addAll()方法调用(链)从。getChildren()方法。

在第九章中,我们还将添加一个名为 boardGameBackPlate 的 ImageView 对象和一个名为 infoOverlay 的 TextFlow 对象。在第九章中,我还需要实例化五个图像对象来保存内存中的数字图像素材,以便我们在本章中声明的图像对象可以被实现。如您所知,我们使用复合 Java 语句将这些对象命名为 splashScreen、helpLayer、legalLayer、creditLayer 和 scoreLayer,就像我们对 Button 对象所做的那样。

交互性:创建 BoardGame 按钮 UI 控件

接下来您需要做的是将 gameButton.setOnAction()事件处理 Java 代码结构复制到您的。start()方法,然后在它本身下面再粘贴四次,以创建 helpButton、legalButton、creditButton 和 scoreButton 按钮控件对象事件处理结构。出于测试目的,在这一阶段,您可能希望将 System.out.println 语句更改为每个语句在输出控制台窗口中打印一条唯一的消息,这样您就可以确保五个按钮 UI 元素中的每一个都是唯一的,并且能够正确地处理其按钮事件。在继续添加更多的 Java 代码从而增加应用的复杂性之前,务必确保 Java 9 代码结构在每个阶段(也就是说,在每次更改或增强之后)都能正常工作。在开发过程中,这比一次编写所有代码花费的时间要长一点,但是可以节省调试时间。

如果您想知道图 8-14 中的黄色波浪下划线警告(或建议)是什么,以及我将鼠标放在您的事件处理程序 ActionEvent 处理构造EventHandler<ActionEvent>() { public void handle(){...} });下的黄色突出显示上时生成的弹出消息,这是因为可以使用较少的代码将该表达式转换为 lambda 表达式。请注意,这样做将确保您的代码只能在 Java 8 和 Java 9 下运行。如果您想在使用 Java 6 和 Java 7 的 Android 中使用您的代码,您可能只想保留这些稍微长一点的 Java 代码结构,因为它们做完全相同的事情。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-14。

Copy the gameButton event processing code and paste it underneath itself and create your helpButton event handling

完成后,新的事件处理结构应该看起来像下面的 Java 代码,如图 8-15 中间所示:

gameButton.setOnAction(new EventHandler<ActionEvent>() {
    @Override
    public void handle(ActionEvent event) {
        System.out.println("Starting Game");
    }
});

helpButton.setOnAction(new EventHandler<ActionEvent>() {
    @Override
    public void handle(ActionEvent event) {
        System.out.println("Game Instructions");
    }
});

scoreButton.setOnAction(new EventHandler<ActionEvent>() {
    @Override
    public void handle(ActionEvent event) {
        System.out.println("High Score");
    }
});

legalButton.setOnAction(new EventHandler<ActionEvent>() {
    @Override
    public void handle(ActionEvent event) {
        System.out.println("Copyrights");
    }
});

creditButton.setOnAction(new EventHandler<ActionEvent>() {
    @Override
    public void handle(ActionEvent event) {
        System.out.println("Credits");
    }
});

正如你在图 8-15 中所看到的,你的事件处理代码是没有错误的,你已经准备好运行和测试你的 JavaFXGame.java 游戏应用,以确保你的场景图形层次被渲染到屏幕上,并且你的按钮 UI 控制对象正在正确地处理事件。一旦你确定你的场景图是在这个高层次上为你的游戏构建的,并且你的核心用户界面处理 Java 9 代码结构也在适当的位置并且正常工作,你就可以在下一章中继续添加数字图像素材并微调所有的 UI 元素定位,这样你就可以在游戏的最高层次上使一切看起来和运行起来都正确。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-15。

Copy the gameButton and helpButton and paste them to create your scoreButton, legalButton, and creditButton

正如您在图 8-16 中看到的,在您复制。setOnAction()事件处理构造,当您使用屏幕左侧的减号图标折叠 EventHandler 例程时(在图 8-16 的左侧用红色圆圈显示),您在。start()方法。第一行代码将调用一个方法来创建节点对象并配置它们,第二行代码将调用一个方法来将这些节点对象添加到场景图形层次结构中,第 3 行到第 6 行将配置 Stage 对象,第 7 行到第 11 行将设置 UI 按钮控件对象事件处理。如果考虑到您正在添加到游戏基础架构顶层的功能数量,这是相对紧凑的,包括为您的游戏、说明、法律免责声明、演职员表和记分牌显示创建顶层(根和分支节点)场景图形结构和用户界面设计元素。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-16。

Click the Run (Play) icon at the top of NetBeans and test your code to make sure your UI design is working

接下来,是时候测试重组 JavaFXGame 类并为游戏应用创建 UI 设计结构和场景图层次结构的代码了。让我们确保所有这些 UI 按钮元素(对象)都正常工作。

测试你的棋盘游戏:处理场景图

单击图 8-16 中用红色圈出的 NetBeans 9 IDE 顶部显示的绿色播放箭头,并运行您的 JavaFXGame 项目。这将调出 VBox UI 布局容器,在图 8-16 的中上部用红色圈出。正如您所看到的,您正在获得专业的结果,没有崩溃,使用了大约 12.5 个导入语句(外部类),几十行 Java 代码,以及场景图形根组节点对象下不到 12 个子节点。优化您的场景图形层次非常重要,因为 JavaFX 将用来处理您的游戏设计结构的每个脉冲事件都必须遍历该层次,因此它越紧凑,您的游戏性能就越好,您的用户体验也就越流畅。因此,您应该从一开始就优化一切。正如你在图 8-17 底部的 Output-JavaFXGame 标签中看到的红色圆圈,我已经测试了所有按钮 UI 控件对象的事件处理结构。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-17。

Click each of the Button objects and make sure your event-handling code is printing the right messages

我这样做是为了确保每个按钮都实现了自己的事件处理,并且在我单击五个 UI 按钮控件中的每一个时都打印出正确的 System.out.println()文本消息。

稍后,我们可以将此 System.out.println()方法调用替换为另一个控制 ImageView 对 Image 对象的引用的方法调用,从而允许我们在您的用户界面设计 ImageView 数字图像背板支架的数字图像素材之间进行切换。

由于我们只复制和粘贴了每个按钮的 EventHandler 例程,并且只更改了按钮对象的名称和在这些例程中执行的代码,所以这些按钮对象应该仍然可以正常工作(将文本写入控制台)并且不会导致任何编译器错误。但是,它们最终不会按照您的要求去做,也就是更改 ImageView 对象(UI 背板)底层中引用的 Image 对象,或者使用 TextFlow 在该对象上放置适当的文本。这是你在下一章将要编写的代码;您还将做一些 UI 设计调整,将按钮库放在显示屏上的适当位置。如图 8-16 所示,虽然按钮控件对象确实在 VBox UI 容器节点内的 TOP_RIGHT 位置对齐,但是 VBox 本身还没有在其父(分支)StackPane 节点对象内对齐。就像第七章中的透明胶片一样,VBox(在 StackPane 中)和 StackPane(在组中)必须正确定位。

恭喜你,你保持了在第七章中添加的改进,并采用了新的方法来组织你的场景图层次,并改进了这个场景图,以包括你的 i3D 游戏分支,我们将在本书的后半部分开始添加对象和素材。

摘要

在第八章中,我们改进了游戏的实际顶级用户界面设计,概述了底层游戏引擎组件设计,并使用不到十几个节点实现大多数顶级游戏用户界面结构,找出了最有效的场景图节点设计,从而让您了解了我们的 JavaFXGame.java 代码。通过重新设计现有的 JavaFXGame.java 引导 Java 代码,您又回到了 Java 游戏编程中,这些代码最初是由 NetBeans 9 在第六章中为您创建的。由于 NetBeans 9 生成的 Java 9 代码设计对您的目的来说不是最佳的,所以您对它进行了重大的重写,使它更加模块化、简化和有组织。

您通过创建两个新的 Java 方法做到了这一点:。createBoardGameNodes()和。addNodesToSceneGraph()。这样做是为了模块化场景图节点创建过程,也是为了模块化添加两个父分支节点和五个控制叶节点对象到场景图根,在这种情况下恰好是组节点对象。在该目录下,您有一个名为 uiLayout 的 StackPane 分支节点,它用于多层 UI 对象合成功能,还有一个名为 gameBoard 的组分支节点,您将使用它来保存您将在本书剩余部分构建的 i3D 游戏对象层次结构。

您了解了我们将在这些新方法中实现的一些 JavaFX 类。其中包括 javafx.scene.geometry 包中的 Pos 类和 Insets 类、javafx.scene.layout 包中的 VBox 类以及 javafx.scene 包中的 Group 类。你编写了新的。createBoardGameNodes()方法,该方法使用 Inset 对象、StackPane uiLayout 分支节点对象、Group gameBoard 分支节点对象和五个 UI 按钮控件叶节点对象来实例化和配置 VBox 对象。

一旦实例化并配置了所有场景图节点,您就可以构建您的。addNodesToSceneGraph()方法将场景图节点对象添加到组根对象。这样做是为了在 Stage 对象中显示正确的场景图节点层次,它将引用和加载场景图根组节点对象以及我们在它下面构建的层次。

最后,您创建了其他四个按钮 UI 控件对象,并添加了 ActionEvent EventHandler 程序逻辑。这就完成了我们本章的编程任务,这些任务与为 JavaFXGame.java Java 9 游戏应用设置场景图层次和用户界面设计基础结构有关。

完成所有编码后,您就可以在 NetBeans 9 中测试您的顶级 Java 9 游戏应用用户界面设计和场景图层次结构了。

在下一章中,你将会在你的用户界面设计中添加很酷的数字图像资源,并在定位和对齐方面下功夫,同时让所有东西都与你的 UI 按钮对象一起工作。

九、JavaFX 9 用户界面设计:Java 9 游戏设计的前端

让我们通过继续设计你的 i3D 棋盘游戏的前端用户界面基础设施来建立你在第八章中建立的顶级场景图架构。这将在 StackPane 分支节点内部完成,使用该节点下的三个主要节点。VBox 分支节点保存按钮叶节点,ImageView 叶节点显示不同的图像对象,TextFlow 叶节点显示(流动)覆盖在 ImageView 节点顶部的不同文本描述。这七个叶子节点将共同组成你游戏的顶层用户界面设计。StackPane 节点将充当背景图像板(holder ),而 ImageView 叶节点将保存五个不同的图像对象,这些对象为五个按钮中的每一个引用您的数字图像部分素材。StartGame 背景图像素材将被视为闪屏。在 StackPane 层次结构中 ImageView 的顶部是 TextFlow 叶节点,它将作为前景文本信息的持有者,并根据单击的按钮控件对象引用不同的文本数据。在 TextFlow 层之上是 VBox 分支节点层,它将包含五个按钮叶节点。这将保持、对齐和定位您的五个按钮控件对象,最终将使用事件处理程序将不同的图像对象交换到您的 ImageView 对象中,并将不同的文本数据交换到您的 TextFlow 对象中。

既然你已经声明了你的五个背景图像对象(以及你的 ImageView 和 TextFlow 对象,用于 JavaFXGame.java 类的顶部),我要介绍的第一件事就是你如何使用你在第八章开始构建的场景图层次来完成你的用户界面设计。

接下来,我们需要介绍 javafx.scene.image 和 javafx.scene.text 包中的四个新 JavaFX 类,在本章中,您将对它们进行实例化和配置,以便在 Java 游戏中使用。这些类包括 Image 类、ImageView 类、Text 类和 TextFlow 类。

接下来您需要做的事情是创建将被加载到 Image 对象中的背景图像,这样您就可以在以后测试您的 Java 代码,从而确保它能够正常工作。

之后,您将学习一个很酷的技巧,将另一个合成层添加到您的合成管道中,而无需将另一个节点对象添加到场景图形层次中。这将包括了解如何利用 JavaFX 背景类(对象)以及 JavaFX 背景图像类(对象)来利用节点子类的背景属性作为 pro Java game 数字图像合成管道中的另一个图像对象保持层。

所有这些都将涉及到向您的。createBoardGameNodes()方法和您的。addNodesToSceneGraph()方法将 ImageView 背景图像板和 TextFlow 信息文本覆盖放置在 VBox 按钮控件组的后面。您还将在 JavaFXGame 类中添加两个新的 Java 方法来加载图像资源(loadImageAssets()方法)和创建文本资源(createTextAssets()方法)。为了让你的用户界面更有条理、更专业,你需要进行大量的编码、重新编码、重新布线(对象引用变化)和参数调整,我们将在学习完本章关于用户界面的课程中用到的一些 JavaFX API 类后开始。

UI 设计基础:完成场景图

在这一章中,你要做的第一件事就是完成顶层用户界面屏幕的场景图设计。这意味着实例化您的 ImageView 数字图像显示底板,它将保存您的背景图像对象,这些对象将引用您的数字图像素材。在本章中,您将引用这些使用 GIMP 2.10 创建的数字图像素材。在场景图层次结构中的 ImageView 之上,您将添加一个 TextFlow 信息容器;因此,您的文本内容将位于背景图像的上方,而不是下方。最后,在这两个叶节点对象之上是 VBox 按钮控件分支节点对象,您已经在第八章中创建并实现了它。图 9-1 显示了最终的场景图层次(在图 7-3 中展开你在第七章看到的通用根、分支和叶场景图)。这一次,我为您的 pro Java 9 游戏应用进行了定制。注意,在 i3D 组分支节点叶节点对象上没有连接器,因为我们还没有在 Java 代码中实现它们。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-1。

BoardGame user interface design Scene Graph hierarchy, showing the root, branch, and leaf Node objects

这将需要您向 StackPane 布局容器父分支节点添加两个叶节点,如图 9-1 左下方所示。在我们开始编写 Java 代码来实例化。createBoardGameNodes()方法,并将其添加到场景图形层次结构中,让我们对您将在本章中放置的新 Java 语句中使用的每个类进行概述。

JavaFX 9 UI 合成:ImageView 和 TextFlow

接下来,让我们看看主要的 JavaFX 类,这些类可以用来为游戏启动画面和文本信息画面创建基本的合成管道,这些屏幕将位于您在前一章中创建的 UI 按钮库的旁边(和下面)。游戏说明、高分、法律和信用屏幕实质上是由背景图像(保存在 ImageView 对象中)合成的文本(保存在 TextFlow 对象中)。启动画面将与开始游戏按钮相关联,并且将在启动游戏应用时显示;当按下开始游戏按钮时,它将变得不可见。这是因为 StackPane UI 构造位于比根组和游戏板组节点对象更高的 z 顺序上,在场景图中它们位于它的上面。这意味着 StackPane 中任何不透明的东西都会覆盖(遮挡视线)场景图形根正下方的 i3D 游戏板组,如图 8-3 所示。我们先来看看图像类。

JavaFX 图像类:在设计中引用数字图像

Image 类是一个公共类,它直接扩展了 java.lang.Object 主类,这意味着 Image 类也是“临时编码”的,以提供图像加载(引用)和缩放(调整大小)。您可以锁定缩放的纵横比,也可以指定缩放(算法)质量。支持所有由java.net.URL类支持的 URL。这意味着您可以从互联网( www.domainname.com/imagename.png )、操作系统文件系统(file:imagename.png)或使用正斜杠字符(/imagename.png)的 JAR 文件中加载图像。

JavaFX Image 类是 javafx.scene.image 包的一部分。javaFX Image 类的类层次结构源自 java.lang.Object 主类,并使用以下 Java 类层次结构:

java.lang.Object
  > javafx.scene.image.Image

Image 类提供了六种不同的(重载的)Image()构造函数方法。这些函数从简单的 URL 到一组指定 URL、宽度、高度、比例、平滑和预加载选项的参数值。这些应该在您的构造函数方法中按此顺序指定。当您使用所有这些构造函数方法中最复杂的方法来编写 Image()构造函数时,您很快就会看到这一点,该方法使用以下格式:

Image(String url, double requestedWidth, double requestedHeight,
      boolean preserveRatio, boolean smooth, boolean backgroundLoading)

Image 对象的最简单的构造函数只指定 URL,并使用以下格式:

Image(String url)

如果您希望加载图像,并让 constructor 方法使用最高质量的重新采样(平滑像素缩放)将图像缩放到不同的宽度和高度(通常会更小,以获得更好的质量),同时锁定(保留)纵横比,则可以使用以下格式的 image 对象构造函数:

Image(String url, double scaleWidth, double scaleHeight, boolean preserveAspect, boolean smooth)

如果您希望使用图像的“原始”或“物理”(默认)分辨率和原始纵横比来加载图像,并让它在后台(异步)加载图像,您可以对 image()构造函数使用以下格式:

Image(String url, boolean backgroundLoading)

还有两个 Image()构造函数方法使用 java.io.InputStream 类。这个类为 Image()构造函数方法提供了一个低级的 Java 输入流。通常,您会使用 URL 来引用您的数码图像文件。这两种图像对象构造器格式采用以下格式。简单的格式如下:

Image(InputStream is)

复杂的 InputStream 构造函数方法允许您指定宽度、高度、纵横比锁定和图像缩放插值平滑算法(开/真或关/假)。第二种格式如下所示:

Image(InputStream is, double newWidth, double newHeight, boolean preserveAspect, boolean smooth)

因此,Image 类(object)用于准备要使用的数字图像素材,也就是说,从 URL 读取其数据,必要时调整其大小(使用您喜欢的任何平滑和纵横比锁定),甚至在应用中进行其他操作时异步加载它。值得注意的是,这个图像类(或对象)不显示您的图像素材;它只是加载它,根据需要进行缩放,并将其放入系统内存,以便在您的应用中使用。

为了显示一个图像对象,你需要使用第二个类(对象),叫做 ImageView,我们将在本章的下一节中讨论它。此 ImageView 对象实现为场景图形和引用中的叶节点,然后将图像对象数据“绘制”到包含此 ImageView 节点的布局容器上。在我们的例子中,这是叶 ImageView 节点之上的 uiLayout StackPane 父(或分支)节点。

从数字图像合成的角度来看,StackPane 类(对象)是层合成引擎,也可以称为层管理器,ImageView 对象表示层堆栈中的一个数字图像层。图像对象包含显示在 ImageView 层内部或多个 ImageView 中的数字图像数据(如果需要的话),因为图像对象和 ImageView 对象是分离的,因此彼此独立存在。我试图最小化场景图节点的使用,所以我使用一个 ImageView 图像板和一个文本信息合成板来创建用户界面屏幕,然后使用代码来切换它们。

JavaFX ImageView 类:在设计中显示数字图像

ImageView 类是一个公共类,它直接扩展 javafx.scene.Node 超类,后者是 java.lang.Object master 类的扩展。因此,ImageView 对象是 JavaFX 场景图中的一种节点对象,用于使用 Image 对象中包含的数据绘制图形视口。该类具有允许图像重采样(调整大小)的方法,并且与 image 类一样,您可以锁定缩放的纵横比,以及指定重采样算法(平滑质量,通过使用像素插值)。

正如您在 Java 代码的第 24 行中所看到的,如图 8-6 所示,您将使用一个名为 boardGameBackPlate 的 ImageView 对象来显示您的图像对象数据。与 Image 类一样,这个 ImageView 类也包含在 javafx.scene.image 包中。ImageView 类的 Java 类层次结构从 java.lang.Object 主类开始,并使用该类创建 javafx.scene.Node 类,然后使用该类创建 javafx.scene.image.ImageView 节点子类。ImageView 类使用以下 Java 类继承层次结构:

java.lang.Object
  > javafx.scene.Node

    > javafx.scene.image.ImageView

ImageView 类提供了三种不同的(重载的)ImageView()构造函数方法。这些构造函数从空的 ImageView 构造函数(您将在后面的代码中使用它)到将 Image 对象作为其参数的构造函数,再到将 URL String 对象作为参数并自动创建 Image 对象的构造函数。最简单的空参数列表 ImageView()构造函数方法将创建一个(空的)ImageView 对象(即没有要显示的图像对象但可以保存图像对象的对象)。它将使用以下格式:

ImageView()

我们将使用这个构造函数方法,这样我就可以向您展示如何使用?setImage()方法调用将图像对象加载到 ImageView 对象中。如果您想避免使用。setImage()方法调用,您可以使用另一个重载的构造函数方法。该 ImageView 对象构造函数将使用以下格式:

ImageView(Image image)

因此,我将显式设置一个 ImageView 并将其连接到 Image 对象的方式如下所示:

boardGameBackPlate = new ImageView();      // This uses empty constructor method approach
boardGameBackPlate.setImage(splashScreen);

这可以使用重载的构造函数方法压缩成一行代码,结构如下:

boardGameBackPlate = new ImageView(splashScreen);  // using the overloaded constructor method

如果您还想跳过创建和加载图像对象的过程,还有另一个构造函数方法,它使用以下格式:

ImageView(String url)

如果您希望使用图像的“原始”或“物理”(默认)分辨率和原始纵横比来加载图像,并让它在后台(异步)加载图像,image()构造函数将使用以下格式:

backPlate = new Image("/backplate8.png", 1280, 640, true, false, true);
boardGameBackplate = new ImageView();
boardGameBackplate.setImage(backPlate); // use empty ImageView constructor method approach

如果您不想指定图像尺寸、背景图像加载或平滑缩放,并且您想锁定任何缩放的纵横比,您可以将前面三行 Java 代码压缩到下面的一个构造函数中:

boardGameBackPlate = new ImageView("/backplate8.png");   // uses third constructor method

至少在开始时,出于学习的目的,我会用长时间的方式来做这件事,我将总是使用 Image()构造函数方法“显式地”加载图像对象,这样我们就可以指定所有不同的属性,这样您就可以看到您在 Java 9 编程逻辑中使用的所有不同的图像素材。我想在这里向您展示快捷方式代码,因为如果您开始将 ImageViews 用作 2D 精灵,您以后可能会想要使用这种快捷方式。你可以对你的精灵使用这种快捷方式,因为你不会缩放他们,因为他们是如此高度优化,以至于后台加载选项,节省了很长的加载时间,将是不必要的。

JavaFX TextFlow 类:在设计中使用文本对象(内容)

TextFlow 类是一个公共类,允许开发人员创建文本段落。文本段落是多行文本的容器,每一行都用“换行符”分隔,在 Java 代码中用“escape n”序列表示。

因此,TextFlow 类将使用以下 Java 类继承层次结构:

java.lang.Object
  > javafx.scene.Node

    > javafx.scene.Parent
      > javafx.scene.layout.Region
        > javafx.scene.layout.Pane
          > javafx.scene.text.TextFlow

该 TextFlow 对象是 JavaFX 场景图中的节点对象类型,可用于使用文本对象中包含的数据呈现文本段落,与 ImageView 呈现图像对象中包含的数据的方式非常相似。但是,TextFlow 可以一次处理多个文本对象,允许您使用类似。setFill()和。setFont()。TextFlow 是一个专门的文本布局类,旨在呈现通常称为富文本格式(RTF)的内容。有些人称之为桌面出版,它涉及到使用不同的字体、风格或颜色来增强基于文本的内容的呈现。有趣的是,javafx.scene.text 保存在 javafx.graphics 模块中,而不是 javafx.controls 模块中。这一点很重要,因为如果您想优化(而不是使用)JavaFX 9 UI 控件类(100 个或更多),您仍然可以仅使用 javafx.base 和 javafx.graphics 模块使用 Image、ImageView、Text 和 3D geometry 对象创建自己的 UI 元素,这为您提供了创建 pro Java 9 i3D 游戏所需的一切。

TextFlow 对象可用于在单个 TextFlow 对象中布局多个文本节点。TextFlow 对象使用其内部每个文本节点对象的文本、字体和样式设置,加上其自己的最大宽度和文本对齐样式属性,来确定呈现每个子文本对象的位置。

由于 TextFlow 对象的包装功能,单个文本节点可以跨越多行,并且由于双向(bidi)重新排序,文本节点的可视位置可以不同于逻辑位置。Java Bidi 对象提供了关于用来创建它的文本的双向重新排序的信息。例如,要正确显示从右向左(RTL)而不是从左向右(LTR)阅读的阿拉伯语或希伯来语文本,这是必需的。

当然,除了文本节点对象之外,任何其他节点对象类型都将被视为 TextFlow 对象布局中嵌入的“富内容”对象。它将使用其首选的宽度、高度和基线偏移值插入到内容中,并相对于父 TextFlow 对象中的其他文本对象进行间隔和对齐。

当文本节点对象位于 TextFlow 对象内部时,它的一些属性将被忽略。例如,文本节点对象的 X 和 Y 属性将被忽略,因为子文本节点的位置是由父 TextFlow 对象决定的。同样,文本节点中的换行宽度将被忽略,因为用于换行的最大宽度将继承 TextFlow 对象的最大宽度属性。TextFlow 布局的环绕宽度将由 Region 对象的当前宽度决定。这可以由应用通过设置 TextFlow 对象的 preferred width 属性来指定。如果不需要换行特性,应用可以将首选宽度设置为两倍。MAX_VALUE 或 Region。USE_COMPUTED_SIZE。应该在任何子文本节点对象中使用换行符或\n(转义符)分隔段落,如下面的粗体代码示例所示。

在 TextFlow 对象中呈现文本节点对象时,该对象的 pickOnBounds 属性值将被设置为 false。发生这种情况是因为单个文本节点对象中的内容可能会被 TextFlow 算法分割,并由于换行和双向重新排序而被放置在 TextFlow 中的不同位置。TextFlow 算法将对每个托管子文本节点对象进行布局,而不考虑该子文本节点的 visibility 属性值,为设置为不可见的文本节点对象留出间隙。以下是 TextFlow 对象创建工作流程的示例:

Text titleText = new Text("Welcome to iTVboardgame! \n");
titleText.setFill(Color.RED).setFont(Font.font("Helvetica", FontPosture.ITALIC, 40));
Text pressPlayText = new Text("Press the Start Game Button to Start!");
pressPlayText.setFill(Color.BLUE).setFont(Font.font("Helvetica", FontWeight.BOLD, 10));
TextFlow gameTextFlow = new TextFlow(titleText, pressPlayText);

TextFlow 类有两个属性:DoubleProperty lineSpacing 属性,它使用文本行之间的像素定义垂直间距;object propertyText alignment 属性,它定义水平文本对齐常量,如 LEFT、RIGHT、CENTER 或 JUSTIFY。

TextFlow 类有两个构造函数方法;第一个有一个空参数区域,并构造一个空的 TextFlow 文本布局对象。此构造函数方法将使用以下格式:

TextFlow()

前面使用的第二个 TextFlow 构造函数方法使用子文本(或富媒体)节点对象创建一个 TextFlow,这些子文本(或富媒体)节点对象使用逗号分隔的列表传递到参数区域,格式如下:

TextFlow(Node... children)

第二个构造函数方法采用节点对象的参数列表数组的原因是因为 TextFlow 对象支持“富文本布局”,这是文本对象和其他支持富媒体(图像、形状、几何图形、网格、动画、视频等)的节点对象的组合。).

让我们回到编码,实例化和配置图像,图像视图,文本和文本流对象,以便您可以将它们添加到您现有的场景图层次结构中,以实现图 9-1 所示的内容。之后,在第十章中,我们可以在你的按钮动作事件处理程序中编写代码,它将基于点击定制你的用户界面。

用户界面编码:UI 合成管道

要进入用户界面设计,您将需要实例化 ImageView 和 TextFlow 对象,将它们添加到场景图的层次结构中的适当位置,将数字图像导入到您的项目中,创建一种用数字图像素材加载图像对象的方法,创建一种用适当的信息创建文本对象的方法,最后调整场景图和 UI 元素以微调 UI 最终结果。

实例化合成层:。createBoardGameNodes()

由于您已经在第八章中声明了 boardgameb 背板 ImageView 和 infoOverlay TextFlow 并编写了这些类的导入语句,接下来您需要做的是使用 Java new 关键字以及它们的基本(空参数列表)构造函数方法将它们实例化为对象。您将在 createBoardGameNodes()方法中做到这一点,以保持事情高度有序。为了镜像场景图形层次,您将在 StackPane 之后和 VBox 之前实例化它们,因为这将是您将使用的合成(层)顺序。正如你在图 9-2 中看到的,Java 代码是没有错误的,你有一个场景图根、i3D 游戏板分支和 UI 布局分支,它们仅使用系统内存中的一个根和三个分支节点对象进行实例化,包括一个组节点、一个 StackPane 和一个 VBox(Insets 对象是一个实用程序对象,而不是一个场景图节点)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-2。

Instantiate boardGameBackPlate and infoOverlay objects inside of your createBoardGameNodes() method

如果算上持有 SceneGraph 的场景对象,内存中有五个游戏组织对象。向其中添加 Stage 对象,该对象是使用。start()方法和由 JavaFXGame 类创建的应用对象扩展了应用声明,并且您已经使用系统内存中的七个对象为 pro Java 9 游戏开发创建了顶级基础结构。使用 ImageView 和 TextFlow 显示,我们在系统内存中仍然有不到 10 个对象。一旦我们用数字图像素材加载了您的五个图像对象,并设置了五个 UI 按钮对象,您在内存中仍然只有不到 20 个对象,这仍然是非常好的优化。在本章的后面,您还将添加八个文本对象,但它们不是以像素为中心的,所以它们不会占用太多内存。我们还将使用一些实用对象,比如 Insets,但即使有这些,在你开始添加核心 3D 对象组成你的 i3D 棋盘游戏之前,你仍然会有 30 个以下的对象。接下来,让我们将 ImageView 和 TextFlow 添加到场景图中,将它们放在 VBox UI 按钮库的后面,以便它们首先渲染。

将 UI 背板添加到场景图形:addNodesToSceneGraph()

对于位于场景、3D 游戏板和 StackPane 之上但在 VBox 按钮库之后的 ImageView 合成层和 TextFlow 信息板,您将需要。getChildren()。在根方法调用之后,uiContainer 方法调用之前,从 uiLayout StackPane 对象中调用 add()方法。这如图 9-3 所示,将在 addNodesToSceneGraph()方法结构中使用以下两个 Java 语句:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-3。

Add boardGameBackPlate and infoOverlay to your Scene Graph in the addNodesToSceneGraph() method

uiLayout.getChildren().add(boardGameBackPlate); // Add ImageView backplate behind TextFlow Node
uiLayout.getChildren().add(infoOverlay);      //  Add TextFlow information overlay second

由于按钮对象不能单独定位,我不得不使用 VBox 类和 Insets 类来包含和定位一组垂直的按钮控件。现在我们已经准备好编写两个素材加载方法了。

素材加载方法:loadImageAssets()和 createTextAssets()

在本书的过程中,当我们创建这个游戏时,我们想做的下一件事是创建另外两个专用的方法来加载图像对象素材和创建文本对象素材。这就创建了一个专门的“基于方法的工作流程”来为你的游戏添加元素。在中实例化。createBoardGameNodes(),添加到。addNodesToSceneGraph(),引用。loadImageAssets(),并在。createTextAssets()。正如你在图 9-4 中看到的,我已经把这两个新的方法调用放在了。start()方法,并让 NetBeans 为它们创建空方法,当我们向游戏中添加资源时,我们将向其中添加 Java 代码。我把它们放在 start 方法的顶部,这样你的应用就可以首先把这些资源加载到系统内存中,这样当你的 pro Java 游戏代码需要它们的时候,它们就在那里了,这样我们就不需要使用任何专门的预加载器了。此外,这些对象在被其他方法调用之前必须就位,因此需要首先调用它们,在设置更高级的对象并将它们添加到 SceneGraph 层次结构的方法之前。稍后,我们可以使用 NetBeans 9 profiler 确保素材加载不到一秒钟,一旦我们有了 3D 对象渲染和游戏处理逻辑等需要确保高度优化的内容,并且在处理场景图时不会占用太多 Pulse 引擎的 60 FPS 中断(时间片)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-4。

Create empty methods for loadImageAssets() and createTextAssets() to create your image and text assets

在我们继续之前,我们需要创建一些新的媒体素材来与图像对象一起使用,我们将使用 PNG32 数字图像素材实例化和引用(加载),这将利用 alpha 通道。这种 alpha 通道数据将允许我们在任何背景图像上合成这些徽标或屏幕字幕,如果我们选择继续下去,甚至可以在 i3D 游戏板本身上合成。在下一节中,我将在 Autodesk 3D Studio Max 中创建一个 iTVBoardGame 徽标,然后将其导出为 OBJ 文件,并使用冷(或者热)岩石纹理进行渲染。然后,我们将有一个专业的 Java 9 游戏 3D 闪屏标题,供你在本章稍后完善你的 UI 设计时使用。

创建闪屏素材:在 2D 管道中使用 3D 素材

正如你在图 9-5 中看到的,我已经使用 2D 文本工具创建了一个“快速和肮脏”的 iTVBoardGame 3D 徽标,然后使用斜角修改器挤压它,正如你在截图右上角的 Autodesk 3D Studio Max 版本的场景图形层次(在 3D Studio Max 中称为修改器列表)中看到的。我后来使用文件➤输出功能输出一个波前。OBJ 3D 文件格式,是 JavaFX 9 支持的几种 3D 文件导入格式之一。根据我们需要导入的 3D 数据类型,我们可能会使用这种格式或其他格式,因为每种格式都支持不同类型的 3D 数据和功能,如纹理贴图、UVW 贴图、反向运动学(IK)骨骼动画数据、网格变形、动画、相机数据、照明数据等。JavaFX 能够导入相当多的高级 3D 格式,如 Collada (DAE)、FrameBox (FBX)、3D Studio 3DS 和 OBJ。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-5。

I created an iTVBoardGame logo with 3D Studio Max, exported it to an OBJ file format, and rendered it

我将把这个网格数据导入渲染引擎,添加一个胡桃木纹理贴图,渲染它,然后把 2D 像素数据导出为 2D 图像素材。我将确保它有一个 alpha 通道,所以它看起来仍然像是一个 3D 对象,即使事实上它不是。这就是业内所说的 2.5D。

如果我们以后想要旋转它等等,当我们了解了 JavaFX 中 i3D 内容生产管道的更多信息时,我们可以在本书的后面将其作为 3D 素材导入。JavaFX 提供的混合 2D+3D 环境(API)的优势之一是能够决定什么 3D 是“幻觉”(像 2.5D,或立体),什么 3D 是“真实”的 i3D。立体 3D(主要是电影)不是真正的 3D,因为你不能走在场景和所有角色的后面。在一个 i3D 游戏中,比如《光环》或《疯狂足球》,你可以,因为它是一个完全虚拟的现实。

接下来,让我们来看一些我为在 ImageView 对象中使用而创建的 UI 屏幕标题数字图像对象,我将向您展示如何将它们添加到 NetBeansProject 文件夹层次结构中的适当文件夹中。NetBeans 9 可以“看到”这些 PNG32 数字图像素材后,您就可以编写 loadImageAssets()方法,该方法会将 PNG32 数据加载到系统内存中的图像对象中,以便 ImageView 可以引用和显示它们。

将图像资源添加到项目中:使用\src\文件夹

正如您在图 9-6 的顶部所看到的,我的 Windows 7 64 位四核 AMD 工作站上的路径从 Users 文件夹开始,看起来像 C:\ Users \ Walls \ my documents \ netbeans projects \ Java FX game \ src \ credits . png。正如您所看到的,我根据文件内部的内容来命名 PNG32 文件,尽管它们看起来像是在白色背景上,但实际上它们是透明的。将图书素材存储库中的文件复制到您的项目文件夹中,然后您将能够在您的代码中引用它们。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-6。

Copy the PNG32 files for the digital image titles for the UI screens to /NetBeansProjects/JavaFXGame/src/

一种加载图像资源的方法:。loadImageAssets()

打开空的 loadImageAssets()方法结构,添加五个 Image()构造函数方法,用正确的图像素材及其规范实例化和加载图像对象,如图 9-7 中突出显示的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-7。

Instantiate and reference your five Image objects inside of the loadImageAssets() method you just created

如图 9-7 所示的 Java 代码应该是这样的:

splashScreen = new Image("/welcome.png", 1280, 640, true, false, true);
helpLayer = new Image("/instructions.png", 1280, 640, true, false, true);
legalLayer = new Image("/copyrights.png", 1280, 640, true, false, true);
creditLayer = new Image("/credits.png", 1280, 640, true, false, true);
scoreLayer = new Image("/highscores.png", 1280, 640, true, false, true);

这个构造函数方法格式所做的是在 JAR 文件中加载带有数字图像素材的图像,使用“根”或正斜杠字符引用,因为该文件位于/src/文件夹中。第二个和第三个条目代表图像的 X 和 Y 分辨率,第四个 true 条目打开纵横比锁定。第五个假输入关闭双线性插值,第六个真输入打开背景图像加载,作为速度优化。

一种创建文本资源的方法:。createTextAssets()

打开空的 createTextAssets()方法结构,添加八个 Text()构造函数方法,用正确的信息实例化和加载文本对象。如图 9-8 所示的代码应该是这样的:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-8。

Declare eight Text objects at top of class; instantiate and load Text objects in the createTextAssets() method

playText = new Text("Press the Start Game Button to Start! \n");
moreText = new Text("Use other buttons for instructions, copyrights, credits and high scores.");
helpText = new Text("To play game roll dice, advance gamepiece, follow gameboard instruction.");
cardText = new Text("If you land on square that requires card draw it will appear in UI area.");
copyText = new Text("Copyright 2015 Wallace Jackson, All Rights Reserved. \n");
riteText = new Text("Visit the iTVboardGame.com website on the Internet: www.iTVboardgame.com");
credText = new Text("Digital Imaging, 3D Modeling, 3D Texture Mapping, by Wallace Jackson. \n");
codeText = new Text("Game Design, User Interface Design, Java Programming by Wallace Jackson.");

接下来,您可能希望使按钮控件的宽度一致,这将通过使用 Button.setMaxWidth()方法来实现。当您升级您的场景对象构造器以支持 iTV 1280x720 时,您将能够看到 TOP_RIGHT Pos 常量的运行,并且统一的按钮块将看起来更专业。

使用 Button.setMaxWidth()方法:使按钮一致

您需要做的第一件事是将场景场景对象的 iTV 宽度设置为 1280,高度设置为 640,这样您就可以使用 2:1 的宽高比,并且具有 pro Java 9 游戏应用支持的最低 iTV 屏幕分辨率。正如你在图 9-9 中看到的,我在下面的 Java 代码中升级了 Scene()构造函数方法来使用这些新的应用窗口屏幕尺寸,如图 9-9 顶部的第 83 行所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-9。

Use the .setMaxWidth() method call to set your Button UI objects to 125 so that they have a uniform width

scene = new Scene(root, 1280, 640);

接下来要做的事情是设置 boardgameb 背板 ImageView 来包含欢迎消息图像。您将使用闪屏图像的. setImage()方法来实现这一点,在图 9-9 的第 89 行使用以下代码:

boardGameBackPlate.setImage(splashScreen);

最后,为了使按钮对象的宽度统一为 125 像素,使用.setMaxWidth(125)方法调用,调用五个按钮 UI 对象中的每一个(如图 9-9 ,代码行 97、100、103、106 和 109 所示)。

我将 VBox 配置为以 10 个像素间隔其子节点,在 VBox(10)构造函数方法调用中放置值 10。我将 Insets()的间距值增加到 Insets(16)。运行项目以查看变更,如图 9-10 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-10。

Use the Run ➤ Project work processing to see your Button bank design improvements in spacing and width

接下来,将 backplate8.png 和 alphalogo.png 图像素材复制到源文件夹,如图 9-11 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-11。

Use your file management utility to copy the backplate8.png and alphalogo.png assets to your /src folder

接下来,让我们使用 StackPane 的背景图像功能。目前我们使用的是 Background 类中的空常量,所以让我们用 BackgroundImage 对象替换它,您的背景类也将支持它。接下来让我们看看如何连接它,以便我们可以通过使用一个未使用的功能(StackPane 背景)而不是通过添加另一个 ImageView 对象来进一步优化您的场景图,大多数人都倾向于这样做。

使用 StackPane 背景:利用所有合成层

JavaFX StackPane 类支持. setBackground(背景背景)方法调用,该方法调用又支持 BackgroundImage 对象,该对象可以用 Image 对象加载或与 EMPTY 常量一起使用。这意味着您可以在 StackPane UI 布局容器对象的背景中引用图像资源,所以让我们来看看如何利用这一点,这样您就可以使用五个合成层(舞台背景、场景背景、ImageView、TextFlow、StackPane ),只需使用您添加到场景图中的节点。所有这些当前都设置为空或透明,或者包含带有 alpha 的 PNG32。使用以下代码,将 backPlate 和 alphaLogo 对象名称添加到类顶部的现有图像声明复合 Java 语句中:

Image splashScreen, helpLayer, legalLayer, creditLayer, scoreLayer, backPlate, alphaLogo;

接下来,在类的顶部声明一个名为 uiBackgroundImage 的 BackgroundImage 对象,并使用 Alt+Enter 让 NetBeans 9 为您编写导入语句。接下来,添加一个名为 uiBackground 的背景对象(注意,在第六章中已经导入了背景类,所以您可以利用背景。空常量),如下面的 Java 代码所示,以及图 9-12 中突出显示的:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-12。

Add a backgroundImage object named uiBackgroundImage; use the .setBackground() method to load it

BackgroundImage uiBackgroundImage;  // Object Declaration at the top of the JavaFXGame class
Background uiBackground;           //  Object Declaration at the top of the JavaFXGame class

在 loadImageAssets()方法的开头,实例化 backPlate 和 alphaLogo 图像对象,然后使用以下 Java 代码加载它们及其相关的数字图像素材,如图 9-12 所示:

backPlate = new Image("/backplate8.png", 1280, 640, true, false, true);
alphaLogo = new Image("/alphalogo.png",  1200, 132, true, false, true);

在这个 loadImageAssets()方法的最后,实例化您的 uiBackgroundImage 对象并使用 backplate Image 对象加载它,我们将使用它作为优化的 8 位 PNG8 背景图像,用于我们使用 Node 子类(StackPane、ImageView 和 VBox)创建的复合闪屏图像;你可以使用下面的 Java 代码来实现,如图 9-12 所示:

uiBackgroundImage = new BackgroundImage(backPlate,
                                         BackgroundRepeat.NO_REPEAT, BackgroundRepeat.NO_REPEAT,
                                        BackgroundPosition.CENTER, BackgroundSize.DEFAULT);

最后,您需要实例化 uiBackground 背景对象,并使用其构造函数方法,用您在前面的 Java 代码行中刚刚创建的 uiBackgroundImage 背景图像对象来加载它。这将使用下面的代码行来完成,在图 9-12 中的 loadImageAssets()方法中突出显示:

uiBackground = new Background(uiBackgroundImage);

在 createBoardGameNodes()方法中,调用。setBackground()方法,并传递一个 uiBackground 背景对象,替换背景。空常数,使用图 9-12 中的代码:

uiLayout.setBackground(uiBackground);

使用“运行➤项目”查看背板图像是否在您的 StackPane 的背景中,如图 9-13 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-13。

Use the Run ➤ Run Project (JavaFXGame) menu sequence to test your new compositing pipeline Java code

现在我们准备使用 textFlow 和 Text 对象将文本层添加到合成管道中。

使用 TextFlow:设置信息叠加对象

打开 createTextAssets()方法,为 playText 和 moreText 对象添加两个方法调用,确保它们使用颜色。白色常量来填充字体,并选择一种广泛支持的 Helvetica 字体,使用其常规字体,并为字体高度设置一个大的 50 像素。使用 FontPosture 辅助类(font face 常量)将 playText 和 moreText 对象设置为使用常规字体样式。在 moreText 对象内添加转义换行符或\n 字符序列,将其分成两行。图 9-14 中间突出显示的新文本对象配置应类似于以下 Java 代码:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-14。

Add .setFill() and .setFont() methods to your SplashScreen text

playText = new Text("Press the Start Game Button to Start! \n");
playText.setFill(Color.WHITE);
playText.setFont(Font.font("Helvetica", FontPosture.REGULAR, 50));
moreText = new Text("Use other buttons for instructions, \n copyrights, credits and scores.");
moreText.setFill(Color.WHITE);
moreText.setFont(Font.font("Helvetica", FontPosture.REGULAR, 50));

打开 createBoardGameNodes()方法,在 infoOverlay 对象实例化之后,添加一行代码并调用。使用 infoOverlay 对象的值 240 设置 Translate X()方法。然后添加另一行代码并调用。值为 420 的 setTranslateY()方法。这将把 TextFlow 容器放置在 ImageView 对象(当前是一条欢迎消息)的下面,这样您的合成文本块将位于屏幕的底部。这些语句的 Java 代码应该如下所示(在图 9-15 中突出显示):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-15。

Add Text objects to your TextFlow object and .setTranslateX() and .setTranslateY()

infoOverlay.setTranslateX(240);
infoOverlay.setTranslateY(420);

打开 addNodesToStackPane()方法。在该方法的末尾,添加一个 infoOverlay 对象并调用。getChildren()。addAll()方法,用逗号分隔 playText 和 moreText 对象,如图 9-16 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-16。

Add infoOverlay object to end of .addNodesToSceneGraph() and use .addAll() to add playText and moreText objects to infoOverlay

该语句的 Java 代码应如下所示,并在图 9-16 中突出显示:

infoOverlay.getChildren().addAll(playText, moreText);

正如你在图 9-17 中看到的,白色的文本对象看起来很酷,你的图像合成管道看起来好像是用专业的数字成像软件创建的。接下来,让我们添加一个徽标的图像合成层。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-17。

Run the project and check the result of adding a TextFlow object to the splash screen compositing pipeline

这个 UI 设计看起来越来越专业,按钮放在岩石露头上,还有“欢迎!”文本在屏幕设计中居中。但是,UI 设计仍然需要一个品牌标志,并且有一个额外的空间将第三行推到右边,需要固定(删除)。让我们在下一节做这件事。

使用 StackPane:添加更多数字图像合成层

让我们在 JavaFXGame 类的顶部添加另一个名为 logoLayer 的 ImageView 对象声明,将 ImageView 声明变成一个ImageView boardGameBackPlate, logoLayer;复合 Java 语句。打开 createBoardGameNodes()方法,为该对象添加一个对象实例化,然后调用. setImage()方法将它连接到您之前在导入该数字图像素材时创建的 alphaLogo 图像对象。接下来,您将添加 logoLayer 对象的两个方法调用,一个用于 X 缩放,一个用于 Y 缩放,使用相同的 80%值 0.8,以便我们锁定此缩放操作的纵横比(也称为统一缩放)。最后,您将使用-225 值将徽标从屏幕中心沿 y 轴上移 225 个像素,因为 StackPane 使用 0,0 中心屏幕引用模型,而不是标准的 0,0 左上角像素引用模型。我们还将使用-75 像素的 X 平移值将徽标向左拉回 75 像素。新 logoLayer ImageView 对象实例化、素材引用和转换(位置/转换和比例)配置代码可以在图 9-18 的中间高亮显示,应该类似于下面的 Java 9 代码语句块:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-18。

Create a logoLayer ImageView referencing the alphaLogo image; set scale to 80 percent and position to -75,-225

logoLayer = new ImageView();
logoLayer.setImage(alphaLogo);
logoLayer.setScaleX(0.8);
logoLayer.setScaleY(0.8);
logoLayer.setTranslateX(-75);
logoLayer.setTranslateY(-225);

接下来,您必须在 addNodesToSceneGraph()方法中将这个新的 logoLayer ImageView 添加到合成层的 StackPane uiLayout 容器中。在这里,由于我们正在向 root 和 uiLayout SceneGraph 层次结构添加多个节点子类,我们将从使用。getChildren()。使用. getChildren()将()方法链添加到。addAll()方法链,将该方法中的 Java 语句数量从八个减少到四个。

添加的顺序会影响合成层的顺序,因此对于。add()语句,这等同于从上到下。添加的第一个语句(顶部)在合成层堆栈的底部(有点违反直觉,不是吗?).

与。addAll()方法,这将变为从左到右,因此首先添加的对象(左)位于合成层堆栈的底部。一个新的 addNodesToStackPane()方法结构,使用。getChildren()。因此,addAll()方法调用看起来如下,如图 9-19 底部突出显示的:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-19。

Consolidate six .add() method calls into two .addAll() method calls off of a SceneGraph root and UI branch

private void addNodesToSCeneGraph() {
    root.getChildren().addAll(gameBoard, uiLayout);
    uiLayout.getChildren().addAll(boardGameBackPlate, logoLayer, infoOverlay, uiContainer);
    uiContainer.getChildren().addAll(gameButton, helpButton, legalButton,
                                     creditButton, scoreButton);
    infoOverlay.getChildren().addAll(playText, moreText);
}

正如您在图 9-20 中看到的,我已经添加了徽标并修复了文本段落(左侧)对齐方式,删除了\n 后面的空格,这是违反直觉的,因为它留下了\ n 版权并且没有转义版权。作为一名 Java 程序员,您需要知道在这种情况下,编译器会查看转义符(),并且只查看其后的一个字母(在本例中是 n 或 newline),然后继续将字符作为文本内容的一部分进行解析。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-20。

Run the project and check the result of adding ImageView object to the splash screen compositing pipeline

徽标已经添加到合成层容器(StackPane)中,调整了大小(缩放)以适合按钮库,并上移(平移)到按钮库的中心。这一切看起来很平衡和专业;它在场景图中使用很少的节点,在系统内存中使用很少的对象,所以它是优化的。

由于我们没有使用我在第七章中向您展示的透明性(技巧),让我们通过恢复到默认的修饰 StageStyle 类常量来替换 OS chrome,这可以通过删除 primaryStage.initStyle()方法调用来实现。相反,我将保留 Java 语句,并将使用透明常量改为使用修饰常量,以防将来我们希望以不同的方式修饰 Stage 对象。这可以通过将图 9-21 中第 46 行所示的这行代码改为以下 Java 代码来实现:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-21。

Revert to StageStyle.DECORATED and add an iTVBoardGame (JavaFX 9 Game) title for your OS window

primaryStage.initStyle(StageStyle.DECORATED);

接下来,通过替换在第六章中为您创建的引导代码中的“Hello World”占位符文本,为您的操作系统窗口 chrome 添加标题。我将使用 iTVBoardGame 来匹配 3D 徽标,并使用括号添加“JavaFX 9 Game ”,以向用户阐明该应用是在什么平台上构建的。执行此操作的代码在上方的图 9-21 中以橙色显示。initStyle()方法,应该类似于下面的 Java 语句:

primaryStage.setTitle("iTVBoardGame (JavaFX 9 Game)");

正如你在图 9-22 中看到的,我们现在有了一个初始的应用启动闪屏,带有徽标、背景图像、用户界面按钮库和部分标题图像层。在闪屏的情况下,这是“欢迎!”

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-22。

Run the project to make sure the OS chrome has been replaced and the window title is in place and correct

我们剩下要做的唯一一件事是完成其他四个部分的图像对象的实现,并在其他四个 TextFlow 对象中实现字体样式和颜色。所有这些对象都将在您的事件处理代码中被调用,我们将在第十章中添加这些代码(涵盖 JavaFX 9 和 Java 9 游戏中的事件处理和效果)。

在所有这些 2D 屏幕设计、UI 设计和事件处理编码完成后,我们可以在本书的后半部分开始进入 3D 和 i3D。

完成 UI 设计对象的创建和配置

让我们打开 createTextAssets()方法并添加。setFill()和。setFont()方法调用其他六个文本对象,将它们的颜色设置为与保存手写文本图像的 boardGameBackPlate ImageView 相匹配,并将它们的字体样式设置为 Helvetica 常规。这是一个相对简单的练习;得到的方法体如图 9-23 所示,应该类似于下面的 Java 方法体和 Java 语句:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-23。

Finish configuring your Text objects using .setFill() and .setFont() methods with Color and Helvetica values

private void createTextAssets(){
    playText = new Text("Press the PLAY GAME Button to Start!\n");
    playText.setFill(Color.WHITE);
    playText.setFont(Font.font("Helvetica", FontPosture.REGULAR, 50));
    moreText = new Text("Use other buttons for instructions,\ncopyrights, credits and scores.");
    moreText.setFill(Color.WHITE);
    moreText.setFont(Font.font("Helvetica", FontPosture.ITALIC, 50));
    helpText = new Text("To play game roll the dice, advance\ngame piece and
                         follow game board\ninstructions. ");
    helpText.setFill(Color.GREEN);
    helpText.setFont(Font.font("Helvetica", FontPosture.REGULAR, 50));
    cardText = new Text("If you land on a square\nthat requires you draw a card, it
                         will\nappear in the floating UI text area.");
    cardText.setFill(Color.GREEN);
    cardText.setFont(Font.font("Helvetica", FontPosture.REGULAR, 50));
    copyText = new Text("Copyright 2015 Wallace Jackson.\nAll Rights Reserved.\n");
    copyText.setFill(Color.PURPLE);
    copyText.setFont(Font.font("Helvetica", FontPosture.REGULAR, 50));
    riteText = new Text("Visit the iTVboardGame.com website on\nthe Internet
                         at www.iTVboardgame.com");
    riteText.setFill(Color.PURPLE);
    riteText.setFont(Font.font("Helvetica", FontPosture.REGULAR, 50));
    credText = new Text("Digital Imaging, 3D Modeling, 3D\nTexture Mapping
                         by Wallace Jackson.\n");
    credText.setFill(Color.BLUE);
    credText.setFont(Font.font("Helvetica", FontPosture.REGULAR, 50));
    codeText = new Text("Game Design, User Interface Design,\nJava Programming
                         by Wallace Jackson.");
    codeText.setFill(Color.BLUE);
    codeText.setFont(Font.font("Helvetica", FontPosture.REGULAR, 50));
}

在本章中,你已经在整合你的专业 Java 游戏闪屏设计、用户界面设计、顶级场景图和类(和方法)基础设施方面取得了很大的进步。您还了解了 Image、ImageView、Text、TextFlow、Background 和 BackgroundImage 类。拍拍自己的背,如果你有那么灵活的话,然后从 Java 9 编程中稍微休息一下!

您还没有完成 pro Java 9 游戏开发的用户界面设计部分。在本书的后面,当我们使它成为交互式的(第十章)和当我们通过添加一个透视相机到场景根(第十一章)将你现在的 2D 场景转换成 3D 场景时,使它成为一个 2D 平面时,准备好进一步完善它,所有这些都需要改变 StackPane 对象合成层管道属性和坐标参考系统。正如我所说的,这本书的每一章都会变得越来越复杂,直到你对 Java 9、JavaFX 和 NetBeans 9 的了解足以创建你能想象的任何 i3D 游戏设计!

摘要

在第九章中,您使用 JavaFX Image、ImageView、Background、BackgroundImage、Text 和 TextFlow 类向游戏的实际顶级用户界面设计的合成管道中添加了更多代码。你做的第一件事是完成 JavaFX 场景图层次结构设计,我在图 9-1 中可视化了它,展示了场景图如何使用一个根节点对象、三个分支节点对象和七个叶节点对象(五个按钮对象、一个 ImageView 对象和一个 TextFlow 对象)。稍后,您将为游戏的 3D 部分添加更多分支和叶节点对象,主要用于保存 JavaFX 提供的 3D 对象(基本体)或您自己的 3D 网格几何体。在本章中,您为徽标合成添加了第二个 ImageView 节点。

接下来,您了解了一些 JavaFX 类,我们将在本章和下一章中在这些新方法中实现这些类。其中包括 Image 类和 ImageView 类,都来自 javafx.scene.image 包。您还了解了 javafx.scene.text 包中的 Text 和 TextFlow 类。

您实例化并配置了这些新的合成节点对象,然后编写了两个新方法来处理您的图像和文本素材。loadImageAssets()方法将数字影像素材实例化并配置到图像对象中,createTextAssets()方法将文本信息素材实例化并配置到文本对象中,以便以后与场景图形中的 TextFlow 节点对象一起使用。

然后,您使用 125 像素的值使按钮宽度一致,并随后学习了如何使用 background 和 BackgroundImage 类(对象),以便能够利用 StackPane 的 Background 属性作为合成管道中的另一个合成层,而无需向 JavaFX 场景图形层次添加任何更多的节点对象。这加强了我对 pro Java 游戏开发的优化方法,即利用场景图中每个节点给你的一切,这样你就可以将每个脉冲事件中遍历的节点总数保持在绝对最低限度。

在下一章中,您将学习 JavaFX 中的事件处理类,并在 ActionEvent EventHandler 程序逻辑中实现 Java 代码。您还将学习如何在这个过程中实现一些很酷的特殊效果,因为其中一些将由 Java 9 语句在您的事件处理程序中触发。在那之后,我们将进入 3D 和你需要知道的进入 3D 领域的职业和素材。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值