0

I am trying to create a basic snake game using the arduino UNO along with the MAX72XX module, the LCD module and the analog joystick module. I have made my program using object orientated programming. I have no experience with C++ so I have done really well to get this far in my program (This is the only thing left to help me complete the game!). The only problem that is holding me back is that the snake head is always diagonal to the rest of the body. Here are a few examples of what I mean:

Here is my code if the issue is in here (I have commented what part does what):

#include "LedControl.h"
#include <LiquidCrystal.h>
LedControl lc=LedControl(12,10,11,1);
LiquidCrystal lcd(8, 13, 3, 5, 6, 7);


/*lcd->setCursor(0, 1);
  // print the number of seconds since reset:
  lcd->print(millis() / 1000);*/

class Snake_body//class of each snake body part
{
  //private:




  public:

    int following_direction;
    int x;
    int y;
    int previous_x;
    int previous_y;
    bool enabled;
    /*Snake_body()
    {
      this->enabled = false;
    }*/
    /*Snake_body(int x_value, int y_value) 
    {
      this->enabled = false;
      this->following_direction = 1;
      this->x = x_value;
      this->y = y_value;
      this->previous_y = y_value;
      this->previous_x = x_value;
    }*/
    void configure(int x_value, int y_value)
    {
      //this->enabled = true;
      this->following_direction = 1;
      this->x = x_value;
      this->y = y_value;
      this->previous_y = y_value;
      this->previous_x = x_value;  
    }

};


class Power_up
{
  private:

  public:
    virtual void init() 
    {
      this->x = 0;
      this->y = 0;
    }

    int x;
    int y;
};

Snake_body *snake[64];
int snakes_length;


//Snake_body *snake[0];
Power_up *power_up;

int score;

void setup() {

  Serial.begin(9600);


  lcd.begin(16, 2);

  snakes_length = 1;

  for(int z = 1; z < 64; z++)
  {
    snake[z] = NULL;//makes all snake body parts except head NULL 
  }

  snake[0] = new Snake_body();//define snake head
  snake[0]->configure(0,0);//set it up
  power_up = new Power_up();//power up to increase in body size
  //Snake_body snake[0] = new Snake_body();
  // put your setup code here, to run once:
  lc.shutdown(0,false);
  /* Set the brightness to a medium values */
  lc.setIntensity(0,8);
  /* and clear the display */
  lc.clearDisplay(0);
  lcd.setCursor(0, 0);
  score = 0;
  lcd.print("score: ");
  lcd.setCursor(6, 0);
  lcd.print(score);
  pinMode(2, INPUT);
  digitalWrite(2, HIGH);
  power_up->x = random(0, 8);
  power_up->y = random(0, 8);
}

int snake_direction;


void loop() 
{
  int x_axis = analogRead(A0);
  int y_axis = analogRead(A1);
  int switcher = digitalRead(2);


   if(x_axis <= 400)//the following 4 directions are for moving the snake
   {
     snake[0]->following_direction = 0;
     //x += 1;
     Serial.println("left");
   }


   else if(x_axis >= 600)
   {
     snake[0]->following_direction = 1;
     //x -= 1;
     Serial.println("right");
   }


   else if(y_axis <= 400)
   {
     snake[0]->following_direction = 2;
     //y -= 1;
     Serial.println("up");
   }


   else if(y_axis >= 600)
   {
     snake[0]->following_direction = 3;
     //y += 1;
     Serial.println("down");
   }





  if(snake[0]->following_direction == 0 && snake[0]->x < 7)//updates the snakes position
  {
    snake[0]->previous_x = snake[0]->x;
    snake[0]->x += 1;
  }

  else if(snake[0]->following_direction == 1 && snake[0]->x > 0)//updates the snakes position
  {
    snake[0]->previous_x = snake[0]->x;
    snake[0]->x -= 1;
  }

  else if(snake[0]->following_direction == 2 && snake[0]->y > 0)//updates the snakes position
  {
    snake[0]->previous_y = snake[0]->y;
    snake[0]->y -= 1;
  }

  else if(snake[0]->following_direction == 3 && snake[0]->y < 7)//updates the snakes position
  {
    snake[0]->previous_y = snake[0]->y;
    snake[0]->y += 1;
  }








  Serial.println("\n");//USED THESE PRINT STATEMENTS TO PRINT VALUES


  Serial.print("previous x: ");
  Serial.print(snake[0]->previous_x);
  Serial.println("");
  Serial.print("previous y: ");
  Serial.print(snake[0]->previous_y);
  Serial.println("");
  Serial.print("direction: ");
  Serial.print(snake[0]->following_direction);
  Serial.println("\n");




  if(snake[0]->x == power_up->x && snake[0]->y == power_up->y)//if the head collides with the power up
  {
    score += 1;
    lcd.setCursor(6,0);
    lcd.print(score);

    power_up->x = random(0, 8);
    power_up->y = random(0, 8);


    for(int j = 0; j < 64; j++)
    {
      if(snake[j] == NULL)//searches for empty snake body
      {

         snake[j] = new Snake_body();//creates new snake body part
         snake[j]->configure(snake[j-1]->previous_x, snake[j-1]->previous_y);//sets up the snake body part

         snake[j]->following_direction = NULL;
         snakes_length += 1;  
         break;
      }
    }
  }


  for(int i = 1; i < 64; i++)
  {
    if(snake[i] != NULL)//updates the other body parts appart from the snake head (it was updated before this)
    {
      snake[i]->previous_x = snake[i]->x;
      snake[i]->previous_y = snake[i]->y;
      snake[i]->x = snake[i-1]->previous_x;
      snake[i]->y = snake[i-1]->previous_y;    
    }
  }


  lc.setLed(0,power_up->x,power_up->y,true);
  for(int w = 0; w < 64; w++)//drawing body parts onto the screen
  {

    if(snake[w] != NULL)
    {
      lc.setLed(0,snake[w]->x,snake[w]->y,true);
    }
  }





  delay(100); 

  lc.clearDisplay(0);
}
  • I'm not sure if I understand the problem well... in the first example the snake body has three straight dots. This means that before the head was straight compared to the body. Only in the screenshot you made it 'turned' diagonal (?) – Michel Keijzers May 29 at 16:04
  • What you can do yourself to 'debug' is to RUN the sketch on a PC. You can do this by creating a class for all Arduino specific classes (like LiquidCrystal, Serial and LedControl) and program all functions (to do nothing or show a simple display, or write just some lines to mimic the output). This will let you easily add break points and step through your code, or see a (long) list of output including history. – Michel Keijzers May 29 at 16:06
  • And some OO improvements (you did already a good job): you don't have to use the 'new'/dynamic way of allocating in your case, just create elements directly. The normal naming for classes is PascalCasing thus PowerUp instead of Power_up, and make all variables in a class private (move the private keyword before int x; in the Power_up class. Instead of snake[0]->y += 1; you can use snake[0]-y++, similar with --. – Michel Keijzers May 29 at 16:09
  • When a new snake body part is added, let the sketch print out it's position. Check, if that position is correct. I see you are adding the new element at the previous position of the last one, but then you let every part (except for the head) move one step further. Please try to move the adding part to after the body updating part – chrisl May 29 at 16:12
  • 1
    Then please write an answer yourself, so that others might profit from your learning and that this question can be marked as answered by yourself. – chrisl May 30 at 13:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.