From c81626e8a4dafcbc7d396b91d15865c758571473 Mon Sep 17 00:00:00 2001 From: kdx Date: Sun, 26 Mar 2023 22:49:52 +0200 Subject: LZR -> TZR --- Makefile | 4 +- compile_flags.txt | 1 + src/TZR.c | 726 ++++++++++++++++++++++++++++++++++++++++++ src/TZR.h | 271 ++++++++++++++++ src/cfg.h | 5 - src/entityimpl.h | 2 +- src/lzr.c | 929 ------------------------------------------------------ src/lzr.h | 129 -------- src/main.c | 26 +- src/player.c | 7 +- 10 files changed, 1020 insertions(+), 1080 deletions(-) create mode 100644 src/TZR.c create mode 100644 src/TZR.h delete mode 100644 src/lzr.c delete mode 100644 src/lzr.h diff --git a/Makefile b/Makefile index 74b3a51..d66b9d5 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ CC := gcc LD := $(CC) WINCC := x86_64-w64-mingw32-gcc -CFLAGS := -g -Os -std=c2x -Wall -Wextra -DLZR_DISABLE_DEVMODE= -LDFLAGS := -lm -lSDL2 -lSDL2_image -lSDL2_mixer -lSDL2_gfx +CFLAGS := -Os -std=c2x -Wall -Wextra -Wno-override-init +LDFLAGS := -lm -lSDL2 -lSDL2_image NAME := jambase SRC := $(wildcard src/*.c) OBJ := $(patsubst src/%.c,obj/%.o,$(SRC)) diff --git a/compile_flags.txt b/compile_flags.txt index f5cab1b..f6d48ab 100644 --- a/compile_flags.txt +++ b/compile_flags.txt @@ -1,3 +1,4 @@ -Wall -Wextra +-Wno-initializer-overrides -std=c2x diff --git a/src/TZR.c b/src/TZR.c new file mode 100644 index 0000000..150cf22 --- /dev/null +++ b/src/TZR.c @@ -0,0 +1,726 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "TZR.h" +#include + +/* sources/drain.h */ + +static void *drain_error(void) +{ + perror("TZR_LoadResourceTyped:drain"); + return NULL; +} + +static char *drain(FILE *fp, size_t *size) +{ + if (fseek(fp, 0, SEEK_END) < 0) + return drain_error(); + *size = ftell(fp); + if (fseek(fp, 0, SEEK_SET) < 0) + return drain_error(); + char *data = malloc(*size); + if (data == NULL) + return drain_error(); + if (fread(data, 1, *size, fp) != *size) + return free(data), drain_error(); + return data; +} + +/* sources/sdl_error.h */ + +static int sdl_error(int rv) +{ + SDL_Log("%s\n", SDL_GetError()); + return rv; +} +/* sources/sdl_rect_to_rect.h */ + +static void TZR_RectFromSDLRect(TZR_Rect *dest, const SDL_Rect *src) +{ + dest->from.x = src->x; + dest->from.y = src->y; + dest->to.x = src->x + src->w - 1; + dest->to.y = src->y + src->h - 1; +} +/* sources/globals.c */ + +TZR_Config ___tzr_config = {0}; +TZR_Color ___tzr_color = {0, 0.0f, 0.0f, 0.0f, 1.0f}; +TZR_Resource *___tzr_resources = NULL; +size_t ___tzr_resources_capacity = 0; +size_t ___tzr_resources_size = 0; +SDL_Window *___tzr_window = NULL; +SDL_Renderer *___tzr_renderer = NULL; +SDL_Texture *___tzr_target = NULL; +unsigned long ___tzr_tick = 0; +unsigned long ___tzr_next_time = 0; +unsigned long ___tzr_min_dt = 0; +int ___tzr_should_quit = 0; +int ___tzr_mouse_x = 0; +int ___tzr_mouse_y = 0; +const char *___tzr_command[___TZR_RES_COUNT] = {0}; +TZR_KeyState ___tzr_keystates[SDL_NUM_SCANCODES] = {0}; +/* sources/TZR_CycleEvents.c */ + +void +TZR_CycleEvents(void) +{ + TZR_ResourcesWatch(); + for (int i = 0; i < SDL_NUM_SCANCODES; i++) { + TZR_KeyState *const keystate = &___tzr_keystates[i]; + switch (*keystate) { + case TZR_KEYSTATE_RELEASE: + case TZR_KEYSTATE_UP: + *keystate = TZR_KEYSTATE_UP; + break; + case TZR_KEYSTATE_PRESS: + case TZR_KEYSTATE_DOWN: + *keystate = TZR_KEYSTATE_DOWN; + break; + default: + break; + } + } + TZR_Event e; + while (TZR_PollEvent(&e)) + ; +} +/* sources/TZR_DestroyResource.c */ + +void +TZR_DestroyResource(TZR_Resource *res, int free_path) +{ + if (res->path != NULL && free_path) + free(res->path); + switch (res->type) { + case TZR_RES_RAW: + if (res->raw.data != NULL) + free(res->raw.data); + break; + case TZR_RES_IMAGE: + if (res->image.ptr != NULL) + SDL_DestroyTexture(res->image.ptr); + break; + default: + fprintf(stderr, "unknown resource type %u\n", res->type); + break; + } +} + +/* sources/TZR_DirectResourceLoad.c */ + +int +TZR_DirectResourceLoad(TZR_Resource *res, const void *data, int size) +{ + switch (res->type) { + case TZR_RES_RAW: + res->raw.size = size; + res->raw.data = malloc(size); + if (res->raw.data == NULL) { + perror("TZR_DirectResourceLoad"); + return -1; + } + memcpy(res->raw.data, data, size); + break; + case TZR_RES_IMAGE: { + SDL_RWops *const rw = SDL_RWFromConstMem(data, size); + if (rw == NULL) + return sdl_error(-1); + SDL_Surface *const surf = IMG_Load_RW(rw, 0); + SDL_RWclose(rw); + if (surf == NULL) + return sdl_error(-1); + SDL_Texture *const tex = + SDL_CreateTextureFromSurface(___tzr_renderer, surf); + SDL_FreeSurface(surf); + if (tex == NULL) + return sdl_error(-1); + if (SDL_SetTextureBlendMode(tex, SDL_BLENDMODE_BLEND) < 0) { + SDL_DestroyTexture(tex); + return sdl_error(-1); + } + if (SDL_QueryTexture(tex, NULL, NULL, + &res->image.width, &res->image.height)) { + SDL_DestroyTexture(tex); + return sdl_error(-1); + } + res->image.ptr = tex; + } break; + default: + fprintf(stderr, "invalid type\n"); + return -1; + } + return 0; +} +/* sources/TZR_DrawBegin.c */ + +int +TZR_DrawBegin(void) +{ + if (SDL_SetRenderTarget(___tzr_renderer, ___tzr_target) < 0) + return sdl_error(-1); + return 0; +} +/* sources/TZR_DrawClear.c */ + +int +TZR_DrawClear(void) +{ + if (SDL_RenderClear(___tzr_renderer) < 0) + return sdl_error(-1); + return 0; +} +/* sources/TZR_DrawEnd.c */ + +int +TZR_DrawEnd(void) +{ + if (SDL_SetRenderTarget(___tzr_renderer, NULL) < 0) + return sdl_error(-1); + if (SDL_SetRenderDrawColor(___tzr_renderer, 0, 0, 0, 255) < 0) + return sdl_error(-1); + if (SDL_RenderClear(___tzr_renderer) < 0) + return sdl_error(-1); + + int win_w, win_h; + SDL_GetWindowSize(___tzr_window, &win_w, &win_h); + win_w = win_w ? win_w : 1; + win_h = win_h ? win_h : 1; + + const float ratio_w = win_w / (float)___tzr_config.width; + const float ratio_h = win_h / (float)___tzr_config.height; + float scale = (ratio_w < ratio_h) ? ratio_w : ratio_h; + if (scale > 1.0f && ___tzr_config.pixel_perfect) + scale = (int)scale; + const int off_x = (win_w - ___tzr_config.width * scale) / 2; + const int off_y = (win_h - ___tzr_config.height * scale) / 2; + const SDL_Rect dest = { + off_x, + off_y, + ___tzr_config.width * scale, + ___tzr_config.height * scale + }; + + if (SDL_RenderCopy(___tzr_renderer, ___tzr_target, NULL, &dest) < 0) + return sdl_error(-1); + if (___tzr_config.target_fps > 0) { + ___tzr_next_time += ___tzr_min_dt; + const unsigned long cur_time = SDL_GetTicks64(); + if (___tzr_next_time <= cur_time) + ___tzr_next_time = cur_time; + else + SDL_Delay(___tzr_next_time - cur_time); + } + SDL_RenderPresent(___tzr_renderer); + ___tzr_tick += 1; + return 0; +} +/* sources/TZR_DrawImage.c */ + +int +_TZR_DrawImage(const TZR_DrawImageArgs *args) +{ + if (args->id == 0) { + fprintf(stderr, "args->id is 0\n"); + return -1; + } + + if (TZR_GetResourceType(args->id) != TZR_RES_IMAGE) { + fprintf(stderr, "%u isn't an image\n", args->id); + return -1; + } + TZR_Resource *const res = TZR_GetResourcePointer(args->id); + const TZR_Image *const img = &res->image; + + if (SDL_SetTextureColorMod(img->ptr, ___tzr_color.r * 255, + ___tzr_color.g * 255, ___tzr_color.b * 255)) + return sdl_error(-1); + if (SDL_SetTextureAlphaMod(img->ptr, ___tzr_color.a * 255)) + return sdl_error(-1); + + float scale_x = args->sx; + float scale_y = args->sy; + + int simg_width = (args->w == INT_MIN) ? img->width : args->w; + if (simg_width < 0) { + simg_width *= -1; + scale_x *= -1; + } + if (simg_width + args->ix > img->width) + simg_width = img->width - args->ix; + + int simg_height = (args->h == INT_MIN) ? img->height : args->h; + if (simg_height < 0) { + simg_height *= -1; + scale_y *= -1; + } + if (simg_height + args->iy > img->height) + simg_height = img->height - args->iy; + + const int flip = (SDL_FLIP_HORIZONTAL * (scale_x < 0.0f)) | + (SDL_FLIP_VERTICAL * (scale_y < 0.0f)); + const SDL_Rect src = { + args->ix, + args->iy, + simg_width, + simg_height + }; + + const int width = simg_width * fabs(scale_x); + const int height = simg_height * fabs(scale_y); + const int x = args->x - (scale_x < 0.0f ? width : 0); + const int y = args->y - (scale_y < 0.0f ? height : 0); + + const SDL_Rect dest = { + x - (args->center ? (simg_width * scale_x / 2) : 0), + y - (args->center ? (simg_height * scale_y / 2) : 0), + width, + height + }; + if (SDL_RenderCopyEx(___tzr_renderer, img->ptr, &src, &dest, + args->r * 360, NULL, flip) < 0) + return sdl_error(-1); + TZR_Rect area; + TZR_RectFromSDLRect(&area, &dest); + return 0; +} +/* sources/TZR_DrawLine.c */ + +int +TZR_DrawLine(int x0, int y0, int x1, int y1) +{ + if (SDL_RenderDrawLine(___tzr_renderer, x0, y0, x1, y1) < 0) + return sdl_error(-1); + return 0; +} +/* sources/TZR_DrawPoint.c */ + +int +TZR_DrawPoint(int x, int y) +{ + if (SDL_RenderDrawPoint(___tzr_renderer, x, y) < 0) + return sdl_error(-1); + return 0; +} +/* sources/TZR_DrawRectangle.c */ + +int +TZR_DrawRectangle(bool fill, int x, int y, int w, int h) +{ + const SDL_Rect rect = { x, y, w, h }; + if (fill) { + if (SDL_RenderFillRect(___tzr_renderer, &rect) < 0) + return sdl_error(-1); + } else { + if (SDL_RenderDrawRect(___tzr_renderer, &rect) < 0) + return sdl_error(-1); + } + return 0; +} +/* sources/TZR_DrawSetColor.c */ + +int +_TZR_DrawSetColor(const TZR_Color *color) +{ + ___tzr_color.r = (color->r < 0.0f) ? ___tzr_color.r : color->r; + ___tzr_color.g = (color->g < 0.0f) ? ___tzr_color.g : color->g; + ___tzr_color.b = (color->b < 0.0f) ? ___tzr_color.b : color->b; + ___tzr_color.a = (color->a < 0.0f) ? ___tzr_color.a : color->a; + const uint8_t r = ___tzr_color.r * 255; + const uint8_t g = ___tzr_color.g * 255; + const uint8_t b = ___tzr_color.b * 255; + const uint8_t a = ___tzr_color.a * 255; + if (SDL_SetRenderDrawColor(___tzr_renderer, r, g, b, a) < 0) + return sdl_error(-1); + return 0; +} +/* sources/TZR_GetImageHeight.c */ + +int +TZR_GetImageHeight(TZR_Uint id) +{ + return TZR_GetResourcePointer(id)->image.height; +} +/* sources/TZR_GetImageWidth.c */ + +int +TZR_GetImageWidth(TZR_Uint id) +{ + return TZR_GetResourcePointer(id)->image.width; +} +/* sources/TZR_GetKeyState.c */ + +TZR_KeyState +TZR_GetKeyState(int scancode) +{ + return ___tzr_keystates[scancode]; +} +/* sources/TZR_GetRawResource.c */ + +TZR_Raw * +TZR_GetRawResource(TZR_Uint id) +{ + return &TZR_GetResourcePointer(id)->raw; +} +/* sources/TZR_GetResourcePath.c */ + +const char * +TZR_GetResourcePath(TZR_Uint id) +{ + return TZR_GetResourcePointer(id)->path; +} +/* sources/TZR_GetResourcePointer.c */ + +TZR_Resource * +TZR_GetResourcePointer(TZR_Uint id) +{ + return &___tzr_resources[id - 1]; +} +/* sources/TZR_GetResourceType.c */ + +TZR_ResourceType +TZR_GetResourceType(TZR_Uint id) +{ + return TZR_GetResourcePointer(id)->type; +} +/* sources/TZR_GetTick.c */ + +unsigned long +TZR_GetTick(void) +{ + return ___tzr_tick; +} +/* sources/TZR_Init.c */ + +static int +_sdl_error(void) +{ + sdl_error(-1); + TZR_Quit(); + return -1; +} + +int +_TZR_Init(const TZR_Config *config) +{ + if (SDL_Init(SDL_INIT_VIDEO) < 0) + return _sdl_error(); + if (IMG_Init(IMG_INIT_PNG) < 0) + return _sdl_error(); + + memcpy(&___tzr_config, config, sizeof(TZR_Config)); + char *const basepath = SDL_GetBasePath(); + if (basepath == NULL) + return _sdl_error(); + const int chdir_rv = chdir(basepath); + SDL_free(basepath); + if (chdir_rv < 0) + return perror("TZR_Init"), -1; + + ___tzr_window = SDL_CreateWindow("TZR", SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, + ___tzr_config.width, + ___tzr_config.height, + SDL_WINDOW_RESIZABLE); + if (___tzr_window == NULL) + return _sdl_error(); + + ___tzr_renderer = SDL_CreateRenderer(___tzr_window, -1, + SDL_RENDERER_ACCELERATED); + if (___tzr_renderer == NULL) + return _sdl_error(); + + if (SDL_SetRenderDrawBlendMode(___tzr_renderer, SDL_BLENDMODE_BLEND)) + return _sdl_error(); + + ___tzr_target = SDL_CreateTexture(___tzr_renderer, + SDL_PIXELFORMAT_RGB888, + SDL_TEXTUREACCESS_TARGET, + ___tzr_config.width, + ___tzr_config.height); + if (___tzr_target == NULL) + return _sdl_error(); + + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, 0); + ___tzr_tick = 0; + + if (___tzr_config.target_fps > 0) { + ___tzr_min_dt = 1000 / ___tzr_config.target_fps; + ___tzr_next_time = SDL_GetTicks64(); + } + + ___tzr_command[TZR_RES_RAW] = getenv("TZR_EDIT_RAW"); + if (___tzr_command[TZR_RES_RAW] == NULL) + ___tzr_command[TZR_RES_RAW] = "foot nvim"; + ___tzr_command[TZR_RES_IMAGE] = getenv("TZR_EDIT_IMAGE"); + if (___tzr_command[TZR_RES_IMAGE] == NULL) + ___tzr_command[TZR_RES_IMAGE] = "gimp"; + return 0; +} +/* sources/TZR_IsKeyDown.c */ + +bool +TZR_IsKeyDown(int scancode) +{ + const TZR_KeyState state = TZR_GetKeyState(scancode); + return (state == TZR_KEYSTATE_DOWN || state == TZR_KEYSTATE_PRESS); +} +/* sources/TZR_IsKeyPressed.c */ + +bool +TZR_IsKeyPressed(int scancode) +{ + return (TZR_GetKeyState(scancode) == TZR_KEYSTATE_PRESS); +} +/* sources/TZR_IsKeyReleased.c */ + +bool +TZR_IsKeyReleased(int scancode) +{ + if (TZR_GetKeyState(scancode) == TZR_KEYSTATE_RELEASE) + return true; + return false; +} +/* sources/TZR_IsKeyUp.c */ + +bool +TZR_IsKeyUp(int scancode) +{ + const TZR_KeyState state = TZR_GetKeyState(scancode); + return (state == TZR_KEYSTATE_UP || state == TZR_KEYSTATE_RELEASE); +} +/* sources/TZR_LoadResource.c */ + +static TZR_ResourceType +deduce_type(const char *path) +{ + const char *const path_extension = strrchr(path, '.'); + if (path_extension == NULL) + return TZR_RES_RAW; + if (strcasecmp(path_extension, ".bmp") == 0 || + strcasecmp(path_extension, ".png") == 0) + return TZR_RES_IMAGE; + return TZR_RES_RAW; +} + +TZR_Uint +TZR_LoadResource(const char *path) +{ + return TZR_LoadResourceTyped(deduce_type(path), path); +} +/* sources/TZR_LoadResourceFromMemory.c */ + +static int +reserve_ressources(size_t size) +{ + if (size <= ___tzr_resources_capacity) + return 0; + size_t target = 16; + while (target < size * sizeof(TZR_Resource)) + target *= 2; + TZR_Resource *new_resources; + if (___tzr_resources == NULL) + new_resources = malloc(target); + else + new_resources = realloc(___tzr_resources, target); + if (new_resources == NULL) { + perror("TZR_LoadResourceFromMemory:reserve_ressources"); + return 1; + } + ___tzr_resources = new_resources; + return 0; +} + +TZR_Uint +TZR_LoadResourceFromMemory(TZR_ResourceType type, const void *data, int size) +{ + if (reserve_ressources(___tzr_resources_size + 1)) { + fprintf(stderr, "failed to reserve for new ressource\n"); + return 0; + } + TZR_Resource *const res = &___tzr_resources[___tzr_resources_size]; + res->type = type; + res->path = NULL; + if (TZR_DirectResourceLoad(res, data, size)) + return 0; + ___tzr_resources_size += 1; + return ___tzr_resources_size; +} +/* sources/TZR_LoadResourceTyped.c */ + +TZR_Uint +TZR_LoadResourceTyped(TZR_ResourceType type, const char *path) +{ + for (TZR_Uint i = 0; i < ___tzr_resources_size; i++) + if (___tzr_resources[i].type == type && + strcmp(___tzr_resources[i].path, path) == 0) + return i + 1; + FILE *const fp = fopen(path, "rb"); + if (fp == NULL) { + perror(path); + return 0; + } + size_t size; + char *const data = drain(fp, &size); + fclose(fp); + if (data == NULL) + return 0; + const TZR_Uint id = TZR_LoadResourceFromMemory(type, data, size); + free(data); + if (id == 0) + return 0; + TZR_Resource *const res = TZR_GetResourcePointer(id); + + const size_t path_len = strlen(path); + struct stat st = {0}; + (void)stat(path, &st); + res->path = malloc(path_len + 1); + res->mtime = 0; + if (res->path == NULL) + perror("TZR_LoadResourceTyped"); + else + strcpy(res->path, path); + return id; +} +/* sources/TZR_PollEvent.c */ + +int +TZR_PollEvent(TZR_Event *e) +{ + TZR_Event discard; + if (e == NULL) + e = &discard; + + SDL_Event se; + while (SDL_PollEvent(&se)) switch (se.type) { + case SDL_QUIT: + e->type = TZR_EV_QUIT; + ___tzr_should_quit = 1; + return 1; + case SDL_KEYDOWN: + if (se.key.repeat) + break; + e->type = TZR_EV_KEYDOWN; + e->button = se.key.keysym.scancode; + ___tzr_keystates[e->button] = TZR_KEYSTATE_PRESS; + break; + case SDL_KEYUP: + e->type = TZR_EV_KEYUP; + e->button = se.key.keysym.scancode; + ___tzr_keystates[e->button] = TZR_KEYSTATE_RELEASE; + break; + case SDL_MOUSEBUTTONDOWN: + ___tzr_mouse_x = se.button.x; + ___tzr_mouse_y = se.button.y; + break; + case SDL_MOUSEBUTTONUP: + ___tzr_mouse_x = se.button.x; + ___tzr_mouse_y = se.button.y; + break; + case SDL_MOUSEMOTION: + ___tzr_mouse_x = se.motion.x; + ___tzr_mouse_y = se.motion.y; + break; + default: + break; + } + return 0; +} +/* sources/TZR_Quit.c */ + +void +TZR_Quit(void) +{ + for (size_t i = 0; i < ___tzr_resources_size; i++) + TZR_DestroyResource(&___tzr_resources[i], 1); + if (___tzr_resources != NULL) + free(___tzr_resources); + ___tzr_resources = NULL; + ___tzr_resources_size = 0; + ___tzr_resources_capacity = 0; + if (___tzr_target != NULL) { + SDL_DestroyTexture(___tzr_target); + ___tzr_target = NULL; + } + if (___tzr_renderer != NULL) { + SDL_DestroyRenderer(___tzr_renderer); + ___tzr_renderer = NULL; + } + if (___tzr_window != NULL) { + SDL_DestroyWindow(___tzr_window); + ___tzr_window = NULL; + } + IMG_Quit(); + SDL_Quit(); +} +/* sources/TZR_ReloadResource.c */ + +int +TZR_ReloadResource(TZR_Uint id) +{ + TZR_Resource *const res = TZR_GetResourcePointer(id); + if (res->path == NULL) { + fprintf(stderr, "resource path of %u is NULL\n", id); + return -1; + } + FILE *const fp = fopen(res->path, "rb"); + if (fp == NULL) { + perror(res->path); + return -1; + } + size_t size; + char *const data = drain(fp, &size); + fclose(fp); + if (data == NULL) + return -1; + TZR_Resource new_res; + memcpy(&new_res, res, sizeof(TZR_Resource)); + const int load_rv = TZR_DirectResourceLoad(&new_res, data, size); + free(data); + if (load_rv) + return -1; + TZR_DestroyResource(res, 0); + memcpy(res, &new_res, sizeof(TZR_Resource)); + return 0; +} +/* sources/TZR_ResourcesWatch.c */ + +void +TZR_ResourcesWatch(void) +{ + for (TZR_Uint i = 0; i < ___tzr_resources_size; i++) { + TZR_Resource *const res = TZR_GetResourcePointer(i + 1); + if (res->path == NULL) + continue; + struct stat st = {0}; + (void)stat(res->path, &st); + if (st.st_mtime != res->mtime) { + if (res->mtime != 0) + TZR_ReloadResource(i + 1); + res->mtime = st.st_mtime; + } + } +} +/* sources/TZR_ShouldQuit.c */ + +int +TZR_ShouldQuit(void) +{ + return ___tzr_should_quit; +} + +/* commit hash: 8b92076145893cfdaf3e648e0324b163c1a6d28e */ diff --git a/src/TZR.h b/src/TZR.h new file mode 100644 index 0000000..33c6af8 --- /dev/null +++ b/src/TZR.h @@ -0,0 +1,271 @@ +#pragma once +#include +#include +#include +#include +#include +#include + +/* headers/TZR_types.h */ + +enum TZR_ResourceType { + TZR_RES_RAW, + TZR_RES_IMAGE, + ___TZR_RES_COUNT +}; + +enum TZR_EventType { + TZR_EV_QUIT, + TZR_EV_KEYDOWN, + TZR_EV_KEYUP +}; + +enum TZR_KeyState { + TZR_KEYSTATE_UP, + TZR_KEYSTATE_DOWN, + TZR_KEYSTATE_RELEASE, + TZR_KEYSTATE_PRESS +}; + +typedef unsigned int TZR_Uint; +typedef struct TZR_Config TZR_Config; +typedef struct TZR_Point TZR_Point; +typedef struct TZR_Color TZR_Color; +typedef struct TZR_Rect TZR_Rect; +typedef enum TZR_ResourceType TZR_ResourceType; +typedef struct TZR_Raw TZR_Raw; +typedef struct TZR_Image TZR_Image; +typedef struct TZR_Resource TZR_Resource; +typedef enum TZR_EventType TZR_EventType; +typedef struct TZR_Event TZR_Event; +typedef struct TZR_DrawImageArgs TZR_DrawImageArgs; +typedef enum TZR_KeyState TZR_KeyState; + +struct TZR_Config { + int _; + int width; + int height; + int target_fps; + bool pixel_perfect; + const char *title; +}; + +struct TZR_Point { + int x; + int y; +}; + +struct TZR_Color { + int _; + float r; + float g; + float b; + float a; +}; + +struct TZR_Rect { + TZR_Point from; + TZR_Point to; +}; + +struct TZR_Raw { + void *data; + size_t size; +}; + +struct TZR_Image { + int width; + int height; + SDL_Texture *ptr; +}; + +struct TZR_Resource { + TZR_ResourceType type; + char *path; /* allocated and freed by TZR; can be NULL */ + long mtime; + union { + TZR_Raw raw; /* raw file data */ + TZR_Image image; + }; +}; + +struct TZR_Event { + TZR_EventType type; + int button; +}; + +struct TZR_DrawImageArgs { + int _; + TZR_Uint id; + int x; + int y; + int ix; + int iy; + int w; + int h; + float r; + float sx; + float sy; + bool center; +}; +/* headers/TZR_globals.h */ + +extern TZR_Config ___tzr_config; +extern TZR_Color ___tzr_color; +extern TZR_Resource *___tzr_resources; +extern size_t ___tzr_resources_capacity; +extern size_t ___tzr_resources_size; +extern SDL_Window *___tzr_window; +extern SDL_Renderer *___tzr_renderer; +extern SDL_Texture *___tzr_target; +extern unsigned long ___tzr_tick; +extern unsigned long ___tzr_next_time; +extern unsigned long ___tzr_min_dt; +extern int ___tzr_should_quit; +extern int ___tzr_mouse_x; +extern int ___tzr_mouse_y; +extern const char *___tzr_command[___TZR_RES_COUNT]; +extern TZR_KeyState ___tzr_keystates[SDL_NUM_SCANCODES]; +/* headers/TZR_resource.h */ + +#define TZR_RES TZR_LoadResource + +/* Return 0 on error. */ +[[nodiscard]] +TZR_Uint TZR_LoadResourceFromMemory(TZR_ResourceType type, const void *data, int size); +[[nodiscard]] +TZR_Uint TZR_LoadResourceTyped(TZR_ResourceType type, const char *path); + +/* Return 0 on error; try to autodetect resource type from file extension. */ +[[nodiscard]] +TZR_Uint TZR_LoadResource(const char *path); + +/* Doesn't handle invalid ID. Pointer might get invalidated by resource + * creation calls, use with caution. */ +TZR_Resource *TZR_GetResourcePointer(TZR_Uint id); + +/* Doesn't handle invalid ID. Pointer might get invalidated by resource + * creation calls, use with caution. */ +TZR_Raw *TZR_GetRawResource(TZR_Uint id); + +/* Doesn't handle invalid ID. */ +TZR_ResourceType TZR_GetResourceType(TZR_Uint id); + +/* Doesn't handle invalid ID. */ +const char *TZR_GetResourcePath(TZR_Uint id); + +/* Doesn't handle invalid ID. */ +int TZR_GetImageWidth(TZR_Uint id); + +/* Doesn't handle invalid ID. */ +int TZR_GetImageHeight(TZR_Uint id); + +/* Reload ressource. Returns -1 on error and doesn't apply changes. */ +int TZR_ReloadResource(TZR_Uint id); + +/* Watch for changes on managed resources and hotreload if appropriate. */ +void TZR_ResourcesWatch(void); + +/* Used internaly. */ +[[nodiscard]] +int TZR_DirectResourceLoad(TZR_Resource *res, const void *data, int size); +void TZR_DestroyResource(TZR_Resource *res, int free_path); +/* headers/TZR_events.h */ + +/* Write event data to `e`. Return 0 when event queue is empty. */ +int TZR_PollEvent(TZR_Event *e); + +/* Drain queued events with TZR_PollEvent and call TZR_ResourcesWatch. */ +void TZR_CycleEvents(void); +/* headers/TZR_render.h */ + +/* All draw calls should happen between TZR_DrawBegin and TZR_DrawEnd. + * Return -1 on error. */ +[[nodiscard]] +int TZR_DrawBegin(void); + +/* Return -1 on error. */ +[[nodiscard]] +int TZR_DrawEnd(void); + +/* Return -1 on error. */ +#define TZR_DrawSetColor(...) _TZR_DrawSetColor(&(const TZR_Color){ \ + .r=-1.0f, .g=-1.0f, .b=-1.0f, .a=-1.0f, ._=0, __VA_ARGS__ }) +#ifdef TZR_PARANOID +[[nodiscard]] +#endif +int _TZR_DrawSetColor(const TZR_Color *color); + +/* Return -1 on error. */ +#ifdef TZR_PARANOID +[[nodiscard]] +#endif +int TZR_DrawClear(void); + +/* Return -1 on error. Draw point on `x`;`y` in the framebuffer. */ +#ifdef TZR_PARANOID +[[nodiscard]] +#endif +int TZR_DrawPoint(int x, int y); + +/* Return -1 on error. Draw line between `x0`;`y0` and `x1`;`y1` in the + * framebuffer. */ +#ifdef TZR_PARANOID +[[nodiscard]] +#endif +int TZR_DrawLine(int x0, int y0, int x1, int y1); + +/* Return -1 on error. Draw rectangle at `x`;`y` position of size `w`x`h` in the + * framebuffer. */ +#ifdef TZR_PARANOID +[[nodiscard]] +#endif +int TZR_DrawRectangle(bool fill, int x, int y, int w, int h); + +/* Return -1 on error. Draw texture ressource `id` at `x`;`y` position of + * the framebuffer. */ +#define TZR_DrawImage(...) _TZR_DrawImage(&(const TZR_DrawImageArgs){ \ + .x=0, .y=0, .ix=0, .iy=0, .w=INT_MIN, .h=INT_MIN, .r=0.0f, .sx=1.0f, \ + .sy=1.0f, .center=false, ._=0, __VA_ARGS__ }) +#ifdef TZR_PARANOID +[[nodiscard]] +#endif +int _TZR_DrawImage(const TZR_DrawImageArgs *args); +/* headers/TZR_keystate.h */ + +TZR_KeyState TZR_GetKeyState(int scancode); +bool TZR_IsKeyDown(int scancode); +bool TZR_IsKeyUp(int scancode); +bool TZR_IsKeyReleased(int scancode); +bool TZR_IsKeyPressed(int scancode); +/* headers/TZR.h */ + +/* TZR manages all loaded resources internally and tries to avoid duplicate. + * A resource can be loaded multiple times if asked, identification doesn't rely + * on filepath. In doubt, use TZR_LoadResource ONCE per asset and store the ID. + * Resources are exposed as ID instead of pointer, as a future proof measure in + * case TZR needs to rearrange memory at runtime in the future. */ + +#define TZR_Init(...) _TZR_Init(&(const TZR_Config){ \ + .width=256, \ + .height=224, \ + .target_fps=60, \ + .pixel_perfect=true, \ + .title="TZR", \ + ._=0, __VA_ARGS__ }) + +/* Should be called only once before usage of any other function unless + * otherwise specified. On error this calls TZR_Quit and returns -1. + * `config` will be duplicated internally and can be safely discarded. */ +[[nodiscard]] +int _TZR_Init(const TZR_Config *config); + +/* Destroy and free everything created by TZR. */ +void TZR_Quit(void); + +/* Return non-zero value when a quit event has been received. */ +int TZR_ShouldQuit(void); + +unsigned long TZR_GetTick(void); + +/* commit hash: 8b92076145893cfdaf3e648e0324b163c1a6d28e */ diff --git a/src/cfg.h b/src/cfg.h index c0e8f4e..45c6e23 100644 --- a/src/cfg.h +++ b/src/cfg.h @@ -1,11 +1,6 @@ #pragma once -#include "lzr.h" #define DWIDTH 400 #define DHEIGHT 224 #define TARGET_FPS 30 #define TSIZE 16 - -static const LZR_Config cfg = { - DWIDTH, DHEIGHT, TARGET_FPS, TSIZE, "jambase", 0.0, true, true -}; diff --git a/src/entityimpl.h b/src/entityimpl.h index afc9dc2..bd88df4 100644 --- a/src/entityimpl.h +++ b/src/entityimpl.h @@ -1,7 +1,7 @@ #pragma once #include "game.h" #include "cfg.h" -#include "lzr.h" +#include "TZR.h" #include "entitytag.h" #include diff --git a/src/lzr.c b/src/lzr.c deleted file mode 100644 index 7f3cfe0..0000000 --- a/src/lzr.c +++ /dev/null @@ -1,929 +0,0 @@ -/* Licensing information can be found at the end of the file. */ -#include "lzr.h" -#include -#ifdef LZR_ENABLE_GFX -# include -#endif -#ifdef LZR_ENABLE_IMAGE -# include -#endif -#ifdef LZR_ENABLE_MIXER -# include -#endif -#ifdef LZR_ENABLE_DEVMODE -# include -#endif -#include -#include -#include -#include - -#define UNPACKED_COLOR color[0], color[1], color[2] -#define UNPACKED_COLOR_RGBA color[0], color[1], color[2], color[3] -#define SCODE_BIND_MENU SDL_SCANCODE_F1 -#define SCODE_FULLSCREEN SDL_SCANCODE_F11 - -static LZR_Config config = {0}; -static char *basepath = NULL; -static SDL_Window *window = NULL; -static SDL_Renderer *renderer = NULL; -static SDL_Texture *target = NULL; -static uint_least64_t next_time = 0; -static uint_least64_t min_dt = 0; -static bool should_quit = false; -static struct { - SDL_Texture *tex; - int width, height; - char *path; - long mtime; -} images[LZR_MAX_IMAGES] = {0}; -static unsigned int color[4] = {0}; -static unsigned int map[LZR_BUTTON_COUNT] = { - SDL_SCANCODE_LEFT, SDL_SCANCODE_RIGHT, SDL_SCANCODE_UP, - SDL_SCANCODE_DOWN, SDL_SCANCODE_X, SDL_SCANCODE_C}; -static bool input[LZR_BUTTON_COUNT] = {false}; -static SDL_Point *points = NULL; -static uint64_t tick = 0; -static int off_x = 0; -static int off_y = 0; -static float scale = 1.0; -static int mouse_x = 0; -static int mouse_y = 0; - -#ifdef LZR_ENABLE_MIXER -static struct { - Mix_Chunk *ptr; -} sounds[LZR_MAX_SOUNDS] = {0}; -static Mix_Music *music = NULL; -#endif - -static char *_lzrstrdup(const char *str) -{ - char *const cpy = malloc(strlen(str) + 1); - if (cpy == NULL) - return NULL; - strcpy(cpy, str); - return cpy; -} - -static int _scode_to_button(unsigned int scode) -{ - for (int i = 0; i < LZR_BUTTON_MOUSE_L; i++) - if (map[i] == scode) - return i; - return -1; -} - -static void _draw_btn(SDL_Renderer *ren, int btn, int x, int y, - unsigned int size) -{ -#ifdef LZR_ENABLE_GFX - const unsigned int size_2thirds = size * 2 / 3; - switch (btn) { - case LZR_BUTTON_LEFT: - filledTrigonRGBA(ren, x - size / 2, y, x + size / 2, - y + size_2thirds, x + size / 2, - y - size_2thirds, 0, 0, 0, 255); - break; - case LZR_BUTTON_RIGHT: - filledTrigonRGBA(ren, x + size / 2, y, x - size / 2, - y + size_2thirds, x - size / 2, - y - size_2thirds, 0, 0, 0, 255); - break; - case LZR_BUTTON_UP: - filledTrigonRGBA(ren, x, y - size / 2, x - size_2thirds, - y + size / 2, x + size_2thirds, y + size / 2, - 0, 0, 0, 255); - break; - case LZR_BUTTON_DOWN: - filledTrigonRGBA(ren, x, y + size / 2, x - size_2thirds, - y - size / 2, x + size_2thirds, y - size / 2, - 0, 0, 0, 255); - break; - case LZR_BUTTON_O: - filledCircleRGBA(ren, x, y, size * 2 / 3, 0, 0, 0, 255); - break; - case LZR_BUTTON_X: - thickLineRGBA(ren, x - size / 2, y - size / 2, x + size / 2, - y + size / 2, size / 16 + 1, 0, 0, 0, 255); - thickLineRGBA(ren, x + size / 2, y - size / 2, x - size / 2, - y + size / 2, size / 16 + 1, 0, 0, 0, 255); - break; - default: - break; - } -#else - (void)ren, (void)btn, (void)x, (void)y, (void)size; -#endif -} - -static void _bind_menu(void) -{ - SDL_Log("entering bind menu"); - SDL_Window *win = NULL; - SDL_Renderer *ren = NULL; - if (SDL_CreateWindowAndRenderer(256, 256, 0, &win, &ren) < 0) { - SDL_Log("%s", SDL_GetError()); - return; - } - int btn = 0; - SDL_Event e; - while (btn < LZR_BUTTON_MOUSE_L) { - while (SDL_PollEvent(&e)) { - if (e.type != SDL_KEYDOWN || e.key.repeat || - e.key.keysym.scancode == SCODE_BIND_MENU || - e.key.keysym.scancode == SCODE_FULLSCREEN) - continue; - if (e.key.keysym.scancode == SDL_SCANCODE_ESCAPE || - e.type == SDL_QUIT) - goto exit_bind_menu; - LZR_ButtonBind(btn, e.key.keysym.scancode); - btn++; - } - SDL_SetRenderDrawColor(ren, 220, 220, 200, 255); - SDL_RenderClear(ren); - SDL_SetRenderDrawColor(ren, 0, 0, 0, 255); - _draw_btn(ren, btn, 128, 128, 104); - SDL_RenderPresent(ren); - sleep(0); - } -exit_bind_menu: - SDL_DestroyRenderer(ren); - SDL_DestroyWindow(win); - SDL_Log("leaving bind menu"); -} - -int LZR_Init(LZR_Config cfg) -{ - memcpy(&config, &cfg, sizeof(config)); - if (config.display_width == 0) { - SDL_Log("display_width can't be 0"); - return -1; - } - if (config.display_height == 0) { - SDL_Log("display_height can't be 0"); - return -1; - } - if (config.title == NULL) { - SDL_Log("title is NULL, defaulting to 'LZR'"); - config.title = "LZR"; - } - if (config.tile_size == 0) - config.tile_size = 1; - if (config.ratio <= 0.0) - config.ratio = 1.0; - else { - const double ratio = - (float)config.display_width / (float)config.display_height; - config.ratio /= ratio; - } - if (SDL_Init(SDL_INIT_VIDEO) < 0) { - SDL_Log("%s", SDL_GetError()); - return -1; - } -#ifdef LZR_ENABLE_IMAGE - if (IMG_Init(IMG_INIT_PNG) != IMG_INIT_PNG) { - SDL_Log("%s", IMG_GetError()); - return -1; - } -#endif -#ifdef LZR_ENABLE_MIXER - if (Mix_Init(MIX_INIT_FLAC) != MIX_INIT_FLAC) { - SDL_Log("%s", Mix_GetError()); - return -1; - } - if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 8, 1024) < 0) { - SDL_Log("%s", Mix_GetError()); - return -1; - } -#endif - basepath = SDL_GetBasePath(); - if (basepath == NULL) { - SDL_Log("%s", SDL_GetError()); - return -1; - } - const int dwidth = config.display_width * config.ratio; - window = SDL_CreateWindow(config.title, SDL_WINDOWPOS_UNDEFINED, - SDL_WINDOWPOS_UNDEFINED, dwidth, - config.display_height, SDL_WINDOW_RESIZABLE); - if (window == NULL) { - SDL_Log("%s", SDL_GetError()); - return -1; - } - renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); - if (renderer == NULL) { - SDL_Log("%s", SDL_GetError()); - return -1; - } - target = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB888, - SDL_TEXTUREACCESS_TARGET, - config.display_width, config.display_height); - if (target == NULL) { - SDL_Log("%s", SDL_GetError()); - return -1; - } - points = - calloc(cfg.display_width * cfg.display_height, sizeof(SDL_Point)); - if (points == NULL) { - SDL_Log("calloc failed"); - return -1; - } - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, 0); - if (config.target_fps) { - min_dt = 1000 / config.target_fps; - next_time = SDL_GetTicks64(); - } - if (config.hide_cursor && SDL_ShowCursor(SDL_DISABLE) < 0) { - SDL_Log("%s", SDL_GetError()); - return -1; - } - if (LZR_DrawSetColor(1.0f, 1.0f, 1.0f, 1.0f)) - return -1; - return 0; -} - -void LZR_Quit(void) -{ -#ifdef LZR_ENABLE_MIXER - for (int i = 0; i < LZR_MAX_SOUNDS; i++) - if (sounds[i].ptr != NULL) { - Mix_FreeChunk(sounds[i].ptr); - sounds[i].ptr = NULL; - } - Mix_CloseAudio(); - Mix_Quit(); -#endif - for (int i = 0; i < LZR_MAX_IMAGES; i++) { - if (images[i].tex != NULL) { - SDL_DestroyTexture(images[i].tex); - images[i].tex = NULL; - } - if (images[i].path != NULL) { - free(images[i].path); - images[i].path = NULL; - } - } - if (points != NULL) { - free(points); - points = NULL; - } - if (target != NULL) { - SDL_DestroyTexture(target); - target = NULL; - } - if (renderer != NULL) { - SDL_DestroyRenderer(renderer); - renderer = NULL; - } - if (window != NULL) { - SDL_DestroyWindow(window); - window = NULL; - } - if (basepath != NULL) { - SDL_free(basepath); - basepath = NULL; - } -#ifdef LZR_ENABLE_IMAGE - IMG_Quit(); -#endif - SDL_Quit(); -} - -bool LZR_ShouldQuit(void) -{ - return should_quit; -} - -char *LZR_PathPrefix(const char *path) -{ - if (path == NULL) { - SDL_Log("path is NULL"); - return NULL; - } - if (basepath == NULL) { - SDL_Log("basepath is NULL"); - return _lzrstrdup(path); - } - char *const buf = malloc(strlen(basepath) + strlen(path) + 1); - if (buf == NULL) { - SDL_Log("malloc failed"); - return NULL; - } - strcpy(buf, basepath); - strcat(buf, path); - return buf; -} - -int LZR_ImageLoad(const char *path) -{ - char *apath; - long mtime = 0; -#ifdef LZR_ENABLE_DEVMODE - apath = LZR_PathPrefix(path); - if (apath == NULL) - return -1; - struct stat st = {0}; - (void)stat(apath, &st); /* stat can fail safely */ - mtime = st.st_mtim.tv_nsec; -#endif - int i; - for (i = 0; i < LZR_MAX_IMAGES; i++) { - if (images[i].path != NULL && - strcmp(images[i].path, path) == 0) { - if (mtime != images[i].mtime) { - SDL_Log("reloading %d", i); - break; - } - return i; - } - if (images[i].tex == NULL) - break; - } - if (i >= LZR_MAX_IMAGES) { - SDL_Log("reached image limit (%d)", LZR_MAX_IMAGES); - return -1; - } - apath = LZR_PathPrefix(path); - if (apath == NULL) { - SDL_Log("LZR_PathPrefix failed"); - return -1; - } -#ifdef LZR_ENABLE_IMAGE - SDL_Surface *const surf = IMG_Load(apath); -#else - SDL_Surface *const surf = SDL_LoadBMP(apath); -#endif - free(apath); - if (surf == NULL) { - SDL_Log("%s: %s", path, SDL_GetError()); - return -1; - } - SDL_Texture *const tex = SDL_CreateTextureFromSurface(renderer, surf); - SDL_FreeSurface(surf); - if (tex == NULL) { - SDL_Log("%s", SDL_GetError()); - return -1; - } - if (images[i].tex != NULL) - SDL_DestroyTexture(images[i].tex); - images[i].tex = tex; - images[i].mtime = mtime; - if (SDL_SetTextureBlendMode(images[i].tex, SDL_BLENDMODE_BLEND) < 0) { - SDL_Log("%s", SDL_GetError()); - return -1; - } - if (SDL_QueryTexture(tex, NULL, NULL, &images[i].width, - &images[i].height)) { - SDL_Log("%s", SDL_GetError()); - return -1; - } - if (images[i].path == NULL) - images[i].path = _lzrstrdup(path); - return i; -} - -int LZR_SoundLoad(const char *path, float volume) -{ -#ifdef LZR_ENABLE_MIXER - int i; - for (i = 0; i < LZR_MAX_SOUNDS; i++) - if (sounds[i].ptr == NULL) - break; - if (i >= LZR_MAX_SOUNDS) { - SDL_Log("reached sounds limit (%d)", LZR_MAX_SOUNDS); - return -1; - } - char *const apath = LZR_PathPrefix(path); - if (apath == NULL) { - SDL_Log("LZR_PathPrefix failed"); - return -1; - } - Mix_Chunk *const chunk = Mix_LoadWAV(apath); - free(apath); - if (chunk == NULL) { - SDL_Log("%s: %s", path, Mix_GetError()); - return -1; - } - Mix_VolumeChunk(chunk, volume); - sounds[i].ptr = chunk; - return i; -#else - (void)path, (void)volume; - return -1; -#endif -} - -bool LZR_PollEvent(LZR_Event *e) -{ - if (e == NULL) { - SDL_Log("e is NULL"); - return false; - } - SDL_Event se; - while (SDL_PollEvent(&se)) { - switch (se.type) { - case SDL_QUIT: - e->type = LZR_EVENT_QUIT; - should_quit = true; - return true; - case SDL_KEYDOWN: { - if (!config.disable_bind_menu && - se.key.keysym.scancode == SCODE_BIND_MENU) - _bind_menu(); - if (se.key.keysym.scancode == SCODE_FULLSCREEN) - LZR_ToggleFullscreen(); - const int b = _scode_to_button(se.key.keysym.scancode); - if (se.key.repeat || b < 0) - break; - e->type = LZR_EVENT_BUTTON_DOWN; - e->button = b; - input[b] = true; - return true; - } - case SDL_MOUSEBUTTONDOWN: { - e->type = LZR_EVENT_BUTTON_DOWN; - e->button = LZR_BUTTON_MOUSE_L + se.button.button - 1; - e->x = se.button.x, e->y = se.button.y; - LZR_ScreenTransform(&e->x, &e->y); - mouse_x = e->x, mouse_y = e->y; - if (e->button >= LZR_BUTTON_COUNT) - continue; - input[e->button] = true; - return true; - } - case SDL_KEYUP: { - const int b = _scode_to_button(se.key.keysym.scancode); - if (b < 0) - break; - e->type = LZR_EVENT_BUTTON_UP; - e->button = b; - input[b] = false; - return true; - } - case SDL_MOUSEBUTTONUP: { - e->type = LZR_EVENT_BUTTON_DOWN; - e->button = LZR_BUTTON_MOUSE_L + se.button.button - 1; - e->x = se.button.x, e->y = se.button.y; - LZR_ScreenTransform(&e->x, &e->y); - mouse_x = e->x, mouse_y = e->y; - if (e->button >= LZR_BUTTON_COUNT) - continue; - input[e->button] = false; - return true; - } - case SDL_MOUSEMOTION: { - e->type = LZR_EVENT_MOUSE_MOVE; - e->x = se.motion.x, e->y = se.motion.y; - LZR_ScreenTransform(&e->x, &e->y); - mouse_x = e->x, mouse_y = e->y; - return true; - } - default: - break; - } - } - return false; -} - -void LZR_CycleEvents(void) -{ - LZR_Event e; - while (LZR_PollEvent(&e)) - ; -} - -bool LZR_ButtonDown(LZR_Button btn) -{ - if (btn >= 0 && btn < LZR_BUTTON_COUNT) - return input[btn]; - else - SDL_Log("%d button doesn't exist", btn); - return false; -} - -void LZR_ButtonBind(LZR_Button btn, unsigned int code) -{ - if (btn < LZR_BUTTON_MOUSE_L && code != SCODE_BIND_MENU) { - map[btn] = code; - SDL_Log("bound key %s to button %u", - SDL_GetScancodeName(map[btn]), btn); - } else - SDL_Log("button %u can't be remapped to key %s", btn, - SDL_GetScancodeName(code)); -} - -int LZR_DrawBegin(void) -{ - if (config.target_fps > 0) - next_time += min_dt; - if (SDL_SetRenderTarget(renderer, target) < 0) { - SDL_Log("%s", SDL_GetError()); - return -1; - } - SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); - SDL_RenderClear(renderer); - return 0; -} - -int LZR_DrawEnd(void) -{ - if (SDL_SetRenderTarget(renderer, NULL)) { - SDL_Log("%s", SDL_GetError()); - return -1; - } - LZR_DrawSetColor(0.0f, 0.0f, 0.0f, 1.0f); - if (LZR_DrawClear()) { - SDL_Log("LZY_DrawClear failed"); - return -1; - } - if (config.target_fps) { - const uint_least64_t cur_time = SDL_GetTicks64(); - if (next_time <= cur_time) - next_time = cur_time; - else - SDL_Delay(next_time - cur_time); - } - int win_w, win_h; - SDL_GetWindowSize(window, &win_w, &win_h); - const int width = config.display_width * config.ratio; - const int height = config.display_height; - const int ratio_w = win_w / width; - const int ratio_h = win_h / height; - scale = (ratio_w <= ratio_h) ? ratio_w : ratio_h; - off_x = (win_w - width * scale) / 2; - off_y = (win_h - height * scale) / 2; - const SDL_Rect dest = {off_x, off_y, width * scale, height * scale}; - if (SDL_RenderCopyEx(renderer, target, NULL, &dest, 0.0, NULL, 0) < 0) { - SDL_Log("%s", SDL_GetError()); - return -1; - } - SDL_RenderPresent(renderer); - tick++; - return 0; -} - -int LZR_DrawSetColor(float r, float g, float b, float a) -{ - const unsigned int ur = (unsigned int)(r * 255) & 255; - const unsigned int ug = (unsigned int)(g * 255) & 255; - const unsigned int ub = (unsigned int)(b * 255) & 255; - const unsigned int ua = (unsigned int)(a * 255) & 255; - if (SDL_SetRenderDrawColor(renderer, ur, ug, ub, ua) < 0) { - SDL_Log("%s", SDL_GetError()); - return -1; - } - color[0] = ur, color[1] = ug, color[2] = ub, color[3] = ua; - return 0; -} - -int LZR_DrawClear(void) -{ - if (SDL_RenderClear(renderer) < 0) { - SDL_Log("%s", SDL_GetError()); - return -1; - } - return 0; -} - -int LZR_DrawPoint(int x, int y) -{ - if (SDL_RenderDrawPoint(renderer, x, y) < 0) { - SDL_Log("%s", SDL_GetError()); - return -1; - } - return 0; -} - -int LZR_DrawPoints(int *x, int *y, int n) -{ - - if (n > (int)(config.display_width * config.display_height)) { - SDL_Log("%d > %u", n, - config.display_width * config.display_height); - return -1; - } - for (int i = 0; i < n; i++) { - points[i].x = x[i]; - points[i].y = y[i]; - } - if (SDL_RenderDrawPoints(renderer, points, n) < 0) { - SDL_Log("%s", SDL_GetError()); - return -1; - } - return 0; -} - -int LZR_DrawLine(int x0, int y0, int x1, int y1) -{ - if (SDL_RenderDrawLine(renderer, x0, y0, x1, y1) < 0) { - SDL_Log("%s", SDL_GetError()); - return -1; - } - return 0; -} - -int LZR_DrawRectangle(bool fill, int x, int y, int w, int h) -{ - SDL_Rect rect = {x, y, w, h}; - if ((fill ? SDL_RenderFillRect : SDL_RenderDrawRect)(renderer, &rect)) { - SDL_Log("%s", SDL_GetError()); - return -1; - } - return 0; -} - -int LZR_DrawCircle(bool fill, int x, int y, int radius) -{ -#ifdef LZR_ENABLE_GFX - if ((fill ? filledCircleRGBA : circleRGBA)(renderer, x, y, radius, - UNPACKED_COLOR_RGBA) < 0) { - SDL_Log("%s", SDL_GetError()); - return -1; - } - return 0; -#else - (void)fill, (void)x, (void)y, (void)radius; - SDL_Log("LZR GFX module is disabled"); - return -1; -#endif -} - -int LZR_DrawPolygon(bool fill, int *vx, int *vy, int n) -{ -#ifdef LZR_ENABLE_GFX - if (n > 32) { - SDL_Log("%d > 32", n); - return -1; - } - Sint16 x[32], y[32]; - for (int i = 0; i < n; i++) - x[i] = vx[i], y[i] = vy[i]; - if ((fill ? filledPolygonRGBA : polygonRGBA)(renderer, x, y, n, - UNPACKED_COLOR_RGBA) < 0) { - SDL_Log("%s", SDL_GetError()); - return -1; - } - return 0; -#else - (void)fill, (void)vx, (void)vy, (void)n; - SDL_Log("LZR GFX module is disabled"); - return -1; -#endif -} - -int LZR_DrawImage(int id, int x, int y) -{ - if (id < 0) { - SDL_Log("id is negative"); - return -1; - } - if (id >= LZR_MAX_IMAGES || images[id].tex == NULL) { - SDL_Log("no image with id %d", id); - return -1; - } - if (SDL_SetTextureColorMod(images[id].tex, UNPACKED_COLOR) < 0) { - SDL_Log("%s", SDL_GetError()); - return -1; - } - if (SDL_SetTextureAlphaMod(images[id].tex, color[3]) < 0) { - SDL_Log("%s", SDL_GetError()); - return -1; - } - const SDL_Rect dest = {x, y, images[id].width, images[id].height}; - if (SDL_RenderCopy(renderer, images[id].tex, NULL, &dest) < 0) { - SDL_Log("%s", SDL_GetError()); - return -1; - } - return 0; -} - -int LZR_DrawImageEx(int id, int x, int y, LZR_ImageDrawSettings stg) -{ - if (id < 0) { - SDL_Log("id is negative"); - return -1; - } - if (id >= LZR_MAX_IMAGES || images[id].tex == NULL) { - SDL_Log("no image with id %d", id); - return -1; - } - const int width = (stg.width > 0) ? stg.width : images[id].width; - const int height = (stg.height > 0) ? stg.height : images[id].height; - if (stg.center) { - x -= stg.scale_x * width / 2; - y -= stg.scale_y * height / 2; - } - SDL_Rect src = {stg.ix, stg.iy, width, height}; - SDL_Rect dst = {x, y, width * stg.scale_x, height * stg.scale_y}; - if (stg.ix < 0) { - src.w += stg.ix; - dst.x = 0 - stg.ix; - dst.w += stg.ix; - } - if (stg.iy < 0) { - src.y = 0 - stg.iy; - src.h += stg.iy; - dst.y -= stg.iy; - dst.h += stg.iy; - } - if (stg.ix + width > images[id].width) { - src.w = images[id].width - stg.ix; - dst.w = images[id].width - stg.ix; - } - if (stg.iy + height > images[id].height) { - src.h = images[id].height - stg.iy; - dst.h = images[id].height - stg.iy; - } - if (SDL_SetTextureColorMod(images[id].tex, UNPACKED_COLOR) < 0) { - SDL_Log("%s", SDL_GetError()); - return -1; - } - if (SDL_SetTextureAlphaMod(images[id].tex, color[3]) < 0) { - SDL_Log("%s", SDL_GetError()); - return -1; - } - const int flip = (stg.flip_v ? SDL_FLIP_VERTICAL : 0) | - (stg.flip_h ? SDL_FLIP_HORIZONTAL : 0); - if (SDL_RenderCopyEx(renderer, images[id].tex, &src, &dst, - stg.angle * 360.0, NULL, flip)) { - SDL_Log("%s", SDL_GetError()); - return -1; - } - return 0; -} - -int LZR_DrawTile(int id, int tile, int x, int y, double rot, int flip) -{ - if (id < 0) { - SDL_Log("id is negative"); - return -1; - } - if (id >= LZR_MAX_IMAGES || images[id].tex == NULL) { - SDL_Log("no image with id %d", id); - return -1; - } - if (tile < 0) { - SDL_Log("tile is negative"); - return -1; - } - const int img_width = images[id].width / config.tile_size; - const int img_height = images[id].height / config.tile_size; - if (tile >= img_width * img_height) { - SDL_Log("tile exceeds boundaries"); - return -1; - } - if (SDL_SetTextureColorMod(images[id].tex, UNPACKED_COLOR) < 0) { - SDL_Log("%s", SDL_GetError()); - return -1; - } - if (SDL_SetTextureAlphaMod(images[id].tex, color[3]) < 0) { - SDL_Log("%s", SDL_GetError()); - return -1; - } - SDL_Rect src; - src.x = (tile % img_width) * config.tile_size; - src.y = (tile / img_width) * config.tile_size; - src.w = config.tile_size, src.h = config.tile_size; - const SDL_Rect dst = {x, y, config.tile_size, config.tile_size}; - if (SDL_RenderCopyEx(renderer, images[id].tex, &src, &dst, rot, NULL, - flip) < 0) { - SDL_Log("%s", SDL_GetError()); - return -1; - } - return 0; -} - -int LZR_PlaySound(int id) -{ -#ifdef LZR_ENABLE_MIXER - if (id < 0) { - SDL_Log("id is negative"); - return -1; - } - if (id >= LZR_MAX_SOUNDS || sounds[id].ptr == NULL) { - SDL_Log("no sound with id %d", id); - return -1; - } - if (Mix_PlayChannel(-1, sounds[id].ptr, 0) < 0) { - SDL_Log("%s", Mix_GetError()); - return -1; - } - return 0; -#else - (void)id; - SDL_Log("LZR MIXER module is disabled"); - return -1; -#endif -} - -int LZR_SetMusicVolume(float volume) -{ -#ifdef LZR_ENABLE_MIXER - if (Mix_VolumeMusic(volume * MIX_MAX_VOLUME) < 0) { - SDL_Log("%s", Mix_GetError()); - return -1; - } - return 0; -#else - (void)volume; - SDL_Log("LZR MIXER module is disabled"); - return -1; -#endif -} - -int LZR_PlayMusic(const char *path, int loops) -{ -#ifdef LZR_ENABLE_MIXER - LZR_StopMusic(); - char *const apath = LZR_PathPrefix(path); - if (apath == NULL) { - SDL_Log("LZR_PathPrefix failed"); - return -1; - } - music = Mix_LoadMUS(apath); - free(apath); - if (music == NULL) { - SDL_Log("%s: %s", path, Mix_GetError()); - return -1; - } - if (Mix_PlayMusic(music, loops) < 0) { - SDL_Log("%s", Mix_GetError()); - return -1; - } - Mix_RewindMusic(); - return 0; -#else - (void)path, (void)loops; - SDL_Log("LZR MIXER module is disabled"); - return -1; -#endif -} - -void LZR_StopMusic(void) -{ -#ifdef LZR_ENABLE_MIXER - if (Mix_PlayingMusic()) - Mix_HaltMusic(); - if (music != NULL) { - Mix_FreeMusic(music); - music = NULL; - } -#endif -} - -void LZR_ToggleFullscreen(void) -{ - static int fullscreen = 0; - fullscreen = !fullscreen; - SDL_SetWindowFullscreen(window, - fullscreen * SDL_WINDOW_FULLSCREEN_DESKTOP); -} - -uint64_t LZR_GetTick(void) -{ - return tick; -} - -void LZR_ScreenTransform(int *x, int *y) -{ - if (scale == 0.0) - return; - if (x != NULL) { - *x -= off_x; - *x /= scale; - } - if (y != NULL) { - *y -= off_y; - *y /= scale; - } -} - -void LZR_MousePosition(int *x, int *y) -{ - if (x != NULL) - *x = mouse_x; - if (y != NULL) - *y = mouse_y; -} - -/* -** Copyright (c) 2022, 2023 kdx -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to -** deal in the Software without restriction, including without limitation the -** rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -** sell copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -** FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -** IN THE SOFTWARE. -*/ diff --git a/src/lzr.h b/src/lzr.h deleted file mode 100644 index 497bd52..0000000 --- a/src/lzr.h +++ /dev/null @@ -1,129 +0,0 @@ -/* Licensing informations can be found at the end of the file. */ -#pragma once -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#ifndef LZR_DISABLE_IMAGE -# define LZR_ENABLE_IMAGE -#endif -#ifndef LZR_DISABLE_MIXER -# define LZR_ENABLE_MIXER -#endif -#ifndef LZR_DISABLE_GFX -# define LZR_ENABLE_GFX -#endif - -/* devmode tracks and autoreloads ressources on change */ -#ifndef LZR_DISABLE_DEVMODE -# define LZR_ENABLE_DEVMODE -#endif - -#define LZR_MAX_IMAGES 64 -#define LZR_MAX_SOUNDS 64 -#define LZR_BUTTON(btn) LZR_ButtonDown(LZR_BUTTON_##btn) -#define LZR_IMAGE(img) LZR_ImageLoad(img) - -typedef struct LZR_Config { - unsigned int display_width; - unsigned int display_height; - unsigned int target_fps; - unsigned int tile_size; - const char *title; - double ratio; - bool disable_bind_menu; - bool hide_cursor; -} LZR_Config; - -typedef enum LZR_EventType { - LZR_EVENT_QUIT, - LZR_EVENT_BUTTON_DOWN, - LZR_EVENT_BUTTON_UP, - LZR_EVENT_MOUSE_MOVE -} LZR_EventType; - -typedef enum LZR_Button { - LZR_BUTTON_LEFT, - LZR_BUTTON_RIGHT, - LZR_BUTTON_UP, - LZR_BUTTON_DOWN, - LZR_BUTTON_O, - LZR_BUTTON_X, - LZR_BUTTON_MOUSE_L, - LZR_BUTTON_MOUSE_M, - LZR_BUTTON_MOUSE_R, - LZR_BUTTON_COUNT -} LZR_Button; - -typedef struct LZR_Event { - LZR_EventType type; - LZR_Button button; - int x, y; -} LZR_Event; - -typedef struct LZR_ImageDrawSettings { - int ix, iy, width, height; - double scale_x, scale_y, angle; - bool center, flip_h, flip_v; -} LZR_ImageDrawSettings; - -int LZR_Init(LZR_Config cfg); -void LZR_Quit(void); -bool LZR_ShouldQuit(void); -bool LZR_PollEvent(LZR_Event *e); -void LZR_CycleEvents(void); -bool LZR_ButtonDown(LZR_Button btn); -void LZR_ButtonBind(LZR_Button btn, unsigned int code); -char *LZR_PathPrefix(const char *path); -int LZR_ImageLoad(const char *path); -int LZR_SoundLoad(const char *path, float volume); -int LZR_DrawBegin(void); -int LZR_DrawEnd(void); -int LZR_DrawSetColor(float r, float g, float b, float a); -int LZR_DrawClear(void); -int LZR_DrawPoint(int x, int y); -int LZR_DrawPoints(int *x, int *y, int n); -int LZR_DrawLine(int x0, int y0, int x1, int y1); -int LZR_DrawRectangle(bool fill, int x, int y, int w, int h); -int LZR_DrawCircle(bool fill, int x, int y, int radius); -int LZR_DrawPolygon(bool fill, int *vx, int *vy, int n); -int LZR_DrawImage(int id, int x, int y); -int LZR_DrawImageEx(int id, int x, int y, LZR_ImageDrawSettings stg); -int LZR_DrawTile(int id, int tile, int x, int y, double rot, int flip); -int LZR_PlaySound(int id); -int LZR_SetMusicVolume(float volume); -int LZR_PlayMusic(const char *path, int loops); -void LZR_StopMusic(void); -void LZR_ToggleFullscreen(void); -uint64_t LZR_GetTick(void); -void LZR_ScreenTransform(int *x, int *y); -void LZR_MousePosition(int *x, int *y); - -#ifdef __cplusplus -} -#endif - -/* -** Copyright (c) 2022, 2023 kdx -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to -** deal in the Software without restriction, including without limitation the -** rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -** sell copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -** FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -** IN THE SOFTWARE. -*/ diff --git a/src/main.c b/src/main.c index ff51bb3..7c053f8 100644 --- a/src/main.c +++ b/src/main.c @@ -1,4 +1,4 @@ -#include "lzr.h" +#include "TZR.h" #include "cfg.h" #include "game.h" #include @@ -11,10 +11,12 @@ static void deinit(void); int main([[maybe_unused]] int argc, [[maybe_unused]] char **argv) { - if (LZR_Init(cfg)) { - LZR_Quit(); + if (TZR_Init(.width = DWIDTH, + .height = DHEIGHT, + .target_fps = TARGET_FPS, + .pixel_perfect = true, + .title = "jambase")) return 1; - } if (atexit(deinit)) { perror("main:atexit"); @@ -28,15 +30,17 @@ main([[maybe_unused]] int argc, [[maybe_unused]] char **argv) } game_init(game); - while (!LZR_ShouldQuit()) { - LZR_CycleEvents(); + while (!TZR_ShouldQuit()) { + TZR_CycleEvents(); game_update(game); - LZR_DrawBegin(); - LZR_DrawSetColor(0, 0, 0, 0); - LZR_DrawClear(); + if (TZR_DrawBegin()) + return 1; + TZR_DrawSetColor(0, 0, 0, 0); + TZR_DrawClear(); game_draw(game); - LZR_DrawEnd(); + if (TZR_DrawEnd()) + return 1; } return 0; } @@ -46,5 +50,5 @@ deinit(void) { if (game != NULL) free(game); - LZR_Quit(); + TZR_Quit(); } diff --git a/src/player.c b/src/player.c index b51572b..1871944 100644 --- a/src/player.c +++ b/src/player.c @@ -1,14 +1,15 @@ #include "entityimpl.h" IMPL(draw) { - LZR_DrawSetColor(1, 1, 1, 1); - LZR_DrawRectangle(true, this->pos[0] - this->width / 2, + TZR_DrawSetColor(1, 1, 1, 1); + TZR_DrawRectangle(true, this->pos[0] - this->width / 2, this->pos[1] - this->height / 2, this->width, this->height); } IMPL(update) { - this->vel[0] = LZR_BUTTON(RIGHT) - LZR_BUTTON(LEFT); + this->vel[0] = TZR_IsKeyDown(SDL_SCANCODE_RIGHT) + - TZR_IsKeyDown(SDL_SCANCODE_LEFT); entity_move(this, g); } -- cgit v1.2.3