使用 Pixi.js 构建作品集

2022-08-13  本文已影响0人  追梦人在路上不断追寻

首先,让我们看一下主页。

1.png

这里为您提供了两个选项。第一,观看互动游戏般的体验。这类似于虚拟艺术画廊。而你浏览一个虚拟的 2D 世界并检查我的每个项目,以纪念碑或高大的黑色柱子表示。还为您提供了一种回退到传统站点的方法——该站点遵循标准 UI 和 UX 模式,用于在每个项目和“关于”页面之间导航。对于匆忙或没有设备或网络连接来享受游戏体验的用户来说,这是安全网和后备方案。

对于游戏体验,您会立即看到几个可以与之交互的独特角色,以及一个大型纪念碑——它触发了我的传记页面的模态嵌入版本。当点击每个角色时,它会触发一个传统的 RPG 风格的对话框出现。每个角色都提供了有关如何与世界互动的小提示。回到老式 2D 口袋妖怪游戏。

2.png
3.png

在这一点上,您可以轻松地浏览世界其他地方。使用鼠标或手指,您可以点击并拖动以移动相机。提供了几种风格独特的生物群系,它们提供了一种对每组项目进行分组的方法。在此过程中,您会发现代表我参与或贡献的每个项目的支柱。点击柱子可在弹出模式中提供描述和其他媒体。

4.png 5.png

您找到并与之交互的每个支柱都将立即开始动画。这有助于直观地识别您访问过和尚未访问过的站点。总的来说,它提供了一种非常有趣和独特的体验,让您在浏览我的完整作品目录的同时,欣赏这个小世界的景象和声音。

工具和技术

当我开始设计这个网站时,我马上就知道我想创建一个外观和感觉都像传统 2D 自上而下 RPG 游戏的演示文稿。它还需要存在于可用浏览器 API 和现代基于 Web 的技术的范围内。鉴于此,canvas元素和WebGL的使用是给定的。配对时,它们允许您在 2D 或 3D 上下文中渲染图形。对于 2D,这意味着绘制原始形状,如矩形和圆形、图像(纹理),所有这些都与最终用户的直接交互和输入。结合起来,它们提供了游戏的基本构建块。

游戏渲染

我早期的原型使用了纯 HTML 和 Javascript 以及一个 canvas 元素。这将涉及从头开始构建所有内容。然而,我很快意识到这对于这种规模的演示来说并不是一个很好的规模。我缺乏游戏开发的支柱,例如动画精灵表,并且发现交互非常棘手。相反,我选择使用 Pixi.js。

7.jpeg

如果您不熟悉 Pixi,它会在您的标准画布集成上提供多项生活质量改进和功能。这包括但不限于:

网络应用框架

接下来我知道我想利用 UI 组件和功能齐全的 Web 应用程序框架来构建网站的基础。为此,我求助于Svelte和Sveltekit。当它们结合起来时,它们的作用类似于Angular、用于 React 的 Next.js 和用于Vue 的Nuxt等工具。

8.png

我通过 Svelte 和 Sveltekit 广泛使用了以下功能:

风格与设计

最后,我需要设置样式并控制每个页面和组件的布局和设计的方法。为此,我求助于Tailwind CSS。Tailwind 提供了一整套实用的 CSS 类,同时仍允许您使用任意覆盖“画线之外”。这肯定是一种后天习得的品味,但它是一种可以显着提高右手生产力的工具。它与 Svelte、React 或 Vue 等组件库搭配得非常好。

9.png

齐心协力

虽然每个工具本身都很棒,但构建 Web 应用程序(任何规模)的主要挑战之一是找到让所有东西协同工作的正确方法。我想花一些时间来解释一下我是如何将所有内容组合在一起以构建体验中最关键的部分的,重点是核心游戏功能。

Pixi 组件

我面临的第一个挑战是确定在哪里放置画布元素并开始使用 Pixi 渲染到屏幕上。为此,我选择了一个简单的独立组件。这使我能够创建一个基本的游戏管理器,并将所有逻辑、布局和样式都包含在一个文件中。这使得在共享引用之间跳转和迭代代码变得快速和容易。

10.png

大致的操作顺序是这样的:

  1. canvas 元素使用 Svelte 的 bind:this={elemRef} 语法进行绑定。

  2. Pixi 应用程序被初始化,它接受元素引用并设置全局设置,例如显示大小。

  3. Pixi 加载器摄取一组静态资源,这使您可以确保提前预加载所有必需的元素。可以点击它以在屏幕上显示加载进度条。

  4. 当游戏应用程序完全加载时,会发生一些步骤......

  5. 世界地图是通过预加载的纹理生成的,然后注入到“关卡”容器中。该容器包含地图和所有其他实体,例如 NPC。

  6. 接下来,初始化相机类,它主要控制关卡容器在 2D 世界空间中的 x/y 位置。我在下面的部分中更详细地解释了这一点。

  7. 我初始化了一个网格类,可以选择启用它以在屏幕上直观地显示单个“平铺”分段和坐标以进行调试。瓷砖在此处具有 16x16 像素的基础。

  8. 大量游戏对象,例如柱子、NPC 和生物被初始化并作为子对象添加到关卡容器中。

  9. 关卡容器被添加到 Pixi 舞台(场景)中。这最终使它在屏幕上可见。

  10. 加载时,我调整相机焦点以集中在我的个人角色上。

  11. 最后,它开始了游戏渲染循环,这使得所有动画和运动都能正常工作。相机、容器级别和实体具有每帧更新各自的渲染方法。

相机控制

在 2D 虚拟空间中渲染时,相机会带来兴趣挑战。如果您使用 Unity 或 Godot 等引擎创建游戏,您可能会认为这些是理所当然的,因为大多数都提供这些交钥匙。Pixi 和 canvas 需要你自己解决这个问题。实现这一点的一种方法需要对最终用户产生一些错觉。我在下面提供了一个插图来可视化这一点。

11.jpg

由于画布(红色)固定在可见页面画布中,因此它实际上无法移动。相反,相机移动的效果是通过移动画布区域本身呈现的内容来创建的。这通常涉及创建一个容器来容纳您的游戏世界地图(绿色)。该容器还可能包含子对象,例如 NPC、生物和建筑物(蓝色)。

不是一个带着相机的小家伙(ala Mario 64)跟着你,而是地图和实际移动的孩子!这是一个非常巧妙的技巧,在执行中效果很好。

12.png

为了在代码中实际处理这个问题,Camera 类简单地控制用户从 A 点拖到 B 点的距离,并设置一个偏移值,表示为 ax 和 y。然后在动画循环期间读取这些偏移值以更新关卡容器的位置。

游戏对象

游戏对象不是 Pixi 固有的。相反,它们是从 Unity 借来的概念。这些对象可能会呈现您游戏中存在的任何东西。这通常通过创建包含视觉元素(例如动画精灵)的包含元素(例如组)来处理,并将其与包含对象应如何与世界交互的逻辑和规则的代码配对。

NPC(不可玩角色)就是其中一个很好的例子。在我的游戏中,我有多个 NPC 实体,每个实体都包含用于视觉空闲和行走动画的动画精灵。但还包括一组逻辑,用于处理鼠标悬停并单击实体时发生的情况。

通过代码实现这一点的一个常见约定是使用面向对象编程(简称 OOP)。OOP 涉及创建一个结构化的类,该类描述对象的属性,以及包含它应该如何运行的逻辑。这些类中的一个或多个可以被实例化以创建该实体的独立副本。

回到那个 NPC 示例——我的 GameObject 类描述了每个 NPC 的属性,例如名称、要显示的纹理图像以及其他描述性细节。同时还包括它自己的逻辑,例如触发对话框出现的 onclick 处理程序。

13.png

这个 GameObject 类包含我的游戏中所有实体可用的所有核心和共享属性和功能逻辑。我使用这个类来实例化从 NPC 到螃蟹,甚至是项目支柱的所有内容。每个实例都有自己的名称、动画精灵参考、坐标位置和尺寸。它们还通过类方法共享通用功能,允许它们在预定义的路径上移动并处理输入事件。请注意,我并没有在每个实体上使用所有功能。螃蟹在我的游戏中不会“说话”……但它们当然可以!

但是,您可能会问自己,当您需要基本 GameObject 类范围之外的属性或功能时会发生什么?这就是 OOP 的另一个关键特性发挥作用的地方——类继承。为此,我创建了一个扩展 GameObject 的单独类。这意味着它继承了基类的所有属性和方法,同时仍然允许您覆盖或扩展特定于这种独特实体类型的功能。

我在游戏开始时出现的类似 NPC 的实体 Layla the Cat 中使用了这个效果。在这里,我创建了一个扩展基本 GameObject 类的 Cat 类——这意味着她仍然可以拥有自己的名字、动画精灵,并且仍然可以触发对话框等功能。同时仍然允许我覆盖和扩展她的基本功能。在这种情况下,猫类型的实体可以根据鼠标位置在 X 轴上翻转精灵。这使她看起来跟随鼠标光标在屏幕上的位置。这是猫独有的功能,因为我们知道猫喜欢追老鼠!

上一篇下一篇

猜你喜欢

热点阅读