跨平台游戏编程与 gameplay3d/创建场景
场景图是一种数据结构,用于定义图形场景的空间(通常也包括逻辑)关系,以便高效管理和渲染图形数据。
它通常表示为层次结构,包含一组节点,包括一个顶级的“根”节点,一些父节点,每个父节点可以有任意数量的子节点,以及一组叶节点,每个叶节点没有子节点,因此共同构成树的底层。
在 gameplay3d 中
- 场景图由 Scene 类表示;
- Node 类实例可以附加到场景对象;
- 可以将更多 Node 类实例作为现有节点的子节点添加;并且
- 各种其他附件(例如模型、灯光、相机、物理对象)可以附加到任何节点;并且
- 对父节点执行的操作会影响其所有子节点。
创建场景、添加两个节点并以编程方式(即不使用 .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::Model |
用于表示场景中的网格/几何体。 |
gameplay::Camera |
用于表示场景中的视图/透视。 |
gameplay::Light |
用于保存灯光信息,可以影响模型的渲染方式。 |
gameplay::PhysicsCollisionObject |
用于定义将要模拟的基本物理动力学。 |
gameplay::ParticleEmitter |
用于表示烟雾、蒸汽、火焰和其他大气效果。 |
gameplay::Terrain |
用于表示基于高度图的地形。 |
gameplay::AudioSource |
用于表示音频播放的来源。 |
gameplay::Form |
用于表示场景中的用户界面。 |
你可以使用任何能够创建 FBX 文件的建模软件。由于一些 3D 建模软件对该格式的支持水平相对较低,因此在 gameplay 2.0.0 中删除了对 Collada 文件的支持,但在未来如果采用率提高,可能会重新添加。
Blender 可以导出 FBX(和 Collada)文件。我们建议使用至少 2.70 版本。即将推出的 2.71 版本具有改进的 FBX 导出功能,包括切线和副法线。
Blender 内置了 FBX 导出器。版本 2.70 可以使用。请注意以下两点重要说明,特别是如果你有动画
- Blender 和 Gameplay 具有不同的向上轴。导出 FBX 文件时,选择向上轴为 Y 轴,向前轴为 Z 轴。如果没有这个,动画将完全变形
- FBX 导出器可以创建空的动画通道。你必须使用
-oa
选项来转换用于 gameplay 的文件
现在您的模型已经导出到已知格式,为了使其可以正常使用,还需要完成最后一步。您的模型需要从导出的交换格式 .FBX 转换为游戏框架可使用的有效二进制捆绑格式。要执行此操作,请使用必要的参数运行 gameplay-encoder。
要将您的 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 文件在 gameplay3d 中组装场景,主要有两个步骤
- 创建一个描述您的场景的 .scene 文本文件;以及
- 通过调用
Scene::load()
静态方法在您的游戏代码中加载场景。
场景文件可以按照以下方式加载到您的游戏中
// Load the scene
_scene = Scene::load("res/myscene.scene");