相位器中的模块化游戏世界

2020-10-17 10:50:20

这是一系列关于在Phaser 3游戏引擎中使用Tablemaps创建模块化世界的博客文章。在第一篇文章中,我们将从零开始,创建一个玩家可以探索的精灵宝可梦风格的自上而下的游戏世界:

下一篇文章将介绍如何创建动态平台,之后的文章将介绍使用Matter.js按程序生成的地下城和跳墙地图。

在我们深入研究之前,本文附带的所有代码都在这个存储库中。这些教程使用截至19年2月26日的最新版本Phaser(v3.16.2)和平铺(v1.2.2)。

我是哥伦比亚大学(Columbia College)的一名创意开发人员和教授,但我是在开发Tilemap API的初始公开v3发布之前的冲刺阶段被带到Phaser团队的。我创建了大约40个指导性示例,并撰写每周时事通讯更新,但我希望将所有这些信息收集成更具指导性和更易于理解的格式,以便人们可以更轻松地进入Phaser 3。

如果你对JavaScript、Phaser和平铺地图编辑器有一定的经验,这篇文章将是最有意义的。如果没有,请继续阅读,但也要将Google、Phaser教程和Phaser Examples&;文档放在手边,以填补任何空白。

Tilemap是一种使用模块化构建块创建游戏世界的技术。当你把一个世界分解成乐高积木一样的碎片时,你会获得记忆、性能和创造性的胜利。

想象一下试图从头开始重新创建马里奥。假设我们决定尝试将每个关卡作为一个巨大的图像文件加载。World 1-1的宽度将超过3500像素:

我们需要很多像素来存储NES游戏中的第一个级别和其他31个级别作为图像。此外,很难将带有逻辑的图像与游戏同步。马里奥可以站在哪些像素上?哪些像素与他可以进入的管道相对应?

Tilemap方法定义了一组模块化的、规则大小的瓷砖,我们可以用它们来构建关卡。这样,我们只需要一个图像,一个瓷砖集:

这样,304px192px的图像就有可能重现原来马里奥游戏的所有关卡,再加上你能想象到的任何新关卡。(当然,你仍然会错过一个留胡子的人和一只两足乌龟,以及其他东西。)。每块瓷砖只有16x16像素。将这些瓷砖排列成一个标高称为平铺地图。使用地图编辑软件,我们也可以轻松地配置切片的属性。例如,我们可以将一些瓷砖(如地面瓷砖)标记为Mario可以站立的实心瓷砖。

因此,有了Tablemaps,我们就有了一个更小的图像(性能和内存制胜),我们可以用它来轻松地创建和迭代关卡设计(创意制胜)。

在我们开始用代码加载一些地图之前,让我们先来看看Phaser 3游戏的结构。在v3中,游戏是围绕SceneObjects构建的。它们类似于v2中的State对象,但更灵活。

这是一个模板,您将在整个Phaser Examples存储库中看到它。这是一种简单的入门方式。它创建游戏并将场景定义为预加载、创建和更新功能的集合。

下面是一个稍微复杂一点的示例,它显示了如何加载和创建背景和一些文本:

如果您没有使用过Phaser,本系列中可能会有很多新概念,如果您迷路了,请查看大量的示例和文档。

让我们从最简单的设置开始,使用以下精简的Mario平铺集重新创建一个迷你Mario级别:

我们将从上一节中的样板开始。在预加载内部,我们可以加载磁贴集图像:

这指的是我们当前的场景,而这个.load是场景的加载器,它处理资源的加载。在预加载中的所有资产完成加载之前,创建功能不会运行。

Level只是指向磁贴集中特定磁贴的数字或索引的二维数组。0是左上角的瓷砖,1是它旁边的瓷砖,依此类推。

分解代码,我们有三个主要部分:Tilemap、Tileset和StaticTilemapLayer。您可以通过this.make.tilemap(或this.add.tilemap)创建一个Tilemap。这不是一个显示对象,相反,它保存有关地图的数据,并允许您添加切片集和切片图层。

一张地图可以有一个或多个图层,这些图层是从拼贴集中实际渲染拼贴的显示对象。它们有两种风格:StaticTilemapLayer和amp;DynamicTilemapLayer。StaticTilemapLayer速度非常快,但该层中的平铺不能修改,也不能渲染翻转或着色等逐平铺效果。DynamicTilemapLayer以一定的速度换取操作单个平铺的灵活性和功能。在这篇文章中,我们将坚持静态层,但下一次,我们将深入到动态层。

除了从二维数组加载贴图外,还可以从CSV加载它:

注:此示例基本上是Phaser示例的副本,其中以Rich Davey&;Ilija Melentijević的Cat Astro Phi资产为特色。

我们可以很容易地在这里增加一些交互性,通过使用Phaser的相机系统让玩家在世界各地摇摆。代码注释是为了解释使用的新相位器,但请查看相位器相机示例以了解更多关于相机的信息。

当你想要测试一些简单的东西或者你正在生成一个过程性的世界时,从二维数组或CSV加载是很棒的,但是很可能你需要一个关卡设计工具。这就是瓷砖的用武之地。这是一个免费的开源地图编辑器,可以导出为CSV、JSON和许多其他格式。

我们不会深入讨论如何使用Tabled--这本身就是一个广泛的主题--所以请查阅Tleed的文档和“从头开始的游戏”教程系列来学习速成课程。您也可以从这里的演示中下载Tablemaps(.tmx文件)和Tableset。把它们打开,玩一玩,你就应该掌握诀窍了。

使用平铺为Phaser生成贴图时,您需要确保执行以下几项操作:

将切片集加载到地图中时,请确保选中“嵌入到地图中”选项。(如果忘记执行此操作,则可以单击屏幕底部的嵌入平铺集按钮。)。请参见下面的前两张图片。

确保您使用的不是压缩的“平铺图层格式”。您可以在地图属性边栏…中进行调整。点击顶部工具栏中的“映射→地图属性”即可打开。请参见下面的第三张图像。

重要的注意事项!最近发布的平铺(1.2版)更改了贴图导出格式,从而中断了Phaser的贴图导入。如果在加载贴图时遇到问题(特别是如果没有加载碰撞信息),请确保您使用的至少是Phaser 3.14.0。

使用tilemapTiledJSON加载器方法,我们可以加载并显示从Tabled导出的切片地图:

这一步主要是连接数据。为了使命名稍微清晰一些,以下是这些名称的来源:

您会注意到,地图由多个层叠放置的层组成:

这是使用平铺时的常见设计模式。它允许我们分离出要放置在游戏中不同“深度”的元素。使用这些层,我们可以确保“Player下方”层(地面和路径)显示在Player Sprite下方,而“Over Player”层(屋顶/雕像/标志顶部)显示在Player Sprite的顶部。“World”层包含所有剩余的东西,包括世界上碰撞/固体的东西。

现在我们已经有了一个世界,我们可以给这个世界添加一个合适的角色,让他们和物理一起走来走去。目前有三个物理引擎集成到Phaser中:Arade Physical(AP)、matter.js和Impact。AP又快又简单,所以这就是我们开始的地方-我们稍后将介绍matter.js。

在AP中,您可以创建矩形或圆形的物理体。矩形实体是轴对齐的边界框,这大致意味着它们不能旋转。在我们的地图上加载AP的碰撞瓷砖将被赋予一个与瓷砖大小相匹配的矩形体。

将world Layer中的某些瓷砖标记为碰撞,以便AP知道要使用它们进行碰撞。

在物理学中使用磁贴图的第一步是,你需要标记哪些磁贴应该是实心的(“碰撞”)。要做到这一点,一种方法是将某些平铺索引标记为在层内发生碰撞:

如果您使用的是平铺索引,则会有setCollision、setCollisionBetweet和setCollisionByExclude。但从指数的角度思考是很困难的,所以有一个更好的方法:setCollisionByProperty。平铺允许您通过平铺编辑器向平铺集中添加属性,因此我们可以只标记哪些平铺直接在平铺中发生碰撞。

通过单击“编辑拼贴”按钮(屏幕右下角)打开拼贴编辑器。

在“属性”窗口(屏幕左侧)下,单击加号图标并添加名为“Collides”的布尔属性。

只选择要冲突的切片,然后通过选中该框将“Collides”设置为true。

回到Phaser内部,我们可以简单地执行以下操作来标记WorldLayer中的碰撞瓷砖:

如果要验证是否已将正确的平铺标记为碰撞,请使用层的调试渲染:

一旦我们将瓷砖标记为碰撞,我们就可以添加物理信息。在游戏的配置中,我们可以通过执行以下操作来打开街机物理引擎:

注意:我在这里使用的是纹理地图集。有关更多信息,请参阅本教程。

最后一步是让玩家和平铺地图层相互碰撞。我们可以使用Collide或addCollider。我们将选择后者:

有很多强大的功能,你可以用Tabled和Phaser来做,让开发游戏世界的创意过程变得更容易。例如,本节的代码使用对象层将玩家的产卵点直接嵌入到地图中。

但这只是皮毛而已!请关注下一篇文章,我们将深入研究动态切片图层并创建程序地牢。

这一切都只是触及了皮毛。看看下一篇文章,我们将深入研究动态平铺地图图层,以创建一个充满谜团的平台:

感谢您的阅读,如果您想在以后的帖子中看到什么,请告诉我!

在最后两节中,您可能已经注意到平铺集名称中的“挤出”一词。如果你曾经注意到你的磁贴图中有轻微的“出血”,你开始看到你的磁贴之间的接缝,解决这个问题的一种方法是使用我写的一个叫做磁贴挤出器的小命令行实用程序来挤压你的磁贴。

我是一名创造性的开发者和教育家。你可以在这里看到更多我的作品,并与我联系。