Render test
This commit is contained in:
@ -39,9 +39,6 @@ project(${DUSK_TARGET_NAME}
|
|||||||
# Executable
|
# Executable
|
||||||
add_executable(${DUSK_TARGET_NAME})
|
add_executable(${DUSK_TARGET_NAME})
|
||||||
|
|
||||||
# Get Libraries
|
|
||||||
add_subdirectory(lib)
|
|
||||||
|
|
||||||
# Add tools
|
# Add tools
|
||||||
add_subdirectory(tools)
|
add_subdirectory(tools)
|
||||||
|
|
||||||
|
@ -3,27 +3,5 @@
|
|||||||
# This software is released under the MIT License.
|
# This software is released under the MIT License.
|
||||||
# https://opensource.org/licenses/MIT
|
# https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
# Libs
|
add_subdirectory(dusk)
|
||||||
target_link_libraries(${DUSK_TARGET_NAME}
|
add_subdirectory(duskraylib)
|
||||||
PUBLIC
|
|
||||||
m
|
|
||||||
)
|
|
||||||
|
|
||||||
# Includes
|
|
||||||
target_include_directories(${DUSK_TARGET_NAME}
|
|
||||||
PUBLIC
|
|
||||||
${CMAKE_CURRENT_LIST_DIR}
|
|
||||||
)
|
|
||||||
|
|
||||||
# Sources
|
|
||||||
target_sources(${DUSK_TARGET_NAME}
|
|
||||||
PRIVATE
|
|
||||||
main.c
|
|
||||||
input.c
|
|
||||||
)
|
|
||||||
|
|
||||||
# Subdirs
|
|
||||||
add_subdirectory(assert)
|
|
||||||
add_subdirectory(display)
|
|
||||||
add_subdirectory(rpg)
|
|
||||||
add_subdirectory(util)
|
|
@ -1,22 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "dusk.h"
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
COLOR_BLACK,
|
|
||||||
COLOR_RED,
|
|
||||||
COLOR_GREEN,
|
|
||||||
COLOR_YELLOW,
|
|
||||||
COLOR_BLUE,
|
|
||||||
COLOR_MAGENTA,
|
|
||||||
COLOR_CYAN,
|
|
||||||
COLOR_WHITE,
|
|
||||||
} color_t;
|
|
||||||
|
|
||||||
#define COLOR_COUNT (COLOR_WHITE + 1)
|
|
@ -1,71 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "assert/assert.h"
|
|
||||||
#include "render.h"
|
|
||||||
#include "term.h"
|
|
||||||
#include "rpg/entity/entity.h"
|
|
||||||
|
|
||||||
void renderInit() {
|
|
||||||
termInit();
|
|
||||||
}
|
|
||||||
|
|
||||||
void renderUpdate() {
|
|
||||||
char_t c;
|
|
||||||
color_t color, colorCurrent;
|
|
||||||
entity_t *ent;
|
|
||||||
|
|
||||||
termUpdate();
|
|
||||||
termClear();
|
|
||||||
|
|
||||||
colorCurrent = COLOR_WHITE;
|
|
||||||
termPushColor(colorCurrent);
|
|
||||||
|
|
||||||
for(int32_t y = 0; y < TERM.height; y++) {
|
|
||||||
for(int32_t x = 0; x < TERM.width; x++) {
|
|
||||||
color = COLOR_WHITE;
|
|
||||||
c = ' ';
|
|
||||||
|
|
||||||
ent = entityGetAt(x, y);
|
|
||||||
if(ent) {
|
|
||||||
color = COLOR_RED;
|
|
||||||
|
|
||||||
switch(ent->dir) {
|
|
||||||
case ENTITY_DIR_UP:
|
|
||||||
c = '^';
|
|
||||||
color = COLOR_GREEN;
|
|
||||||
break;
|
|
||||||
case ENTITY_DIR_DOWN:
|
|
||||||
c = 'v';
|
|
||||||
color = COLOR_RED;
|
|
||||||
break;
|
|
||||||
case ENTITY_DIR_LEFT:
|
|
||||||
c = '<';
|
|
||||||
color = COLOR_YELLOW;
|
|
||||||
break;
|
|
||||||
case ENTITY_DIR_RIGHT:
|
|
||||||
c = '>';
|
|
||||||
color = COLOR_BLUE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assertUnreachable("Invalid entity direction");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(c == ' ') {
|
|
||||||
termPushChar(' ');
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(color != colorCurrent) termPushColor((colorCurrent = color));
|
|
||||||
termPushChar(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
termFlush();
|
|
||||||
}
|
|
@ -1,59 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "assert/assert.h"
|
|
||||||
#include "term.h"
|
|
||||||
#include "util/memory.h"
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
|
|
||||||
term_t TERM;
|
|
||||||
|
|
||||||
const char_t* TERM_COLORS[COLOR_COUNT] = {
|
|
||||||
[COLOR_BLACK] = "\033[30m",
|
|
||||||
[COLOR_RED] = "\033[31m",
|
|
||||||
[COLOR_GREEN] = "\033[32m",
|
|
||||||
[COLOR_YELLOW] = "\033[33m",
|
|
||||||
[COLOR_BLUE] = "\033[34m",
|
|
||||||
[COLOR_MAGENTA] = "\033[35m",
|
|
||||||
[COLOR_CYAN] = "\033[36m",
|
|
||||||
[COLOR_WHITE] = "\033[37m"
|
|
||||||
};
|
|
||||||
|
|
||||||
void termInit() {
|
|
||||||
memoryZero(&TERM, sizeof(term_t));
|
|
||||||
|
|
||||||
struct winsize w;
|
|
||||||
if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == 0) {
|
|
||||||
TERM.width = w.ws_col;
|
|
||||||
TERM.height = w.ws_row;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void termUpdate() {
|
|
||||||
struct winsize w;
|
|
||||||
if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == 0) {
|
|
||||||
TERM.width = w.ws_col;
|
|
||||||
TERM.height = w.ws_row;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void termClear() {
|
|
||||||
printf("\033[2J\033[H");
|
|
||||||
}
|
|
||||||
|
|
||||||
void termPushColor(const color_t color) {
|
|
||||||
assertTrue(color < COLOR_COUNT, "Invalid color index");
|
|
||||||
printf("%s", TERM_COLORS[color]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void termPushChar(const char_t c) {
|
|
||||||
putchar(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
void termFlush() {
|
|
||||||
fflush(stdout);
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "dusk.h"
|
|
||||||
#include "display/color.h"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int32_t width;
|
|
||||||
int32_t height;
|
|
||||||
} term_t;
|
|
||||||
|
|
||||||
extern term_t TERM;
|
|
||||||
|
|
||||||
extern const char_t* TERM_COLORS[COLOR_COUNT];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize the terminal system.
|
|
||||||
*/
|
|
||||||
void termInit();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the terminal system, typically called each frame.
|
|
||||||
*/
|
|
||||||
void termUpdate();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear the terminal screen and reset cursor position.
|
|
||||||
*/
|
|
||||||
void termClear();
|
|
||||||
|
|
||||||
void termPushColor(const color_t color);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Push a character to the terminal output buffer.
|
|
||||||
*
|
|
||||||
* @param c The character to push.
|
|
||||||
*/
|
|
||||||
void termPushChar(const char_t c);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Flush the terminal output buffer to the terminal.
|
|
||||||
*/
|
|
||||||
void termFlush();
|
|
29
src/dusk/CMakeLists.txt
Normal file
29
src/dusk/CMakeLists.txt
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# Copyright (c) 2025 Dominic Masters
|
||||||
|
#
|
||||||
|
# This software is released under the MIT License.
|
||||||
|
# https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
# Libs
|
||||||
|
target_link_libraries(${DUSK_TARGET_NAME}
|
||||||
|
PUBLIC
|
||||||
|
m
|
||||||
|
)
|
||||||
|
|
||||||
|
# Includes
|
||||||
|
target_include_directories(${DUSK_TARGET_NAME}
|
||||||
|
PUBLIC
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Sources
|
||||||
|
target_sources(${DUSK_TARGET_NAME}
|
||||||
|
PRIVATE
|
||||||
|
main.c
|
||||||
|
input.c
|
||||||
|
)
|
||||||
|
|
||||||
|
# Subdirs
|
||||||
|
add_subdirectory(assert)
|
||||||
|
add_subdirectory(display)
|
||||||
|
add_subdirectory(rpg)
|
||||||
|
add_subdirectory(util)
|
@ -3,4 +3,7 @@
|
|||||||
# This software is released under the MIT License.
|
# This software is released under the MIT License.
|
||||||
# https://opensource.org/licenses/MIT
|
# https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
include(FetchContent)
|
# Sources
|
||||||
|
target_sources(${DUSK_TARGET_NAME}
|
||||||
|
PRIVATE
|
||||||
|
)
|
@ -8,6 +8,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "dusk.h"
|
#include "dusk.h"
|
||||||
|
|
||||||
|
extern const uint16_t RENDER_WIDTH;
|
||||||
|
extern const uint16_t RENDER_HEIGHT;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Init the render system.
|
* Init the render system.
|
||||||
*/
|
*/
|
||||||
@ -16,4 +19,9 @@ void renderInit();
|
|||||||
/**
|
/**
|
||||||
* Update the render system.
|
* Update the render system.
|
||||||
*/
|
*/
|
||||||
void renderUpdate();
|
bool_t renderUpdate();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispose of the render system.
|
||||||
|
*/
|
||||||
|
void renderDispose();
|
29
src/dusk/input.c
Normal file
29
src/dusk/input.c
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "input.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
|
||||||
|
input_t INPUT;
|
||||||
|
|
||||||
|
bool_t inputIsDown(const uint8_t key) {
|
||||||
|
assertTrue(key < INPUT_COUNT, "Invalid input key");
|
||||||
|
return (INPUT.current & key) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t inputWasDown(const uint8_t key) {
|
||||||
|
assertTrue(key < INPUT_COUNT, "Invalid input key");
|
||||||
|
return (INPUT.previous & key) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t inputWasPressed(const uint8_t key) {
|
||||||
|
return inputIsDown(key) && !inputWasDown(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t inputWasReleased(const uint8_t key) {
|
||||||
|
return !inputIsDown(key) && inputWasDown(key);
|
||||||
|
}
|
@ -15,25 +15,17 @@
|
|||||||
#define INPUT_RIGHT (1 << 3)
|
#define INPUT_RIGHT (1 << 3)
|
||||||
#define INPUT_ACTION (1 << 4)
|
#define INPUT_ACTION (1 << 4)
|
||||||
#define INPUT_CANCEL (1 << 5)
|
#define INPUT_CANCEL (1 << 5)
|
||||||
|
#define INPUT_COUNT (INPUT_CANCEL + 1)
|
||||||
|
|
||||||
#define INPUT_BUFFER_SIZE 128
|
#define INPUT_BUFFER_SIZE 128
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t current;
|
uint8_t current;
|
||||||
uint8_t previous;
|
uint8_t previous;
|
||||||
bool_t isRawMode;
|
|
||||||
struct termios origin;
|
|
||||||
} input_t;
|
} input_t;
|
||||||
|
|
||||||
extern input_t INPUT;
|
extern input_t INPUT;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char_t *key;
|
|
||||||
uint8_t value;
|
|
||||||
} inputmap_t;
|
|
||||||
|
|
||||||
extern inputmap_t INPUT_MAP[];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the input system.
|
* Initializes the input system.
|
||||||
*/
|
*/
|
||||||
@ -44,6 +36,11 @@ void inputInit();
|
|||||||
*/
|
*/
|
||||||
void inputUpdate();
|
void inputUpdate();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disposes of the input system, restoring terminal settings.
|
||||||
|
*/
|
||||||
|
void inputDispose();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the specified key is currently pressed down.
|
* Returns true if the specified key is currently pressed down.
|
||||||
*
|
*
|
@ -33,14 +33,7 @@ int32_t main(const int32_t argc, const char **argv) {
|
|||||||
entityUpdate(ent++);
|
entityUpdate(ent++);
|
||||||
} while(ent < (ENTITIES + ENTITY_COUNT));
|
} while(ent < (ENTITIES + ENTITY_COUNT));
|
||||||
|
|
||||||
if(inputIsDown(INPUT_DOWN)) {
|
if(!renderUpdate()) break;
|
||||||
printf("Input down pressed\n");
|
|
||||||
} else {
|
|
||||||
printf("Input down not pressed\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// renderUpdate();
|
|
||||||
usleep(16 * 1000); // Sleep for 16 milliseconds (60 FPS)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
@ -8,7 +8,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
|
|
||||||
#define ENTITY_MOVE_SUBPIXEL 4
|
#define ENTITY_WIDTH 16
|
||||||
|
#define ENTITY_HEIGHT 16
|
||||||
|
#define ENTITY_MOVE_SUBPIXEL ENTITY_WIDTH
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ENTITY_DIR_UP = 0,
|
ENTITY_DIR_UP = 0,
|
||||||
@ -31,7 +33,7 @@ typedef enum {
|
|||||||
typedef struct _entity_t {
|
typedef struct _entity_t {
|
||||||
entitytype_t type;
|
entitytype_t type;
|
||||||
uint8_t x, y;
|
uint8_t x, y;
|
||||||
uint8_t subX, subY;
|
int8_t subX, subY;
|
||||||
entitydir_t dir;
|
entitydir_t dir;
|
||||||
|
|
||||||
// Per type data
|
// Per type data
|
34
src/duskraylib/CMakeLists.txt
Normal file
34
src/duskraylib/CMakeLists.txt
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# Copyright (c) 2025 Dominic Masters
|
||||||
|
#
|
||||||
|
# This software is released under the MIT License.
|
||||||
|
# https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
include(FetchContent)
|
||||||
|
|
||||||
|
# Libs
|
||||||
|
FetchContent_Declare(
|
||||||
|
raylib
|
||||||
|
URL https://github.com/raysan5/raylib/archive/refs/tags/5.5.tar.gz
|
||||||
|
URL_HASH MD5=61638c4c2c097fbca1d6a71e4da36c16
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(raylib)
|
||||||
|
|
||||||
|
target_link_libraries(${DUSK_TARGET_NAME}
|
||||||
|
PUBLIC
|
||||||
|
raylib
|
||||||
|
)
|
||||||
|
|
||||||
|
# Includes
|
||||||
|
target_include_directories(${DUSK_TARGET_NAME}
|
||||||
|
PUBLIC
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Sources
|
||||||
|
target_sources(${DUSK_TARGET_NAME}
|
||||||
|
PRIVATE
|
||||||
|
input.c
|
||||||
|
)
|
||||||
|
|
||||||
|
# Subdirs
|
||||||
|
add_subdirectory(display)
|
@ -7,5 +7,4 @@
|
|||||||
target_sources(${DUSK_TARGET_NAME}
|
target_sources(${DUSK_TARGET_NAME}
|
||||||
PRIVATE
|
PRIVATE
|
||||||
render.c
|
render.c
|
||||||
term.c
|
|
||||||
)
|
)
|
53
src/duskraylib/display/render.c
Normal file
53
src/duskraylib/display/render.c
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "assert/assert.h"
|
||||||
|
#include "display/render.h"
|
||||||
|
#include "raylib.h"
|
||||||
|
#include "rpg/entity/entity.h"
|
||||||
|
|
||||||
|
const uint16_t RENDER_WIDTH = 800;
|
||||||
|
const uint16_t RENDER_HEIGHT = 600;
|
||||||
|
|
||||||
|
void renderInit() {
|
||||||
|
InitWindow(RENDER_WIDTH, RENDER_HEIGHT, "Dusk");
|
||||||
|
SetTargetFPS(60);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t renderUpdate() {
|
||||||
|
// End rendering?
|
||||||
|
if(WindowShouldClose()) return false;
|
||||||
|
|
||||||
|
BeginDrawing();
|
||||||
|
ClearBackground(RAYWHITE);
|
||||||
|
DrawText("Hello, Dusk!", 10, 10, 20, BLACK);
|
||||||
|
|
||||||
|
entity_t *ent = ENTITIES;
|
||||||
|
do {
|
||||||
|
if(ent->type == ENTITY_TYPE_NULL) {
|
||||||
|
ent++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawRectangle(
|
||||||
|
(ent->x * ENTITY_WIDTH) + ent->subX,
|
||||||
|
(ent->y * ENTITY_HEIGHT) + ent->subY,
|
||||||
|
ENTITY_WIDTH,
|
||||||
|
ENTITY_HEIGHT,
|
||||||
|
RED
|
||||||
|
);
|
||||||
|
ent++;
|
||||||
|
} while(ent < (ENTITIES + ENTITY_COUNT));
|
||||||
|
|
||||||
|
EndDrawing();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void renderDispose() {
|
||||||
|
CloseWindow();
|
||||||
|
}
|
47
src/duskraylib/input.c
Normal file
47
src/duskraylib/input.c
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "input.h"
|
||||||
|
#include "raylib.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int32_t key;
|
||||||
|
uint8_t flag;
|
||||||
|
} inputmap_t;
|
||||||
|
|
||||||
|
const inputmap_t INPUT_MAP[] = {
|
||||||
|
{ KEY_W, INPUT_UP },
|
||||||
|
{ KEY_S, INPUT_DOWN },
|
||||||
|
{ KEY_A, INPUT_LEFT },
|
||||||
|
{ KEY_D, INPUT_RIGHT },
|
||||||
|
{ KEY_SPACE, INPUT_ACTION },
|
||||||
|
{ KEY_ESCAPE, INPUT_CANCEL },
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
void inputInit() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void inputUpdate() {
|
||||||
|
uint8_t state = 0;
|
||||||
|
inputmap_t *map = INPUT_MAP;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if(IsKeyDown(map->key)) {
|
||||||
|
state |= map->flag;
|
||||||
|
}
|
||||||
|
map++;
|
||||||
|
} while(map->key != 0);
|
||||||
|
|
||||||
|
INPUT.previous = INPUT.current;
|
||||||
|
INPUT.current = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void inputDispose() {
|
||||||
|
|
||||||
|
}
|
120
src/input.c
120
src/input.c
@ -1,120 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "input.h"
|
|
||||||
#include "util/memory.h"
|
|
||||||
#include "assert/assert.h"
|
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
input_t INPUT;
|
|
||||||
|
|
||||||
inputmap_t INPUT_MAP[] = {
|
|
||||||
{"w", INPUT_UP},
|
|
||||||
{"s", INPUT_DOWN},
|
|
||||||
{"a", INPUT_LEFT},
|
|
||||||
{"d", INPUT_RIGHT},
|
|
||||||
{" ", INPUT_ACTION},
|
|
||||||
{"e", INPUT_ACTION},
|
|
||||||
{"\n", INPUT_ACTION}, // Enter key
|
|
||||||
{"\x1B", INPUT_CANCEL}, // Escape key
|
|
||||||
{"\033[A", INPUT_UP}, // Up arrow
|
|
||||||
{"\033[B", INPUT_DOWN}, // Down arrow
|
|
||||||
{"\033[C", INPUT_RIGHT}, // Right arrow
|
|
||||||
{"\033[D", INPUT_LEFT}, // Left arrow
|
|
||||||
{ 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
void inputEnableRawMode() {
|
|
||||||
if (INPUT.isRawMode) return;
|
|
||||||
tcgetattr(STDIN_FILENO, &INPUT.origin);
|
|
||||||
struct termios raw = INPUT.origin;
|
|
||||||
raw.c_lflag &= ~(ICANON | ECHO);
|
|
||||||
tcsetattr(STDIN_FILENO, TCSANOW, &raw);
|
|
||||||
INPUT.isRawMode = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void inputDisableRawMode() {
|
|
||||||
if(!INPUT.isRawMode) return;
|
|
||||||
tcsetattr(STDIN_FILENO, TCSANOW, &INPUT.origin);
|
|
||||||
INPUT.isRawMode = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void inputSetNonBlocking() {
|
|
||||||
int flags = fcntl(STDIN_FILENO, F_GETFL, 0);
|
|
||||||
fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK);
|
|
||||||
}
|
|
||||||
|
|
||||||
void inputInit() {
|
|
||||||
memoryZero(&INPUT, sizeof(input_t));
|
|
||||||
|
|
||||||
inputEnableRawMode();
|
|
||||||
inputSetNonBlocking();
|
|
||||||
}
|
|
||||||
|
|
||||||
void inputUpdate() {
|
|
||||||
char_t buffer[INPUT_BUFFER_SIZE];
|
|
||||||
ssize_t n = read(STDIN_FILENO, buffer, sizeof(buffer) - 1);
|
|
||||||
|
|
||||||
if(n < 0) {
|
|
||||||
INPUT.previous = INPUT.current;
|
|
||||||
INPUT.current = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
assertTrue(n < INPUT_BUFFER_SIZE, "Input buffer overflow");
|
|
||||||
|
|
||||||
uint8_t val = 0;
|
|
||||||
inputmap_t *map;
|
|
||||||
uint8_t len;
|
|
||||||
char_t *c;
|
|
||||||
for(uint8_t i = 0; i < n; i++) {
|
|
||||||
map = INPUT_MAP;
|
|
||||||
|
|
||||||
do {
|
|
||||||
len = strlen(map->key);
|
|
||||||
|
|
||||||
if(i + len > n) {
|
|
||||||
map++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
c = buffer + i;
|
|
||||||
if(memoryCompare(c, map->key, len) != 0) {
|
|
||||||
map++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Button was pressed
|
|
||||||
val |= map->value;
|
|
||||||
i += len - 1;
|
|
||||||
break;
|
|
||||||
} while(map->key);
|
|
||||||
}
|
|
||||||
|
|
||||||
INPUT.previous = INPUT.current;
|
|
||||||
INPUT.current = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool_t inputIsDown(const uint8_t key) {
|
|
||||||
return (INPUT.current & key) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool_t inputWasDown(const uint8_t key) {
|
|
||||||
return (INPUT.previous & key) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool_t inputWasPressed(const uint8_t key) {
|
|
||||||
return inputIsDown(key) && !inputWasDown(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool_t inputWasReleased(const uint8_t key) {
|
|
||||||
return !inputIsDown(key) && inputWasDown(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
void inputDispose() {
|
|
||||||
inputDisableRawMode();
|
|
||||||
}
|
|
Reference in New Issue
Block a user