Skip to content

Commit

Permalink
window close handled for the user
Browse files Browse the repository at this point in the history
  • Loading branch information
durkisneer1 committed Dec 9, 2024
1 parent 973708a commit f60b960
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 43 deletions.
10 changes: 3 additions & 7 deletions docs/getting_started/create_window.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@ The following code creates a window and keeps it open until the user closes it.

while (kn::window::isOpen()) {
kn::window::pollEvent(event);
if (event.type == kn::QUIT)
kn::window::close();

kn::window::flip();
}
kn::window::quit();
Expand All @@ -36,14 +33,13 @@ Let's break down the key components that make this program function:
This function prepares the underlying graphical context, ensuring the application is ready to display content.

* Event Handling
Before entering the main game loop, an Event union is instantiated.
Before entering the main game loop, an ``Event`` union is instantiated.
This union acts as a container for user inputs and system events.
The call to ``kn::window::pollEvent(event)`` continuously monitors for user interactions or system-generated signals, populating the event union with the details of the most recent occurrence.

* Closing the Application
The event-handling system allows the program to respond dynamically to user actions.
Specifically, ``if (event.type == kn::QUIT)`` detects when the user clicks the window’s close button.
Upon detecting this event, the call to ``kn::window::close()`` ends the game loop.
By default, Kraken Engine applications close when the user clicks the window’s close button.
Upon detecting this event internally, the call to ``kn::window::close()`` ends the game loop.

* Updating the Display
``kn::window::flip()`` acts as the final piece in the game loop, swapping the back buffer to the front.
Expand Down
6 changes: 1 addition & 5 deletions example/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,8 @@ int main()
const double dt = clock.tick();

kn::window::pollEvent(event);
if (event.type == kn::QUIT ||
(event.type == kn::KEYDOWN && event.key.keysym.sym == kn::K_ESCAPE))
if (event.type == kn::KEYDOWN && event.key.keysym.sym == kn::K_ESCAPE)
kn::window::close();
if (event.type == kn::MOUSEMOTION)
if (event.type == kn::MOUSEBUTTONDOWN)
std::cout << "yes\n";

kn::window::clear({21, 18, 37});

Expand Down
25 changes: 21 additions & 4 deletions include/Input.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#pragma once

#include <SDL.h>
#include <vector>

#include "Constants.hpp"
Expand All @@ -10,7 +9,7 @@ namespace kn
namespace math
{
class Vec2;
} // namespace math
} // namespace math

namespace input
{
Expand Down Expand Up @@ -51,5 +50,23 @@ bool isKeyPressed(int key);
*/
math::Vec2 getVector(const std::vector<KEYS>& left = {}, const std::vector<KEYS>& right = {},
const std::vector<KEYS>& up = {}, const std::vector<KEYS>& down = {});
} // namespace input
} // namespace kn

// /**
// * @brief Change the dead zone for controller joystick input.
// *
// * @param deadZone The dead zone for the controller from the range 0.0 to 1.0.
// *
// * @note Negative values will be clamped to 0.0 and values greater than 1.0 will be clamped
// to 1.0.
// */
// void setControllerDeadZone(float deadZone);
//
// /**
// * @brief Get the dead zone for controller joystick input.
// *
// * @return The dead zone for the controller from the range 0.0 to 1.0.
// */
// float getControllerDeadZone();

} // namespace input
} // namespace kn
18 changes: 10 additions & 8 deletions include/Window.hpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#pragma once

#include <string>
#include <vector>

#include <SDL.h>

Expand All @@ -26,15 +25,18 @@ namespace window
* @param resolution The size of the window.
* @param title The title of the window.
* @param scale The scale of the window.
*
* @return Whether the window was successfully initialized.
*/
void init(const math::Vec2& resolution, const std::string& title = "Kraken Window", int scale = 1);
[[maybe_unused]] bool init(const math::Vec2& resolution, const std::string& title = "Kraken Window",
int scale = 1);

/**
* @brief Get whether the window is open.
*
* @return Whether the window is open.
*/
bool isOpen();
[[nodiscard]] bool isOpen();

/**
* @brief Close the window.
Expand Down Expand Up @@ -75,7 +77,7 @@ void blit(const Texture& texture, const math::Vec2& position = {});
*
* @return The window renderer.
*/
SDL_Renderer* getRenderer();
[[nodiscard]] SDL_Renderer* getRenderer();

/**
* @brief Populate an event with the next window events.
Expand All @@ -89,21 +91,21 @@ void pollEvent(Event& event);
*
* @return Whether the window is fullscreen or not.
*/
bool getFullscreen();
[[nodiscard]] bool getFullscreen();

/**
* @brief Get the scale of the window.
*
* @return The scale of the window.
*/
int getScale();
[[nodiscard]] int getScale();

/**
* @brief Get the size of the screen.
*
* @return The size of the screen.
*/
math::Vec2 getSize();
[[nodiscard]] math::Vec2 getSize();

/**
* @brief Set the title of the window.
Expand All @@ -117,7 +119,7 @@ void setTitle(const std::string& newTitle);
*
* @return The title of the window.
*/
std::string getTitle();
[[nodiscard]] std::string getTitle();

/**
* @brief Set whether the window is fullscreen or not.
Expand Down
8 changes: 8 additions & 0 deletions include/_globals.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#pragma once

#include <SDL.h>

namespace kn
{
inline SDL_GameController* _controller = nullptr;
} // namespace kn
41 changes: 36 additions & 5 deletions src/input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

namespace kn::input
{
// static float _deadZone = 0.1f;

math::Vec2 getMousePos()
{
int x, y;
Expand All @@ -16,7 +18,10 @@ math::Vec2 getMousePos()
return pos + camera;
}

bool isMouseButtonPressed(const int button) { return SDL_GetMouseState(nullptr, nullptr) == button; }
bool isMouseButtonPressed(const Uint32 button)
{
return SDL_GetMouseState(nullptr, nullptr) == button;
}

bool isKeyPressed(const int key) { return SDL_GetKeyboardState(nullptr)[key]; }

Expand All @@ -27,16 +32,42 @@ math::Vec2 getVector(const std::vector<KEYS>& left, const std::vector<KEYS>& rig

if (std::any_of(up.begin(), up.end(), [&](auto scancode) { return isKeyPressed(scancode); }))
vector.y -= 1;
if (std::any_of(left.begin(), left.end(), [&](auto scancode) { return isKeyPressed(scancode); }))
if (std::any_of(left.begin(), left.end(),
[&](auto scancode) { return isKeyPressed(scancode); }))
vector.x -= 1;
if (std::any_of(down.begin(), down.end(), [&](auto scancode) { return isKeyPressed(scancode); }))
if (std::any_of(down.begin(), down.end(),
[&](auto scancode) { return isKeyPressed(scancode); }))
vector.y += 1;
if (std::any_of(right.begin(), right.end(), [&](auto scancode) { return isKeyPressed(scancode); }))
if (std::any_of(right.begin(), right.end(),
[&](auto scancode) { return isKeyPressed(scancode); }))
vector.x += 1;

if (vector.getLength() > 0)
if (vector.getLength() > 1)
vector.normalize();

// if (_controller)
// {
// const double leftX = SDL_GameControllerGetAxis(_controller, SDL_CONTROLLER_AXIS_LEFTX) /
// 32767.0; const double leftY = SDL_GameControllerGetAxis(_controller,
// SDL_CONTROLLER_AXIS_LEFTY) / 32767.0; if (std::abs(leftX) > _deadZone || std::abs(leftY)
// > _deadZone)
// {
// vector.x += leftX;
// vector.y += leftY;
// }
// }
//
// if (vector.getLength() > 1)
// vector.scaleToLength(1);

return vector;
}

// void setControllerDeadZone(const float deadZone)
// {
// _deadZone = std::clamp(deadZone, 0.0f, 1.0f);
// }
//
// float getControllerDeadZone() { return _deadZone; }

} // namespace kn::input
8 changes: 4 additions & 4 deletions src/time.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ double Clock::tick(int frameRate)
frameRate = 1;

m_targetFrameTime = 1000.0 / frameRate;
m_frameTime =
(static_cast<double>(SDL_GetPerformanceCounter()) / m_frequency - m_last / m_frequency) *
1000.0;
const double currentTime = static_cast<double>(SDL_GetPerformanceCounter()) / m_frequency;
m_frameTime = (currentTime - m_last / m_frequency) * 1000.0;

if (m_frameTime < m_targetFrameTime)
SDL_Delay(static_cast<uint32_t>(m_targetFrameTime - m_frameTime));

m_now = static_cast<double>(SDL_GetPerformanceCounter());
m_deltaTime = m_now / m_frequency - m_last / m_frequency;
m_deltaTime = (m_now - m_last) / m_frequency;
m_last = m_now;

return std::min(m_deltaTime, 0.033); // Limit delta time at 33ms or 30fps
Expand Down
65 changes: 55 additions & 10 deletions src/window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,59 +5,78 @@
#include "ErrorLogger.hpp"
#include "Music.hpp"
#include "Window.hpp"
#include "_globals.hpp"

namespace kn::window
{
static SDL_Renderer* _renderer;
static SDL_Window* _window;
static bool _isOpen;

void init(const math::Vec2& resolution, const std::string& title, const int scale)
bool init(const math::Vec2& resolution, const std::string& title, const int scale)
{
if (_renderer)
{
WARN("Cannot initialize renderer more than once")
return false;
}

if (SDL_Init(SDL_INIT_VIDEO))
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER) < 0)
{
FATAL("SDL_Init Error: " + std::string(SDL_GetError()))
return false;
}

if (!IMG_Init(IMG_INIT_PNG))
{
FATAL("IMG_Init Error: " + std::string(IMG_GetError()))
SDL_Quit();
return false;
}

if (TTF_Init())
{
FATAL("TTF_Init Error: " + std::string(TTF_GetError()))
IMG_Quit();
SDL_Quit();
return false;
}

if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048))
{
FATAL("Mix_OpenAudio Error: " + std::string(Mix_GetError()))
TTF_Quit();
IMG_Quit();
SDL_Quit();
return false;
}

const int resolutionWidth = static_cast<int>(resolution.x);
const int resolutionHeight = static_cast<int>(resolution.y);
_window = SDL_CreateWindow("Kraken Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
static_cast<int>(resolution.x) * scale,
static_cast<int>(resolution.y) * scale, SDL_WINDOW_SHOWN);
resolutionWidth * scale, resolutionHeight * scale, SDL_WINDOW_SHOWN);
if (!_window)
{
FATAL("SDL_CreateWindow Error: " + std::string(SDL_GetError()))
return false;
}

_renderer = SDL_CreateRenderer(_window, -1, SDL_RENDERER_ACCELERATED);
if (!_renderer)
FATAL("SDL_CreateRenderer Error: " + std::string(SDL_GetError()));

if (scale > 1)
{
SDL_RenderSetLogicalSize(_renderer, static_cast<int>(resolution.x),
static_cast<int>(resolution.y));
FATAL("SDL_CreateRenderer Error: " + std::string(SDL_GetError()))
return false;
}

if (scale > 1)
SDL_RenderSetLogicalSize(_renderer, resolutionWidth, resolutionHeight);

setTitle(title);
setIcon("../example/assets/kraken_engine_window_icon.png");

_isOpen = true;

return true;
}

bool isOpen() { return _isOpen; }
Expand All @@ -66,12 +85,15 @@ void close() { _isOpen = false; }

void quit()
{
music::unload();

if (_renderer)
SDL_DestroyRenderer(_renderer);
if (_window)
SDL_DestroyWindow(_window);
if (_controller)
SDL_GameControllerClose(_controller);

music::unload();
Mix_CloseAudio();
IMG_Quit();
TTF_Quit();
Expand All @@ -84,6 +106,29 @@ void pollEvent(Event& event)
WARN("Cannot get events before creating the window")

SDL_PollEvent(&event);

switch (event.type)
{
case QUIT:
close();
break;
// case CONTROLLERDEVICEADDED:
// {
// if (!_controller)
// _controller = SDL_GameControllerOpen(event.cdevice.which);
// break;
// }
// case CONTROLLERDEVICEREMOVED:
// if (_controller && event.cdevice.which == SDL_JoystickInstanceID(
// SDL_GameControllerGetJoystick(_controller)))
// {
// SDL_GameControllerClose(_controller);
// _controller = nullptr;
// }
// break;
default:
break;
}
}

void clear(const Color color)
Expand Down

0 comments on commit f60b960

Please sign in to comment.