247 lines
5.3 KiB
C
247 lines
5.3 KiB
C
#include <raylib.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
|
|
/* typedef struct map_t { */
|
|
|
|
/* } Map; */
|
|
|
|
int screenHeight = 800;
|
|
int screenWidth = 800;
|
|
int fps = 60;
|
|
int rows = 10;
|
|
int cols = 10;
|
|
int size;
|
|
int food_x;
|
|
int food_y;
|
|
int score = 0;
|
|
char score_text[16] = "0";
|
|
|
|
typedef enum directions {
|
|
UP,
|
|
DOWN,
|
|
LEFT,
|
|
RIGHT
|
|
} Direction;
|
|
|
|
typedef struct snake_body {
|
|
int x;
|
|
int y;
|
|
} SnakeBody;
|
|
|
|
typedef struct snake_t {
|
|
SnakeBody *body;
|
|
int max_length;
|
|
int length;
|
|
int direction;
|
|
int frame_duration;
|
|
bool alive;
|
|
} Snake;
|
|
|
|
Snake make_snake(int max_len, int speed){
|
|
Snake snek;
|
|
if (max_len < 3){
|
|
snek.alive = false;
|
|
snek.length = 0;
|
|
return snek;
|
|
}
|
|
|
|
snek.body = (SnakeBody*) calloc(max_len, sizeof(SnakeBody));
|
|
snek.max_length = max_len;
|
|
snek.length = 3;
|
|
snek.body[0].x = GetRandomValue(0, cols - 1);
|
|
snek.body[0].y = GetRandomValue(0, rows - 1);
|
|
snek.frame_duration = fps / speed;
|
|
snek.direction = snek.body[0].x < cols / 2 ? RIGHT : LEFT;
|
|
snek.alive = true;
|
|
snek.body[1] = snek.body[2] = snek.body[0];
|
|
snek.body[1].x += snek.direction == LEFT ? 1 : -1;
|
|
snek.body[2].x += snek.direction == LEFT ? 2 : -2;
|
|
return snek;
|
|
}
|
|
|
|
void free_snake(Snake* s){
|
|
free(s->body);
|
|
}
|
|
|
|
void grow_snake(Snake* s){
|
|
int i = s->length;
|
|
if (i < s->max_length){
|
|
s->body[i] = (SnakeBody) {
|
|
2 * s->body[i - 1].x - s->body[i - 2].x,
|
|
2 * s->body[i - 1].y - s->body[i - 2].y
|
|
};
|
|
|
|
s->length++;
|
|
}
|
|
}
|
|
|
|
void draw_snake(Snake* s){
|
|
for (int i = 0; i < s->length; i++){
|
|
DrawRectangle(size * s->body[i].x, size * s->body[i].y, size, size, BLACK);
|
|
}
|
|
return ;
|
|
}
|
|
|
|
bool collides_with_snake(Snake* s, int x, int y){
|
|
for (int i = 0; i < s->length; i++){
|
|
if (s->body[i].x == x && s->body[i].y == y){
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void place_food(Snake* s){
|
|
do {
|
|
food_x = GetRandomValue(0, cols - 1);
|
|
food_y = GetRandomValue(0, rows - 1);
|
|
} while (collides_with_snake(s, food_x, food_y));
|
|
}
|
|
|
|
void move_snake(Snake* s){
|
|
SnakeBody temp1 = s->body[0];
|
|
SnakeBody temp2;
|
|
switch (s->direction){
|
|
case LEFT:
|
|
s->body[0].x--;
|
|
if (s->body[0].x < 0 || s->body[0].x >= cols){
|
|
s->alive = false;
|
|
}
|
|
break;
|
|
case RIGHT:
|
|
s->body[0].x++;
|
|
if (s->body[0].x < 0 || s->body[0].x >= cols){
|
|
s->alive = false;
|
|
}
|
|
break;
|
|
case UP:
|
|
s->body[0].y--;
|
|
if (s->body[0].y < 0 || s->body[0].y >= rows){
|
|
s->alive = false;
|
|
}
|
|
break;
|
|
case DOWN:
|
|
s->body[0].y++;
|
|
if (s->body[0].x < 0 || s->body[0].y >= rows){
|
|
s->alive = false;
|
|
}
|
|
break;
|
|
}
|
|
for (int i = 1; i < s->length; i++){
|
|
if (s->body[0].x == s->body[i].x &&
|
|
s->body[0].y == s->body[i].y){
|
|
s->alive = false;
|
|
break;
|
|
}
|
|
temp2 = s->body[i];
|
|
s->body[i] = temp1;
|
|
temp1 = temp2;
|
|
}
|
|
}
|
|
|
|
|
|
/* int frame = 0; */
|
|
void update_snake(Snake* s){
|
|
static int frame = 0;
|
|
if (frame++ > s->frame_duration){
|
|
move_snake(s);
|
|
frame = 0;
|
|
}
|
|
int key;
|
|
while ((key = GetKeyPressed()) != 0){
|
|
switch (key){
|
|
case KEY_W:
|
|
s->direction = UP;
|
|
break;
|
|
case KEY_A:
|
|
s->direction = LEFT;
|
|
break;
|
|
case KEY_S:
|
|
s->direction = DOWN;
|
|
break;
|
|
case KEY_D:
|
|
s->direction = RIGHT;
|
|
break;
|
|
case KEY_G:
|
|
grow_snake(s);
|
|
}
|
|
}
|
|
if (collides_with_snake(s, food_x, food_y)){
|
|
food_x = food_y = -1;
|
|
score++;
|
|
snprintf(score_text, 16, "%d", score);
|
|
grow_snake(s);
|
|
place_food(s);
|
|
}
|
|
}
|
|
|
|
void draw_grid(int size){
|
|
/* DrawGrid(10, screenWidth / 10); */
|
|
|
|
for (int i = 0; i < rows; i++){
|
|
DrawLine(0, i * size, screenWidth, i * size, BLACK);
|
|
}
|
|
for (int j = 0; j < cols; j++){
|
|
DrawLine(j * size, 0, j * size, screenHeight, BLACK);
|
|
}
|
|
}
|
|
|
|
void calculate_tile_size(){
|
|
int width = screenWidth / cols;
|
|
int height = screenHeight / rows;
|
|
size = height > width ? width : height;
|
|
}
|
|
|
|
void init_game(){
|
|
InitWindow(screenHeight, screenHeight, "Snek");
|
|
SetTargetFPS(fps);
|
|
calculate_tile_size();
|
|
}
|
|
|
|
int main(void){
|
|
|
|
init_game();
|
|
Snake snek = make_snake(100, 5);
|
|
int b;
|
|
while (!WindowShouldClose()){
|
|
|
|
if (snek.alive){
|
|
update_snake(&snek);
|
|
} else {
|
|
DrawText("Died!", screenWidth / 2, screenHeight / 2, 20, BLACK);
|
|
}
|
|
if (food_x >= 0){
|
|
DrawRectangle(size * food_x, size * food_y, size, size, RED);
|
|
}
|
|
|
|
if (IsKeyPressed(KEY_R)){
|
|
if (b){
|
|
screenWidth = screenHeight = 500;
|
|
/* MinimizeWindow(); */
|
|
} else {
|
|
screenWidth = screenHeight = 800;
|
|
/* MaximizeWindow(); */
|
|
}
|
|
SetWindowSize(screenWidth, screenHeight);
|
|
calculate_tile_size();
|
|
b = !b;
|
|
}
|
|
|
|
BeginDrawing();
|
|
|
|
ClearBackground(WHITE);
|
|
draw_grid(size);
|
|
draw_snake(&snek);
|
|
DrawText(score_text, 0, 0, 20, BLACK);
|
|
|
|
EndDrawing();
|
|
}
|
|
|
|
free_snake(&snek);
|
|
|
|
CloseWindow();
|
|
|
|
return 0;
|
|
}
|