mirror of
https://github.com/fredrikr79/SnakeDL3.git
synced 2025-12-24 19:20:21 +01:00
!!! use arena and vector
This commit is contained in:
5
Makefile
5
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
|
||||
|
||||
108
src/main.c
108
src/main.c
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
// }
|
||||
|
||||
@@ -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;
|
||||
// }
|
||||
|
||||
Reference in New Issue
Block a user