aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkdx <kikoodx@paranoici.org>2022-10-21 01:24:30 +0200
committerkdx <kikoodx@paranoici.org>2022-10-21 01:24:30 +0200
commit0543cbcc26bb4e48a521063b41c9e0951d58a69c (patch)
tree4cb41207fa0c0f30f7fdaa276a91ef277fc026c2
parent4ddfa1468e86b56c1d66b6c1fa4e71c75742e5a3 (diff)
downloadlzr-0543cbcc26bb4e48a521063b41c9e0951d58a69c.tar.gz
merge improvements from tyoz
-rw-r--r--lzr.c190
-rw-r--r--lzr.h12
2 files changed, 170 insertions, 32 deletions
diff --git a/lzr.c b/lzr.c
index c69d210..6fcfd16 100644
--- a/lzr.c
+++ b/lzr.c
@@ -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
**
diff --git a/lzr.h b/lzr.h
index 71e0750..e09a2a5 100644
--- a/lzr.h
+++ b/lzr.h
@@ -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