feat: add firstpersoncontroller
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
#include <components/FirstPersonController.h>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
#include <glm/gtx/norm.hpp>
|
||||
|
||||
#include <destrum/Components/Physics/CapsuleCollider.h>
|
||||
#include <destrum/Components/Physics/Rigidbody.h>
|
||||
#include <destrum/Input/InputManager.h>
|
||||
#include <destrum/ObjectModel/GameObject.h>
|
||||
#include <destrum/Physics/PhysicsWorld.h>
|
||||
#include <destrum/Scene/Scene.h>
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
FirstPersonController::FirstPersonController(GameObject& parent)
|
||||
: Component(parent, "FirstPersonController")
|
||||
{
|
||||
}
|
||||
|
||||
void FirstPersonController::SetMouseCaptured(bool captured)
|
||||
{
|
||||
InputManager::GetInstance().SetMouseCaptured(captured);
|
||||
}
|
||||
|
||||
void FirstPersonController::Start()
|
||||
{
|
||||
auto* obj = GetGameObject();
|
||||
m_Capsule = obj->AddComponent<CapsuleCollider>(0.5f, 2.0f);
|
||||
m_Rigidbody = obj->AddComponent<Rigidbody>();
|
||||
m_Rigidbody->SetMass(80.0f);
|
||||
m_Rigidbody->SetAllowSleep(false);
|
||||
m_Rigidbody->SetUseGravity(true);
|
||||
}
|
||||
|
||||
void FirstPersonController::Update(float)
|
||||
{
|
||||
const auto& input = InputManager::GetInstance();
|
||||
|
||||
if (input.WasKeyPressed(SDL_SCANCODE_F5))
|
||||
{
|
||||
SetMouseCaptured(!IsMouseCaptured());
|
||||
}
|
||||
|
||||
if (!IsMouseCaptured())
|
||||
{
|
||||
if (input.WasMousePressed(SDL_BUTTON_LEFT) && !ImGui::GetIO().WantCaptureMouse)
|
||||
{
|
||||
SetMouseCaptured(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (input.WasKeyPressed(SDL_SCANCODE_ESCAPE))
|
||||
{
|
||||
SetMouseCaptured(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (input.WasKeyPressed(SDL_SCANCODE_SPACE) && m_Rigidbody->HasPhysicsBody())
|
||||
{
|
||||
m_Rigidbody->AddImpulse(glm::vec3(0.0f, 400.0f, 0.0f));
|
||||
}
|
||||
|
||||
m_Yaw += static_cast<float>(input.MouseDeltaX()) * m_MouseSensitivity;
|
||||
m_Pitch -= static_cast<float>(input.MouseDeltaY()) * m_MouseSensitivity;
|
||||
m_Pitch = glm::clamp(m_Pitch, glm::radians(-89.0f), glm::radians(89.0f));
|
||||
}
|
||||
|
||||
void FirstPersonController::FixedUpdate(float)
|
||||
{
|
||||
if (!IsMouseCaptured() || m_Rigidbody == nullptr || !m_Rigidbody->HasPhysicsBody())
|
||||
return;
|
||||
|
||||
const auto& input = InputManager::GetInstance();
|
||||
|
||||
const float cosY = glm::cos(m_Yaw);
|
||||
const float sinY = glm::sin(m_Yaw);
|
||||
const glm::vec3 forward{cosY, 0.0f, sinY};
|
||||
const glm::vec3 right{-sinY, 0.0f, cosY};
|
||||
|
||||
glm::vec3 moveDir(0.0f);
|
||||
if (input.IsKeyDown(SDL_SCANCODE_W)) moveDir += forward;
|
||||
if (input.IsKeyDown(SDL_SCANCODE_S)) moveDir -= forward;
|
||||
if (input.IsKeyDown(SDL_SCANCODE_D)) moveDir += right;
|
||||
if (input.IsKeyDown(SDL_SCANCODE_A)) moveDir -= right;
|
||||
|
||||
glm::vec3 velocity(0.0f);
|
||||
if (glm::length2(moveDir) > 0.0f)
|
||||
{
|
||||
moveDir = glm::normalize(moveDir);
|
||||
velocity = moveDir * m_MovementSpeed;
|
||||
}
|
||||
|
||||
velocity.y = m_Rigidbody->GetLinearVelocity().y;
|
||||
m_Rigidbody->SetLinearVelocity(velocity);
|
||||
|
||||
auto* world = m_Rigidbody->GetPhysicsWorld();
|
||||
if (world != nullptr)
|
||||
{
|
||||
PhysicsTransform xform = world->GetBodyTransform(m_Rigidbody->GetBody());
|
||||
xform.rotation = glm::quat(glm::vec3(0.0f, m_Yaw, 0.0f));
|
||||
world->SetBodyTransform(m_Rigidbody->GetBody(), xform);
|
||||
}
|
||||
}
|
||||
|
||||
void FirstPersonController::ImGuiInspector()
|
||||
{
|
||||
Component::ImGuiInspector();
|
||||
ImGui::DragFloat("Movement Speed", &m_MovementSpeed, 0.1f, 0.0f, 100.0f);
|
||||
ImGui::DragFloat("Mouse Sensitivity", &m_MouseSensitivity, 0.0001f, 0.0f, 0.1f);
|
||||
ImGui::DragFloat("Eye Height", &m_EyeHeight, 0.01f, 0.0f, 5.0f);
|
||||
ImGui::Text("Yaw: %.1f deg", glm::degrees(m_Yaw));
|
||||
ImGui::Text("Pitch: %.1f deg", glm::degrees(m_Pitch));
|
||||
bool captured = IsMouseCaptured();
|
||||
ImGui::Checkbox("Mouse Captured", &captured);
|
||||
if (captured != IsMouseCaptured()) {
|
||||
SetMouseCaptured(captured);
|
||||
}
|
||||
}
|
||||
|
||||
nlohmann::json FirstPersonController::Serialize() const
|
||||
{
|
||||
return {
|
||||
{"movementSpeed", m_MovementSpeed},
|
||||
{"mouseSensitivity", m_MouseSensitivity},
|
||||
{"eyeHeight", m_EyeHeight},
|
||||
{"yaw", m_Yaw},
|
||||
{"pitch", m_Pitch},
|
||||
};
|
||||
}
|
||||
|
||||
void FirstPersonController::Deserialize(const nlohmann::json& data)
|
||||
{
|
||||
if (data.contains("movementSpeed")) m_MovementSpeed = data.at("movementSpeed").get<float>();
|
||||
if (data.contains("mouseSensitivity")) m_MouseSensitivity = data.at("mouseSensitivity").get<float>();
|
||||
if (data.contains("eyeHeight")) m_EyeHeight = data.at("eyeHeight").get<float>();
|
||||
if (data.contains("yaw")) m_Yaw = data.at("yaw").get<float>();
|
||||
if (data.contains("pitch")) m_Pitch = data.at("pitch").get<float>();
|
||||
}
|
||||
Reference in New Issue
Block a user