Need help figuring out how to adapt a code for a Snake Game I'm trying to make. Help greatly appreciated!

today

Active today

Viewed 7 times

0

first of all thanks for clicking on this post :smiley:

For the last couple of days I've been trying to test out a game for the classic nokia snake game I've found online, but I can't seem to get it to work.

This is the code: (Yes I know it's in russian but google autotranslates it to english pretty well)

Игра змейка. Проекты. Ардуино - Arcade PUB - Проекты (Complete game)

Змейка. Проекты. Ардуино - Arcade PUB - Змейка. Проекты. Ардуино (Only the snake itself)

Now, for a bit of context: I'm using a CJMCU 8X8 Neopixel LED Matrix and a standard joystick. As you've probably noticed, the code in question is for a 16x16 matrix. The reason I have chosen this code in specific is because it's the only one I could find that isn't just broken for me, and also has an explanation on how the code works, (I kinda wanna understand the code I'm using so I can later tweak it :D)

So, no biggie right? If their matrix and my matrix work the same way, I should be able to just change every 256 to 64, every 16 to 8, every 15 to 7, and every 255 to 63 (excluding the 255s reffering to the rgb values ofc) and it should work.

The thing is, my matrix is also different in that the rows all go from left to right. So, in the first row we have LEDs 0 to 7, in the second row, 8 to 15, in the third 16 to 23, and so on. This code, however, is designed for rows that alternate each row. So, they start form left to right (0-7), but then they change to right to left (15-8), and then they go back to left to right (16-23), and then again, and again.

So, what I would need help with is figuring out what I'd have to change for the code to work with my matrix. Of course, the column and row calculations will have to change, but I'm not smart enough to figure out HOW exactly :sweat_smile: I also don't know if I would have to change anything else, so if you could help me, that'd be great!

Thanks in advance!

Can you post your actual code.. no one want to have to reassemble it based on the snippets in the article you linked to.

Make sure you use code tags (</>).

Right, My bad! This is the code with the 16/256 values I talked about changed.

#include <FastLED.h>

//matrix settings
#define NUM_LEDS 64
#define DATA_PIN 4
#define BRIGHTNESS 8

//joystick settings
#define pinX    A2  // ось X джойстика
#define pinY    A1  // ось Y джойстика
#define swPin    2  // кнопка джойстика

int snake[64]; // array of snake elements
int snakeSize = 2;  // real snake size 
int snakeSpeed = 500;

int row;        // row number
int col;        // column number

int lastDirection = 20; // start direction
int i, newDirection, OlddX = 1, OlddY, f;

int red, green, blue, fred, fgreen, fblue; //colors
CRGB leds[NUM_LEDS];

void setup() {
  Serial.begin(9600);
  red = random(0, 255);
  green = random(0, 255);
  blue = random(0, 255);
  fred = random(127, 255);
  fgreen = random(127, 255);
  fblue = random(127, 255);
  
  Serial.begin(9600);
  pinMode(pinX, INPUT);
  pinMode(pinY, INPUT);
  pinMode(swPin, INPUT);
  digitalWrite(swPin, HIGH);
    
  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
  FastLED.setBrightness(BRIGHTNESS);
  for( i=0; i<=64; i++ ){
    snake[i] = 0;
  }

  for( i=0; i<=snakeSize; i++ ){
    snake[i] = lastDirection+i;
  }
    
  f = random(0, 63);
  FastLED.show();
}

int Snakedirection(int last, int dX, int dY ){
  dX = map(dX, 0, 1000, -1, 1);
  dY = map(dY, 0, 1000, -1, 1);
  if(dX == 0 && dY == 0 && OlddX != dX){
    dX = OlddX;
  }
  if(dY == 0 && dX == 0 && OlddY != dY){
    dY = OlddY;
  }
  int newDirection = last;
  if( dX != 0 ){ // moving in X direction
    if ( row&1 ){
        if( col == 0 && dX == 1){ newDirection = last -7; } 
        else if( col == 7 && dX == -1){ newDirection = last +7; }
        else newDirection = last + dX; // четная
    } else {
        if( col == 0 && dX == 1){ newDirection = last +7; }
        else if( col == 7 && dX == -1 ){ newDirection = last -7; }
        else newDirection = last - dX; // не четная
    }
  } 
  if( dY < 0){ // moving in Y DOWN direction
    if(row == 7 && dY == -1){newDirection = col;}
    else if ( row&1 ){
      newDirection = last + (col*2)+1; // четная
    } else {
      newDirection = last + (8-col-1)+(8-col); // не четная
    }
  }
  if( dY > 0){ // moving in Y UP direction
    if( row == 0 && dY == 1){ newDirection = 64 - col;}
    else if ( row&1 ){
      newDirection = last - (last - 8*row) - (8 - col); // четная
    } else {
      newDirection = last - (col*2)-1; // не четная
    }
  }
  OlddX = dX;
  OlddY = dY;
  return newDirection;
}

int snakeMove(int snakeDirection){

  for( i=0; i<=64; i++ ){
    if( snake[i] == snakeDirection ){
      death();
    }
  }
  
  FastLED.clear();
  for(i=snakeSize; i>=1; i--){
    snake[i] = snake[i-1];
  }
  snake[0] = snakeDirection;
  for( i=0; i<=64; i++ ){
    if( snake[i] ){
      leds[snake[i]].setRGB(red, green, blue);
    }
  }
  FastLED.show();
  row = (int)(snakeDirection/8);  // row number 
  if ( row&1 ){
    col = (row+1) * 8 - snakeDirection - 1;
  } else {
    col = snakeDirection - row * 8;
  }
  return snakeDirection;
}

void food( int eaten ){
  if( eaten == f ){
    snakeSize++;
    f = random(0, 63);
    red = fred; 
    green = fgreen; 
    blue = fblue;
    fred = random(0, 255);
    fgreen = random(0, 255);
    fblue = random(0, 255);
    snakeSpeed = snakeSpeed / 1.1;
  } else {
    leds[f].setRGB(fred, fgreen, fblue);
    FastLED.show();
  }
}

void death(){
    snakeSize = 2;
    snakeSpeed = 500;
    red = 255;
    green = 0;
    blue = 0;  
}

void color(boolean sw){
  if(!sw){

    red = random(0,255);
    green = random(0,255);
    blue = random(0,255);
    
  }
}

void loop() {
  Serial.print("lastDirection:");
  Serial.print(lastDirection);
  Serial.print("          newDirection:");
  Serial.println(newDirection);
  color( digitalRead(swPin) );
  newDirection = Snakedirection(lastDirection, analogRead(pinX), analogRead(pinY));
  lastDirection = snakeMove(newDirection);
  food(newDirection);
  delay(snakeSpeed);
}

https://github.com/FastLED/FastLED/blob/master/examples/XYMatrix/XYMatrix.ino

// Param for different pixel layouts
const bool    kMatrixSerpentineLayout = true;
const bool    kMatrixVertical = false;

// Set 'kMatrixSerpentineLayout' to false if your pixels are 
// laid out all running the same way, like this:
//
//     0 >  1 >  2 >  3 >  4
//                         |
//     .----<----<----<----'
//     |
//     5 >  6 >  7 >  8 >  9
//                         |
//     .----<----<----<----'
//     |
//    10 > 11 > 12 > 13 > 14
//                         |
//     .----<----<----<----'
//     |
//    15 > 16 > 17 > 18 > 19
//

Thanks! But I still don-t really understand how I would implement this into my code :sweat_smile: , Should I just replace the column and row calculation with the kMatrixSerpentineLayout == false lines? (92 to 98)

I haven't worked with FastLED.
I've always made an array that corrects for the serpentine paradigm.

Oh well... thanks anyways!

The code you're using is not particularly nice... and I can see why you are having trouble.

Firstly... the variable naming is terrible. In most cases where something is named "direction" it actually means "position". i.e. position within the grid. Very confusing.

There are some actual bugs. For example

Should be < 64, since 63 is the largest index possible.

The code is not well indented.. also makes it hard to read.

The code has virtually no comments... making it very hard to understand what it's doing

I have created a version with the above rectified... I have not addressed your specific issue, but now the code is more readable it should be relatively easy for you to see what needs to be changed. Hopefully you can also see the importance of writing more readable code.

I believe you will need to change routines:

snakeMove and snakePosition

New version

#include <FastLED.h>

//matrix settings
#define NUM_LEDS 64
#define DATA_PIN 4
#define BRIGHTNESS 8

//joystick settings
#define pinX    A2  // ось X джойстика
#define pinY    A1  // ось Y джойстика
#define swPin    2  // кнопка джойстика

int snake[64]; // array of snake elements
int snakeSize = 2;  // real snake size 
int snakeSpeed = 500;

int row;        // row number
int col;        // column number

int lastPosition = 20; // start position

int i, newPosition, OlddX = 1, OlddY, f;

int red, green, blue, fred, fgreen, fblue; //colors
CRGB leds[NUM_LEDS];

void setup() 
{
  Serial.begin(9600);
  red = random(0, 255);
  green = random(0, 255);
  blue = random(0, 255);
  fred = random(127, 255);
  fgreen = random(127, 255);
  fblue = random(127, 255);
  
  Serial.begin(9600);
  pinMode(pinX, INPUT);
  pinMode(pinY, INPUT);
  pinMode(swPin, INPUT);
  digitalWrite(swPin, HIGH);
    
  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
  FastLED.setBrightness(BRIGHTNESS);
  
  for( i=0; i<64; i++ )
  {
    snake[i] = 0;
  }

  for( i=0; i<=snakeSize; i++ )
  {
    snake[i] = lastPosition+i;
  }
    
  f = random(0, 63);
  FastLED.show();
}

int SnakePosition(int last, int dX, int dY )
{
  // Convert analog values from joystick to -1, 0, 1)
  dX = map(dX, 0, 1000, -1, 1);
  dY = map(dY, 0, 1000, -1, 1);

  
  //No input, direction unchanged.
  if(dX == 0 && dY == 0 && OlddX != dX)
  {
    dX = OlddX;
  }
  if(dY == 0 && dX == 0 && OlddY != dY)
  {
    dY = OlddY;
  }

  // THE LOGIC BELOW NEEDS TO BE CHANGED
  int newPosition = last;
  
  // Left/right input (1/-1)
  if( dX != 0 )
  {
    if ( row&1 ) // Odd row
    {
        if( col == 0 && dX == 1)       // In 1st col & moving left
          { newPosition = last -7; } 
        else if( col == 7 && dX == -1) // In last col & moving right
          { newPosition = last +7; }
        else 
          newPosition = last + dX;     // Any other scenario 
    } 
    else // Even row
    {
        if( col == 0 && dX == 1)        // In 1st col & moving left
          { newPosition = last +7; }
        else if( col == 7 && dX == -1 ) // In last col & moving right
          { newPosition = last -7; }
        else 
          newPosition = last - dX;      // Any other scenario 
    }
  } 

  // Up/down input (1/-1)
  if( dY < 0)                                 // Moving down
  { 
    if(row == 7 && dY == -1)                  // Last row (&& dY == -1 not required - always true)
      {newPosition = col;}
    else if ( row&1 )                         // Odd row
    {
      newPosition = last + (col*2)+1;   
    } 
    else                                      // Even row
    {
      newPosition = last + (8-col-1)+(8-col); // Any other scenario
    }
  }
  
  if( dY > 0)                                          // Moving up
  { 
    if( row == 0 && dY == 1)                           // Row 0 (&& dY == 1 not required, always true)
      { newPosition = 64 - col;}
    else if ( row&1 )
    {
      newPosition = last - (last - 8*row) - (8 - col); // Odd row
    } 
    else 
    {
      newPosition = last - (col*2)-1;                  // Even
    }
  }
  
  OlddX = dX;
  OlddY = dY;
  
  return newPosition;
}

int snakeMove(int snakePosition){

  // Check if we ran over ourself.
  for( i=0; i<64; i++ ){
    if( snake[i] == snakePosition )
    {
      death();
    }
  }

  // Clear the display
  FastLED.clear();

  // Shuffle the positions to make room for the new snake head.  This also removes the tail.
  for (i=snakeSize; i>=1; i--)
  {
    snake[i] = snake[i-1];
  }

  // Create the new head.
  snake[0] = snakePosition;

  // Display the snake on the display
  for( i=0; i<64; i++ )
  {
    if( snake[i] )  // If snake[i] is non zero.
    {
      leds[snake[i]].setRGB(red, green, blue);
    }
  }
  FastLED.show();
  
  // Calculate the new row & col global values. THIS LOGIC NEEDS TO BE CHANGED
  row = (int)(snakePosition/8);  // row number 
  if ( row&1 )  // Odd row
  {
    col = (row+1) * 8 - snakePosition - 1;
  } 
  else // Even row
  {
    col = snakePosition - row * 8;
  }

  // This just returns what was passed in? 
  return snakePosition;  
}

void food( int eaten )
{
  if( eaten == f )
  {
    snakeSize++;
    f = random(0, 63);
    red = fred; 
    green = fgreen; 
    blue = fblue;
    fred = random(0, 255);
    fgreen = random(0, 255);
    fblue = random(0, 255);
    snakeSpeed = snakeSpeed / 1.1;
  }
  else 
  {
    leds[f].setRGB(fred, fgreen, fblue);
    FastLED.show();
  }
}

void death()
{
    snakeSize = 2;
    snakeSpeed = 500;
    red = 255;
    green = 0;
    blue = 0;  
}

void color(boolean sw){
  if(!sw){

    red = random(0,255);
    green = random(0,255);
    blue = random(0,255);
    
  }
}

void loop() {
  Serial.print("lastPosition:");
  Serial.print(lastPosition);
  Serial.print("          newPosition:");
  Serial.println(newPosition);
  color( digitalRead(swPin) );
  newPosition = SnakePosition(lastPosition, analogRead(pinX), analogRead(pinY));
  lastPosition = snakeMove(newPosition);
  food(newPosition);
  delay(snakeSpeed);
}
1 Like

Oh thank you thank you thank you!! This seems much more readable, it will be very useful :smile: