1

I'm trying to make a snake game using the u8g lib. But for now, only the second body part of the snake follows the head, where I want the whole body to follow the snake's head and I don't understand why it doesn't work. Here is the code:

#include "U8glib.h"

U8GLIB_PCD8544 u8g(13, 11, 10, 9, 8);    // SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, Reset = 8

const int SNAKEMAXSIZE = 10;

bool title = true;
bool gameRunning = false;

enum direction {HAUT, BAS, GAUCHE, DROITE};

int snakeDirection = GAUCHE;

class snakeCell
{
  private:
  int x;
  int y;

  public:

  snakeCell(int x, int y)
  {
    this->x = x;
    this->y = y;
  }

  snakeCell()
  {
    x = 42;
    y = 24;
  }

  void setX(int x)
  {
    this->x = x;
  }

  void setY(int y)
  {
    this->y = y;
  } 

  int getX()
  {
    return x;
  }

  int getY()
  {
    return y;
  }



  void draw()
  {
    u8g.drawBox(x, y, 5,5);
  }
};

class Pomme
{
  public:
  int x;
  int y;

  Pomme(int x, int y)
  {
    this->x = x;
    this->y = y;
  }

  Pomme()
  {
    x = 42;
    y = 24;
  }

  void randomSpawn()
  {
    x = random(48);
    y = random(84);
  }

  void draw()
  {
    u8g.drawCircle(x, y, 5);
  }
};

snakeCell snake[10] = {snakeCell(), snakeCell(47,24), snakeCell(52,24), snakeCell(57,24), snakeCell(62,24), snakeCell(62,29), snakeCell(62,34), snakeCell(57,34), snakeCell(52,34), snakeCell(52,39)};

Pomme pomme = Pomme();

void draw(void) {
  // graphic commands to redraw the complete screen should be placed here  
  u8g.setFont(u8g_font_6x13);
  //u8g.setFont(u8g_font_osb21);
  u8g.drawRFrame(0, 0, 84, 48, 0);   //Screen frame
  printTitle();
  game();
}

void setup(void) {
  // flip screen, if required
   //u8g.setRot180();

  // set SPI backup if required
  //u8g.setHardwareBackup(u8g_backup_avr_spi);

  // assign default color value

  randomSeed(analogRead(0));

  if ( u8g.getMode() == U8G_MODE_R3G3B2 ) {
    u8g.setColorIndex(255);     // white
  }
  else if ( u8g.getMode() == U8G_MODE_GRAY2BIT ) {
    u8g.setColorIndex(3);         // max intensity
  }
  else if ( u8g.getMode() == U8G_MODE_BW ) {
    u8g.setColorIndex(1);         // pixel on
  }
  else if ( u8g.getMode() == U8G_MODE_HICOLOR ) {
    u8g.setHiColorByRGB(255,255,255);
  }

}

void loop(void) {
  // picture loop
  u8g.firstPage(); 
  do {
    draw();
  } while( u8g.nextPage() );

  // rebuild the picture after some delay
  delay(50);
}

void printTitle()
{
  if(title == true)
  {
    u8g.setFont(u8g_font_6x13);
    //u8g.drawStr( 26, 30, "SNAKE");
    delay(2000);
    title = false;
    gameRunning = true;
  }
}

void moveSnake()
{ 
  //move head accordingly to movement
  if(snakeDirection == GAUCHE)
  {
    snake[0].setX(snake[0].getX() - 1);
  }
  else if(snakeDirection == DROITE)
  {
    snake[0].setX(snake[0].getX() + 1);
  }
  else if(snakeDirection == BAS)
  {
    snake[0].setY(snake[0].getY() + 1);
  }
  else if(snakeDirection == HAUT)
  {
    snake[0].setY(snake[0].getY() - 1);
  }

  //tail follow head
  for(int i = 9; i > 0; i--)
  {
    snake[i] = snakeCell(snake[i-1].getX(),snake[i-1].getY());
  }
  delay(100);
}

void restart()
{
  //snakeCell snake[10] = {snakeCell(), snakeCell(47,24), snakeCell(52,24), snakeCell(57,24), snakeCell(62,24), snakeCell(62,29), snakeCell(62,34), snakeCell(57,34), snakeCell(52,34), snakeCell(47,34)};
}

void drawSnake()
{
  for(int i = 0; i < SNAKEMAXSIZE; i++)
  {
    snake[i].draw();
  }
}

void spawnApple()
{
  pomme = Pomme();
  pomme.randomSpawn();
}

void checkCollision()
{
  // detect if apple eaten
  for(int i = 0; i < SNAKEMAXSIZE; i++)
  {
    if((snake[i].getX() == pomme.x) && (snake[i].getY() == pomme.y))
    {
      pomme.randomSpawn();
    }
  }
  // detect if snake hit wall
  for(int i = 0; i < SNAKEMAXSIZE; i++)
  {
    if((snake[i].getX() >= 84) || (snake[i].getX() <= 0) || (snake[i].getY() >= 48) || (snake[i].getY() <= 0))
    {
      //gameOver();
      restart();
    }
  }
}

void gameOver()
{
  gameRunning = false;
  //u8g.setFont(u8g_font_6x13);
  //u8g.drawStr( 14, 30, "GAME OVER");
  //delay(1000);
  restart();
  gameRunning = true;
}

void game()
{
  if(gameRunning == true)
  {
    checkCollision();
    moveSnake();
    drawSnake();
  }
}

Thanks in advance.

1

There might be a problem with going through your snake array from the back. I'm not sure if you're filling it from front or back, but you should read it from there aswell.

And, every time you re-draw your snake, you're creating a new snakeCell?

//tail follow head
  for(int i = 9; i > 0; i--)
  {
    snake[i] = snakeCell(snake[i-1].getX(),snake[i-1].getY());
  }

You should differentiate between a snakeCell that is active or not. And just re-position and draw it when it's active.

Be sure to check if you're not placing them ontop of eachother. You should put each piece of the tail in the previous position of the preceding part.

Also: You shouldn't really be mixing up French and English naming in your code.

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.