!!! use arena and vector

This commit is contained in:
2025-04-06 00:16:19 +02:00
parent 98a26c71f3
commit eddf71a2b4
4 changed files with 80 additions and 77 deletions

View File

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

View File

@@ -1,8 +1,10 @@
#define SDL_MAIN_USE_CALLBACKS 1
#include "utils/arena.h"
#include "utils/vector.h"
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
#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);
}
arena_free(&arena);
}

View File

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

View File

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