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是一款游戏,您在其中收集能量道具,使自己收缩以解决无限的分形迷宫。 我从事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机器人!
警告: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一些简单的动画。
传统上,游戏循环如何运作? 他们接受用户输入,分析旧的“世界状态”,并返回新的世界状态以进行渲染。 为了方便起见,让我们将“游戏状态”对象存储在组件状态中。 在更成熟的项目中,您可以将游戏状态移至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支持适用于Chrome和Firefox的React开发人员工具扩展。 您可以检查场景,就像是原始DOM! 将鼠标悬停在检查器中的元素上会在场景中显示其边界框。 您还可以将鼠标悬停在纹理定义上,以查看场景中哪些对象使用了这些纹理。
您也可以加入我们的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 Brown和Kev Zettler进行了同行评审。 感谢所有SitePoint的同行评审员使SitePoint内容达到最佳状态!
翻译自: https://www.sitepoint.com/building-a-game-reactjs-and-webgl/
react webgl