From 0f0fa04661531daafe3fa7238cc9022adcb35f65 Mon Sep 17 00:00:00 2001 From: fredrikr79 Date: Tue, 1 Apr 2025 00:24:40 +0200 Subject: [PATCH] make snake move and change directions --- src/main.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 79 insertions(+), 9 deletions(-) diff --git a/src/main.c b/src/main.c index 92e1e2f..df063a8 100644 --- a/src/main.c +++ b/src/main.c @@ -3,6 +3,7 @@ #include #define FPS 60 +#define STEP_RATE_MS 500 static SDL_Window *window = NULL; static SDL_Renderer *renderer = NULL; @@ -16,7 +17,7 @@ static SDL_Renderer *renderer = NULL; #define TILE_HEIGHT 24 enum GRID_TILES { EMPTY, SNAKE, FRUIT }; -enum SNAKE_PARTS { TAIL, BODY, HEAD }; +// enum SNAKE_PARTS { TAIL, BODY, HEAD }; #define COLOR_SNAKE 80, 250, 123, SDL_ALPHA_OPAQUE #define COLOR_FRUIT 255, 85, 85, SDL_ALPHA_OPAQUE @@ -28,15 +29,21 @@ typedef enum DIRECTION { LEFT, RIGHT, UP, DOWN } DIRECTION; typedef struct Snake { DIRECTION direction; Uint8 length; + int head_index; + int tail_index; } Snake; typedef struct State { Uint8 grid[GRID_HEIGHT * GRID_WIDTH]; Snake *player; + Uint64 last_frame; } State; -#define SET_GRID_AT(grid, row, col, value) grid[row * GRID_WIDTH + col] = value -#define GET_GRID_AT(grid, row, col) grid[row * GRID_WIDTH + col] +#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)] void log_game_grid(Uint8 *game_grid) { char buf[GRID_WIDTH * 2]; @@ -69,28 +76,91 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) { } SDL_memset(state->grid, EMPTY, sizeof(state->grid)); - SET_GRID_AT(state->grid, GRID_WIDTH / 2, GRID_HEIGHT / 2, SNAKE); + 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->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->last_frame = SDL_GetTicks(); *appstate = state; return SDL_APP_CONTINUE; } SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) { - if ((event->type == SDL_EVENT_KEY_UP && event->key.scancode == SDL_SCANCODE_ESCAPE) || - event->type == SDL_EVENT_QUIT) { + State *stateptr = (State *)appstate; + switch (event->type) { + case SDL_EVENT_QUIT: return SDL_APP_SUCCESS; + case SDL_EVENT_KEY_UP: + switch (event->key.scancode) { + case SDL_SCANCODE_ESCAPE: + return SDL_APP_SUCCESS; + case SDL_SCANCODE_RIGHT: + stateptr->player->direction = RIGHT; + break; + case SDL_SCANCODE_UP: + stateptr->player->direction = UP; + break; + case SDL_SCANCODE_LEFT: + stateptr->player->direction = LEFT; + break; + case SDL_SCANCODE_DOWN: + stateptr->player->direction = DOWN; + break; + default: + break; + } + default: + return SDL_APP_CONTINUE; + } +} + +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); + + switch (player->direction) { + case RIGHT: + player->head_index = INDEX_AT(ROW_AT(player->head_index), COL_AT(player->head_index) + 1); + break; + case UP: + player->head_index = INDEX_AT(ROW_AT(player->head_index) - 1, COL_AT(player->head_index)); + break; + case LEFT: + player->head_index = INDEX_AT(ROW_AT(player->head_index), COL_AT(player->head_index) - 1); + break; + case DOWN: + player->head_index = INDEX_AT(ROW_AT(player->head_index) + 1, COL_AT(player->head_index)); + break; } - return SDL_APP_CONTINUE; } SDL_AppResult SDL_AppIterate(void *appstate) { State *stateptr = appstate; Uint8 *game_grid = stateptr->grid; + Snake *player = 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); + 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); @@ -101,7 +171,6 @@ SDL_AppResult SDL_AppIterate(void *appstate) { 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_Log("%d %d\n", startx, starty); for (int i = 0; i < GRID_HEIGHT; i++) { for (int j = 0; j < GRID_WIDTH; j++) { switch (GET_GRID_AT(game_grid, i, j)) { @@ -130,5 +199,6 @@ 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