假设您有一个由世界,玩家和老板组成的场景。哦,这是第三人称游戏,所以您也有摄像头。
因此,您的场景如下所示:
class Scene {
World* world
Player* player
Enemy* boss
Camera* camera
}
(至少,这是基本数据。如何包含数据取决于您自己。)
您只想在玩游戏时而不是在暂停时或在主菜单中更新和渲染场景,因此您可以将其附加到游戏状态!
State* gameState = new State();
gameState->addScene(scene);
现在,您的游戏状态有了一个场景。接下来,您要在场景上运行逻辑并渲染场景。对于逻辑,您只需运行更新功能。
State::update(double delta) {
scene->update(delta);
}
这样,您可以将所有游戏逻辑都保留在Scene
类中。只是为了参考,实体组件系统可能会这样做:
State::update(double delta) {
physicsSystem->applyPhysics(scene);
}
无论如何,您现在已经设法更新了场景。现在您要显示它!为此,我们执行与上面类似的操作:
State::render() {
renderSystem->render(scene);
}
你去。renderSystem从场景中读取信息,并显示适当的图像。简化后,渲染场景的方法可能如下所示:
RenderSystem::renderScene(Scene* scene) {
Camera* camera = scene->camera;
lookAt(camera); // Set up the appropriate viewing matrices based on
// the camera location and direction
renderHeightmap(scene->getWorld()->getHeightMap()); // Just as an example, you might
// use a height map as your world
// representation.
renderModel(scene->getPlayer()->getType()); // getType() will return, for example "orc"
// or "human"
renderModel(scene->getBoss()->getType());
}
确实简化了,例如,您仍然需要根据玩家所在的位置和观看的位置应用旋转和平移。(我的示例是3D游戏,如果使用2D,它将是在公园散步)。
我希望这是您想要的?正如您希望从上述内容中回忆到的那样,渲染系统不在乎游戏的逻辑。它仅使用场景的当前状态进行渲染,即从场景中提取必要的信息以进行渲染。和游戏逻辑?不管渲染器做什么。哎呀,根本不显示它!
而且您也不需要将渲染信息附加到场景。渲染器知道需要渲染兽人就足够了。您已经加载了一个Orc模型,渲染器随后便知道该模型可以显示。
这应该满足您的要求。图形表示和逻辑是耦合的,因为它们都使用相同的数据。但是它们是分开的,因为两者都不依赖对方!
编辑:只是为了回答为什么人们会这样做呢?因为更容易是最简单的原因。您无需考虑“这样的情况,我现在应该更新图形”。取而代之的是让事情发生,游戏的每个帧都会查看当前正在发生的事情,并以某种方式对其进行解释,从而为您提供屏幕上的效果。