添加简单物理模拟模式功能

This commit is contained in:
2025-06-24 22:08:22 +08:00
parent a32ce57503
commit fdb1ada6cd
7 changed files with 203 additions and 47 deletions

View File

@ -21,6 +21,6 @@ file(GLOB_RECURSE SOURCES
src/logo/logo.rc
)
add_executable(${PROJECT_NAME} ${SOURCES})
add_executable(${PROJECT_NAME} WIN32 ${SOURCES})
target_link_libraries(${PROJECT_NAME} PRIVATE Hazel)

View File

@ -38,8 +38,9 @@ namespace Hazel
m_LogoTexture = Texture2D::Create("assets/textures/iceLogo.png");
m_CheckerBoardTexture = Texture2D::Create("assets/textures/Checkerboard.png");
m_PlayIcon = Texture2D::Create("Resources/Icons/PlayButton.png");
m_StopIcon = Texture2D::Create("Resources/Icons/PauseButton.png");
m_IconPlay = Texture2D::Create("Resources/Icons/PlayButton.png");
m_IconStop = Texture2D::Create("Resources/Icons/PauseButton.png");
m_IconSimulate = Texture2D::Create("Resources/Icons/SimulateButton.png");
m_EditorScene = CreateRef<Scene>();
m_EditorScene->OnViewportResize((uint32_t)m_ViewPortSize.x, (uint32_t)m_ViewPortSize.y);
@ -94,6 +95,10 @@ namespace Hazel
m_EditorCamera.OnUpdate(ts);
m_ActiveScene->OnUpdateEditor(ts, m_EditorCamera);
break;
case SceneState::Simulate:
m_EditorCamera.OnUpdate(ts);
m_ActiveScene->OnUpdateSimulation(ts, m_EditorCamera);
break;
}
@ -127,8 +132,12 @@ namespace Hazel
if (m_SceneState == SceneState::Play)
{
Entity camera = m_ActiveScene->GetPrimaryCameraEntity();
Renderer2D::BeginScene(camera.GetComponent<CameraComponent>().Camera, camera.GetComponent<TransformComponent>().GetTransform());
if (camera)
Renderer2D::BeginScene(camera.GetComponent<CameraComponent>().Camera, camera.GetComponent<TransformComponent>().GetTransform());
else
Renderer2D::BeginScene(m_EditorCamera);
}else
{
Renderer2D::BeginScene(m_EditorCamera);
@ -137,6 +146,46 @@ namespace Hazel
if (m_ShowPhysicsColliders)
{
// box collider
auto bcview = m_ActiveScene->GetAllEntitiesWith<TransformComponent, BoxCollider2DComponent>();
for (auto entity : bcview)
{
auto [tc, bc2D] = bcview.get<TransformComponent, BoxCollider2DComponent>(entity);
glm::vec3 scaledOffset = glm::vec3(
bc2D.Offset.x * tc.Scale.x,
bc2D.Offset.y * tc.Scale.y,
0.0f
);
glm::vec3 translation1 = tc.Translation + scaledOffset + glm::vec3(0.0f, 0.0f, 0.001f);
// 创建完整的模型变换矩阵
glm::mat4 model = glm::translate(glm::mat4(1.0f), translation1)
* glm::rotate(glm::mat4(1.0f), tc.Rotation.z, glm::vec3(0.0f, 0.0f, 1.0f))
* glm::scale(glm::mat4(1.0f), tc.Scale);
// 将 offset 从局部空间变换到世界空间
glm::vec4 worldOffset = model * glm::vec4(bc2D.Offset.x, bc2D.Offset.y, 0.0f, 1.0f);
// 最终位置 = 实体位置 + 变换后的offset + Z偏移
glm::vec3 translation = glm::vec3(worldOffset) + glm::vec3(0.0f, 0.0f, 0.001f);
// 计算缩放 (Size 是半宽半高所以要乘2)
glm::vec3 scale = tc.Scale * glm::vec3(bc2D.Size * 2.0f, 1.0f);
// 创建碰撞体变换矩阵 (包含旋转)
glm::mat4 transform =
glm::translate(glm::mat4(1.0f), translation)
* glm::rotate(glm::mat4(1.0f), tc.Rotation.z, glm::vec3(0.0f, 0.0f, 1.0f))
* glm::scale(glm::mat4(1.0f), scale);
Renderer2D::DrawRect(transform, glm::vec4(0.2f, 1.0f, 0.2f, 1.0f));
}
/*
auto bcview = m_ActiveScene->GetAllEntitiesWith<TransformComponent, BoxCollider2DComponent>();
for (auto entity : bcview)
{
@ -149,6 +198,7 @@ namespace Hazel
Renderer2D::DrawRect(transform, glm::vec4(0.2, 1.0f, 0.2f, 1.0f));
}
*/
// circle collider
auto ccview = m_ActiveScene->GetAllEntitiesWith<TransformComponent, CircleCollider2DComponent>();
for (auto entity : ccview)
@ -357,7 +407,7 @@ namespace Hazel
cameraProjection = camera.GetProjection();
cameraView = glm::inverse(cameraEntity.GetComponent<TransformComponent>().GetTransform());
}else if (m_SceneState == SceneState::Edit)
}else
{
cameraProjection = m_EditorCamera.GetProjection();
cameraView = m_EditorCamera.GetViewMatrix();
@ -477,6 +527,9 @@ namespace Hazel
void EditorLayer::OnScenePlay()
{
if (m_SceneState == SceneState::Simulate)
OnSceneStop();
// SaveScene();
m_SceneState = SceneState::Play;
@ -488,9 +541,31 @@ namespace Hazel
void EditorLayer::OnSceneStop()
{
if (m_SceneState != SceneState::Play && m_SceneState != SceneState::Simulate)
{
HZ_CORE_WARN("Scene is not playing or simulating!");
return;
}
if (m_SceneState == SceneState::Play)
m_ActiveScene->OnRuntimeStop();
else if (m_SceneState == SceneState::Simulate)
m_ActiveScene->OnSimulationStop();
m_SceneState = SceneState::Edit;
m_ActiveScene->OnRuntimeStop();
m_ActiveScene = m_EditorScene;
m_SceneHierachyPanel.SetContext(m_ActiveScene);
}
void EditorLayer::OnSceneSimulation()
{
if (m_SceneState == SceneState::Simulate)
OnSceneStop();
// SaveScene();
m_SceneState = SceneState::Simulate;
m_ActiveScene = Scene::Copy(m_EditorScene);
m_ActiveScene->OnSimulationStart();
m_SceneHierachyPanel.SetContext(m_ActiveScene);
}
@ -583,18 +658,30 @@ namespace Hazel
// ImGui::Begin("##ToolBar", nullptr);
float size = ImGui::GetWindowHeight() - 10.0f;
Ref<Texture2D> icon = m_SceneState == SceneState::Edit ? m_PlayIcon : m_StopIcon;
ImGui::SetCursorPosX(ImGui::GetWindowContentRegionMax().x * 0.5f - size * 0.5f);
ImGui::SetCursorPosX(ImGui::GetWindowContentRegionMax().x * 0.5f - (size * 0.5f));
if (ImGui::ImageButton("toolbar", icon->GetRendererID(), ImVec2{size, size}, ImVec2{0, 0}, ImVec2{1, 1}))
Ref<Texture2D> icon = (m_SceneState == SceneState::Edit || m_SceneState == SceneState::Simulate)? m_IconPlay : m_IconStop;
if (ImGui::ImageButton("toolbar-play-edit", icon->GetRendererID(), ImVec2{size, size}, ImVec2{0, 0}, ImVec2{1, 1}))
{
if (m_SceneState == SceneState::Edit)
if (m_SceneState == SceneState::Edit || m_SceneState == SceneState::Simulate)
OnScenePlay();
else if (m_SceneState == SceneState::Play)
OnSceneStop();
}
ImGui::SameLine();
{
Ref<Texture2D> icon = (m_SceneState == SceneState::Edit || m_SceneState == SceneState::Play)? m_IconSimulate : m_IconStop;
if (ImGui::ImageButton("toolbar-simulate", icon->GetRendererID(), ImVec2{size, size}, ImVec2{0, 0}, ImVec2{1, 1}))
{
if (m_SceneState == SceneState::Edit || m_SceneState == SceneState::Play)
OnSceneSimulation();
else if (m_SceneState == SceneState::Simulate)
OnSceneStop();
}
}
ImGui::PopStyleVar(2);
ImGui::PopStyleColor(3);
ImGui::End();

View File

@ -27,8 +27,10 @@ namespace Hazel
void UI_ToolBar();
void OnScenePlay();
void OnSceneSimulation();
void OnSceneStop();
void SaveSceneAs() const;
void OpenScene();
void OpenScene(const std::filesystem::path& scenePath);
@ -76,12 +78,12 @@ namespace Hazel
enum class SceneState
{
Edit = 0, Play = 1
Edit = 0, Play = 1, Simulate = 2
};
SceneState m_SceneState = SceneState::Edit;
Ref<Texture2D> m_PlayIcon, m_StopIcon;
Ref<Texture2D> m_IconPlay, m_IconStop, m_IconSimulate;
};
}