#include "snake.h" #include "matrix.h" // Initialize snake with starting position void snake_Init(Snake* snake, int start_x, int start_y) { for (int i = 0; i < SNAKE_START_LENGTH; i++) { snake->nodes[i].x = start_x - i; snake->nodes[i].y = start_y - i; snake->nodes[i].color = (i == 0) ? BLACK : SNAKE_COLOR; } snake->head_index = SNAKE_START_LENGTH - 1; snake->tail_index = 0; snake->direction = DIR_RIGHT; snake->length = SNAKE_START_LENGTH; printf("START SNAKE: %d %d, length %d\n", start_x, start_y, SNAKE_START_LENGTH); } void snake_SetDirection(Snake* snake, Direction new_dir) { if ((snake->direction == DIR_UP && new_dir == DIR_DOWN) || (snake->direction == DIR_DOWN && new_dir == DIR_UP) || (snake->direction == DIR_LEFT && new_dir == DIR_RIGHT) || (snake->direction == DIR_RIGHT && new_dir == DIR_LEFT)) { return; } snake->direction = new_dir; } static inline unsigned char rise_dt( unsigned char v, unsigned char target, uint64_t diff, uint64_t diff_max) { if (v >= target) return v; uint32_t delta = (uint32_t)((diff * target) / diff_max); if (delta == 0) delta = 1; uint32_t nv = v + delta; return (nv > target) ? target : (unsigned char)nv; } static inline unsigned char fall_dt( unsigned char v, uint64_t diff, uint64_t diff_max) { if (v == 0) return 0; uint32_t delta = (uint32_t)((diff * MAX_BRIGHTNESS) / diff_max); if (delta == 0) delta = 1; return (delta >= v) ? 0 : (unsigned char)(v - delta); } bool snake_Move(Snake* snake, bool is_next_step, uint64_t diff_max, uint64_t diff) { SnakeTile* head = &snake->nodes[snake->head_index]; SnakeTile* tail = &snake->nodes[snake->tail_index]; // FADE Color sc = SNAKE_COLOR; head->color.r = rise_dt(head->color.r, sc.r, diff, diff_max); head->color.g = rise_dt(head->color.g, sc.g, diff, diff_max); head->color.b = rise_dt(head->color.b, sc.b, diff, diff_max); tail->color.r = fall_dt(tail->color.r, diff, diff_max); tail->color.g = fall_dt(tail->color.g, diff, diff_max); tail->color.b = fall_dt(tail->color.b, diff, diff_max); matrix->pixels[head->y][head->x].color = head->color; matrix->pixels[tail->y][tail->x].color = tail->color; if (!is_next_step) return true; // MOVE int new_x = head->x; int new_y = head->y; switch (snake->direction) { case DIR_UP: new_y--; break; case DIR_DOWN: new_y++; break; case DIR_LEFT: new_x--; break; case DIR_RIGHT: new_x++; break; } if (WALL_COLLISION && (new_x >= MATRIX_WIDTH || new_x < 0 || new_y >= MATRIX_HEIGHT || new_y < 0)) { printf("Collided with Wall %d %d %d %d!\n", new_x, new_y, MATRIX_WIDTH, MATRIX_HEIGHT); return false; } new_x = (new_x + MATRIX_WIDTH) % MATRIX_WIDTH; new_y = (new_y + MATRIX_HEIGHT) % MATRIX_HEIGHT; int next = (snake->head_index + 1) % MAX_SNAKE_LENGTH; SnakeTile* head_next = &snake->nodes[next]; head_next->x = new_x; head_next->y = new_y; head_next->color = (Color){0, 0, 0}; snake->head_index = next; bool grow = matrix->pixels[new_y][new_x].type == APPLE; matrix->pixels[new_y][new_x].type = SNAKE; if (!grow) { snake->tail_index = (snake->tail_index + 1) % MAX_SNAKE_LENGTH; } else { spawn_apple(); snake->length++; } return !snake_IsColliding(snake); } bool snake_IsColliding(Snake* snake) { int idx = snake->tail_index; int count = snake->length - 1; int hx = snake->nodes[snake->head_index].x; int hy = snake->nodes[snake->head_index].y; while (count-- > 0) { if (snake->nodes[idx].x == hx && snake->nodes[idx].y == hy) return true; idx = (idx + 1) % MAX_SNAKE_LENGTH; } return false; } void spawn_apple() { int x, y; // Find an empty pixel do { x = random_Int(MATRIX_WIDTH); y = random_Int(MATRIX_HEIGHT); } while (matrix->pixels[y][x].type != NONE); // Set the apple pixel matrix->pixels[y][x].type = APPLE; matrix->pixels[y][x].color = (Color){0, MAX_BRIGHTNESS, 0}; }