From 98b50eff084f9c1d07090c65d02ada9c2d4d5ae8 Mon Sep 17 00:00:00 2001 From: kdx Date: Fri, 31 Mar 2023 17:09:15 +0200 Subject: tzr update --- Makefile | 2 +- src/TZR.c | 180 ++++++++++++++++++++++++++++++++++++++++++++++------------- src/TZR.h | 55 +++++++++++++++++- src/main.c | 8 +-- src/part.c | 4 +- src/player.c | 4 +- 6 files changed, 202 insertions(+), 51 deletions(-) diff --git a/Makefile b/Makefile index d66b9d5..7edfe57 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ CC := gcc LD := $(CC) WINCC := x86_64-w64-mingw32-gcc CFLAGS := -Os -std=c2x -Wall -Wextra -Wno-override-init -LDFLAGS := -lm -lSDL2 -lSDL2_image +LDFLAGS := -lm -lSDL2 -lSDL2_image -lSDL2_mixer NAME := jambase SRC := $(wildcard src/*.c) OBJ := $(patsubst src/%.c,obj/%.o,$(SRC)) diff --git a/src/TZR.c b/src/TZR.c index 150cf22..77ab2e0 100644 --- a/src/TZR.c +++ b/src/TZR.c @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #include #include @@ -58,8 +60,8 @@ static void TZR_RectFromSDLRect(TZR_Rect *dest, const SDL_Rect *src) } /* sources/globals.c */ -TZR_Config ___tzr_config = {0}; -TZR_Color ___tzr_color = {0, 0.0f, 0.0f, 0.0f, 1.0f}; +TZR_Config ___tzr_config = {}; +TZR_Color ___tzr_color = {0.0f, 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; @@ -72,29 +74,38 @@ 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}; +TZR_KeyState ___tzr_keystates[SDL_NUM_SCANCODES] = {}; +TZR_KeyState ___tzr_mousestates[256] = {}; //doc says than mouse button is u8 +float ___tzr_scale = 1.0; +int ___tzr_off_x = 1.0; +int ___tzr_off_y = 1.0; /* sources/TZR_CycleEvents.c */ +void +next_state(TZR_KeyState *keystate) +{ + 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; + } +} + 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; - } - } + for (int i = 0; i < SDL_NUM_SCANCODES; i++) + next_state(&___tzr_keystates[i]); + for (int i = 0; i < 256; i++) + next_state(&___tzr_mousestates[i]); TZR_Event e; while (TZR_PollEvent(&e)) ; @@ -115,6 +126,10 @@ TZR_DestroyResource(TZR_Resource *res, int free_path) if (res->image.ptr != NULL) SDL_DestroyTexture(res->image.ptr); break; + case TZR_RES_SOUND: + if (res->sound.ptr != NULL) + Mix_FreeChunk(res->sound.ptr); + break; default: fprintf(stderr, "unknown resource type %u\n", res->type); break; @@ -160,6 +175,20 @@ TZR_DirectResourceLoad(TZR_Resource *res, const void *data, int size) } res->image.ptr = tex; } break; + case TZR_RES_SOUND: { + if (!___tzr_config.mixer) { + SDL_Log("audio mixer disabled, skip loading"); + return -1; + } + SDL_RWops *const rw = SDL_RWFromConstMem(data, size); + if (rw == NULL) + return sdl_error(-1); + Mix_Chunk *const chunk = Mix_LoadWAV_RW(rw, 0); + SDL_RWclose(rw); + if (chunk == NULL) + return sdl_error(-1); + res->sound.ptr = chunk; + } break; default: fprintf(stderr, "invalid type\n"); return -1; @@ -203,16 +232,16 @@ TZR_DrawEnd(void) 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; + ___tzr_scale = (ratio_w < ratio_h) ? ratio_w : ratio_h; + if (___tzr_scale > 1.0f && ___tzr_config.pixel_perfect) + ___tzr_scale = (int)___tzr_scale; + ___tzr_off_x = (win_w - ___tzr_config.width * ___tzr_scale) / 2; + ___tzr_off_y = (win_h - ___tzr_config.height * ___tzr_scale) / 2; const SDL_Rect dest = { - off_x, - off_y, - ___tzr_config.width * scale, - ___tzr_config.height * scale + ___tzr_off_x, + ___tzr_off_y, + ___tzr_config.width * ___tzr_scale, + ___tzr_config.height * ___tzr_scale }; if (SDL_RenderCopy(___tzr_renderer, ___tzr_target, NULL, &dest) < 0) @@ -319,10 +348,15 @@ TZR_DrawPoint(int x, int y) /* sources/TZR_DrawRectangle.c */ int -TZR_DrawRectangle(bool fill, int x, int y, int w, int h) +_TZR_DrawRectangle(const TZR_DrawRectangleArgs *args) { - const SDL_Rect rect = { x, y, w, h }; - if (fill) { + const SDL_Rect rect = { + args->x - args->center * (args->w / 2), + args->y - args->center * (args->h / 2), + args->w, + args->h + }; + if (args->fill) { if (SDL_RenderFillRect(___tzr_renderer, &rect) < 0) return sdl_error(-1); } else { @@ -369,6 +403,17 @@ TZR_GetKeyState(int scancode) { return ___tzr_keystates[scancode]; } +/* sources/TZR_GetMousePosition.c */ + +void +TZR_GetMousePosition(int *x, int *y) +{ + if (x != NULL) + *x = ___tzr_mouse_x; + if (y != NULL) + *y = ___tzr_mouse_y; + TZR_ScreenTransform(x, y); +} /* sources/TZR_GetRawResource.c */ TZR_Raw * @@ -417,12 +462,17 @@ _sdl_error(void) int _TZR_Init(const TZR_Config *config) { + memcpy(&___tzr_config, config, sizeof(TZR_Config)); + if (SDL_Init(SDL_INIT_VIDEO) < 0) return _sdl_error(); if (IMG_Init(IMG_INIT_PNG) < 0) return _sdl_error(); + if (___tzr_config.mixer && Mix_Init(MIX_INIT_FLAC) != MIX_INIT_FLAC) { + SDL_Log("%s", Mix_GetError()); + ___tzr_config.mixer = false; + } - memcpy(&___tzr_config, config, sizeof(TZR_Config)); char *const basepath = SDL_GetBasePath(); if (basepath == NULL) return _sdl_error(); @@ -463,12 +513,19 @@ _TZR_Init(const TZR_Config *config) ___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"; + if (!___tzr_config.show_cursor) + SDL_ShowCursor(SDL_FALSE); + ___tzr_mouse_x = ___tzr_config.width / 2; + ___tzr_mouse_y = ___tzr_config.height / 2; + + /* Setup audio. */ + if (___tzr_config.mixer) { + if (Mix_OpenAudio(48000, MIX_DEFAULT_FORMAT, 8, 1024) < 0) { + sdl_error(0); + Mix_Quit(); + ___tzr_config.mixer = false; + } + } return 0; } /* sources/TZR_IsKeyDown.c */ @@ -514,6 +571,8 @@ deduce_type(const char *path) if (strcasecmp(path_extension, ".bmp") == 0 || strcasecmp(path_extension, ".png") == 0) return TZR_RES_IMAGE; + if (strcasecmp(path_extension, ".wav") == 0) + return TZR_RES_SOUND; return TZR_RES_RAW; } @@ -596,6 +655,27 @@ TZR_LoadResourceTyped(TZR_ResourceType type, const char *path) strcpy(res->path, path); return id; } +/* sources/TZR_PlaySound.c */ + +int +_TZR_PlaySound(const TZR_PlaySoundArgs *args) +{ + if (args->id == 0) { + fprintf(stderr, "args->id is 0\n"); + return -1; + } + + if (TZR_GetResourceType(args->id) != TZR_RES_SOUND) { + fprintf(stderr, "%u isn't a sound\n", args->id); + return -1; + } + + const __auto_type sound = &TZR_GetResourcePointer(args->id)->sound; + Mix_VolumeChunk(sound->ptr, args->volume * MIX_MAX_VOLUME); + if (Mix_PlayChannel(-1, sound->ptr, args->loop) < 0) + return sdl_error(-1); + return 0; +} /* sources/TZR_PollEvent.c */ int @@ -626,10 +706,12 @@ TZR_PollEvent(TZR_Event *e) case SDL_MOUSEBUTTONDOWN: ___tzr_mouse_x = se.button.x; ___tzr_mouse_y = se.button.y; + ___tzr_mousestates[se.button.button] = TZR_KEYSTATE_PRESS; break; case SDL_MOUSEBUTTONUP: ___tzr_mouse_x = se.button.x; ___tzr_mouse_y = se.button.y; + ___tzr_mousestates[se.button.button] = TZR_KEYSTATE_RELEASE; break; case SDL_MOUSEMOTION: ___tzr_mouse_x = se.motion.x; @@ -664,6 +746,10 @@ TZR_Quit(void) SDL_DestroyWindow(___tzr_window); ___tzr_window = NULL; } + if (___tzr_config.mixer) { + Mix_CloseAudio(); + Mix_Quit(); + } IMG_Quit(); SDL_Quit(); } @@ -715,6 +801,22 @@ TZR_ResourcesWatch(void) } } } +/* sources/TZR_ScreenTransform.c */ + +void +TZR_ScreenTransform(int *x, int *y) +{ + if (___tzr_scale == 0.0) + return; + if (x != NULL) { + *x -= ___tzr_off_x; + *x /= ___tzr_scale; + } + if (y != NULL) { + *y -= ___tzr_off_y; + *y /= ___tzr_scale; + } +} /* sources/TZR_ShouldQuit.c */ int @@ -723,4 +825,4 @@ TZR_ShouldQuit(void) return ___tzr_should_quit; } -/* commit hash: 8b92076145893cfdaf3e648e0324b163c1a6d28e */ +/* commit hash: e96c359a840974adea4d3d1d3445377f159ecdf0 */ diff --git a/src/TZR.h b/src/TZR.h index 33c6af8..d307f6e 100644 --- a/src/TZR.h +++ b/src/TZR.h @@ -1,6 +1,7 @@ #pragma once #include #include +#include #include #include #include @@ -11,6 +12,7 @@ enum TZR_ResourceType { TZR_RES_RAW, TZR_RES_IMAGE, + TZR_RES_SOUND, ___TZR_RES_COUNT }; @@ -35,10 +37,13 @@ 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_Sound TZR_Sound; 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 struct TZR_DrawRectangleArgs TZR_DrawRectangleArgs; +typedef struct TZR_PlaySoundArgs TZR_PlaySoundArgs; typedef enum TZR_KeyState TZR_KeyState; struct TZR_Config { @@ -47,6 +52,8 @@ struct TZR_Config { int height; int target_fps; bool pixel_perfect; + bool show_cursor; + bool mixer; const char *title; }; @@ -79,6 +86,10 @@ struct TZR_Image { SDL_Texture *ptr; }; +struct TZR_Sound { + Mix_Chunk *ptr; +}; + struct TZR_Resource { TZR_ResourceType type; char *path; /* allocated and freed by TZR; can be NULL */ @@ -86,6 +97,7 @@ struct TZR_Resource { union { TZR_Raw raw; /* raw file data */ TZR_Image image; + TZR_Sound sound; }; }; @@ -108,6 +120,23 @@ struct TZR_DrawImageArgs { float sy; bool center; }; + +struct TZR_DrawRectangleArgs { + int _; + int x; + int y; + int w; + int h; + bool fill; + bool center; +}; + +struct TZR_PlaySoundArgs { + int _; + int id; + int loop; + float volume; +}; /* headers/TZR_globals.h */ extern TZR_Config ___tzr_config; @@ -124,8 +153,11 @@ 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]; +extern TZR_KeyState ___tzr_mousestates[256]; +extern float ___tzr_scale; +extern int ___tzr_off_x; +extern int ___tzr_off_y; /* headers/TZR_resource.h */ #define TZR_RES TZR_LoadResource @@ -170,6 +202,14 @@ void TZR_ResourcesWatch(void); [[nodiscard]] int TZR_DirectResourceLoad(TZR_Resource *res, const void *data, int size); void TZR_DestroyResource(TZR_Resource *res, int free_path); +/* headers/TZR_sound.h */ + +#define TZR_PlaySound(...) _TZR_PlaySound(&(const TZR_PlaySoundArgs){ \ + .id=0, .loop=0, .volume=1.0f, ._=0, __VA_ARGS__ }) +#ifdef TZR_PARANOID +[[nodiscard]] +#endif +int _TZR_PlaySound(const TZR_PlaySoundArgs *args); /* headers/TZR_events.h */ /* Write event data to `e`. Return 0 when event queue is empty. */ @@ -177,6 +217,8 @@ int TZR_PollEvent(TZR_Event *e); /* Drain queued events with TZR_PollEvent and call TZR_ResourcesWatch. */ void TZR_CycleEvents(void); + +void TZR_GetMousePosition(int *x, int *y); /* headers/TZR_render.h */ /* All draw calls should happen between TZR_DrawBegin and TZR_DrawEnd. @@ -217,10 +259,13 @@ 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. */ +#define TZR_DrawRectangle(...) _TZR_DrawRectangle( \ + &(const TZR_DrawRectangleArgs){ \ + .x=0, .y=0, .w=0, .h=0, .fill=false, .center=false, ._=0, __VA_ARGS__ }) #ifdef TZR_PARANOID [[nodiscard]] #endif -int TZR_DrawRectangle(bool fill, int x, int y, int w, int h); +int _TZR_DrawRectangle(const TZR_DrawRectangleArgs *args); /* Return -1 on error. Draw texture ressource `id` at `x`;`y` position of * the framebuffer. */ @@ -231,6 +276,8 @@ int TZR_DrawRectangle(bool fill, int x, int y, int w, int h); [[nodiscard]] #endif int _TZR_DrawImage(const TZR_DrawImageArgs *args); + +void TZR_ScreenTransform(int *x, int *y); /* headers/TZR_keystate.h */ TZR_KeyState TZR_GetKeyState(int scancode); @@ -251,6 +298,8 @@ bool TZR_IsKeyPressed(int scancode); .height=224, \ .target_fps=60, \ .pixel_perfect=true, \ + .show_cursor=false, \ + .mixer=true, \ .title="TZR", \ ._=0, __VA_ARGS__ }) @@ -268,4 +317,4 @@ int TZR_ShouldQuit(void); unsigned long TZR_GetTick(void); -/* commit hash: 8b92076145893cfdaf3e648e0324b163c1a6d28e */ +/* commit hash: e96c359a840974adea4d3d1d3445377f159ecdf0 */ diff --git a/src/main.c b/src/main.c index 7c053f8..9fb5875 100644 --- a/src/main.c +++ b/src/main.c @@ -11,10 +11,10 @@ static void deinit(void); int main([[maybe_unused]] int argc, [[maybe_unused]] char **argv) { - if (TZR_Init(.width = DWIDTH, - .height = DHEIGHT, - .target_fps = TARGET_FPS, - .pixel_perfect = true, + if (TZR_Init(.width=DWIDTH, + .height=DHEIGHT, + .target_fps=TARGET_FPS, + .pixel_perfect=true, .title = "jambase")) return 1; diff --git a/src/part.c b/src/part.c index 86e17f9..a722193 100644 --- a/src/part.c +++ b/src/part.c @@ -24,6 +24,6 @@ IMPL(update) { IMPL(draw) { TZR_DrawSetColor(1, 1, 1, 1); - TZR_DrawRectangle(true, this->pos[0], this->pos[1], - this->width, this->height); + TZR_DrawRectangle(this->pos[0], this->pos[1], + this->width, this->height, .fill=true); } diff --git a/src/player.c b/src/player.c index 460e80a..36a5131 100644 --- a/src/player.c +++ b/src/player.c @@ -2,9 +2,9 @@ IMPL(draw) { TZR_DrawSetColor(1, 1, 1, 0.5); - TZR_DrawRectangle(true, this->pos[0] - this->width / 2, + TZR_DrawRectangle(this->pos[0] - this->width / 2, this->pos[1] - this->height / 2, - this->width, this->height); + this->width, this->height, .fill=true); } IMPL(update) { -- cgit v1.2.3