summaryrefslogtreecommitdiff
path: root/in_practice/breakout/linux.c
diff options
context:
space:
mode:
Diffstat (limited to 'in_practice/breakout/linux.c')
-rw-r--r--in_practice/breakout/linux.c93
1 files changed, 81 insertions, 12 deletions
diff --git a/in_practice/breakout/linux.c b/in_practice/breakout/linux.c
index 2150ed9..8b7f28a 100644
--- a/in_practice/breakout/linux.c
+++ b/in_practice/breakout/linux.c
@@ -1,26 +1,34 @@
#include "game.h"
#include "sys.h"
+#include "audio.h"
#include <SDL3/SDL.h>
#include <GL/glew.h>
-#define DEBUG 1
+#include <stdio.h>
-typedef struct {
+#define DEBUG 0
+
+struct sdl_context {
SDL_Window *window;
i32 width;
i32 height;
SDL_Renderer *renderer;
+ SDL_AudioDeviceID audio_device;
+ SDL_AudioStream *streams[max_sounds];
+ i32 last_sound;
u64 last_counter;
f32 dt;
-} sdl_context_t;
+};
+
+static struct sdl_context ctx;
-static sdl_context_t init_sdl(i32 width, i32 height, i32 debug)
+static struct sdl_context init_sdl(i32 width, i32 height, i32 debug)
{
- sdl_context_t ctx = {0};
+ struct sdl_context ctx = {0};
ctx.width = width;
ctx.height = height;
- SDL_Init(SDL_INIT_VIDEO);
+ SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);
u64 flags = SDL_WINDOW_OPENGL;
SDL_CreateWindowAndRenderer("breakout", ctx.width, ctx.height, flags, &ctx.window, &ctx.renderer);
if (debug)
@@ -30,10 +38,13 @@ static sdl_context_t init_sdl(i32 width, i32 height, i32 debug)
SDL_GL_SetSwapInterval(0);
ctx.last_counter = SDL_GetPerformanceCounter();
glewInit();
+ ctx.audio_device = SDL_OpenAudioDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, 0);
+ if (!ctx.audio_device)
+ die("failed to open audio device");
return ctx;
}
-static void process_sdl_key(input_t *input, i32 scancode, i32 pressed)
+static void process_sdl_key(struct input *input, i32 scancode, i32 pressed)
{
switch (scancode) {
case SDL_SCANCODE_ESCAPE:
@@ -45,15 +56,24 @@ static void process_sdl_key(input_t *input, i32 scancode, i32 pressed)
case SDL_SCANCODE_LEFT:
input->left.current = pressed;
break;
+ case SDL_SCANCODE_UP:
+ input->up.current = pressed;
+ break;
+ case SDL_SCANCODE_DOWN:
+ input->down.current = pressed;
+ break;
case SDL_SCANCODE_SPACE:
input->space.current = pressed;
break;
+ case SDL_SCANCODE_RETURN:
+ input->start.current = pressed;
+ break;
default:
break;
}
}
-static void process_sdl_events(game_t *game)
+static void process_sdl_events(struct game *game)
{
SDL_Event event;
while (SDL_PollEvent(&event)) {
@@ -74,11 +94,11 @@ static f32 get_elapsed(u64 last_counter)
return (f32)(current_counter - last_counter) / (f32)frequency;
}
-static void lock_framerate_sdl(sdl_context_t *ctx, i32 fps)
+static void lock_framerate_sdl(struct sdl_context *ctx, i32 fps)
{
f32 elapsed = get_elapsed(ctx->last_counter) * 1000.0f;
f32 target = 1000.0f / (f32)fps;
- f32 sleep = target - elapsed;
+ f32 sleep = target - elapsed - 1.0f;
if (sleep > 0)
SDL_Delay((u32)sleep);
do {
@@ -88,6 +108,7 @@ static void lock_framerate_sdl(sdl_context_t *ctx, i32 fps)
ctx->last_counter = SDL_GetPerformanceCounter();
}
+#if DEBUG
static void fps_info(f32 dt, i32 again)
{
static f32 time = 0;
@@ -112,18 +133,66 @@ static void fps_info(f32 dt, i32 again)
}
}
}
+#endif
+
+void load_wav(const char *dir, const char *filename, const char *name)
+{
+ char path[512] = {0};
+ snprintf(path, 512, "%s/%s", (dir ? dir : "."), filename);
+ SDL_AudioSpec spec;
+ u8 *data;
+ u32 size;
+ if (!SDL_LoadWAV(path, &spec, &data, &size))
+ die("failed to load wav \"%s\"", path);
+ if (ctx.last_sound >= max_sounds) {
+ info("max sounds reached");
+ return;
+ }
+ sounds[ctx.last_sound] = (struct sound){data, size, name};
+ if (!(ctx.streams[ctx.last_sound] = SDL_CreateAudioStream(&spec, 0)))
+ die("failed to create audio stream");
+ if (!SDL_BindAudioStream(ctx.audio_device, ctx.streams[ctx.last_sound]))
+ die("failed to bind audio stream");
+ ctx.last_sound++;
+ info("sound \"%s\" loaded successfuly", path);
+}
+
+void play_audio(const char *name, i32 loop)
+{
+ i32 i = get_sound(name);
+ if (i == -1)
+ info("no audio with the name \"%s\"", name);
+ sounds[i].loop = loop;
+ if (SDL_GetAudioStreamQueued(ctx.streams[i]))
+ SDL_ClearAudioStream(ctx.streams[i]);
+ SDL_PutAudioStreamData(ctx.streams[i], sounds[i].data, sounds[i].size);
+}
+
+static void update_audio(void)
+{
+ for (i32 i = 0; i < max_sounds; i++) {
+ if (sounds[i].loop) {
+ i32 queued = SDL_GetAudioStreamQueued(ctx.streams[i]);
+ if (queued < (i32)sounds[i].size)
+ SDL_PutAudioStreamData(ctx.streams[i], sounds[i].data, sounds[i].size);
+ }
+ }
+}
i32 main(void)
{
- sdl_context_t ctx = init_sdl(1600, 800, DEBUG);
- game_t game = init_game(ctx.width, ctx.height);
+ ctx = init_sdl(800, 600, DEBUG);
+ struct game game = init_game(ctx.width, ctx.height);
while (game.running) {
process_sdl_events(&game);
process_input(&game);
update_game(&game, ctx.dt);
+ update_audio();
update_input(&game.input);
lock_framerate_sdl(&ctx, 60);
+#if DEBUG
fps_info(ctx.dt, 10);
+#endif
render_game(game);
SDL_GL_SwapWindow(ctx.window);
}