react webgl_使用Three.js,React和WebGL构建游戏

react webgl

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

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

拿着一个红色药片和一个蓝色药片的手,与在一条胳膊的一个变色蜥蜴。

一切如何开始

前一段时间, Pete Hunt开玩笑说在#reactjs IRC频道中使用React构建游戏:

我敢打赌,我们可以用React做第一人称射击游戏!
敌人有<Head /> <Body> <Legs>等。

我笑了。 他笑了。 每个人都玩得很开心。 “到底是谁做的?” 我想知道

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

Charisma The Chameleon的GIF游戏

Charisma The Chameleon是一款游戏,您在其中收集能量道具,使自己收缩以解决无限的分形迷宫。 我从事React开发已经有几年了,我很好奇是否有一种使用React来驱动Three.js的方法。 那是R3R引起我注意的时候。

为什么要React?

我知道您在想什么: 为什么? 幽默一下。 考虑使用React驱动3D场景的一些原因如下:

  • “声明式”视图使您可以清晰地将场景渲染与游戏逻辑分离。
  • 设计易于推理的组件,例如<Player /><Wall /><Level />等。
  • “热”(实时)重新加载游戏资产。 更改纹理和模型,并在场景中实时更新它们!
  • 使用Chrome浏览器之类的本地浏览器工具检查和调试3D场景作为标记。
  • 使用Webpack在依赖关系图中管理游戏资产,例如<Texture src={ require('../assets/image.png') } />

让我们设置一个场景,以了解这一切的工作原理。

React和WebGL

我已经创建了一个示例GitHub存储库以随附本文。 克隆存储库,并按照自述文件中的说明运行代码并遵循。 它使SitePointy成为3D机器人!

SitePointy 3D机器人截图

警告:R3R仍处于测试阶段。 其API易变,将来可能会更改。 目前,它仅处理Three.js的子集。 我发现它足以完成一个完整的游戏,但是您的里程可能会有所不同。

整理视图代码

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

R3R公开了包装Three.js的声明性API。 例如,我们可以这样写:

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

现在,我们有了带相机的空3D场景。 将网格添加到场景就像包含一个<mesh />组件并为其提供<geometry /><material />

<scene>
  …
  <mesh>
    <boxGeometry
      width={ 1 }
      height={ 1 }
      depth={ 1 }
    />
    <meshBasicMaterial
      color={ 0x00ff00 }
    />
</mesh>

在引擎盖下,这将创建THREE.Scene并自动添加带有THREE.BoxGeometry的网格。 R3R可以处理任何变化使旧场景产生差异。 如果将新网格物体添加到场景,则不会重新创建原始网格物体。 就像普通的React和DOM一样,3D场景仅使用差异进行更新。

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

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

免费学习PHP!

全面介绍PHP和MySQL,从而实现服务器端编程的飞跃。

原价$ 11.95 您的完全免费

现在,在我们的3D场景中加入<Robot />

<scene>
  …
  <mesh>…</mesh>
  <Robot
    position={…}
    rotation={…}
  />
</scene>

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

组织游戏逻辑

等式的后半部分处理游戏逻辑。 让我们给我们的机器人SitePointy一些简单的动画。

SitePointy具有生命力

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

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

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

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

render() {
  const { robotPosition } = this.state;
  return <Game
    robotPosition={ robotPosition }
  />;
}

我们可以使用一种有用的模式来帮助组织此代码。 更新机器人位置是基于时间的简单计算。 将来,它可能还会考虑先前游戏状态中的先前机器人位置。 接收某些数据,对其进行处理并返回新数据的函数通常称为reducer 。 我们可以将运动代码抽象为化简函数!

现在我们可以编写一个干净,简单的游戏循环,其中仅包含函数调用:

import robotMovementReducer from './game-reducers/robotMovementReducer.js';

// …

gameLoop() {
  const oldState = this.state;
  const newState = robotMovementReducer( oldState );
  this.setState( newState );
}

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

const newState = physicsReducer( robotMovementReducer( oldState ) );

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

资产管理

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

<texture url={ require( '../local/image/path.png' ) } />

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

对于其他资产(如3D模型),您仍然必须使用Three.js的内置加载器(如JSONLoader)对其进行处理 。 我尝试使用自定义的Webpack加载器加载3D模型文件,但最终,这样做耗费了很多精力。 将模型视为二进制数据并使用file-loader加载它们会更容易。 这样仍然可以实时重载模型数据。 您可以在示例代码中看到这一点。

调试

R3R支持适用于ChromeFirefox的React开发人员工具扩展。 您可以检查场景,就像是原始DOM! 将鼠标悬停在检查器中的元素上会在场景中显示其边界框。 您还可以将鼠标悬停在纹理定义上,以查看场景中哪些对象使用了这些纹理。

使用react-three-renderer和React devtools调试场景

您也可以加入我们的React三渲染器Gitter聊天室,以帮助调试您的应用程序。

性能考量

在构建Charisma The Chameleon时,我遇到了此工作流程特有的几个性能问题。

  • 我使用Webpack的热装时间长达三十秒! 这是因为每次重装时都必须将大型资产重新写入捆绑中。 解决方案是实施Webpack的DLLPlugin ,它将重新加载时间减少到五秒钟以下。
  • 理想情况下,场景每帧渲染应只调用一个setState() 。 对游戏进行性能分析后,React本身就是主要瓶颈。 每帧多次调用setState()会导致双重渲染并降低性能。
  • 经过一定数量的对象后, R3R的性能将不如原始Three.js代码。 对我来说,这大约有1,000个对象。 您可以在示例中的 “基准”下将R3R与Three.js进行比较。

Chrome DevTools时间轴功能是用于调试性能的出色工具。 直观地检查您的游戏循环很容易,并且比DevTools的“配置文件”功能更具可读性。

而已!

查看Charisma The Chameleon,以了解使用此设置可能发生的情况。 虽然这个工具链还很年轻,但是我发现React with R3R是整洁地组织WebGL游戏代码所不可或缺的。 您还可以查看小型但不断增长的R3R示例页面,以查看一些组织良好的代码示例。

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

翻译自: https://www.sitepoint.com/building-a-game-reactjs-and-webgl/

react webgl

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值