diff options
author | kdx <kikoodx@paranoici.org> | 2022-10-21 01:24:30 +0200 |
---|---|---|
committer | kdx <kikoodx@paranoici.org> | 2022-10-21 01:24:30 +0200 |
commit | 0543cbcc26bb4e48a521063b41c9e0951d58a69c (patch) | |
tree | 4cb41207fa0c0f30f7fdaa276a91ef277fc026c2 | |
parent | 4ddfa1468e86b56c1d66b6c1fa4e71c75742e5a3 (diff) | |
download | lzr-0543cbcc26bb4e48a521063b41c9e0951d58a69c.tar.gz |
merge improvements from tyoz
-rw-r--r-- | lzr.c | 190 | ||||
-rw-r--r-- | lzr.h | 12 |
2 files changed, 170 insertions, 32 deletions
@@ -3,6 +3,7 @@ #include <SDL2/SDL.h> #include <SDL2/SDL2_gfxPrimitives.h> #include <SDL2/SDL_image.h> +#include <SDL2/SDL_mixer.h> #include <dx/log.h> #include <dx/mem.h> #include <dx/str.h> @@ -11,8 +12,9 @@ #include <string.h> #include <unistd.h> -#define UNPACKED_COLOR color[0], color[1], color[2] -#define SCODE_BIND_MENU SDL_SCANCODE_F1 +#define UNPACKED_COLOR color[0], color[1], color[2] +#define SCODE_BIND_MENU SDL_SCANCODE_F1 +#define SCODE_FULLSCREEN SDL_SCANCODE_F11 static LZR_Config config = {0}; static char *basepath = NULL; @@ -32,26 +34,9 @@ static unsigned int map[LZR_BUTTON_COUNT] = { SDL_SCANCODE_DOWN, SDL_SCANCODE_X, SDL_SCANCODE_C}; static bool input[LZR_BUTTON_COUNT] = {false}; static SDL_Point *points = NULL; - -static char *_path_prefix(const char *path) -{ - if (path == NULL) { - dx_log_error("path is NULL"); - return NULL; - } - if (basepath == NULL) { - dx_log_warn("basepath is NULL"); - return dx_strdup(path); - } - char *const buf = dx_alloc(strlen(basepath) + strlen(path) + 1); - if (buf == NULL) { - dx_log_error("dx_alloc failed"); - return NULL; - } - dx_strcpy(buf, basepath); - dx_strcat(buf, path); - return buf; -} +static uint64_t tick = 0; +static Mix_Chunk *sounds[LZR_MAX_SOUNDS] = {0}; +static Mix_Music *music = NULL; static int _scode_to_button(unsigned int scode) { @@ -114,7 +99,8 @@ static void _bind_menu(void) while (btn < LZR_BUTTON_COUNT) { while (SDL_PollEvent(&e)) { if (e.type != SDL_KEYDOWN || e.key.repeat || - e.key.keysym.scancode == SCODE_BIND_MENU) + 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) @@ -161,6 +147,14 @@ int LZR_Init(LZR_Config cfg) dx_log_error("%s", IMG_GetError()); return -1; } + if (Mix_Init(MIX_INIT_OGG) != MIX_INIT_OGG) { + dx_log_error("%s", Mix_GetError()); + return -1; + } + if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 8, 1024) < 0) { + dx_log_error("%s", Mix_GetError()); + return -1; + } basepath = SDL_GetBasePath(); if (basepath == NULL) { dx_log_error("%s", SDL_GetError()); @@ -201,6 +195,13 @@ int LZR_Init(LZR_Config cfg) void LZR_Quit(void) { + LZR_StopMusic(); + for (int i = 0; i < LZR_MAX_SOUNDS; i++) + if (sounds[i] != NULL) { + Mix_FreeChunk(sounds[i]); + sounds[i] = NULL; + dx_log_trace("destroyed sound %d", i); + } for (int i = 0; i < LZR_MAX_IMAGES; i++) if (images[i].tex != NULL) { SDL_DestroyTexture(images[i].tex); @@ -227,6 +228,9 @@ void LZR_Quit(void) SDL_free(basepath); basepath = NULL; } + Mix_CloseAudio(); + Mix_Quit(); + IMG_Quit(); SDL_Quit(); } @@ -235,6 +239,26 @@ bool LZR_ShouldQuit(void) return should_quit; } +char *LZR_PathPrefix(const char *path) +{ + if (path == NULL) { + dx_log_error("path is NULL"); + return NULL; + } + if (basepath == NULL) { + dx_log_warn("basepath is NULL"); + return dx_strdup(path); + } + char *const buf = dx_alloc(strlen(basepath) + strlen(path) + 1); + if (buf == NULL) { + dx_log_error("dx_alloc failed"); + return NULL; + } + dx_strcpy(buf, basepath); + dx_strcat(buf, path); + return buf; +} + int LZR_ImageLoad(const char *path) { int i; @@ -245,9 +269,9 @@ int LZR_ImageLoad(const char *path) dx_log_error("reached image limit (%d)", LZR_MAX_IMAGES); return -1; } - char *const apath = _path_prefix(path); + char *const apath = LZR_PathPrefix(path); if (apath == NULL) { - dx_log_error("_path_prefix failed"); + dx_log_error("LZR_PathPrefix failed"); return -1; } SDL_Surface *const bmp = IMG_Load(apath); @@ -271,6 +295,32 @@ int LZR_ImageLoad(const char *path) return i; } +int LZR_SoundLoad(const char *path, float volume) +{ + int i; + for (i = 0; i < LZR_MAX_SOUNDS; i++) + if (sounds[i] == NULL) + break; + if (i >= LZR_MAX_SOUNDS) { + dx_log_error("reached sounds limit (%d)", LZR_MAX_SOUNDS); + return -1; + } + char *const apath = LZR_PathPrefix(path); + if (apath == NULL) { + dx_log_error("LZR_PathPrefix failed"); + return -1; + } + Mix_Chunk *const chunk = Mix_LoadWAV(apath); + dx_free(apath); + if (chunk == NULL) { + dx_log_error("%s: %s", path, Mix_GetError()); + return -1; + } + Mix_VolumeChunk(chunk, volume * MIX_MAX_VOLUME); + sounds[i] = chunk; + return i; +} + bool LZR_PollEvent(LZR_Event *e) { if (e == NULL) { @@ -285,16 +335,19 @@ bool LZR_PollEvent(LZR_Event *e) should_quit = true; return true; case SDL_KEYDOWN: { - const int b = _scode_to_button(se.key.keysym.scancode); 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; - } break; + return true; + } case SDL_KEYUP: { const int b = _scode_to_button(se.key.keysym.scancode); if (b < 0) @@ -302,7 +355,8 @@ bool LZR_PollEvent(LZR_Event *e) e->type = LZR_EVENT_BUTTON_UP; e->button = b; input[b] = false; - } break; + return true; + } default: break; } @@ -375,11 +429,13 @@ int LZR_DrawEnd(void) const int off_y = (win_h - config.display_height * scale) / 2; const SDL_Rect dest = {off_x, off_y, config.display_width * scale, config.display_height * scale}; - if (SDL_RenderCopy(renderer, target, NULL, &dest) < 0) { + if (SDL_RenderCopyEx(renderer, target, NULL, &dest, 0.0, NULL, 0) < + 0) { dx_log_error("%s", SDL_GetError()); return -1; } SDL_RenderPresent(renderer); + tick++; return 0; } @@ -552,7 +608,7 @@ int LZR_DrawImageEx(int id, int x, int y, LZR_ImageDrawSettings stg) return 0; } -int LZR_DrawTile(int id, int tile, int x, int y) +int LZR_DrawTile(int id, int tile, int x, int y, double rot, int flip) { if (id < 0) { dx_log_error("id is negative"); @@ -581,13 +637,85 @@ int LZR_DrawTile(int id, int tile, int x, int y) 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_RenderCopy(renderer, images[id].tex, &src, &dst) < 0) { + if (SDL_RenderCopyEx(renderer, images[id].tex, &src, &dst, rot, NULL, + flip) < 0) { dx_log_error("%s", SDL_GetError()); return -1; } return 0; } +int LZR_PlaySound(int id) +{ + if (id < 0) { + dx_log_error("id is negative"); + return -1; + } + if (id >= LZR_MAX_SOUNDS || sounds[id] == NULL) { + dx_log_error("no sound with id %d", id); + return -1; + } + if (Mix_PlayChannel(-1, sounds[id], 0) < 0) { + dx_log_error("%s", Mix_GetError()); + return -1; + } + return 0; +} + +int LZR_SetMusicVolume(float volume) +{ + if (Mix_VolumeMusic(volume * MIX_MAX_VOLUME) < 0) { + dx_log_warn("%s", Mix_GetError()); + return -1; + } + return 0; +} + +int LZR_PlayMusic(const char *path, int loops) +{ + LZR_StopMusic(); + char *const apath = LZR_PathPrefix(path); + if (apath == NULL) { + dx_log_error("LZR_PathPrefix failed"); + return -1; + } + music = Mix_LoadMUS(apath); + dx_free(apath); + if (music == NULL) { + dx_log_error("%s: %s", path, Mix_GetError()); + return -1; + } + if (Mix_PlayMusic(music, loops) < 0) { + dx_log_error("%s", Mix_GetError()); + return -1; + } + Mix_RewindMusic(); + return 0; +} + +void LZR_StopMusic(void) +{ + if (Mix_PlayingMusic()) + Mix_HaltMusic(); + if (music != NULL) { + Mix_FreeMusic(music); + music = NULL; + } +} + +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; +} + /* ** Copyright (c) 2022 kdx ** @@ -2,8 +2,10 @@ #ifndef LZR_H_ #define LZR_H_ #include <stdbool.h> +#include <stdint.h> #define LZR_MAX_IMAGES 32 +#define LZR_MAX_SOUNDS 64 #define LZR_BUTTON(btn) LZR_ButtonDown(LZR_BUTTON_##btn) typedef struct LZR_Config { @@ -49,7 +51,9 @@ 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); @@ -62,7 +66,13 @@ 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); +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); +uint64_t LZR_GetTick(void); +void LZR_ToggleFullscreen(void); #endif |