From ddeb82fdc84b23d1c5a724d1ae5d2814fc907a05 Mon Sep 17 00:00:00 2001 From: samstalhandske Date: Fri, 12 Dec 2025 18:28:10 +0100 Subject: [PATCH] The snake must grow. --- src/assets/sprites/spr_floor_grass.png | Bin 643 -> 643 bytes src/presentation/states/state_ingame.c | 10 ++++++--- src/presentation/states/state_ingame.h | 4 ++++ src/shared/entity.h | 4 ++++ src/shared/game_world.c | 18 +++++++++------ src/shared/game_world.h | 2 ++ src/shared/grid.c | 6 +++++ src/shared/random.c | 25 +++++++++++++++++++++ src/shared/random.h | 27 +++++----------------- src/simulation/simulation_world.c | 30 +++++++++++++++++-------- 10 files changed, 85 insertions(+), 41 deletions(-) create mode 100644 src/shared/random.c diff --git a/src/assets/sprites/spr_floor_grass.png b/src/assets/sprites/spr_floor_grass.png index acd7858c9b7af985a4bc71148d8524b87617c261..6ff0cb26bd53dc94ca8e6d1f917f9da50f40181b 100644 GIT binary patch delta 105 zcmZo>ZD!rDi_wq)1b#a2t_M<_1s;*b3=De8Ak0{?)V>TT$X?><>&pI;heuFS;N`1B z8IxZ#=4wAMZkVw^RrSY4tA-F}4bHl*BF3#Ud<^S^mCt0`GdY9I^mO%eS?83{1ON#Q B9=rem delta 105 zcmZo>ZD!rDi_!2u0}w9QyL>VO0|RG)M`SSrgPt-7Ggd6MF9Qm)mw5WRvcKfv;?p;4 zc$Hf?`88v%_JqgWMa}Z7nNRda7s;M;S^LIi)%ipQhT6@_XB^(`Jqpyu;OXk;vd$@? F2>@q-C3*k= diff --git a/src/presentation/states/state_ingame.c b/src/presentation/states/state_ingame.c index 1827971..9e9ed9f 100644 --- a/src/presentation/states/state_ingame.c +++ b/src/presentation/states/state_ingame.c @@ -80,6 +80,10 @@ static void state_tick(Presentation_State *state) { game_session_update(session, delta_time); { // TEMP: SS + if(IsKeyPressed(KEY_TAB)) { + ctx->debug_render_match_state = !ctx->debug_render_match_state; + } + if(IsKeyPressed(KEY_ESCAPE)) { presentation_state_machine_go_to(&presentation_state_main_menu); } @@ -196,7 +200,7 @@ static void state_render(Presentation_State *state) { }, (Rectangle) { // Destination. pres_x + origin.x, - pres_y + origin.y + ENTITY_PRESENTATION_Y_OFFSET - (sin(GetTime() * sin_frequency)) * sin_amplitude, + pres_y + origin.y + ENTITY_PRESENTATION_Y_OFFSET - (sin((GetTime() + (float)(entity->child_index) / 4.0) * sin_frequency)) * sin_amplitude, GRID_CELL_SIZE, GRID_CELL_SIZE }, @@ -245,11 +249,11 @@ static void state_render(Presentation_State *state) { // TODO: SS - Switch on 'sim_world->match_state'. - { // TEMP: SS - Render match state. + if(ctx->debug_render_match_state) { char buf[512]; snprintf(&buf[0], sizeof(buf), "Match-state: %i. Tick: %lu.", sim_world->match_state, sim_world->tick); - DrawText(buf, 32, 32, 12, RED); + DrawText(buf, 16, 16, 8, RED); } } EndMode2D(); diff --git a/src/presentation/states/state_ingame.h b/src/presentation/states/state_ingame.h index fdd17b5..21ab765 100644 --- a/src/presentation/states/state_ingame.h +++ b/src/presentation/states/state_ingame.h @@ -15,6 +15,10 @@ typedef struct { Texture2D texture_apple; Texture2D texture_snake_head; Texture2D texture_snake_body; + + // Debug. + bool debug_render_match_state; + } Presentation_State_Ingame_Context; void presentation_state_ingame_init(Presentation_State_Ingame_Context *ctx); diff --git a/src/shared/entity.h b/src/shared/entity.h index 01af87f..a079dba 100644 --- a/src/shared/entity.h +++ b/src/shared/entity.h @@ -32,10 +32,14 @@ typedef struct { uint16_t x; uint16_t y; + uint16_t prev_x; + uint16_t prev_y; + Entity_Movement_Direction move_direction; Entity_Movement_Direction prev_move_direction; Entity_ID child; + uint16_t child_index; // Primarily used when presenting the body-parts. // TODO: SS - Color/tint? } Entity; diff --git a/src/shared/game_world.c b/src/shared/game_world.c index a1cd01f..9a93126 100644 --- a/src/shared/game_world.c +++ b/src/shared/game_world.c @@ -14,6 +14,7 @@ Game_World *game_world_create(uint32_t seed, uint16_t level_width, uint16_t leve Game_World *w = (Game_World *)calloc(1, sizeof(Game_World)); assert(w != NULL); w->seed = seed; + random_init(&w->random_generator, w->seed); w->max_entities = level_width * level_height; w->entities = (Entity *)calloc(w->max_entities, sizeof(Entity)); @@ -28,13 +29,16 @@ Game_World *game_world_create(uint32_t seed, uint16_t level_width, uint16_t leve grid_initialize(&w->grid, level_width, level_height); { // TEMP: SS - Testing .. - Entity_ID entity_food; - assert(game_world_create_entity( - w, - Entity_Type_Food, - 4, 8, - &entity_food - )); + for(uint16_t i = 0; i < 8; i++) { + Entity_ID entity_food; + 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), + &entity_food + )); + } } return w; diff --git a/src/shared/game_world.h b/src/shared/game_world.h index e5f09ad..4228280 100644 --- a/src/shared/game_world.h +++ b/src/shared/game_world.h @@ -5,9 +5,11 @@ #include "entity.h" #include "grid.h" #include "shared/squeue.h" +#include "shared/random.h" typedef struct { uint32_t seed; + Random_Generator random_generator; SQueue entity_id_queue; Entity *entities; diff --git a/src/shared/grid.c b/src/shared/grid.c index 3c70c10..787a44e 100644 --- a/src/shared/grid.c +++ b/src/shared/grid.c @@ -114,7 +114,13 @@ void grid_move_entity_from_cell_to_cell(Grid_Cell *cell_a, Grid_Cell *cell_b) { assert(cell_b->entity == NULL); // We expect cell B to NOT have an Entity. Entity *entity_to_be_moved = cell_a->entity; + + uint16_t start_x = cell_a->x; + uint16_t start_y = cell_a->y; assert(grid_try_remove_entity_from_cell(cell_a)); assert(grid_try_add_entity_to_cell(cell_b, entity_to_be_moved)); + + entity_to_be_moved->prev_x = start_x; + entity_to_be_moved->prev_y = start_y; } \ No newline at end of file diff --git a/src/shared/random.c b/src/shared/random.c new file mode 100644 index 0000000..7fefdfe --- /dev/null +++ b/src/shared/random.c @@ -0,0 +1,25 @@ +#include "random.h" + +void random_init(Random_Generator *random_generator, uint32_t seed) { + if(seed == 0) { + seed = 1; + } + random_generator->seed = seed; + random_generator->state = random_generator->seed; +} + +uint32_t random_u32(Random_Generator *random_generator) { + uint32_t x = random_generator->state; + + x ^= x << 13; + x ^= x >> 17; + x ^= x << 5; + + random_generator->state = x; + + return x; +} + +uint32_t random_u32_range(Random_Generator *random_generator, uint32_t min, uint32_t max) { + return min + (random_u32(random_generator) % (max - min + 1)); +} \ No newline at end of file diff --git a/src/shared/random.h b/src/shared/random.h index 08e5af5..1b181d0 100644 --- a/src/shared/random.h +++ b/src/shared/random.h @@ -1,34 +1,17 @@ #ifndef RANDOM_H #define RANDOM_H +#include + typedef struct { uint32_t seed; uint32_t state; } Random_Generator; -static inline void random_init(Random_Generator *random_generator, uint32_t seed) { - if(seed == 0) { - seed = 1; - } - random_generator->seed = seed; - random_generator->state = random_generator->seed; -} +void random_init(Random_Generator *random_generator, uint32_t seed); -static inline uint32_t random_next_u32(Random_Generator *random_generator) { - uint32_t x = random_generator->state; - - x ^= x << 13; - x ^= x >> 17; - x ^= x << 5; - - random_generator->state = x; - - return x; -} - -static inline uint32_t random_u64_range(Random_Generator *random_generator, uint32_t min, uint32_t max) { - return min + (random_next_u32(rng) % (max - min + 1)); -} +uint32_t random_u32(Random_Generator *random_generator); +uint32_t random_u32_range(Random_Generator *random_generator, uint32_t min, uint32_t max); #endif \ No newline at end of file diff --git a/src/simulation/simulation_world.c b/src/simulation/simulation_world.c index b1c4fc3..f97bd96 100644 --- a/src/simulation/simulation_world.c +++ b/src/simulation/simulation_world.c @@ -111,7 +111,7 @@ void simulation_world_tick(Simulation_World *simulation_world) { break; } case Simulation_Match_State_Counting_Down: { - if(simulation_world->tick > 50) { // TEMP: SS - Hardcoded number and condition to break out of this state. + if(simulation_world->tick > 20) { // TEMP: SS - Hardcoded number and condition to break out of this state. simulation_world->match_state = Simulation_Match_State_Active; } @@ -308,19 +308,31 @@ void simulation_world_tick(Simulation_World *simulation_world) { t = a; } } - // // TODO: SS - Recurse through this entity's children and move them too. - // if(entity->child != INVALID_ENTITY_ID) { - // printf("TODO: SS - MOVE CHILDREN TOO!\n"); - // } - if(snake_should_grow) { + Entity *e = entity; + uint16_t child_index = 0; + while(e->child != INVALID_ENTITY_ID) { + e = game_world_try_get_entity_by_id(gw, e->child); + child_index += 1; + } + // TODO: SS - Spawn the entity and make it a child of the snake's last child. Entity_ID child_entity = INVALID_ENTITY_ID; - assert(game_world_create_entity(gw, Entity_Type_Snake_Body, start_cell->x, start_cell->y, &child_entity)); + assert(game_world_create_entity( + gw, + Entity_Type_Snake_Body, + e->prev_x, + e->prev_y, + &child_entity + )); - assert(entity->child == INVALID_ENTITY_ID); - entity->child = child_entity; + assert(e->child == INVALID_ENTITY_ID); + e->child = child_entity; + + Entity *child = game_world_try_get_entity_by_id(gw, child_entity); + assert(child != NULL); + child->child_index = child_index; } } }