From 73df1319af91751e850478ef7f7bd013137d0f06 Mon Sep 17 00:00:00 2001 From: iWas-Coder Date: Fri, 26 Apr 2024 02:45:54 +0200 Subject: [PATCH] First implementation of a ring buffer (FIFO, queue-like) DS --- include/sk_rngbuf.h | 43 ++++++++++++++++++++ include/sk_state.h | 2 + src/sk_rngbuf.c | 88 +++++++++++++++++++++++++++++++++++++++++ src/sk_scene_gameplay.c | 3 +- src/sk_state.c | 4 +- 5 files changed, 138 insertions(+), 2 deletions(-) create mode 100644 include/sk_rngbuf.h create mode 100644 src/sk_rngbuf.c diff --git a/include/sk_rngbuf.h b/include/sk_rngbuf.h new file mode 100644 index 0000000..5670f1b --- /dev/null +++ b/include/sk_rngbuf.h @@ -0,0 +1,43 @@ +/* + * GNU Sparky --- A 5v5 character-based libre tactical shooter + * Copyright (C) 2024 Wasym A. Alonso + * + * This file is part of Sparky. + * + * Sparky is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Sparky is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Sparky. If not, see . + */ + + +#pragma once + +#include + +typedef struct { + u32 capacity; + u32 element_size; + u32 curr_len; + i32 head; + i32 tail; + void *data; +} sk_rngbuf; + +sk_rngbuf sk_rngbuf_create(u32 capacity, u32 element_size); + +void sk_rngbuf_destroy(sk_rngbuf *rb); + +u8 sk_rngbuf_push(sk_rngbuf *rb, void *value); + +u8 sk_rngbuf_pop(sk_rngbuf *rb, void *out_value); + +u8 sk_rngbuf_peek(const sk_rngbuf *rb, void *out_value); diff --git a/include/sk_state.h b/include/sk_state.h index 6a3093b..1e3df0d 100644 --- a/include/sk_state.h +++ b/include/sk_state.h @@ -25,6 +25,7 @@ #include #include #include +#include #define SK_STATE_MAX_LOBBIES 256 @@ -44,6 +45,7 @@ typedef struct sk_state { struct { sk_map map; sk_player player; + sk_rngbuf shots_rb; }; }; } sk_state; diff --git a/src/sk_rngbuf.c b/src/sk_rngbuf.c new file mode 100644 index 0000000..366c632 --- /dev/null +++ b/src/sk_rngbuf.c @@ -0,0 +1,88 @@ +/* + * GNU Sparky --- A 5v5 character-based libre tactical shooter + * Copyright (C) 2024 Wasym A. Alonso + * + * This file is part of Sparky. + * + * Sparky is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Sparky is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Sparky. If not, see . + */ + + +#include +#include +#include +#include + +sk_rngbuf sk_rngbuf_create(u32 capacity, u32 element_size) { + return (sk_rngbuf) { + .capacity = capacity, + .element_size = element_size, + .curr_len = 0, + .head = 0, + .tail = -1, + .data = malloc(capacity * element_size) + }; +} + +void sk_rngbuf_destroy(sk_rngbuf *rb) { + if (!rb) { + SK_LOG_WARN("sk_rngbuf_destroy :: `rb` is not a valid pointer, skipping destruction"); + return; + } + *rb = (sk_rngbuf) {0}; + rb = 0; +} + +u8 sk_rngbuf_push(sk_rngbuf *rb, void *value) { + if (!rb || !value) { + SK_LOG_ERROR("sk_rngbuf_push :: `rb` and `value` need to be valid pointers"); + return 0; + } + if (rb->curr_len == rb->capacity) { + SK_LOG_ERROR("sk_rngbuf_push :: ring buffer is full (%p)", rb); + return 0; + } + rb->tail = (rb->tail + 1) % rb->capacity; + memcpy((void *) ((i32 *) rb->data + (rb->tail * rb->element_size)), value, rb->element_size); + ++rb->curr_len; + return 1; +} + +u8 sk_rngbuf_pop(sk_rngbuf *rb, void *out_value) { + if (!rb || !out_value) { + SK_LOG_ERROR("sk_rngbuf_pop :: `rb` and `out_value` need to be valid pointers"); + return 0; + } + if (rb->curr_len == 0) { + SK_LOG_ERROR("sk_rngbuf_pop :: ring buffer is empty (%p)", rb); + return 0; + } + memcpy(out_value, (void *) ((i32 *) rb->data + (rb->head * rb->element_size)), rb->element_size); + rb->head = (rb->head + 1) % rb->capacity; + --rb->curr_len; + return 1; +} + +u8 sk_rngbuf_peek(const sk_rngbuf *rb, void *out_value) { + if (!rb || !out_value) { + SK_LOG_ERROR("sk_rngbuf_peek :: `rb` and `out_value` need to be valid pointers"); + return 0; + } + if (rb->curr_len == 0) { + SK_LOG_ERROR("sk_rngbuf_peek :: ring buffer is empty (%p)", rb); + return 0; + } + memcpy(out_value, (void *) ((i32 *) rb->data + (rb->head * rb->element_size)), rb->element_size); + return 1; +} diff --git a/src/sk_scene_gameplay.c b/src/sk_scene_gameplay.c index 6a4aa4d..0e54cf1 100644 --- a/src/sk_scene_gameplay.c +++ b/src/sk_scene_gameplay.c @@ -26,7 +26,7 @@ void sk_scene_gameplay_update(sk_state *s) { if (IsMouseButtonPressed(s->config.controls.shoot)) { sk_shot shot = {0}; if (!sk_weapon_shoot(&s->player.weapon, s->player.id, &s->player.camera, &shot)) return; - SK_LOG_DEBUG("sk_shot :: {"); + SK_LOG_DEBUG("sk_shot = {"); SK_LOG_DEBUG(" .bullet = {"); SK_LOG_DEBUG(" .position = (%f, %f, %f),", shot.bullet.position.x, shot.bullet.position.y, shot.bullet.position.z); SK_LOG_DEBUG(" .direction = (%f, %f, %f)", shot.bullet.direction.x, shot.bullet.direction.y, shot.bullet.direction.z); @@ -34,6 +34,7 @@ void sk_scene_gameplay_update(sk_state *s) { SK_LOG_DEBUG(" .shooter_id = %s,", shot.shooter_id.value); SK_LOG_DEBUG(" .weapon_kind = %d", shot.weapon_kind); SK_LOG_DEBUG("};"); + sk_rngbuf_push(&s->shots_rb, &shot); } if (IsKeyPressed(s->config.controls.reload)) sk_weapon_reload(&s->player.weapon); sk_player_jump(&s->player, &s->config); diff --git a/src/sk_state.c b/src/sk_state.c index 0fdec69..8279167 100644 --- a/src/sk_state.c +++ b/src/sk_state.c @@ -64,13 +64,15 @@ sk_state sk_state_create_offline(void) { .curr_scene = sk_scene_create(SK_SCENE_KIND_INTRO), .menu_music = LoadMusicStream(TextFormat(MUSIC_PATH_PLACEHOLDER, "menu")), .map = sk_map_create(SK_MAP_CAMPING), - .player = sk_player_create(0, 0, SK_PLAYER_KIND_AGENT69, &config) + .player = sk_player_create(0, 0, SK_PLAYER_KIND_AGENT69, &config), + .shots_rb = sk_rngbuf_create(2 << 14, sizeof(sk_shot)) }; SetWindowIcon(s.win_icon); return s; } void sk_state_destroy_offline(sk_state *s) { + sk_rngbuf_destroy(&s->shots_rb); sk_player_destroy(&s->player); sk_map_destroy(&s->map); UnloadMusicStream(s->menu_music);