# HG changeset patch # User Mike Becker # Date 1755807231 -7200 # Node ID 966bfca56b9d5848f86acaa3e3c2172ad7a3f12d # Parent 6ed9fb9662c03696a28961e962942025cf481a05 add random spawn positions diff -r 6ed9fb9662c0 -r 966bfca56b9d demo/snake/Makefile --- 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 $< diff -r 6ed9fb9662c0 -r 966bfca56b9d demo/snake/snake.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 #include #include +#include #include #include @@ -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); diff -r 6ed9fb9662c0 -r 966bfca56b9d src/ascension/util.h --- 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 +#include 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 diff -r 6ed9fb9662c0 -r 966bfca56b9d src/util.c --- 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 -#include -#include +#include 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); + } +}