The snake must grow.

This commit is contained in:
2025-12-12 18:28:10 +01:00
parent 2a0e5779cb
commit ddeb82fdc8
10 changed files with 85 additions and 41 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 643 B

After

Width:  |  Height:  |  Size: 643 B

View File

@@ -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();

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;
}

25
src/shared/random.c Normal file
View File

@@ -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));
}

View File

@@ -1,34 +1,17 @@
#ifndef RANDOM_H
#define RANDOM_H
#include <stdint.h>
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

View File

@@ -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;
}
}
}