Thu, 21 Aug 2025 22:13:51 +0200
add random spawn positions
demo/snake/Makefile | file | annotate | diff | comparison | revisions | |
demo/snake/snake.c | file | annotate | diff | comparison | revisions | |
src/ascension/util.h | file | annotate | diff | comparison | revisions | |
src/util.c | file | annotate | diff | comparison | revisions |
--- a/demo/snake/Makefile Wed Aug 20 23:51:40 2025 +0200 +++ b/demo/snake/Makefile Thu Aug 21 22:13:51 2025 +0200 @@ -59,7 +59,7 @@ ../../src/ascension/text.h ../../src/ascension/font.h \ ../../src/ascension/mesh.h ../../src/ascension/texture.h \ ../../src/ascension/sprite.h ../../src/ascension/2d.h \ - ../../src/ascension/shader.h + ../../src/ascension/shader.h ../../src/ascension/util.h @echo "Compiling $<" $(CC) -o $@ $(CFLAGS) -c $<
--- a/demo/snake/snake.c Wed Aug 20 23:51:40 2025 +0200 +++ b/demo/snake/snake.c Thu Aug 21 22:13:51 2025 +0200 @@ -30,6 +30,7 @@ #include <ascension/sprite.h> #include <ascension/2d.h> #include <ascension/shader.h> +#include <ascension/util.h> #include <cx/printf.h> #include <cx/linked_list.h> @@ -368,7 +369,6 @@ // remark: some calculations are repeated here, but they are cheap enough { const asc_vec2u tile_coords = game_field_tile_at_position(node->position); - // TODO: player should have been destroyed before leaving the field if (tile_coords.x > GAME_FIELD_SIZE || tile_coords.y > GAME_FIELD_SIZE) return; if (game_field_tile_chown(tile_coords, player)) { // new owner of the tile! @@ -416,6 +416,15 @@ pl->reset_position = true; } +static void player_position_random(Player *pl) { + // TODO: check if the spawn location is viable when there is more action on the board + player_position( + pl, + 4 + asc_util_rand(GAME_FIELD_SIZE - 8), + 4 + asc_util_rand(GAME_FIELD_SIZE - 8) + ); +} + static void player_destroy(CxAllocator *allocator, Player *player) { cxListFree(player->trace); cxFree(allocator, player); @@ -435,7 +444,7 @@ ); asc_scene_add_node(MAIN_SCENE, node); Player *player = asc_scene_node_allocate_data(node, sizeof(Player)); - player_position(player, 12, 8); + player_position_random(player); player->speed = 3.f; // start with 3 tiles/sec player->number = 1; player->health = 100; @@ -572,7 +581,7 @@ asc_scene_node_show(text_game_over); if (asc_key_pressed(ASC_KEY(R))) { // TODO: re-load the "level" - player_position(game.players[0], 12, 8); + player_position_random(game.players[0]); player_set_health(game.players[0], 100); game.state = GAME_STATE_PLAYING; asc_scene_node_hide(text_game_over);
--- a/src/ascension/util.h Wed Aug 20 23:51:40 2025 +0200 +++ b/src/ascension/util.h Thu Aug 21 22:13:51 2025 +0200 @@ -29,6 +29,7 @@ #define ASC_UTIL_H #include <cx/string.h> +#include <stdint.h> cxmutstr asc_util_gen_name(const char *prefix); @@ -48,4 +49,22 @@ int: asc_util_check_and_set_int, \ unsigned: asc_util_check_and_set_unsigned)(&(v), x) +/** + * Seeds or re-seeds the PRNG. + * + * @note You do not @em need to call this function before generating numbers, + * as the PRNG will be initialized automatically as if you had called asc_util_seed_rand(0). + * + * @param seed the seed or zero when some sort of clock time should be used as a seed + */ +void asc_util_seed_rand(uint64_t seed); + +/** + * Returns a positive number less than @p n from the PRNG. + * + * @param n the upper bound + * @return a positive number less than n + */ +uint32_t asc_util_rand(uint32_t n); + #endif //ASC_UTIL_H
--- a/src/util.c Wed Aug 20 23:51:40 2025 +0200 +++ b/src/util.c Thu Aug 21 22:13:51 2025 +0200 @@ -28,10 +28,22 @@ #include "ascension/util.h" #include <cx/printf.h> -#include <inttypes.h> -#include <assert.h> +#include <SDL3/SDL_stdinc.h> cxmutstr asc_util_gen_name(const char *prefix) { static unsigned counter = 0; return cx_asprintf("%s_gen%u", prefix, ++counter); } + +void asc_util_seed_rand(uint64_t seed) { + SDL_srand(seed); +} + +uint32_t asc_util_rand(uint32_t n) { + if (n > INT32_MAX) { + // TODO: this probably uses quality of the generated numbers + return SDL_rand_bits() % n; + } else { + return SDL_rand((int32_t) n); + } +}