Skip to main content

Collision Detection

Your game is progressing nicely. Only two more things and you're done: Growing the snake and "Game Over". For the first, you need to check if the snake collides with the fruit. For the second, you need to check if the snake collides with itself.

Collision Detection with the Fruit#

Collision detection can be one of the harder to understand concepts of game development. Lucky for you, this is not the case this time. This game is using a 20x20 grid. Each cell can either be occupied or free. To check this, you can compare the X and Y values of the 2 entities that are checked.

In our update function in main.c after calling snake_update, an if statement comparing the location of the snake's head with the location of the fruit

if(snake.body[0].x == fruit.x && snake.body[0].y == fruit.y){  //snake's head hits the fruit}

is enough already to check if the snake eats the fruit. To add to the snake we will create a copy of the snake's last body part, and add it to the snake using snake_push, and then relocate the fruit:

if(snake.body[0].x == fruit.x && snake.body[0].y == fruit.y){  struct point p = snake.body[snake.length-1];  snake_push(&snake,p);  fruit.x = rand()%20;  fruit.y = rand()%20;}

Now you're almost done. Only "Game Over" is left to finish this game.

Collision Detection with Itself#

For the player to have any sense of "danger", the game needs a possibility for the player to lose. Usually the snake can't touch itself or it dies. For this, just loop through the body and check if the piece and the head have the same coordinates. Just like with the fruit. But it might be a good idea to move this to its own function:

int snake_isdead(struct snake *snake){    for(size_t i = 1; i < snake->length; i++)    {        if(snake->body[i].x == snake->body[0].x && snake->body[i].y == snake->body[0].y)        {            return 1;        }    }
    return 0;}

Add the above function to the snake.c file and add a corresponding declaration to snake.h.

Now you can call this function from update in main.cto check if the snake died in this frame:

    if (frame_count % 15 == 0)    {        snake_update(&snake);
        if(snake_isdead(&snake))        {          //snake is dead        }
        if(snake.body[0].x == fruit.x && snake.body[0].y == fruit.y)        {            struct point p = snake.body[snake.length-1];            snake_push(&snake,p);            fruit.x = rand()%20;            fruit.y = rand()%20;        }    }

What you do, is up to you. You could stop the game and show the score. Or you could simply reset the game like so:

    if (frame_count % 15 == 0)    {        snake_update(&snake);
        if(snake_isdead(&snake))        {            snake_create(&snake);                       snake_push(&snake,(struct point){2,0});             snake_push(&snake,(struct point){1,0});            snake_push(&snake,(struct point){0,0});
            snake.direction = (struct point){1,0};        }
        if(snake.body[0].x == fruit.x && snake.body[0].y == fruit.y)        {            struct point p = snake.body[snake.length-1];            snake_push(&snake,p);            fruit.x = rand()%20;            fruit.y = rand()%20;        }    }