diff --git a/Makefile b/Makefile index 7269515..fe34670 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,10 @@ clean: mkdir out/ compile: - gcc -W -Wall -Wextra -pedantic -o out/main src/main.c -Iinclude -lpthread -Llib -lSDL3 + gcc -W -Wall -Wextra -pedantic -o out/main src/main.c src/utils/arena.c src/utils/vector.c -Iinclude -Iutils -lpthread -Llib -lSDL3 + +debug: + gcc -W -Wall -Wextra -pedantic -g -O0 -o out/main_debug src/main.c src/utils/arena.c src/utils/vector.c -Iinclude -Iutils -lpthread -Llib -lSDL3 run: make compile diff --git a/src/main.c b/src/main.c index df063a8..c5ec36c 100644 --- a/src/main.c +++ b/src/main.c @@ -1,8 +1,10 @@ #define SDL_MAIN_USE_CALLBACKS 1 +#include "utils/arena.h" +#include "utils/vector.h" #include #include -#define FPS 60 +// #define FPS 60 #define STEP_RATE_MS 500 static SDL_Window *window = NULL; @@ -10,7 +12,7 @@ static SDL_Renderer *renderer = NULL; #define WINDOW_WIDTH 640 #define WINDOW_HEIGHT 480 -#define GRID_PADDING 2 +#define GRID_PADDING 4 #define GRID_WIDTH 18 #define GRID_HEIGHT 15 #define TILE_WIDTH 24 @@ -28,22 +30,23 @@ typedef enum DIRECTION { LEFT, RIGHT, UP, DOWN } DIRECTION; typedef struct Snake { DIRECTION direction; - Uint8 length; - int head_index; - int tail_index; + int length; + Vector *body; } Snake; typedef struct State { - Uint8 grid[GRID_HEIGHT * GRID_WIDTH]; Snake *player; + Vector *fruits; Uint64 last_frame; } State; +static Arena arena; + #define INDEX_AT(row, col) ((row) * GRID_WIDTH + (col)) -#define ROW_AT(index) (index / GRID_WIDTH) -#define COL_AT(index) (index % GRID_WIDTH) -#define SET_GRID_AT(grid, row, col, value) grid[INDEX_AT(row, col)] = value -#define GET_GRID_AT(grid, row, col) grid[INDEX_AT(row, col)] +#define ROW_AT(index) ((index) / GRID_WIDTH) +#define COL_AT(index) ((index) % GRID_WIDTH) +#define SET_GRID_AT(grid, row, col, value) (grid)[INDEX_AT((row), (col))] = (value) +#define GET_GRID_AT(grid, row, col) (grid)[INDEX_AT((row), (col))] void log_game_grid(Uint8 *game_grid) { char buf[GRID_WIDTH * 2]; @@ -69,27 +72,25 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) { return SDL_APP_FAILURE; } - State *state = SDL_malloc(sizeof(State)); + arena_init(&arena, KB(42)); + State *state = arena_alloc(&arena, 1, sizeof(State), _Alignof(State)); if (!state) { SDL_Log("Failed to allocate state"); return SDL_APP_FAILURE; } - SDL_memset(state->grid, EMPTY, sizeof(state->grid)); - SET_GRID_AT(state->grid, GRID_HEIGHT / 2, GRID_WIDTH / 2, SNAKE); - SET_GRID_AT(state->grid, GRID_HEIGHT / 2, GRID_WIDTH / 2 - 1, SNAKE); - SET_GRID_AT(state->grid, GRID_HEIGHT / 2, GRID_WIDTH / 2 - 2, SNAKE); - - state->player = SDL_malloc(sizeof(Snake)); + state->player = arena_alloc(&arena, 1, sizeof(Snake), _Alignof(Snake)); + if (!state->player) { + SDL_Log("Failed to allocate player"); + return SDL_APP_FAILURE; + } state->player->direction = UP; state->player->length = 3; - state->player->head_index = INDEX_AT(GRID_HEIGHT / 2, GRID_WIDTH / 2); - state->player->tail_index = INDEX_AT(GRID_HEIGHT / 2, GRID_WIDTH / 2 - 2); - - SET_GRID_AT(state->grid, 4, 12, FRUIT); - SET_GRID_AT(state->grid, 13, 5, FRUIT); - - log_game_grid(state->grid); + state->player->body = (Vector *)arena_alloc(&arena, 1, sizeof(Vector), _Alignof(Vector)); + if (!state->player->body) { + SDL_Log("Failed to allocate player body"); + return SDL_APP_FAILURE; + } state->last_frame = SDL_GetTicks(); *appstate = state; @@ -126,71 +127,67 @@ SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) { } } -void game_step(Uint8 **game_grid, Snake *player) { - SDL_Log("snek: %d %d %d %d", player->direction, player->length, player->head_index, - player->tail_index); +void game_step(State *stateptr) { + // SDL_Log("snek: %d %d %d %d", player->direction, player->length, player->head_index, + // player->tail_index); + Snake *playerptr = stateptr->player; + int head = vector_pop(stateptr->player->body); + vector_push(stateptr->player->body, head); - switch (player->direction) { + switch (playerptr->direction) { case RIGHT: - player->head_index = INDEX_AT(ROW_AT(player->head_index), COL_AT(player->head_index) + 1); + vector_push(playerptr->body, head + 1); break; case UP: - player->head_index = INDEX_AT(ROW_AT(player->head_index) - 1, COL_AT(player->head_index)); + vector_push(playerptr->body, head - GRID_WIDTH); break; case LEFT: - player->head_index = INDEX_AT(ROW_AT(player->head_index), COL_AT(player->head_index) - 1); + vector_push(playerptr->body, head - 1); break; case DOWN: - player->head_index = INDEX_AT(ROW_AT(player->head_index) + 1, COL_AT(player->head_index)); + vector_push(playerptr->body, head + GRID_WIDTH); break; } } SDL_AppResult SDL_AppIterate(void *appstate) { State *stateptr = appstate; - Uint8 *game_grid = stateptr->grid; - Snake *player = stateptr->player; + Snake *playerptr = stateptr->player; const Uint64 now = SDL_GetTicks(); // step multiple times if we are behind while (now - stateptr->last_frame >= STEP_RATE_MS) { - game_step(&game_grid, player); + game_step(stateptr); stateptr->last_frame += STEP_RATE_MS; } - SET_GRID_AT(game_grid, ROW_AT(player->head_index), COL_AT(player->head_index), SNAKE); - SET_GRID_AT(game_grid, ROW_AT(player->tail_index), COL_AT(player->tail_index), SNAKE); - - SDL_SetRenderDrawColor(renderer, COLOR_BG); - SDL_RenderClear(renderer); - SDL_FRect rect; rect.w = TILE_WIDTH; rect.h = TILE_HEIGHT; const int startx = (WINDOW_WIDTH - GRID_WIDTH * (TILE_WIDTH + GRID_PADDING)) / 2; const int starty = (WINDOW_HEIGHT - GRID_HEIGHT * (TILE_HEIGHT + GRID_PADDING)) / 2; + SDL_SetRenderDrawColor(renderer, COLOR_BG); + SDL_RenderClear(renderer); + + SDL_SetRenderDrawColor(renderer, COLOR_EMPTY); for (int i = 0; i < GRID_HEIGHT; i++) { for (int j = 0; j < GRID_WIDTH; j++) { - switch (GET_GRID_AT(game_grid, i, j)) { - case EMPTY: - SDL_SetRenderDrawColor(renderer, COLOR_EMPTY); - break; - case SNAKE: - SDL_SetRenderDrawColor(renderer, COLOR_SNAKE); - break; - case FRUIT: - SDL_SetRenderDrawColor(renderer, COLOR_FRUIT); - break; - } rect.x = startx + j * (rect.w + GRID_PADDING); rect.y = starty + i * (rect.h + GRID_PADDING); // SDL_Log("x: %f, y: %f, w: %f, h: %f", rect.x, rect.y, rect.w, rect.h); SDL_RenderFillRect(renderer, &rect); } } - // SDL_Log("---"); + + SDL_SetRenderDrawColor(renderer, COLOR_SNAKE); + for (int i = 0; i < playerptr->length; i++) { + int b = playerptr->body->data[i]; + rect.x = startx + ROW_AT(b) * (rect.w + GRID_PADDING); + rect.y = starty + COL_AT(b) * (rect.h + GRID_PADDING); + SDL_RenderFillRect(renderer, &rect); + } SDL_RenderPresent(renderer); @@ -199,6 +196,5 @@ SDL_AppResult SDL_AppIterate(void *appstate) { void SDL_AppQuit(void *appstate, SDL_AppResult result) { /* SDL will clean up the window/renderer for us. */ - SDL_free(((State *)appstate)->player); - SDL_free(appstate); -} \ No newline at end of file + arena_free(&arena); +} diff --git a/src/utils/arena.c b/src/utils/arena.c index e11c817..1d2e7b6 100644 --- a/src/utils/arena.c +++ b/src/utils/arena.c @@ -46,17 +46,17 @@ void arena_free(Arena *a) { free(a); } -int main(void) { - printf("this is the `arena.c` utility main method.\n"); +// int main(void) { +// printf("this is the `arena.c` utility main method.\n"); - Arena a = {0}; - arena_init(&a, KB(2)); +// Arena a = {0}; +// arena_init(&a, KB(2)); - int *t = arena_alloc(&a, 6, sizeof(int), _Alignof(int)); +// int *t = arena_alloc(&a, 6, sizeof(int), _Alignof(int)); - for (int *i = t; i < t + 6; i++) { - printf("%d ", *i); - } +// for (int *i = t; i < t + 6; i++) { +// printf("%d ", *i); +// } - return 0; -} +// return 0; +// } diff --git a/src/utils/vector.c b/src/utils/vector.c index 3a751d3..2c8b16c 100644 --- a/src/utils/vector.c +++ b/src/utils/vector.c @@ -48,6 +48,10 @@ void vector_pusha(Vector *v, int *vals, int n) { } int vector_pop(Vector *v) { + if (v->size < 1) { + printf("vector_pop: popping empty vector"); + return 0; + } int val = v->data[v->size - 1]; v->size--; return val; @@ -68,13 +72,13 @@ void vector_print(Vector v) { printf("\n"); } -int main(int argc, char *argv[]) { - Vector *v = vector_new(); - vector_push(v, 20); - vector_pusha(v, (int[]){1, 2, 3}, 3); - vector_print(*v); - printf("oops, i removed %d\n", vector_pop(v)); - vector_print(*v); - vector_free(v); - return 0; -} +// int main(int argc, char *argv[]) { +// Vector *v = vector_new(); +// vector_push(v, 20); +// vector_pusha(v, (int[]){1, 2, 3}, 3); +// vector_print(*v); +// printf("oops, i removed %d\n", vector_pop(v)); +// vector_print(*v); +// vector_free(v); +// return 0; +// }