Hallo,
Sorry, das ich so lange weg war, aber ich hatte Schwierigkeiten mich anzumelden, bis ich mitbekommen hatte, das ich hier ne andere Mail Adresse hatte.Aber nun gut.
Ich beschäftige micht gerade mit SDL2 und fand das Input Handling etwas irritierend. Einerseits scheint es nach meinen rudimentären Recherchen unterschiedliche Vorgehensweisen für gedrückte und gehaltene Tasten zu geben, andererseits will ich keine EventLoop für Tastendrücke haben.
So kam ich zu einer für mich zufriedenstellenden Lösung, die ich hier gerne vorstellen möchte. Diese ist natürlich nur in meinem Horizont, es mag bestimmt besserere Lösungen geben, die ich nur noch nicht gesehen habe. Ich finde meine Lösung aber recht intuitiv, weil es nur zwei Bedingungen gibt. Man muss eine 'Mouse Update' Methode vor einem Frame setzen und eine "Key Update" nach jedem Frame.
Außerdem werden drei Tastenzustände registriert; Pressed, Held, Released.
Das Ganze sieht dann so aus:
#pragma once
#include <zp/Core/Common.h>
namespace zp
{
struct KeyState
{
bool Pressed = false;
bool Released = false;
bool Held = false;
};
}
namespace zp
{
class SDLInput
{
public:
SDLInput();
void updateKeyInput();
void updateMouseInput();
private:
const Uint8* m_CurrentKeyStates;
Uint8 m_PreviousKeyStates[SDL_NUM_SCANCODES];
KeyState m_KeyState;
static constexpr Uint32 MOUSE_KEY_BUFFER = 5;
Uint32 m_CurrentMouseStates[MOUSE_KEY_BUFFER];
Uint32 m_PreviousMouseStates[MOUSE_KEY_BUFFER];
KeyState m_MouseState[MOUSE_KEY_BUFFER];
ivec2 m_MousePos;
public:
const KeyState& getKey(const SDL_Scancode key);
const KeyState& getKey(const KeyCode key);
const KeyState& getMouse(const MouseButton button) const;
const ivec2& getMousePos() const;
private:
void updateKeyState(const SDL_Scancode key);
void updateMouseState();
};
}
Hier die cpp:
#include <zp/Input/SDLInput.h>
zp::SDLInput::SDLInput() :
m_CurrentKeyStates(SDL_GetKeyboardState(nullptr))
{
updateKeyInput();
}
void zp::SDLInput::updateKeyInput() // set after frame
{
// Update previous states
memcpy(m_PreviousKeyStates, m_CurrentKeyStates, SDL_NUM_SCANCODES);
}
void zp::SDLInput::updateMouseInput() // set before frame
{
updateMouseState();
}
const zp::KeyState& zp::SDLInput::getKey(const SDL_Scancode key)
{
updateKeyState(key);
return m_KeyState;
}
const zp::KeyState& zp::SDLInput::getKey(const KeyCode key)
{
updateKeyState(static_cast<SDL_Scancode>(key));
return m_KeyState;
}
const zp::KeyState& zp::SDLInput::getMouse(const MouseButton button) const
{
return m_MouseState[static_cast<Uint32>(button)];
}
const zp::ivec2& zp::SDLInput::getMousePos() const
{
return m_MousePos;
}
/* private */
void zp::SDLInput::updateKeyState(const SDL_Scancode key)
{
if (m_CurrentKeyStates[key])
{
if (!m_PreviousKeyStates[key])
{
m_KeyState.Pressed = true;
m_KeyState.Held = true;
m_KeyState.Released = false;
}
else
{
m_KeyState.Pressed = false;
m_KeyState.Held = true;
m_KeyState.Released = false;
}
}
else
{
if (m_PreviousKeyStates[key])
{
m_KeyState.Pressed = false;
m_KeyState.Held = false;
m_KeyState.Released = true;
}
else
{
m_KeyState.Pressed = false;
m_KeyState.Held = false;
m_KeyState.Released = false;
}
}
}
void zp::SDLInput::updateMouseState()
{
int x, y;
auto mouseState = SDL_GetMouseState(&x, &y);
m_MousePos = ivec2(x, y);
for (auto i = 0; i < MOUSE_KEY_BUFFER; ++i)
{
m_CurrentMouseStates[i] = mouseState & SDL_BUTTON(i);
m_MouseState[i].Pressed = false;
m_MouseState[i].Released = false;
if (m_CurrentMouseStates[i] != m_PreviousMouseStates[i])
{
if (m_CurrentMouseStates[i])
{
m_MouseState[i].Pressed = true;
m_MouseState[i].Held = true;
}
else
{
m_MouseState[i].Released = true;
m_MouseState[i].Held = false;
}
}
m_PreviousMouseStates[i] = m_CurrentMouseStates[i];
}
}
Ich habe dann auch eigene enums, die ich auch intuitiver finde.
Die KeysCodes habe ich einfach von der sdl2 wiki kopiert.
enum class MouseButton : Uint32
{
LEFT = SDL_BUTTON_LEFT,
MIDDLE = SDL_BUTTON_MIDDLE,
RIGHT = SDL_BUTTON_RIGHT,
X1 = SDL_BUTTON_X1,
X2 = SDL_BUTTON_X2
};
enum class KeyCode : Uint32
{
A = 4,
B = 5,
C = 6,
D = 7,
E = 8,
F = 9,
G = 10,
H = 11,
I = 12,
J = 13,
K = 14,
L = 15,
M = 16,
N = 17,
O = 18,
P = 19,
Q = 20,
R = 21,
S = 22,
T = 23,
U = 24,
V = 25,
W = 26,
X = 27,
Y = 28,
Z = 29,
D1 = 30,
D2 = 31,
D3 = 32,
D4 = 33,
D5 = 34,
D6 = 35,
D7 = 36,
D8 = 37,
D9 = 38,
D0 = 39,
RETURN = 40,
ESCAPE = 41,
BACKSPACE = 42,
TAB = 43,
SPACE = 44,
F1 = 58,
F2 = 59,
F3 = 60,
F4 = 61,
F5 = 62,
F6 = 63,
F7 = 64,
F8 = 65,
F9 = 66,
F10 = 67,
F11 = 68,
F12 = 69,
HOME = 74,
PAGEUP = 75,
DELETE = 76,
END = 77,
PAGEDOWN = 78,
RIGHT = 79,
LEFT = 80,
DOWN = 81,
UP = 82
};
Sorry, das ich wieder kaum kommentiert habe, aber da habe ich echt noch Schwierigkeiten. Zwar bin ich nicht besonders kritikreselient aber wer mag, kann gerne seine Gedanken dazu schreiben.
LG