aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ctrl/keyboard.h43
-rw-r--r--src/ctrl/mouse.h13
-rw-r--r--src/engine.cpp297
3 files changed, 208 insertions, 145 deletions
diff --git a/src/ctrl/keyboard.h b/src/ctrl/keyboard.h
index de7297c..4f3b4ef 100644
--- a/src/ctrl/keyboard.h
+++ b/src/ctrl/keyboard.h
@@ -1,15 +1,50 @@
#ifndef CTRL_KEYBOARD_H
#define CTRL_KEYBOARD_H
+#include <cstdint>
+#include "math/vector.h"
+
+using engine::math::Vector2;
+
namespace engine::controllers {
+enum class KeyboardKey {
+ fw,
+ bw,
+ key_left,
+ key_right,
+ zoom,
+};
+
+static constexpr std::size_t keyboard_key_count = 5;
+
+template<typename KeyDownCallback, typename KeyUpCallback>
class Keyboard {
public:
- bool fw_down, bw_down, left_down, right_down, zoom_down;
+ constexpr Keyboard(KeyDownCallback key_down_cb, KeyUpCallback key_up_cb) :
+ key_down_cb{key_down_cb}, key_up_cb{key_up_cb}, key_down_list{{{}}} {}
+
+ void key_down_event(KeyboardKey key) {
+ key_down_list[static_cast<std::size_t>(key) / (sizeof(std::size_t) * 8)]
+ |= 1 << (static_cast<std::size_t>(key) % (sizeof(std::size_t) * 8));
+ key_down_cb(key);
+ }
+
+ void key_up_event(KeyboardKey key) {
+ key_down_list[static_cast<std::size_t>(key) / (sizeof(std::size_t) * 8)]
+ &= ~(1 << (static_cast<std::size_t>(key) % (sizeof(std::size_t) * 8)));
+ key_up_cb(key);
+ }
+
+ constexpr bool is_down(KeyboardKey key) const & {
+ return (key_down_list[static_cast<std::size_t>(key) / (sizeof(std::size_t) * 8)]
+ & (1 << (static_cast<std::size_t>(key) % (sizeof(std::size_t) * 8)))) != 0;
+ }
- constexpr Keyboard() :
- fw_down{false}, bw_down{false}, left_down{false},
- right_down{false}, zoom_down{false} {}
+ private:
+ KeyDownCallback key_down_cb;
+ KeyUpCallback key_up_cb;
+ std::array<std::size_t, (keyboard_key_count + sizeof(std::size_t) * 8 - 1) / (sizeof(std::size_t) * 8)> key_down_list;
};
}
diff --git a/src/ctrl/mouse.h b/src/ctrl/mouse.h
index 8b66cee..521b0a4 100644
--- a/src/ctrl/mouse.h
+++ b/src/ctrl/mouse.h
@@ -3,16 +3,19 @@
#include "math/vector.h"
-using engine::math::Vector2;
-
namespace engine::controllers {
+template<typename MouseMotionCallback>
class Mouse {
public:
- bool moved;
- Vector2 rel_motion;
+ constexpr Mouse(MouseMotionCallback mouse_motion_cb) : mouse_motion_cb{mouse_motion_cb} {}
+
+ void mouse_motion_event(Vector2 rel) const & {
+ mouse_motion_cb(rel);
+ }
- constexpr Mouse() : moved{false}, rel_motion{0.f, 0.f} {}
+ private:
+ MouseMotionCallback mouse_motion_cb;
};
}
diff --git a/src/engine.cpp b/src/engine.cpp
index 6e05d7f..453f8c5 100644
--- a/src/engine.cpp
+++ b/src/engine.cpp
@@ -14,6 +14,7 @@
#include <utility>
#include <SDL.h>
#include <numbers>
+#include <optional>
#ifdef ENABLE_NCURSES
#include <ncurses.h>
@@ -51,6 +52,7 @@ using
engine::math::Matrix4,
engine::math::Quaternion,
engine::controllers::Keyboard,
+ engine::controllers::KeyboardKey,
engine::controllers::Mouse;
#define FPS 60
@@ -129,9 +131,19 @@ static void scene_main(Renderer<FrameBuffer>& renderer, const Matrix4& final_tra
}
};
- Keyboard kb{};
- Mouse mouse{};
float rx = 0.f, ry = 0.f;
+ Keyboard kb{[&](KeyboardKey key) {
+ (void) key;
+ }, [&](KeyboardKey key) {
+ (void) key;
+ }};
+ Mouse mouse{[&](Vector2 rel) {
+ rx += -rel.y;
+ ry += -rel.x;
+ if (rx < -PI / 2.f) rx = -PI / 2.f;
+ if (rx > PI / 2.f) rx = PI / 2.f;
+ scene.camera.transform.rot = Quaternion::euler_zxy(rx, ry, 0.f);
+ }};
camera = &scene.camera;
@@ -157,22 +169,15 @@ static void scene_main(Renderer<FrameBuffer>& renderer, const Matrix4& final_tra
}
cont = update_frame(scene, kb, mouse);
- if (mouse.moved) {
- rx += -mouse.rel_motion.y;
- ry += -mouse.rel_motion.x;
- if (rx < -PI / 2.f) rx = -PI / 2.f;
- if (rx > PI / 2.f) rx = PI / 2.f;
- scene.camera.transform.rot = Quaternion::euler_zxy(rx, ry, 0.f);
- }
-
Vector3 movement(0.f, 0.f, 0.f);
- if (kb.fw_down) movement.z += -1.f;
- if (kb.left_down) movement.x += -1.f;
- if (kb.bw_down) movement.z += +1.f;
- if (kb.right_down) movement.x += +1.f;
- if (kb.fw_down || kb.left_down || kb.bw_down || kb.right_down) movement.normalize();
+ if (kb.is_down(KeyboardKey::fw)) movement.z += -1.f;
+ if (kb.is_down(KeyboardKey::key_left)) movement.x += -1.f;
+ if (kb.is_down(KeyboardKey::bw)) movement.z += +1.f;
+ if (kb.is_down(KeyboardKey::key_right)) movement.x += +1.f;
+ if (kb.is_down(KeyboardKey::fw) || kb.is_down(KeyboardKey::key_left)
+ || kb.is_down(KeyboardKey::bw) || kb.is_down(KeyboardKey::key_right)) movement.normalize();
scene.camera.transform.loc += movement.rot(Quaternion::rot_y(ry)) * .05f;
- scene.camera.fov = (kb.zoom_down ? 40.f : 80.f) * PI / 180.f;
+ scene.camera.fov = (kb.is_down(KeyboardKey::zoom) ? 40.f : 80.f) * PI / 180.f;
}
}
@@ -194,64 +199,85 @@ static int main_term() {
getmaxyx(stdscr, h, w);
Renderer<CharacterFrameBuffer> renderer{CharacterFrameBuffer{static_cast<unsigned int>(w), static_cast<unsigned int>(h)}};
- scene_main(renderer, Matrix4::scale(Vector3(2.f, 1.f, 1.f)), [&](Scene& scene, Keyboard& kb, Mouse& mouse) {
- (void) scene;
- mvaddnstr(0, 0, renderer.fb.chars(), renderer.width() * renderer.height());
-
- bool cont = true;
- //timeout(1000 / FPS);
- timeout(10);
- int c = getch();
-
- kb.fw_down = false;
- kb.left_down = false;
- kb.bw_down = false;
- kb.right_down = false;
-
- mouse.moved = false;
- mouse.rel_motion = Vector2(0.f, 0.f);
-
- switch (c) {
- case 'z':
- kb.fw_down = true;
- break;
- case 'q':
- kb.left_down = true;
- break;
- case 's':
- kb.bw_down = true;
- break;
- case 'd':
- kb.right_down = true;
- break;
- case 'p':
- kb.zoom_down = !kb.zoom_down;
- break;
- case KEY_UP:
- mouse.moved = true;
- mouse.rel_motion = Vector2(0.f, -.1f);
- break;
- case KEY_LEFT:
- mouse.moved = true;
- mouse.rel_motion = Vector2(-.1f, 0.f);
- break;
- case KEY_DOWN:
- mouse.moved = true;
- mouse.rel_motion = Vector2(0.f, +.1f);
- break;
- case KEY_RIGHT:
- mouse.moved = true;
- mouse.rel_motion = Vector2(+.1f, 0.f);
- break;
- case MKEY_ESC:
- return false;
- }
+ scene_main(renderer, Matrix4::scale(Vector3(2.f, 1.f, 1.f)),
+ [&](Scene& scene, auto& kb, auto& mouse) {
+ (void) scene;
+ mvaddnstr(0, 0, renderer.fb.chars(), renderer.width() * renderer.height());
+
+ bool cont = true;
+ std::optional<KeyboardKey> key;
+ std::optional<Vector2> rel;
+ //timeout(1000 / FPS);
+ timeout(10);
+ int c = getch();
+
+ switch (c) {
+ case 'z':
+ key = KeyboardKey::fw;
+ break;
+ case 'q':
+ key = KeyboardKey::key_left;
+ break;
+ case 's':
+ key = KeyboardKey::bw;
+ break;
+ case 'd':
+ key = KeyboardKey::key_right;
+ break;
+ case 'p':
+ key = KeyboardKey::zoom;
+ break;
+ case KEY_UP:
+ rel = Vector2(0.f, -.1f);
+ break;
+ case KEY_LEFT:
+ rel = Vector2(-.1f, 0.f);
+ break;
+ case KEY_DOWN:
+ rel = Vector2(0.f, +.1f);
+ break;
+ case KEY_RIGHT:
+ rel = Vector2(+.1f, 0.f);
+ break;
+ case MKEY_ESC:
+ return false;
+ }
+
+ if (key && *key == KeyboardKey::fw) {
+ if (!kb.is_down(KeyboardKey::fw)) kb.key_down_event(KeyboardKey::fw);
+ } else {
+ if (kb.is_down(KeyboardKey::fw)) kb.key_up_event(KeyboardKey::fw);
+ }
+ if (key && *key == KeyboardKey::key_left) {
+ if (!kb.is_down(KeyboardKey::key_left)) kb.key_down_event(KeyboardKey::key_left);
+ } else {
+ if (kb.is_down(KeyboardKey::key_left)) kb.key_up_event(KeyboardKey::key_left);
+ }
+ if (key && *key == KeyboardKey::bw) {
+ if (!kb.is_down(KeyboardKey::bw)) kb.key_down_event(KeyboardKey::bw);
+ } else {
+ if (kb.is_down(KeyboardKey::bw)) kb.key_up_event(KeyboardKey::bw);
+ }
+ if (key && *key == KeyboardKey::key_right) {
+ if (!kb.is_down(KeyboardKey::key_right)) kb.key_down_event(KeyboardKey::key_right);
+ } else {
+ if (kb.is_down(KeyboardKey::key_right)) kb.key_up_event(KeyboardKey::key_right);
+ }
+
+ if (key && *key == KeyboardKey::zoom) {
+ if (kb.is_down(KeyboardKey::zoom)) kb.key_up_event(KeyboardKey::zoom);
+ else kb.key_down_event(KeyboardKey::zoom);
+ }
- getmaxyx(stdscr, h, w);
- renderer.resize(static_cast<unsigned int>(w), static_cast<unsigned int>(h));
+ if (rel)
+ mouse.mouse_motion_event(*rel);
- return cont;
- });
+ getmaxyx(stdscr, h, w);
+ renderer.resize(static_cast<unsigned int>(w), static_cast<unsigned int>(h));
+
+ return cont;
+ }
+ );
// terminate
endwin();
@@ -285,76 +311,75 @@ static int main_graphical() {
SDL_Event e;
- scene_main(engine_renderer, Matrix4::idty(), [&](Scene& scene, Keyboard& kb, Mouse& mouse) {
- (void) scene;
- SDL_UpdateTexture(texture, nullptr, engine_renderer.fb.pixels(), SCREEN_WIDTH * 4);
- SDL_RenderClear(renderer);
- SDL_RenderCopy(renderer, texture, nullptr, nullptr);
- SDL_RenderPresent(renderer);
- SDL_UpdateWindowSurface(window);
- SDL_SetRelativeMouseMode(SDL_TRUE);
- bool cont = true;
- mouse.moved = false;
- mouse.rel_motion = Vector2(0.f, 0.f);
- if (SDL_WaitEventTimeout(&e, 10)) {
- do {
- switch (e.type) {
- case SDL_QUIT:
- cont = false;
- break;
- case SDL_KEYDOWN:
- switch (e.key.keysym.sym) {
- case SDLK_z:
- kb.fw_down = true;
- break;
- case SDLK_q:
- kb.left_down = true;
- break;
- case SDLK_s:
- kb.bw_down = true;
- break;
- case SDLK_d:
- kb.right_down = true;
- break;
- case SDLK_LCTRL:
- kb.zoom_down = true;
- break;
- }
- break;
- case SDL_KEYUP:
- switch (e.key.keysym.sym) {
- case SDLK_z:
- kb.fw_down = false;
- break;
- case SDLK_q:
- kb.left_down = false;
- break;
- case SDLK_s:
- kb.bw_down = false;
+ scene_main(engine_renderer, Matrix4::idty(),
+ [&](Scene& scene, auto& kb, auto& mouse) {
+ (void) scene;
+ SDL_UpdateTexture(texture, nullptr, engine_renderer.fb.pixels(), SCREEN_WIDTH * 4);
+ SDL_RenderClear(renderer);
+ SDL_RenderCopy(renderer, texture, nullptr, nullptr);
+ SDL_RenderPresent(renderer);
+ SDL_UpdateWindowSurface(window);
+ SDL_SetRelativeMouseMode(SDL_TRUE);
+ bool cont = true;
+ if (SDL_WaitEventTimeout(&e, 10)) {
+ do {
+ switch (e.type) {
+ case SDL_QUIT:
+ cont = false;
break;
- case SDLK_d:
- kb.right_down = false;
+ case SDL_KEYDOWN:
+ switch (e.key.keysym.sym) {
+ case SDLK_z:
+ kb.key_down_event(KeyboardKey::fw);
+ break;
+ case SDLK_q:
+ kb.key_down_event(KeyboardKey::key_left);
+ break;
+ case SDLK_s:
+ kb.key_down_event(KeyboardKey::bw);
+ break;
+ case SDLK_d:
+ kb.key_down_event(KeyboardKey::key_right);
+ break;
+ case SDLK_LCTRL:
+ kb.key_down_event(KeyboardKey::zoom);
+ break;
+ }
break;
- case SDLK_LCTRL:
- kb.zoom_down = false;
+ case SDL_KEYUP:
+ switch (e.key.keysym.sym) {
+ case SDLK_z:
+ kb.key_up_event(KeyboardKey::fw);
+ break;
+ case SDLK_q:
+ kb.key_up_event(KeyboardKey::key_left);
+ break;
+ case SDLK_s:
+ kb.key_up_event(KeyboardKey::bw);
+ break;
+ case SDLK_d:
+ kb.key_up_event(KeyboardKey::key_right);
+ break;
+ case SDLK_LCTRL:
+ kb.key_up_event(KeyboardKey::zoom);
+ break;
+ case SDLK_ESCAPE:
+ cont = false;
+ break;
+ }
break;
- case SDLK_ESCAPE:
- cont = false;
+ case SDL_MOUSEMOTION:
+ mouse.mouse_motion_event(Vector2(
+ static_cast<float>(e.motion.xrel) * .01f,
+ static_cast<float>(e.motion.yrel) * .01f));
break;
}
- break;
- case SDL_MOUSEMOTION:
- mouse.moved = true;
- mouse.rel_motion += Vector2(
- static_cast<float>(e.motion.xrel) * .01f,
- static_cast<float>(e.motion.yrel) * .01f);
- break;
- }
- } while (SDL_PollEvent(&e));
- }
+ } while (SDL_PollEvent(&e));
+ }
- return cont;
- });
+ return cont;
+ }
+ );
// terminate
SDL_DestroyTexture(texture);