文中若有代码、术语等错误,欢迎指正
113节
这节没有新功能,只是说了一些教学视频的改变和引擎的规划
-
引擎的规划
完成引擎能制作和发布像空洞骑士的2D游戏
-
教学视频
不再直播敲完新功能,再压缩简短的视频,而是直接发布直播时候写的东西。
-
其它
- 此教学视频对应的引擎应该不会即支持OpenGL又支持Vulkan,工作量很大
- 引擎的项目版本切换到2022的
114节
文中若有代码、术语等错误,欢迎指正
前言
-
此节目的
-
增加一个物理模拟运行模式
来运行给物体添加的物理效果,摄像机使用编辑模式下的摄像机。
-
区分Play运行模式的物理效果
这个模式的摄像机会变成场景里的主摄像机,而不是当前的编辑相机。
-
-
关于物理模拟模式
-
渲染的场景部分
物理模拟模式下:渲染的场景和编辑模式下一样
-
物理模拟部分
物理模拟模式下:物理模拟和Play模式下的部分一样
所以物理模拟模式编辑模式和Play模式下的交集,物理模拟模式也要复制当前编辑场景。
-
-
如何实现
添加一个图标、一个状态来控制
-
实现细节
- 物理模拟模式运行时再点击Play模式应无bug
- 物理模拟或者Play模式运行时切换Scene应无bug
- 空场景点击Play模式和物理模拟模式应无bug
关键代码+代码流程
代码流程
-
点击物理模拟模式的图标
ImGui::SameLine(); { Ref<Texture2D> icon = ( m_SceneState == SceneState::Edit || m_SceneState == SceneState::Play)? m_IconSimulate : m_IconStop; if (ImGui::ImageButton((ImTextureID)icon->GetRendererID(), ImVec2(size, size), ImVec2(0, 0), ImVec2(1, 1), 0, ImVec4(0.0f, 0.0f, 0.0f, 0.0f), tintColor) && toolbarEnabled) { // 图标可以换,但是下面的代码不会执行 if (m_SceneState == SceneState::Edit || m_SceneState == SceneState::Play) { OnSceneSimulate(); } else if (m_SceneState == SceneState::Simulate) { OnSceneStop(); } } }
-
开始物理模拟模式+场景执行物理模拟
void EditorLayer::OnSceneSimulate()// 开始物理模拟模式 { if (m_SceneState == SceneState::Play) { OnSceneStop(); // 停止物理 } m_SceneState = SceneState::Simulate; // 复制新场景给活动场景 m_ActiveScene = Scene::Copy(m_EditorScene); m_ActiveScene->OnSimulationStart(); // 复制完新场景就开始运行。场景执行物理模拟 // 当前上下文是新场景---------------------------- m_SceneHierarchyPanel.SetContext(m_ActiveScene); } void EditorLayer::OnUpdate(Timestep ts) { // Scene更新 switch (m_SceneState) { case SceneState::Simulate: { // 摄像机要更新 m_EditorCamera.OnUpdate(ts); m_ActiveScene->OnUpdateSimulation(ts, m_EditorCamera); break; } }
-
执行物理计算+渲染场景
void Scene::OnUpdateSimulation(Timestep ts, EditorCamera& camera) { // Physics { // 先script脚本影响Physics变化再当前帧渲染出来 // 迭代速度:使用更少的迭代可以提高性能,但准确性会受到影响。使用更多迭代会降低性能但会提高模拟质量 // 有点不董。。。。说啥:时间步长和迭代次数完全无关。迭代不是子步骤 // Cherno说迭代速度,多久进行一次计算模拟。好奇这个6,是多少毫秒计算6次吗? const int32_t velocityIterations = 6;// 这些参数应该移到编辑器 const int32_t positionIterations = 2; m_PhysicsWorld->Step(ts, velocityIterations, positionIterations); auto view = m_Registry.view<Rigidbody2DComponent>(); for (auto e : view) { Entity entity = { e, this }; auto& transform = entity.GetComponent<TransformComponent>(); auto& rb2d = entity.GetComponent<Rigidbody2DComponent>(); // 获取物理模拟计算后的主体 b2Body* body = (b2Body*)rb2d.RuntimeBody; // 将计算后的值赋予实体 const auto& position = body->GetPosition(); transform.Translation.x = position.x; transform.Translation.y = position.y; transform.Rotation.z = body->GetAngle();// 获取z轴角度 } // 脚本影响Pyhsics再下面渲染出来 } // Render 渲染场景 RenderScene(camera); }
代码细节
-
空场景点击Play模式和物理模拟模式应无bug
- 切换这两个状态,没有东西渲染,物理世界只会增加点消耗。
- Play按钮点击,Play模式下要切换为主摄像机,但当前场景是为空,并没有主摄像机,所以需判空不执行渲染,不然会报错。
void EditorLayer::OnOverlayRender() { // 两个不同摄像机 if (m_SceneState == SceneState::Play) { // Play模式下找主摄像机 Entity camera = m_ActiveScene->GetPrimaryCameraEntity(); if (!camera) { return; // 找不到就退出 } Renderer2D::BeginScene(camera.GetComponent<CameraComponent>().camera, camera.GetComponent<TransformComponent>().GetTransform()); } else { Renderer2D::BeginScene(m_EditorCamera); }