15.Game loops & User input

This commit is contained in:
hoenking 2025-12-18 22:40:57 +08:00
parent 2e7056c246
commit 6733eb3495
8 changed files with 121 additions and 7 deletions

Binary file not shown.

View File

@ -1,6 +1,8 @@
#include "first_app.hpp" #include "first_app.hpp"
#include "simple_render_system.hpp" #include "simple_render_system.hpp"
#include "rainbow_system.hpp" #include "rainbow_system.hpp"
#include "keyboard_movement_controller.hpp"
#include "hk_camera.hpp" #include "hk_camera.hpp"
// libs // libs
@ -11,6 +13,7 @@
// std // std
#include <stdexcept> #include <stdexcept>
#include <chrono>
#include <array> #include <array>
@ -30,18 +33,27 @@ namespace hk
SimpleRenderSystem simpleRenderSystem{m_device, m_renderer.getSwapChainRenderPass()}; SimpleRenderSystem simpleRenderSystem{m_device, m_renderer.getSwapChainRenderPass()};
RainbowSystem rainbowSystem(2000.0f); RainbowSystem rainbowSystem(2000.0f);
Camera camera{}; Camera camera{};
//camera.setViewDirection(glm::vec3(0.f), glm::vec3(0.5f, 0.f, 1.f));
camera.setViewTarget(glm::vec3(-1.f, -2.f, -2.f), glm::vec3(0.f, 0.f, 2.5f)); auto viewerObject = GameObject::createGameObject();
KeyboardMovementController cameraController{};
auto currentTime = std::chrono::high_resolution_clock::now();
while (!m_window.shouldClose()) while (!m_window.shouldClose())
{ {
glfwPollEvents(); glfwPollEvents();
auto newTime = std::chrono::high_resolution_clock::now();
float frameTime = std::chrono::duration<float, std::chrono::seconds::period>(newTime - currentTime).count();
currentTime = newTime;
cameraController.moveInPlaneXZ(m_window.getWindow(), frameTime, viewerObject);
camera.setViewYXZ(viewerObject.m_transform.translation, viewerObject.m_transform.rotation);
// update objects color // update objects color
rainbowSystem.update(5.0f, m_gameObjects); rainbowSystem.update(5.0f, m_gameObjects);
float aspect = m_renderer.getAspectRatio(); float aspect = m_renderer.getAspectRatio();
//camera.setOrthographicProjection(-aspect, aspect, -1, 1, -1, 1);
camera.setPerspectiveProjection(glm::radians(50.f), aspect, 0.1f, 10.f); camera.setPerspectiveProjection(glm::radians(50.f), aspect, 0.1f, 10.f);
if (auto commandBuffer = m_renderer.beginFrame()) if (auto commandBuffer = m_renderer.beginFrame())
{ {

View File

@ -43,6 +43,20 @@ namespace hk
m_viewMatrix[3][0] = -glm::dot(u, position); m_viewMatrix[3][0] = -glm::dot(u, position);
m_viewMatrix[3][1] = -glm::dot(v, position); m_viewMatrix[3][1] = -glm::dot(v, position);
m_viewMatrix[3][2] = -glm::dot(w, position); m_viewMatrix[3][2] = -glm::dot(w, position);
m_inverseViewMatrix = glm::mat4{1.0f};
m_inverseViewMatrix[0][0] = u.x;
m_inverseViewMatrix[0][1] = u.y;
m_inverseViewMatrix[0][2] = u.z;
m_inverseViewMatrix[1][0] = v.x;
m_inverseViewMatrix[1][1] = v.y;
m_inverseViewMatrix[1][2] = v.z;
m_inverseViewMatrix[2][0] = w.x;
m_inverseViewMatrix[2][1] = w.y;
m_inverseViewMatrix[2][2] = w.z;
m_inverseViewMatrix[3][0] = position.x;
m_inverseViewMatrix[3][1] = position.y;
m_inverseViewMatrix[3][2] = position.z;
} }
void Camera::setViewTarget(glm::vec3 position, glm::vec3 target, glm::vec3 up) void Camera::setViewTarget(glm::vec3 position, glm::vec3 target, glm::vec3 up)
{ {
@ -73,5 +87,19 @@ namespace hk
m_viewMatrix[3][0] = -glm::dot(u, position); m_viewMatrix[3][0] = -glm::dot(u, position);
m_viewMatrix[3][1] = -glm::dot(v, position); m_viewMatrix[3][1] = -glm::dot(v, position);
m_viewMatrix[3][2] = -glm::dot(w, position); m_viewMatrix[3][2] = -glm::dot(w, position);
m_inverseViewMatrix = glm::mat4{1.0f};
m_inverseViewMatrix[0][0] = u.x;
m_inverseViewMatrix[0][1] = u.y;
m_inverseViewMatrix[0][2] = u.z;
m_inverseViewMatrix[1][0] = v.x;
m_inverseViewMatrix[1][1] = v.y;
m_inverseViewMatrix[1][2] = v.z;
m_inverseViewMatrix[2][0] = w.x;
m_inverseViewMatrix[2][1] = w.y;
m_inverseViewMatrix[2][2] = w.z;
m_inverseViewMatrix[3][0] = position.x;
m_inverseViewMatrix[3][1] = position.y;
m_inverseViewMatrix[3][2] = position.z;
} }
} // namespace hk } // namespace hk

View File

@ -22,8 +22,10 @@ namespace hk
const glm::mat4& getProjection() const { return m_projectionMatrix; } const glm::mat4& getProjection() const { return m_projectionMatrix; }
const glm::mat4& getView() const { return m_viewMatrix; } const glm::mat4& getView() const { return m_viewMatrix; }
const glm::mat4& getInverseView() const { return m_inverseViewMatrix; }
private: private:
glm::mat4 m_projectionMatrix{1.0f}; glm::mat4 m_projectionMatrix{1.0f};
glm::mat4 m_viewMatrix{1.0f}; glm::mat4 m_viewMatrix{1.0f};
glm::mat4 m_inverseViewMatrix{1.0f};
}; };
} // namespace hk } // namespace hk

View File

@ -16,6 +16,8 @@ namespace hk
Window(const Window&) = delete; Window(const Window&) = delete;
Window &operator=(const Window&) = delete; Window &operator=(const Window&) = delete;
GLFWwindow* getWindow() { return m_window; }
bool shouldClose() { return glfwWindowShouldClose(m_window); } bool shouldClose() { return glfwWindowShouldClose(m_window); }
VkExtent2D getExtend() { return {static_cast<uint32_t>(m_width), static_cast<uint32_t>(m_height)}; } VkExtent2D getExtend() { return {static_cast<uint32_t>(m_width), static_cast<uint32_t>(m_height)}; }
bool wasWindowResized() { return m_framebufferResized; } bool wasWindowResized() { return m_framebufferResized; }

View File

@ -0,0 +1,42 @@
#include "keyboard_movement_controller.hpp"
namespace hk
{
void KeyboardMovementController::moveInPlaneXZ(GLFWwindow *window, float dt, GameObject &gameObject)
{
glm::vec3 rotate{0};
if (glfwGetKey(window, m_keys.lookRight) == GLFW_PRESS) rotate.y += 1.f;
if (glfwGetKey(window, m_keys.lookLeft) == GLFW_PRESS) rotate.y -= 1.f;
if (glfwGetKey(window, m_keys.lookUp) == GLFW_PRESS) rotate.x += 1.f;
if (glfwGetKey(window, m_keys.lookDown) == GLFW_PRESS) rotate.x -= 1.f;
if (glm::dot(rotate, rotate) > std::numeric_limits<float>::epsilon())
{
gameObject.m_transform.rotation += m_lookSpeed * dt * glm::normalize(rotate);
}
// limit pitch values between about +/-85ish degrees
gameObject.m_transform.rotation.x = glm::clamp(gameObject.m_transform.rotation.x, -1.5f, 1.5f);
gameObject.m_transform.rotation.y = glm::mod(gameObject.m_transform.rotation.y, glm::two_pi<float>());
float yaw = gameObject.m_transform.rotation.y;
const glm::vec3 forwardDir{sin(yaw), 0.f, cos(yaw)};
const glm::vec3 rightDir{forwardDir.z, 0.f, -forwardDir.x};
const glm::vec3 upDir{0.f, -1.f, 0.f};
glm::vec3 moveDir{0.f};
if (glfwGetKey(window, m_keys.moveForward) == GLFW_PRESS) moveDir += forwardDir;
if (glfwGetKey(window, m_keys.moveBackward) == GLFW_PRESS) moveDir -= forwardDir;
if (glfwGetKey(window, m_keys.moveRight) == GLFW_PRESS) moveDir += rightDir;
if (glfwGetKey(window, m_keys.moveLeft) == GLFW_PRESS) moveDir -= rightDir;
if (glfwGetKey(window, m_keys.moveUp) == GLFW_PRESS) moveDir += upDir;
if (glfwGetKey(window, m_keys.moveDown) == GLFW_PRESS) moveDir -= upDir;
if (glm::dot(moveDir, moveDir) > std::numeric_limits<float>::epsilon())
{
gameObject.m_transform.translation += m_moveSpeed * dt * glm::normalize(moveDir);
}
}
}

View File

@ -0,0 +1,31 @@
#pragma once
#include <hk_game_object.hpp>
#include <hk_window.hpp>
namespace hk
{
class KeyboardMovementController
{
public:
struct KeyMappings
{
int moveLeft{ GLFW_KEY_A };
int moveRight{ GLFW_KEY_D };
int moveForward{ GLFW_KEY_W };
int moveBackward{ GLFW_KEY_S };
int moveUp{ GLFW_KEY_E };
int moveDown{ GLFW_KEY_Q };
int lookLeft{ GLFW_KEY_LEFT };
int lookRight{ GLFW_KEY_RIGHT };
int lookUp{ GLFW_KEY_UP };
int lookDown{ GLFW_KEY_DOWN };
};
void moveInPlaneXZ(GLFWwindow *window, float dt, GameObject &gameObject);
KeyMappings m_keys{};
float m_moveSpeed{ 3.f };
float m_lookSpeed{ 1.5f };
};
}

View File

@ -70,13 +70,10 @@ namespace hk
{ {
m_pipeline->bind(commandBuffer); m_pipeline->bind(commandBuffer);
auto projectionView = camera.getProjection() * camera.getView(); auto projectionView = camera.getProjection() * camera.getInverseView();
for (auto &obj : gameObjects) for (auto &obj : gameObjects)
{ {
obj.m_transform.rotation.y = glm::mod(obj.m_transform.rotation.y + 0.01f, glm::two_pi<float>());
obj.m_transform.rotation.x = glm::mod(obj.m_transform.rotation.x + 0.005f, glm::two_pi<float>());
SimplePushConstantData push{}; SimplePushConstantData push{};
push.color = obj.m_color; push.color = obj.m_color;
push.transform = projectionView * obj.m_transform.mat4(); push.transform = projectionView * obj.m_transform.mat4();