mirror of
https://github.com/fredrikr79/SnakeDL3.git
synced 2025-12-24 19:20:21 +01:00
make snake move and change directions
This commit is contained in:
88
src/main.c
88
src/main.c
@@ -3,6 +3,7 @@
|
||||
#include <SDL3/SDL_main.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user