Search code examples
c#openglopentk

Save position of Snake and Detect Collison with it self. Whats wrong?


using System;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Drawing;
using OpenTK;
using OpenTK.Graphics.OpenGL;
using OpenTK.Graphics;

namespace Snake
    {
    public partial class GameWindow : Form
    {
    private int glcontrolFieldWidth = 20, glcontrolFieldHeight = 20; //Playing Field 
    public int speedincr = 0; //Speed, Increase by 5% Check out GenerateFood()
    public int GamePoints = -10; //Score 
    private int shaderProgram, color_attribute; //Shader Program
    private int view, model, projection;//Shader Program
    private Matrix4 ViewMatrix, ModelMatrix, ProjectionMatrix; // Matrix4
    private List<Point> snake = new List<Point>() { new Point(1, 1) }; //Where the Snake Start off
    private Point snakeDirection = new Point(1, 0);//Snake Direction
    private Point mouse = new Point(); //Food
    private Random random = new Random(); //Random Genereator 
    public bool bGameOver;
    private static readonly Timer timer = new Timer();

    public GameWindow()
    {
        //Form1.Designer
        InitializeComponent();

        // Centers the form on the current screen
        CenterToScreen();

        // Create a timer 
        //var timer = new Timer();
        timer.Tick += new EventHandler(GameLoop);
        timer.Interval = 150; // This is the snake inital speed
        timer.Start();

        // Generate an initial random position for the food
        GenerateFood();
    }

    public void GameOver(bool bGameOver)
    {
        //Snake Collision with its own body
        //for (int i = 0; i < snake.Count; i++)
        //{
        //    //if Snake equal itself then snake hasn't touch any other parts of its body
        //    if (snake[0].X == snake[i].X || snake[0].Y == snake[i].Y)
        //    {
        //        this.bGameOver = false;
        //        //Console.WriteLine("Snake " + snake2[i].X + "," + snake2[i].Y);
        //        //Console.WriteLine("Snake2 " + snake[i].X + "," + snake[i].Y);
        //    }
        //    else
        //    {
        //        this.bGameOver = true;
        //        //Console.WriteLine(snake[i].X+","+snake[i].Y);
        //    }
        //}



        ////---Display GameOver Message If Where Dead-- - //

        //if (bGameOver == true)
        //{
        //    Console.WriteLine("Game Over! Push Enter to Continue");
        //    if (bGameOver == false)
        //    {
        //        //Game Start Over

        //    }
        //}
        return;
    } //GameOver Reset Game

    public void GameLoop(object sender, System.EventArgs e)
    {
        // Update coordinates of game entities and check collisions
        Update();
        // UpdateWall check collisions with snake to bounce off wall
        UpdateWall();
        GameOver(bGameOver);
        glControl.Invalidate();
    } //Basic of the Game Loop

    private void UpdateWall()
    {
        // Snake collison with Walls
        if (snake[0].X < 1)
        {
            //snake[0].X = (glcontrolFieldWidth - 2) / 10; //Warp to right
            //snakeDirection.X = (snake[0].X + glcontrolFieldWidth-2)/10;
            //snakeDirection.X = (glcontrolFieldWidth-2)/10;
            snakeDirection.X = (int)(glcontrolFieldWidth-0.5) / 10;
            snakeDirection.Y = (int)(glcontrolFieldWidth-0.5) / 10;
            Console.WriteLine("Snake hit left wall");
        }
        else if (snake[0].X > glcontrolFieldWidth - 2)
        {
            //snakeDirection.X = 0; //Warp to left
            snakeDirection.X = (int)(glcontrolFieldWidth - 0.5) / -10;
            snakeDirection.Y = (int)(glcontrolFieldWidth - 0.5) / -10;
            Console.WriteLine("Snake hit right wall");
        }

        if (snake[0].Y < 1)
        {
            //snake.getFirst().y = windowHeight / 10; //Warp to bottom
            //snakeDirection.Y = (snake[0].Y + glcontrolFieldWidth - 2)/10;
            snakeDirection.X = (int)(glcontrolFieldHeight - 0.5)/10;
            snakeDirection.Y = (int)(glcontrolFieldHeight - 0.5)/10;
            Console.WriteLine("Snake hit Top wall");
        }
        else if (snake[0].Y > glcontrolFieldHeight - 2)
        {
            //snake.getFirst().y = 0; //Warp to top
            snakeDirection.X = (int)(glcontrolFieldHeight - 0.5) / -10;
            snakeDirection.Y = (int)(glcontrolFieldHeight - 0.5) / -10;
            Console.WriteLine("Snake hit Bottom wall");
        }

    } //Wall Collision

    private new void Update()
    {
        // Calculate a new position of the head of the snake
        Point newHeadPosition = new Point(snake[0].X + snakeDirection.X, snake[0].Y + snakeDirection.Y);
        // Insert new position in the beginning of the snake list
        snake.Insert(0, newHeadPosition);
        snake.RemoveAt(snake.Count - 1);

        // Check snake collision with the food
        if (snake[0].X != mouse.X || snake[0].Y != mouse.Y)
        {
            return;
        }
        else
        {
            //Snake Grow
            snake.Add(new Point(mouse.X, mouse.Y));
        }
        Console.WriteLine();

        //foreach (Point aPart in snake)
        //{
        //    Console.WriteLine(aPart);
        //}

        // Generate a new food(mouse) position
        GenerateFood();

    }//...more code.

The rest of the code in GitHub @mrcoffeecode Snake Game C#. I manage to create the wall,food and snake. Also the detection with food and walls. Now am stuck in trying to figure out Game Over basically the snake detect it self getting bitten. The code is ready to run without any errors you just need opentk, opengl, openglcontrol.dll.


Solution

  • It is sufficient to evaluate if the head of the snake hits its body. Test if snake[0] hits any element from 1 to snake.Count-1. You have to verify if the x component and (&&) the y component is equal:

    //Snake Collision with its own body
    for (int i = 1; i < snake.Count; i++)
    {
        //if Snake equal itself then snake hasn't touch any other parts of its body
        if (snake[0].X == snake[i].X && snake[0].Y == snake[i].Y)
        {
            this.bGameOver = true;
            break;
        }
    }
    

    Note, in your code every time when the snake grows, a collision of the head with the body will be detected, because you insert a new element at the had position.
    You can get rid about set, if you just avoid to remove the tail element of the snake instead:

    private new void Update()
    {
        // Calculate a new position of the head of the snake
        Point newHeadPosition = new Point(snake[0].X + snakeDirection.X, snake[0].Y + snakeDirection.Y);
        // Insert new position in the beginning of the snake list
        snake.Insert(0, newHeadPosition);
        # snake.RemoveAt(snake.Count - 1); <--------- DELETE    
    
        // Check snake collision with the food
        if (snake[0].X != mouse.X || snake[0].Y != mouse.Y)
        {
            # remove tail if snake does not grow
            snake.RemoveAt(snake.Count - 1); # <---------- ADD
            return;
        }
        else
        {
            //Snake Grow
            // snake.Add(new Point(mouse.X, mouse.Y)); <------ DELETE
        }
        Console.WriteLine();
    
        // Generate a new food(mouse) position
        GenerateFood();
    
    } //Events