snake_compiler git · main
Snake compiled to a bare-metal RISC-V microcontroller
C 95.2% Markdown 3.3%git clone https://git.christianimmanuel.de/embedded/snake_compiler.gitwget https://git.christianimmanuel.de/embedded/snake_compiler/archive/snake_compiler.tar.gzsnake_SDL/src/snake.c raw
#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};
}