implement edge-triggered key press/release default tip

Mon, 09 Jun 2025 14:02:40 +0200

author
Mike Becker <universe@uap-core.de>
date
Mon, 09 Jun 2025 14:02:40 +0200
changeset 141
cd82643bb6d9
parent 140
d190fe5315bd

implement edge-triggered key press/release

src/ascension/input.h file | annotate | diff | comparison | revisions
src/context.c file | annotate | diff | comparison | revisions
test/snake/snake.c file | annotate | diff | comparison | revisions
--- a/src/ascension/input.h	Mon Jun 09 13:18:41 2025 +0200
+++ b/src/ascension/input.h	Mon Jun 09 14:02:40 2025 +0200
@@ -28,8 +28,6 @@
 #ifndef ASCENSION_INPUT_H
 #define ASCENSION_INPUT_H
 
-#include "window.h"
-
 #include <SDL2/SDL_scancode.h>
 
 typedef struct AscInput AscInput;
@@ -55,19 +53,39 @@
      * The index of the window, the mouse was last seen in.
      */
     unsigned mouse_window;
-    bool keys[SDL_NUM_SCANCODES];
+    /**
+     * State of the keys.
+     * @see asc_key_pressed()
+     * @see asc_key_released()
+     * @see asc_key_down()
+     * @see asc_key_up()
+     */
+    unsigned char keys[SDL_NUM_SCANCODES];
 };
 
+#define ASC_KEY_DOWN_FLAG     1u
+#define ASC_KEY_PRESS_FLAG    2u
+#define ASC_KEY_RELEASE_FLAG  4u
+
+#define ASC_KEY(name) SDL_SCANCODE_##name
+
+#define asc_key_down(scancode) \
+    (asc_context.input.keys[scancode] & ASC_KEY_DOWN_FLAG)
+#define asc_key_up(scancode) \
+    (asc_context.input.keys[scancode] == 0)
 #define asc_key_pressed(scancode) \
-    (asc_context.input.keys[SDL_SCANCODE_##scancode])
+    (asc_context.input.keys[scancode] & ASC_KEY_PRESS_FLAG)
+#define asc_key_released(scancode) \
+    (asc_context.input.keys[scancode] & ASC_KEY_RELEASE_FLAG)
 
 #define asc_mouse_x asc_context.input.mouse_x
 #define asc_mouse_y asc_context.input.mouse_y
 #define asc_mouse_window asc_context.input.mouse_window
-#define asc_mouse_pos (asc_vec2i) {asc_mouse_x, asc_mouse_y}
+// TODO: think about whether this should be asc_vec2u
+#define asc_mouse_pos ((asc_vec2i) {asc_mouse_x, asc_mouse_y})
 
 #define asc_mouse_move_x asc_context.input.mouse_xrel
 #define asc_mouse_move_y asc_context.input.mouse_yrel
-#define asc_mouse_move (asc_vec2i) {asc_mouse_move_x, asc_mouse_move_y}
+#define asc_mouse_move ((asc_vec2i) {asc_mouse_move_x, asc_mouse_move_y})
 
 #endif //ASCENSION_INPUT_H
--- a/src/context.c	Mon Jun 09 13:18:41 2025 +0200
+++ b/src/context.c	Mon Jun 09 14:02:40 2025 +0200
@@ -147,6 +147,11 @@
     asc_context.input.mouse_xrel = 0;
     asc_context.input.mouse_yrel = 0;
 
+    // reset key flags
+    for (unsigned int i = 0 ; i < SDL_NUM_SCANCODES ; i++) {
+        asc_clear_flag(asc_context.input.keys[i], ASC_KEY_RELEASE_FLAG|ASC_KEY_PRESS_FLAG);
+    }
+
     // dispatch SDL events
     SDL_Event event;
     while (SDL_PollEvent(&event)) {
@@ -183,10 +188,14 @@
                 break;
             }
             case SDL_KEYDOWN:
-                asc_context.input.keys[event.key.keysym.scancode] = true;
+                // we only set the down and press flags if the key is not already known to be down
+                if (asc_key_up(event.key.keysym.scancode)) {
+                    asc_set_flag(asc_context.input.keys[event.key.keysym.scancode], ASC_KEY_DOWN_FLAG|ASC_KEY_PRESS_FLAG);
+                }
                 break;
             case SDL_KEYUP:
-                asc_context.input.keys[event.key.keysym.scancode] = false;
+                // we can directly set the release flag - it will be cleared next round
+                asc_context.input.keys[event.key.keysym.scancode] = ASC_KEY_RELEASE_FLAG;
                 break;
         }
     }
--- a/test/snake/snake.c	Mon Jun 09 13:18:41 2025 +0200
+++ b/test/snake/snake.c	Mon Jun 09 14:02:40 2025 +0200
@@ -207,14 +207,13 @@
         }
 
         // debug-key for clearing the shader registry
-        if (asc_key_pressed(S)) {
-            // TODO: implement edge-triggered key press handling
+        if (asc_key_pressed(ASC_KEY(S))) {
             asc_shader_clear_registry();
             asc_dprintf("Shader cache cleared.");
         }
 
         // quit application on ESC key press
-        if (asc_key_pressed(ESCAPE)) {
+        if (asc_key_pressed(ASC_KEY(ESCAPE))) {
             asc_context_quit();
         }
     } while (asc_loop_next());

mercurial