搜索
首页web前端js教程用三分,react和webGL构建游戏

Building a Game with Three.js, React and WebGL

核心要点

  • 使用React驱动游戏开发中的3D场景,具有诸多优势,包括清晰地将场景渲染与游戏逻辑分离,易于理解的组件,游戏资源的实时重载,以及能够使用原生浏览器工具将3D场景作为标记进行检查和调试。
  • react-three-renderer (R3R) 提供了一个声明式API,它封装了Three.js,允许将视图代码与游戏逻辑解耦,并创建小型易于理解的组件。
  • 随着游戏引擎的增长,使用reducer模式将游戏逻辑组织成单独的函数至关重要。这种模式允许创建简洁明了的游戏循环,并轻松地向游戏循环添加更多逻辑。
  • 使用Three.js、React和WebGL构建游戏的过程中,调试和性能方面的考虑是独一无二的。使用Chrome DevTools的时间轴功能对于调试性能来说非常宝贵,而实现诸如最小化React中重新渲染次数之类的策略可以帮助优化性能。

我正在制作一款名为“变色龙魅力”的游戏。它使用Three.js、React和WebGL构建。本文介绍了这些技术如何使用react-three-renderer(缩写为R3R)协同工作。

请查看SitePoint上的《WebGL入门指南》和《React和JSX入门指南》,了解React和WebGL的介绍。本文和随附的代码使用ES6语法。

Building a Game with Three.js, React and WebGL

一切的开始

一段时间前,Pete Hunt在#reactjs IRC频道中开了一个玩笑,说要用React来制作游戏:

我敢打赌我们可以用React制作一款第一人称射击游戏!敌人有

等等。我笑了。他也笑了。大家都玩得很开心。“世界上谁会这么做?”我想。

几年后,我做的正是这件事。

Building a Game with Three.js, React and WebGL

《变色龙魅力》是一款收集增强道具的游戏,这些道具会让你缩小以解决无限分形迷宫。我已经做了几年的React开发者,我很想知道是否有办法使用React驱动Three.js。这时,R3R吸引了我的注意。

为什么选择React?

我知道你在想什么:为什么?请容我解释一下。以下是一些考虑使用React驱动3D场景的原因:

  • “声明式”视图允许你清晰地将场景渲染与游戏逻辑分离。
  • 设计易于理解的组件,例如<player></player><wall></wall><level></level>等等。
  • 游戏资源的“热”(实时)重载。更改纹理和模型,并实时查看它们在场景中的更新!
  • 使用原生浏览器工具(如Chrome检查器)将3D场景作为标记进行检查和调试。
  • 使用Webpack在依赖关系图中管理游戏资源,例如<texture require="" src="%7B"></texture>

让我们设置一个场景来了解这一切是如何工作的。

React和WebGL

我创建了一个示例GitHub存储库来配合本文。克隆存储库并按照README中的说明运行代码并继续学习。它以SitePointy 3D机器人为主角!

Building a Game with Three.js, React and WebGL

警告:R3R仍在测试阶段。其API不稳定,将来可能会发生变化。目前它只处理Three.js的一个子集。我发现它足够完整,可以构建一个完整的游戏,但你的结果可能会有所不同。

组织视图代码

使用React驱动WebGL的主要好处是我们的视图代码与游戏逻辑解耦。这意味着我们渲染的实体是小而易于理解的组件。

R3R公开了一个封装Three.js的声明式API。例如,我们可以编写:

<code><scene>></scene>
  <perspectivecamera>    position={ new THREE.Vector3( 1, 1, 1 )
  />
>
</perspectivecamera></code>

现在我们有一个带有摄像机的空3D场景。向场景添加网格就像包含<mesh></mesh>组件并赋予它<geometry></geometry><material></material>一样简单。

<code><scene>></scene>
  …
  <mesh>></mesh>
    <boxgeometry></boxgeometry>      width={ 1 }
      height={ 1 }
      depth={ 1 }
    />
    <meshbasicmaterial></meshbasicmaterial>      color={ 0x00ff00 }
    />
>
</code>

在幕后,这将创建一个THREE.Scene并自动添加一个带有THREE.BoxGeometry的网格。R3R处理旧场景与任何更改的差异。如果你向场景添加一个新的网格,则不会重新创建原始网格。就像使用普通的React和DOM一样,3D场景只更新差异。

因为我们在React中工作,所以我们可以将游戏实体分离到组件文件中。示例存储库中的Robot.js文件演示了如何使用纯React视图代码表示主要角色。它是一个“无状态函数”组件,这意味着它不保存任何本地状态:

<code>const Robot = ({ position, rotation }) => <group></group>  position={ position }
  rotation={ rotation }
>
  <mesh> rotation={ localRotation }></mesh>
    <geometryresource></geometryresource>      resourceId="robotGeometry"
    />
    <materialresource></materialresource>      resourceId="robotTexture"
    />
  >
>;
</code>

现在我们将<robot></robot>包含在我们的3D场景中!

<code><scene>></scene>
  …
  <mesh>></mesh>…>
  <robot></robot>    position={…}
    rotation={…}
  />
>
</code>

你可以在R3R GitHub存储库上查看更多API示例,或者在随附的项目中查看完整的示例设置。

组织游戏逻辑

等式的另一半是处理游戏逻辑。让我们给我们的机器人SitePointy添加一些简单的动画。

Building a Game with Three.js, React and WebGL

传统的游戏循环是如何工作的?它们接受用户输入,分析旧的“世界状态”,并返回新的世界状态以进行渲染。为方便起见,让我们将“游戏状态”对象存储在组件状态中。在一个更成熟的项目中,你可以将游戏状态移动到Redux或Flux存储中。

我们将使用浏览器的requestAnimationFrame API回调来驱动我们的游戏循环,并在GameContainer.js中运行循环。为了动画化机器人,让我们根据传递给requestAnimationFrame的时间戳计算一个新的位置,然后将新的位置存储在状态中。

<code><scene>></scene>
  <perspectivecamera>    position={ new THREE.Vector3( 1, 1, 1 )
  />
>
</perspectivecamera></code>

调用setState()将触发子组件的重新渲染,并更新3D场景。我们将状态从容器组件传递到演示性<game></game>组件:

<code><scene>></scene>
  …
  <mesh>></mesh>
    <boxgeometry></boxgeometry>      width={ 1 }
      height={ 1 }
      depth={ 1 }
    />
    <meshbasicmaterial></meshbasicmaterial>      color={ 0x00ff00 }
    />
>
</code>

我们可以应用一个有用的模式来帮助组织这段代码。更新机器人位置是一个简单的基于时间的计算。将来,它还可能考虑来自先前游戏状态的先前机器人位置。一个接受一些数据、处理它并返回新数据的函数通常被称为reducer。我们可以将移动代码抽象成一个reducer函数!

现在我们可以编写一个简洁明了的游戏循环,其中只包含函数调用:

<code>const Robot = ({ position, rotation }) => <group></group>  position={ position }
  rotation={ rotation }
>
  <mesh> rotation={ localRotation }></mesh>
    <geometryresource></geometryresource>      resourceId="robotGeometry"
    />
    <materialresource></materialresource>      resourceId="robotTexture"
    />
  >
>;
</code>

要向游戏循环添加更多逻辑,例如处理物理,请创建另一个reducer函数并将其传递给先前reducer的结果:

<code><scene>></scene>
  …
  <mesh>></mesh>…>
  <robot></robot>    position={…}
    rotation={…}
  />
>
</code>

随着游戏引擎的增长,将游戏逻辑组织成单独的函数变得至关重要。使用reducer模式,这种组织非常简单。

资源管理

这仍然是R3R的一个发展领域。对于纹理,你可以在JSX标签上指定一个url属性。使用Webpack,你可以要求本地图像路径:

<code>// …
gameLoop( time ) {
  this.setState({
    robotPosition: new THREE.Vector3(
      Math.sin( time * 0.01 ), 0, 0
    )
  });
}
</code>

有了这个设置,如果你更改磁盘上的图像,你的3D场景将实时更新!这对于快速迭代游戏设计和内容非常宝贵。

对于其他资源(如3D模型),你仍然必须使用Three.js的内置加载器(如JSONLoader)来处理它们。我尝试过使用自定义Webpack加载器来加载3D模型文件,但最终工作量太大,没有好处。将模型视为二进制数据并使用文件加载器加载它们更容易。这仍然可以实现模型数据的实时重载。你可以在示例代码中看到这一点。

调试

R3R支持Chrome和Firefox的React开发者工具扩展。你可以像检查普通DOM一样检查你的场景!将鼠标悬停在检查器中的元素上会在场景中显示它们的边界框。你还可以将鼠标悬停在纹理定义上以查看场景中哪些对象使用这些纹理。

Building a Game with Three.js, React and WebGL

你还可以加入react-three-renderer Gitter聊天室,以获得有关调试应用程序的帮助。

性能注意事项

在构建《变色龙魅力》时,我遇到了一些此工作流程特有的性能问题。

  • 我使用Webpack的热重载时间长达30秒!这是因为每次重载都必须将大型资源写入包中。解决方案是实现Webpack的DLLPlugin,这将重载时间缩短到5秒以下。
  • 理想情况下,你的场景每帧渲染应该只调用一次setState()。在分析我的游戏后,React本身是主要的瓶颈。每帧调用setState()多次会导致双重渲染并降低性能。
  • 超过一定数量的对象后,R3R的性能将比普通的Three.js代码差。对我来说,大约是1000个对象。你可以在示例中的“基准测试”中比较R3R和Three.js。

Chrome DevTools的时间轴功能是调试性能的绝佳工具。你可以轻松地直观地检查游戏循环,而且它比DevTools的“配置文件”功能更易于阅读。

就是这样!

查看《变色龙魅力》以了解使用此设置可以实现的功能。虽然此工具链还很年轻,但我发现使用R3R的React对于清晰地组织我的WebGL游戏代码至关重要。你还可以查看小型但不断增长的R3R示例页面,以查看一些组织良好的代码示例。

本文由Mark Brown和Kev Zettler进行同行评审。感谢所有SitePoint的同行评审人员,使SitePoint的内容达到最佳状态!

使用ReactJS和WebGL构建游戏的常见问题解答(FAQ)

使用ReactJS和WebGL构建游戏的先决条件是什么?

要开始使用ReactJS和WebGL构建游戏,你需要对JavaScript、HTML和CSS有基本的了解。还需要了解ReactJS(一个流行的用于构建用户界面的JavaScript库)。此外,了解WebGL(Web图形库)(一个用于渲染交互式3D和2D图形的JavaScript API)至关重要。熟悉ES6语法、npm(Node包管理器)和命令行也将大有裨益。

如何将Unity与ReactJS集成?

可以使用react-unity-webgl包将Unity与ReactJS集成。此包允许你将Unity WebGL构建嵌入到ReactJS应用程序中。你可以使用npm安装它并将其导入到你的项目中。然后,你可以使用包提供的Unity组件将你的Unity游戏嵌入到你的ReactJS应用程序中。

使用React创建3D应用程序的不同方法有哪些?

有几种方法可以使用React创建3D应用程序。最流行的方法之一是使用Three.js,这是一个用于创建和显示动画3D计算机图形的跨浏览器JavaScript库。另一种方法是直接使用WebGL,但这可能更复杂。其他库(如react-three-fiber和react-unity-webgl)也可以用于使用React创建3D应用程序。

如何使用WebGL创建交互式3D图形?

WebGL允许你直接在浏览器中创建交互式3D图形,无需插件。你可以使用WebGL的API创建复杂的3D图形、动画和游戏。但是,WebGL的API是低级的,直接使用可能很复杂。因此,许多开发人员更喜欢使用像Three.js这样的库,这些库为WebGL提供了更高级别的接口。

react-unity-webgl在游戏开发中的作用是什么?

react-unity-webgl包允许你将Unity WebGL构建嵌入到ReactJS应用程序中。这意味着你可以使用Unity创建复杂的3D游戏,然后轻松地将它们集成到你的ReactJS应用程序中。如果你想创建一个基于Web的游戏或交互式3D应用程序,这将特别有用。

如何优化我的ReactJS和WebGL游戏以提高性能?

优化使用ReactJS和WebGL构建的游戏可能涉及多种策略。这些策略包括最小化React中的重新渲染次数,使用WebGL的内置性能功能(如requestAnimationFrame)实现流畅的动画,以及为Web优化3D模型和纹理。

我可以使用ReactJS和WebGL构建手机游戏吗?

是的,你可以使用ReactJS和WebGL构建在移动设备上的Web浏览器中运行的游戏。但是,对于原生移动游戏,你可能需要考虑使用Unity或Unreal Engine等游戏开发平台,这些平台可以直接导出到iOS和Android。

如何在我的ReactJS和WebGL游戏中处理用户输入?

可以使用标准JavaScript事件处理程序在ReactJS和WebGL游戏中处理用户输入。你可以监听键盘、鼠标和触摸事件,然后相应地更新游戏状态。ReactJS还提供合成事件,可以用来以一致的方式跨不同浏览器处理用户输入。

我可以将其他JavaScript库与ReactJS和WebGL一起使用吗?

是的,你可以将其他JavaScript库与ReactJS和WebGL一起使用。例如,你可能会使用Three.js进行3D图形处理,使用Howler.js进行音频处理,或使用Matter.js进行物理处理。关键是确保这些库可以在你的游戏中无缝协同工作。

如何调试我的ReactJS和WebGL游戏?

可以使用Web浏览器中的开发者工具调试使用ReactJS和WebGL构建的游戏。这些工具允许你检查HTML、CSS和JavaScript代码,查看控制台日志,并逐步调试代码。此外,React开发者工具是一个浏览器扩展,允许你检查React组件层次结构、道具和状态。

以上是用三分,react和webGL构建游戏的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
Python和JavaScript:了解每个的优势Python和JavaScript:了解每个的优势May 06, 2025 am 12:15 AM

Python和JavaScript各有优势,选择取决于项目需求和个人偏好。1.Python易学,语法简洁,适用于数据科学和后端开发,但执行速度较慢。2.JavaScript在前端开发中无处不在,异步编程能力强,Node.js使其适用于全栈开发,但语法可能复杂且易出错。

JavaScript的核心:它是在C还是C上构建的?JavaScript的核心:它是在C还是C上构建的?May 05, 2025 am 12:07 AM

javascriptisnotbuiltoncorc; saninterpretedlanguagethatrunsonenginesoftenwritteninc.1)javascriptwasdesignedAsalightweight,解释edganguageforwebbrowsers.2)Enginesevolvedfromsimpleterterterpretpreterterterpretertestojitcompilerers,典型地提示。

JavaScript应用程序:从前端到后端JavaScript应用程序:从前端到后端May 04, 2025 am 12:12 AM

JavaScript可用于前端和后端开发。前端通过DOM操作增强用户体验,后端通过Node.js处理服务器任务。1.前端示例:改变网页文本内容。2.后端示例:创建Node.js服务器。

Python vs. JavaScript:您应该学到哪种语言?Python vs. JavaScript:您应该学到哪种语言?May 03, 2025 am 12:10 AM

选择Python还是JavaScript应基于职业发展、学习曲线和生态系统:1)职业发展:Python适合数据科学和后端开发,JavaScript适合前端和全栈开发。2)学习曲线:Python语法简洁,适合初学者;JavaScript语法灵活。3)生态系统:Python有丰富的科学计算库,JavaScript有强大的前端框架。

JavaScript框架:为现代网络开发提供动力JavaScript框架:为现代网络开发提供动力May 02, 2025 am 12:04 AM

JavaScript框架的强大之处在于简化开发、提升用户体验和应用性能。选择框架时应考虑:1.项目规模和复杂度,2.团队经验,3.生态系统和社区支持。

JavaScript,C和浏览器之间的关系JavaScript,C和浏览器之间的关系May 01, 2025 am 12:06 AM

引言我知道你可能会觉得奇怪,JavaScript、C 和浏览器之间到底有什么关系?它们之间看似毫无关联,但实际上,它们在现代网络开发中扮演着非常重要的角色。今天我们就来深入探讨一下这三者之间的紧密联系。通过这篇文章,你将了解到JavaScript如何在浏览器中运行,C 在浏览器引擎中的作用,以及它们如何共同推动网页的渲染和交互。JavaScript与浏览器的关系我们都知道,JavaScript是前端开发的核心语言,它直接在浏览器中运行,让网页变得生动有趣。你是否曾经想过,为什么JavaScr

node.js流带打字稿node.js流带打字稿Apr 30, 2025 am 08:22 AM

Node.js擅长于高效I/O,这在很大程度上要归功于流。 流媒体汇总处理数据,避免内存过载 - 大型文件,网络任务和实时应用程序的理想。将流与打字稿的类型安全结合起来创建POWE

Python vs. JavaScript:性能和效率注意事项Python vs. JavaScript:性能和效率注意事项Apr 30, 2025 am 12:08 AM

Python和JavaScript在性能和效率方面的差异主要体现在:1)Python作为解释型语言,运行速度较慢,但开发效率高,适合快速原型开发;2)JavaScript在浏览器中受限于单线程,但在Node.js中可利用多线程和异步I/O提升性能,两者在实际项目中各有优势。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )专业的PHP集成开发工具

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

功能强大的PHP集成开发环境

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中