From c1f43fdc61af061db58b34c2a7eb9caad5b145cf Mon Sep 17 00:00:00 2001 From: samstalhandske Date: Thu, 18 Dec 2025 12:57:06 +0100 Subject: [PATCH] Try to get a good position to spawn at. Also gets a good initial move-direction based on where you spawn. --- src/game/session/game_session.c | 4 +- src/game/shared/game_world.c | 67 +++++++++++++++++++++++++- src/game/shared/game_world.h | 5 ++ src/game/simulation/simulation_world.c | 19 ++++++-- src/todo.md | 15 +++++- 5 files changed, 99 insertions(+), 11 deletions(-) diff --git a/src/game/session/game_session.c b/src/game/session/game_session.c index 39e9018..9789194 100644 --- a/src/game/session/game_session.c +++ b/src/game/session/game_session.c @@ -42,8 +42,8 @@ void game_session_init_default_settings(bool online, Game_Session_Settings *out_ out_settings->seed = 1337; // TODO: SS - Randomize. out_settings->online = online; out_settings->tickrate = 10.0; - out_settings->level_width = 128; - out_settings->level_height = 64; + out_settings->level_width = 32; + out_settings->level_height = 32; out_settings->max_players = online ? 8 : 2; } diff --git a/src/game/shared/game_world.c b/src/game/shared/game_world.c index 2386c92..ec382ef 100644 --- a/src/game/shared/game_world.c +++ b/src/game/shared/game_world.c @@ -31,11 +31,15 @@ Game_World *game_world_create(uint32_t seed, uint16_t level_width, uint16_t leve { // TEMP: SS - Testing .. for(uint16_t i = 0; i < 8; i++) { Entity_ID entity_food; + + uint16_t x = 0; + uint16_t y = 0; + assert(game_world_find_position_to_spawn(w, &x, &y)); + assert(game_world_create_entity( w, Entity_Type_Food, - (uint16_t)random_u32_range(&w->random_generator, 0, level_width), - (uint16_t)random_u32_range(&w->random_generator, 0, level_height), + x, y, &entity_food )); } @@ -127,4 +131,63 @@ Entity *game_world_try_get_entity_by_id(Game_World *world, Entity_ID id) { } return &world->entities[id]; +} + +bool game_world_find_position_to_spawn(Game_World *world, uint16_t *out_x, uint16_t *out_y) { + assert(world != NULL); + assert(out_x != NULL); + assert(out_y != NULL); + + uint8_t attempts = MAX_ATTEMPTS_AT_FINDING_POSITION_TO_SPAWN; + while(attempts > 0) { + uint16_t potential_x = random_u32_range(&world->random_generator, 0, (uint32_t) world->grid.width); + uint16_t potential_y = random_u32_range(&world->random_generator, 0, (uint32_t) world->grid.height); + + Grid_Cell *cell = grid_get_cell(&world->grid, potential_x, potential_y); + assert(cell != NULL); + + // Check if cell is free. + if(cell->entity == NULL) { + *out_x = potential_x; + *out_y = potential_y; + return true; + } + + if(attempts > 0) { + attempts -= 1; + } + else { + break; + } + } + + *out_x = 0; + *out_y = 0; + return false; +} + +Entity_Movement_Direction game_world_choose_initial_move_direction_based_on_coords(Game_World *world, uint16_t x, uint16_t y) { + assert(world != NULL); + + Grid *grid = &world->grid; + + // TODO: SS - Consider potential obstacles in the grid (lava, walls etc) if we ever have them. + + if (x == 0) { + return Entity_Movement_Direction_Right; + } + + if (x == grid->width - 1) { + return Entity_Movement_Direction_Left; + } + + if (y == 0) { + return Entity_Movement_Direction_Down; + } + + if (y == grid->height - 1) { + return Entity_Movement_Direction_Up; + } + + return Entity_Movement_Direction_Up; } \ No newline at end of file diff --git a/src/game/shared/game_world.h b/src/game/shared/game_world.h index 25ed6ed..d9813c3 100644 --- a/src/game/shared/game_world.h +++ b/src/game/shared/game_world.h @@ -29,4 +29,9 @@ void game_world_destroy_entity(Game_World *world, Entity_ID entity_id, bool dest Entity *game_world_try_get_entity_by_id(Game_World *world, Entity_ID id); +#define MAX_ATTEMPTS_AT_FINDING_POSITION_TO_SPAWN 8 + +bool game_world_find_position_to_spawn(Game_World *world, uint16_t *out_x, uint16_t *out_y); +Entity_Movement_Direction game_world_choose_initial_move_direction_based_on_coords(Game_World *world, uint16_t x, uint16_t y); + #endif \ No newline at end of file diff --git a/src/game/simulation/simulation_world.c b/src/game/simulation/simulation_world.c index dad6279..c05fed3 100644 --- a/src/game/simulation/simulation_world.c +++ b/src/game/simulation/simulation_world.c @@ -62,18 +62,27 @@ void simulation_world_tick(Simulation_World *simulation_world) { assert(!player->active); player->active = true; + Game_World *gw = simulation_world->game_world; + assert(gw != NULL); + + uint16_t spawn_x = 0; + uint16_t spawn_y = 0; + assert(game_world_find_position_to_spawn(gw, &spawn_x, &spawn_y)); + assert(game_world_create_entity( - simulation_world->game_world, + gw, Entity_Type_Snake_Head, - i+6, 15, // NOTE: SS - Hardcoded spawn-position. + spawn_x, spawn_y, &player->entity_id )); - Entity *player_entity = game_world_try_get_entity_by_id(simulation_world->game_world, player->entity_id); + Entity *player_entity = game_world_try_get_entity_by_id(gw, player->entity_id); // Set initial move-direction for player-entities. - // The initial direction should probably take the spawn-position in to account. - player_entity->move_direction = Entity_Movement_Direction_Up; + player_entity->move_direction = game_world_choose_initial_move_direction_based_on_coords( + gw, + spawn_x, spawn_y + ); break; } diff --git a/src/todo.md b/src/todo.md index 6e659c6..6fa4bdf 100644 --- a/src/todo.md +++ b/src/todo.md @@ -1,10 +1,16 @@ # TODO +- [x] find_good_position_to_spawn() + - A lot of gameplay-functionality depends on this. +- [x] Set initial move-direction based on where you spawn. + - Can be improved and take more things in to account. + - Right now it's only considering the size of of the grid, but what if we want to have obstacles in the grid? + - We also don't take if two players spawn one cell from each other in to consideration. - Add player-death. - [ ] Went out of bounds. - [ ] Hit other snake's head. - [ ] Hit yours/other snake's body. - Spawn players at a random position. - - [ ] When initially joining. + - [x] When initially joining. - [ ] When dead and should respawn. - Spawn food every N tick(?) - [ ] Spawn food at a random position every N tick. @@ -13,6 +19,11 @@ - This can easily be implemented later. - If we have that much food on the board, don't spawn new food. - Otherwise, spawn new food at a random position. -- [ ] When a player disconnects, all children should recursively be destroyed too. Not just the head. +- [x] When a player disconnects, all children should recursively be destroyed too. Not just the head. +- [ ] Change player-movement? + - Only inputs needed are RIGHT and LEFT. Turn relative to your head. + - Right now we're moving relative to world-up. + - This would fix issues with invalid inputs, for example when the player inputs RIGHT when going LEFT. + - Make this an option later? - [ ] Sound effects + music. - [ ] Customize the session. \ No newline at end of file