跳转到内容

跨平台游戏编程与 gameplay3d/创建场景

来自 Wikibooks,开放世界的开放书籍


场景图概述

[编辑 | 编辑源代码]

场景图是一种数据结构,用于定义图形场景的空间(通常也包括逻辑)关系,以便高效管理和渲染图形数据。

它通常表示为层次结构,包含一组节点,包括一个顶级的“根”节点,一些父节点,每个父节点可以有任意数量的子节点,以及一组叶节点,每个叶节点没有子节点,因此共同构成树的底层。

在 gameplay3d 中

  • 场景图由 Scene 类表示;
  • Node 类实例可以附加到场景对象;
  • 可以将更多 Node 类实例作为现有节点的子节点添加;并且
  • 各种其他附件(例如模型、灯光、相机、物理对象)可以附加到任何节点;并且
  • 对父节点执行的操作会影响其所有子节点。
gameplay3d 场景图的示意图

创建场景、添加两个节点并以编程方式(即不使用 .scene 文件)附加相机和灯光的示例如下。该示例取自“sample-browser”项目中的“CreateSceneSample.cpp”。

// In your game class's initialize() method

// Create a new empty scene.
_scene = Scene::create();

// Create the camera.
Camera* camera = Camera::createPerspective(45.0f, getAspectRatio(), 1.0f, 10.0f);
Node* cameraNode = _scene->addNode("camera");

// Attach the camera to a node. This determines the position of the camera.
cameraNode->setCamera(camera);

// Make this the active camera of the scene.
_scene->setActiveCamera(camera);
SAFE_RELEASE(camera);

// Move the camera to look at the origin.
cameraNode->translate(0, 1, 5);
cameraNode->rotateX(MATH_DEG_TO_RAD(-11.25f));

// Create a white light.
Light* light = Light::createDirectional(0.75f, 0.75f, 0.75f);
Node* lightNode = _scene->addNode("light");
lightNode->setLight(light);

// Release the light because the node now holds a reference to it.
SAFE_RELEASE(light);

// Rotate the camera downwards.
lightNode->rotateX(MATH_DEG_TO_RAD(-45.0f));

通常,在使用 gameplay3d 制作游戏时

  • 你会先加载/构建一个大型场景,代表游戏关卡中需要的所有组件。这会在 Game::initialize() 中完成一次;
  • 在每次调用 Game::update() 方法时,你的代码会根据事件(例如用户输入)更新对节点和附加组件的更改;
  • 在每次调用 Game::render() 方法时,你的代码会遍历场景并渲染场景中从场景的活动相机可见的部分;并且
  • 退出时,会调用 Game::finalize() 方法,在此过程中,你将释放所有未完成的动态分配资源(参见 跨平台游戏编程与 gameplay3d/gameplay3d 设计概念#管理共享对象)。

以下组件可以附加到 gameplay::Node

可以附加到 gameplay::Node 类的组件
组件 描述
gameplay::Model 用于表示场景中的网格/几何体。
gameplay::Camera 用于表示场景中的视图/透视。
gameplay::Light 用于保存灯光信息,可以影响模型的渲染方式。
gameplay::PhysicsCollisionObject 用于定义将要模拟的基本物理动力学。
gameplay::ParticleEmitter 用于表示烟雾、蒸汽、火焰和其他大气效果。
gameplay::Terrain 用于表示基于高度图的地形。
gameplay::AudioSource 用于表示音频播放的来源。
gameplay::Form 用于表示场景中的用户界面。

关于变换顺序的说明

[编辑 | 编辑源代码]

模型和网格

[编辑 | 编辑源代码]

其他节点附件

[编辑 | 编辑源代码]

在建模软件中创建场景资产

[编辑 | 编辑源代码]

你可以使用任何能够创建 FBX 文件的建模软件。由于一些 3D 建模软件对该格式的支持水平相对较低,因此在 gameplay 2.0.0 中删除了对 Collada 文件的支持,但在未来如果采用率提高,可能会重新添加。

使用 Maya 创建场景资产

[编辑 | 编辑源代码]

使用 Blender 创建场景资产

[编辑 | 编辑源代码]

Blender 可以导出 FBX(和 Collada)文件。我们建议使用至少 2.70 版本。即将推出的 2.71 版本具有改进的 FBX 导出功能,包括切线和副法线。

导出 FBX 文件

[编辑 | 编辑源代码]

Blender 内置了 FBX 导出器。版本 2.70 可以使用。请注意以下两点重要说明,特别是如果你有动画

  • Blender 和 Gameplay 具有不同的向上轴。导出 FBX 文件时,选择向上轴为 Y 轴,向前轴为 Z 轴。如果没有这个,动画将完全变形
  • FBX 导出器可以创建空的动画通道。你必须使用 -oa 选项来转换用于 gameplay 的文件

将资产编码为 .GPB

[编辑 | 编辑源代码]

现在您的模型已经导出到已知格式,为了使其可以正常使用,还需要完成最后一步。您的模型需要从导出的交换格式 .FBX 转换为游戏框架可使用的有效二进制捆绑格式。要执行此操作,请使用必要的参数运行 gameplay-encoder。

从 FBX (.FBX) 编码

[编辑 | 编辑源代码]

要将您的 FBX 场景文件 (.fbx) 编码为 gameplay 二进制格式 (.gpb),请运行以下命令

gameplay-encoder -oa -g HIKCharacterNode_boy_Reference animations "../../gameplay-samples/sample-character/res/boy.fbx"

让我们看一下传递到编码器中的一些额外参数。

-g 参数表示您希望将 HIKCharacterNode_boy_reference 及其子节点上的所有动画分组到一个名为“animations”的动画中。-oa 选项表示您希望优化动画。如果您从 Blender 导入复杂文件,这一点非常重要,否则可能会由于空动画通道导致文件无法读取。

此编码是必要的,因为 FBX(或者在字体的情况下,TrueType 文件)实际上只是交换格式,并且是大型 ASCII 文件,不建议用作运行时格式。对它们进行编码会将它们打包到更有效的二进制捆绑包中,并且只包含游戏框架所需的数据。

使用 .scene 文件

[编辑 | 编辑源代码]

为了使用 .scene 文件在 gameplay3d 中组装场景,主要有两个步骤

  • 创建一个描述您的场景的 .scene 文本文件;以及
  • 通过调用 Scene::load() 静态方法在您的游戏代码中加载场景。

创建您的 .scene 文件

[编辑 | 编辑源代码]

在您的游戏代码中加载场景

[编辑 | 编辑源代码]

场景文件可以按照以下方式加载到您的游戏中

// Load the scene
_scene = Scene::load("res/myscene.scene");
华夏公益教科书