发布于 2026-01-05 5 阅读
0

我如何使用 Pixi.js 构建我的新作品集

我如何使用 Pixi.js 构建我的新作品集

我的新作品集

请访问以下网址查看网站:endigodesign.com

我最近推出了新版的个人作品集网站 Endigo Design。每隔几年,我都会进行一次这样的更新。我会花几天时间搭建一个简单的网站,介绍我的个人情况和工作内容。不过这次,我决定要大手笔一些,充分展现我在网页开发和游戏开发方面的综合知识和技能,打造一个独一无二的作品展示平台。在这篇文章中,我将对网站进行评测,并探讨一些幕后技术和方法。

浏览网站

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

首页提供游戏模式和传统模式之间的选择。

这里为您提供两种选择。第一种是体验互动游戏,类似于虚拟艺术画廊。您可以在虚拟的二维世界中浏览我的每个项目,它们以纪念碑或高耸的黑色柱子的形式呈现。您也可以选择返回传统的网站——该网站遵循标准的用户界面和用户体验模式,方便您在各个项目和“关于”页面之间切换。这为那些时间紧迫或没有设备或网络连接来体验游戏的用户提供了安全保障和备用方案。

游戏一开始,你会看到几个各具特色的角色可以互动,还有一个大型纪念碑——点击纪念碑会弹出我的个人简介页面。点击每个角色,都会弹出传统的RPG风格对话框。每个角色都会提供一些与游戏世界互动的小提示。这让人想起经典的2D宝可梦游戏。

游戏体验的初始画面。展示了一座石碑和一些NPC角色。

通过简短的对话与我的形象进行交流。

现在,您可以自由探索这个世界了。使用鼠标或手指,点击并拖动即可移动视角。游戏提供了几种风格独特的生物群落,方便您将不同的项目进行分组。沿途您会看到一些柱子,它们代表了我参与或贡献过的每个项目。点击柱子即可在弹出的模态框中查看项目描述和其他媒体内容。

发现项目支柱之一。

轻敲柱子即可显示详细信息,包括描述和媒体。

你找到并与之互动的每一根柱子都会立即开始动起来。这有助于你直观地分辨哪些柱子你已经访问过,哪些还没有。总而言之,它提供了一种非常有趣且独特的体验,让你在浏览我全部作品的同时,也能欣赏这个小世界的景色和声音。

工具和技术

在着手设计这个网站时,我立刻就决定要打造一个外观和感觉都像传统2D俯视角角色扮演游戏的界面。同时,它还必须符合现有浏览器API和现代Web技术的限制。因此,使用canvas元素和WebGL是必然之选。两者结合,可以让你在2D或3D环境中渲染图形。对于2D来说,这意味着绘制矩形、圆形等基本形状以及图像(纹理),所有这些都可以通过与最终用户的直接交互和输入来实现。这些要素结合起来,就构成了游戏的基本组成部分。

游戏渲染

我早期的原型使用了纯 HTML 和 JavaScript,并搭配了一个 canvas 元素。这意味着一切都要从零开始构建。然而,我很快意识到,对于这种规模的演示来说,这种方法并不适用。我缺乏游戏开发的基本要素,例如动画精灵图,而且发现交互也相当棘手。因此,我最终选择了使用 Pixi.js。

如果您还不熟悉 Pixi,它相比标准的画布集成提供了多项提升用户体验的功能和改进。这些功能包括但不限于:

  • 容器:允许您创建一组元素,类似于 Unity 等引擎中的游戏对象。

  • 纹理:可在场景中使用的预加载图像资源。

  • 图形:动态渲染的图元,例如矩形、弧线等。

  • 精灵/精灵图:通常由一个或多个图形或纹理组成。Pixi 甚至提供动画精灵图,它使用基于行和列的引用,从单个图像中创建角色动画。

  • 交互:Pixi API 提供了一种非常便捷的方式来监听和响应场景中任何对象的事件。
    渲染循环:一个标准化的循环,用于处理动画并监控场景中的时间流逝。

  • 文本:直接支持文本、字体,甚至栅格化位图,以实现高性能。

Web应用程序框架

接下来,我知道我需要使用 UI 组件和一个功能齐全的 Web 应用框架来构建网站的基础架构。为此,我选择了SvelteSveltekit 。它们组合起来可以起到类似于AngularNext.js(用于 React)和Nuxt(用于 Vue)等工具的作用

我通过 Svelte 和 Sveltekit 大量使用了以下功能:

  • 组件:指构成网站基础结构的可重用代码块/模板/样式。例如可重用的页脚、页面模板等。

  • 路由:Sveltekit 提供了一个很棒的基于文件的路由系统,可以帮助控制我的网站和页面的导航。

  • 状态管理:通过 Svelte 可写对象进行管理。数据存储采用类似发布/订阅模型的数据流。

  • 构建与打包:Sveltekit 是基于Vite开发的,Vite 是由 Evan You(Vue 的开发者)创建的构建工具。它提供了一套非常快速且响应迅速的工具集,用于创建本地服务器、处理热模块刷新、TypeScript 编译、构建、打包等等。

风格与设计

最后,我需要一些方法来设置和控制每个页面和组件的布局和设计。为此,我选择了Tailwind CSS。Tailwind提供了一整套实用的 CSS 类,同时还允许你通过任意覆盖来“打破常规”。它确实需要一些时间来适应,但如果运用得当,它可以显著提高工作效率。它与 Svelte、React 或 Vue 等组件库配合使用效果非常好。

整合所有信息

虽然每种工具本身都很出色,但构建 Web 应用程序(无论规模大小)的关键挑战之一在于如何找到合适的方法让所有组件协同工作。我想花些时间解释一下我是如何将所有组件组合在一起,构建用户体验中最关键的部分,重点关注核心游戏功能。

Pixi 组件

我遇到的第一个挑战是确定画布元素的放置位置,以及如何使用 Pixi 开始渲染到屏幕上。为此,我选择了一个简单的独立组件。这使我能够创建一个基本的游戏管理器,并将所有逻辑、布局和样式都包含在一个文件中。这样一来,在共享引用之间快速轻松地切换和迭代代码就变得非常容易。

大致的操作顺序如下:

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

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

  3. Pixi 加载器会加载一组静态资源,确保所有必需元素都已预先加载完毕。点击即可在屏幕上显示加载进度条。

  4. 游戏应用完全加载后,会经历一系列步骤……

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

  6. 接下来,初始化相机类,它主要控制关卡容器在二维世界空间中的 x/y 位置。我将在下文详细解释这一点。

  7. 我初始化了一个网格类,该类可以选择性地启用,以便在屏幕上直观地显示各个“图块”的分割情况和坐标,用于调试目的。这里的图块底边大小为 16x16 像素。

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

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

  10. 加载完成后,我调整相机焦点,使之以我的角色为中心。

  11. 最终,游戏渲染循环启动,所有动画和动作得以实现。摄像机、容器关卡和实体各自的渲染方法会在每一帧更新。

相机控制

在二维虚拟空间中渲染时,摄像机的处理会带来一些有趣的挑战。如果您使用过 Unity 或 Godot 等引擎开发游戏,可能会觉得这些处理理所当然,因为大多数引擎都提供了开箱即用的摄像机功能。但 Pixi 和 Canvas 则需要您自行解决。其中一种方法需要为最终用户制造一些视觉错觉。我在下面提供了一张插图来帮助您理解。

由于画布(红色)固定在可见页面画布内,它本身无法移动。因此,摄像机的移动效果是通过移动画布区域内渲染的内容来实现的。这通常需要创建一个容器来容纳游戏世界地图(绿色)。该容器还可以包含子元素,例如NPC、生物和建筑物(蓝色)。

游戏中不再像《超级马里奥64》那样有个小人扛着摄像机跟着你走,而是地图和会动的小孩!这真是一个巧妙的设计,而且效果非常好。

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

游戏对象

游戏对象并非 Pixi 的固有概念,而是借鉴自 Unity。这些对象可以呈现游戏中存在的任何事物。通常的做法是创建一个包含视觉元素(例如动画精灵)的容器元素(例如组),并将该容器元素与包含对象如何与游戏世界交互的逻辑和规则的代码配对。

非玩家角色(NPC)就是一个很好的例子。在我的游戏中,我有多个NPC实体,每个实体都包含用于视觉待机和行走动画的动画精灵。此外,每个实体还包含一组逻辑,用于处理鼠标悬停并点击实体时发生的情况。

实现这一目标的常用方法是使用面向对象编程(简称 OOP)。OOP 涉及创建结构化的类,该类描述对象的属性以及其运行逻辑。可以实例化一个或多个此类,从而创建该实体的独立副本。

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

核心 GameObject 类,所有实体都使用或继承它。

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

不过,你可能会问,当你需要超出基类 GameObject 范围的属性或功能时该怎么办?这时,面向对象编程的另一个关键特性——类继承——就派上用场了。为此,我创建了一个继承自 GameObject 的独立类。这意味着它继承了基类的所有属性和方法,同时仍然允许你重写或扩展这种特殊实体类型的功能。

我巧妙地运用了这种方法来设计游戏开始时出现的NPC角色——猫咪莱拉。我创建了一个继承自GameObject基类的Cat类,这意味着她仍然可以拥有自己的名字、动画精灵,并触发对话框等功能。同时,我还能重写和扩展她的基础功能。在这个例子中,Cat类型的实体可以根据鼠标位置沿X轴翻转精灵。这使得她看起来像是在跟随屏幕上的鼠标光标移动。这是猫咪独有的特性,因为我们都知道猫咪喜欢追逐老鼠!

总结

虽然还有很多内容我想介绍,但或许应该留到以后的文章中再谈!不过,如果您对网站的搭建过程感兴趣,欢迎您查看源代码,源代码已上传至 GitHub:
GitHub - endigo9740/endigo-design:Chris Simmons 的作品集

如果您想进一步了解情况并直接向我提问,我提供了多种联系方式。

感谢您的阅读,请尽情享受本网站!

文章来源:https://dev.to/endigo9740/my-new-portfolio-3ke6