Render test

This commit is contained in:
2025-06-10 17:09:33 -05:00
parent a2fd58fda7
commit 1b6db0c643
47 changed files with 219 additions and 370 deletions

View File

@ -39,9 +39,6 @@ project(${DUSK_TARGET_NAME}
# Executable
add_executable(${DUSK_TARGET_NAME})
# Get Libraries
add_subdirectory(lib)
# Add tools
add_subdirectory(tools)

View File

@ -1,29 +1,7 @@
# 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)
add_subdirectory(dusk)
add_subdirectory(duskraylib)

View File

@ -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)

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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
View 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)

View File

@ -3,4 +3,7 @@
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
include(FetchContent)
# Sources
target_sources(${DUSK_TARGET_NAME}
PRIVATE
)

View File

@ -8,6 +8,9 @@
#pragma once
#include "dusk.h"
extern const uint16_t RENDER_WIDTH;
extern const uint16_t RENDER_HEIGHT;
/**
* Init the render system.
*/
@ -16,4 +19,9 @@ void renderInit();
/**
* Update the render system.
*/
void renderUpdate();
bool_t renderUpdate();
/**
* Dispose of the render system.
*/
void renderDispose();

29
src/dusk/input.c Normal file
View 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);
}

View File

@ -15,25 +15,17 @@
#define INPUT_RIGHT (1 << 3)
#define INPUT_ACTION (1 << 4)
#define INPUT_CANCEL (1 << 5)
#define INPUT_COUNT (INPUT_CANCEL + 1)
#define INPUT_BUFFER_SIZE 128
typedef struct {
uint8_t current;
uint8_t previous;
bool_t isRawMode;
struct termios origin;
} input_t;
extern input_t INPUT;
typedef struct {
char_t *key;
uint8_t value;
} inputmap_t;
extern inputmap_t INPUT_MAP[];
/**
* Initializes the input system.
*/
@ -44,6 +36,11 @@ void inputInit();
*/
void inputUpdate();
/**
* Disposes of the input system, restoring terminal settings.
*/
void inputDispose();
/**
* Returns true if the specified key is currently pressed down.
*

View File

@ -33,14 +33,7 @@ int32_t main(const int32_t argc, const char **argv) {
entityUpdate(ent++);
} while(ent < (ENTITIES + ENTITY_COUNT));
if(inputIsDown(INPUT_DOWN)) {
printf("Input down pressed\n");
} else {
printf("Input down not pressed\n");
}
// renderUpdate();
usleep(16 * 1000); // Sleep for 16 milliseconds (60 FPS)
if(!renderUpdate()) break;
}
return EXIT_SUCCESS;

View File

@ -8,7 +8,9 @@
#pragma once
#include "player.h"
#define ENTITY_MOVE_SUBPIXEL 4
#define ENTITY_WIDTH 16
#define ENTITY_HEIGHT 16
#define ENTITY_MOVE_SUBPIXEL ENTITY_WIDTH
typedef enum {
ENTITY_DIR_UP = 0,
@ -31,7 +33,7 @@ typedef enum {
typedef struct _entity_t {
entitytype_t type;
uint8_t x, y;
uint8_t subX, subY;
int8_t subX, subY;
entitydir_t dir;
// Per type data

View 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)

View File

@ -7,5 +7,4 @@
target_sources(${DUSK_TARGET_NAME}
PRIVATE
render.c
term.c
)

View 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
View 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() {
}

View File

@ -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();
}