Big initial commit: States, simulation, presentation, menus, some art.

This commit is contained in:
2025-12-10 23:12:19 +01:00
parent 0b0d920c84
commit 5a71d16d1f
49 changed files with 15852 additions and 0 deletions

View File

@@ -0,0 +1,206 @@
#include "state_ingame.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include "raylib.h"
#include "raygui.h"
#include "session/game_session.h"
#define GRID_CELL_SIZE 8
#define ENTITY_PRESENTATION_Y_OFFSET -2
static void state_enter(Presentation_State *state) {
Presentation_State_Ingame_Context *ctx = (Presentation_State_Ingame_Context *)state->context;
(void)ctx;
printf("Entered ingame.\n");
printf("Setting up session ...\n");
assert(g_current_session != NULL);
Game_Session_Settings *settings = &g_current_session->settings;
printf(
"Singleplayer? %i.\n"
"Settings:\n"
"- Seed: %u\n"
"- Level width: %u, height: %u\n"
"- Max players: %u\n"
,
g_current_session->is_singleplayer,
settings->seed,
settings->level_width, settings->level_height,
settings->max_players
);
printf("Setting up context ...\n");
ctx->main_camera = (Camera2D) {
.offset = (Vector2) { 0, 0 },
.target = (Vector2) { 0, 0 },
.rotation = 0.0f,
.zoom = 3.0f
};
// TODO: SS - Maybe put the textures in an array and index them using an enum?
// These should probably be loaded at start-up instead of here.
ctx->texture_grass = LoadTexture("assets/sprites/spr_floor_grass.png");
assert(IsTextureValid(ctx->texture_grass));
ctx->texture_apple = LoadTexture("assets/sprites/spr_food_apple.png");
assert(IsTextureValid(ctx->texture_apple));
ctx->texture_snake_head = LoadTexture("assets/sprites/spr_snake_head.png");
assert(IsTextureValid(ctx->texture_snake_head));
ctx->texture_snake_body = LoadTexture("assets/sprites/spr_snake_body.png");
assert(IsTextureValid(ctx->texture_snake_body));
}
static void state_tick(Presentation_State *state) {
Presentation_State_Ingame_Context *ctx = (Presentation_State_Ingame_Context *)state->context;
(void)ctx;
{ // TEMP: SS
if(IsKeyPressed(KEY_ESCAPE)) {
presentation_state_machine_go_to(&presentation_state_main_menu);
}
}
}
static void state_render(Presentation_State *state) {
Presentation_State_Ingame_Context *ctx = (Presentation_State_Ingame_Context *)state->context;
(void)ctx;
ClearBackground((Color) { 240, 236, 226, 255 });
Game_World *world = g_current_session->simulation_world.game_world;
Grid *grid = &world->grid;
uint32_t grid_total_size = grid->width * grid->height;
BeginMode2D(ctx->main_camera); {
// Render the level.
for(uint32_t i = 0; i < grid_total_size; i++) {
uint32_t x = i % grid->width;
uint32_t y = i / grid->width;
uint32_t pres_x = x * GRID_CELL_SIZE;
uint32_t pres_y = y * GRID_CELL_SIZE;
uint32_t random_floor_index = i; // TODO: SS - Get a deterministic random value based on seed.
DrawTextureRec(
ctx->texture_grass,
(Rectangle) { GRID_CELL_SIZE * random_floor_index, 0, GRID_CELL_SIZE, GRID_CELL_SIZE },
(Vector2) { pres_x, pres_y },
WHITE
);
DrawRectangleLines(pres_x, pres_y, GRID_CELL_SIZE, GRID_CELL_SIZE, (Color) { 0, 0, 0, 8 });
}
for(uint32_t i = 0; i < grid_total_size; i++) {
uint32_t x = i % grid->width;
uint32_t y = i / grid->width;
uint32_t pres_x = x * GRID_CELL_SIZE;
uint32_t pres_y = y * GRID_CELL_SIZE;
Grid_Cell *cell = &grid->cells[i];
Entity *entity = &cell->entity;
switch(entity->type) {
case Entity_Type_None: {
break;
}
case Entity_Type_Snake_Head:
case Entity_Type_Snake_Body: {
Color tint = (Color) { 255, 135, 102, 255 }; // TODO: SS - Get tint based on player ID.
Vector2 origin = (Vector2) { GRID_CELL_SIZE/2, GRID_CELL_SIZE/2 };
float sin_frequency = 0.0f;
float sin_amplitude = 0.0f;
Texture2D *texture = NULL;
if(entity->type == Entity_Type_Snake_Head) {
texture = &ctx->texture_snake_head;
}
else {
texture = &ctx->texture_snake_body;
// TODO: SS - If it's a body, check what index it is and use that as an y-offset to make it look cool, like a wave.
sin_frequency = 4.0f;
sin_amplitude = 1.0f;
}
DrawTexturePro(
*texture,
(Rectangle) { // Source.
0, 0, GRID_CELL_SIZE, GRID_CELL_SIZE
},
(Rectangle) { // Destination.
pres_x + origin.x,
pres_y + origin.y + ENTITY_PRESENTATION_Y_OFFSET - (sin(GetTime() * sin_frequency)) * sin_amplitude,
GRID_CELL_SIZE,
GRID_CELL_SIZE
},
origin, // Origin.
0, // Rotation.
tint // Tint.
);
break;
}
case Entity_Type_Food: {
uint32_t flash = ((sin(GetTime() * 8) + 1)/2) * 32;
Color tint = (Color) { 255-flash, 255-flash, 255-flash, 255 };
Vector2 origin = (Vector2) { GRID_CELL_SIZE/2, GRID_CELL_SIZE/2 };
DrawTexturePro(
ctx->texture_apple,
(Rectangle) { // Source.
0, 0, GRID_CELL_SIZE, GRID_CELL_SIZE
},
(Rectangle) { // Destination.
pres_x + origin.x,
pres_y + origin.y + ENTITY_PRESENTATION_Y_OFFSET - ((sin(GetTime() * 12) + 1)/2) * 1,
GRID_CELL_SIZE,
GRID_CELL_SIZE
},
origin, // Origin.
0, // Rotation.
tint // Tint.
);
break;
}
}
}
}
EndMode2D();
}
static void state_exit(Presentation_State *state) {
Presentation_State_Ingame_Context *ctx = (Presentation_State_Ingame_Context *)state->context;
(void)ctx;
printf("Exiting ingame\n");
UnloadTexture(ctx->texture_grass);
UnloadTexture(ctx->texture_apple);
UnloadTexture(ctx->texture_snake_head);
UnloadTexture(ctx->texture_snake_body);
game_session_destroy();
}
Presentation_State presentation_state_ingame;
void presentation_state_ingame_init(Presentation_State_Ingame_Context *ctx) {
presentation_state_ingame = (Presentation_State) {
.name = "Ingame",
.context = (void *)ctx,
.enter = state_enter,
.tick = state_tick,
.render = state_render,
.exit = state_exit
};
}