ArrayList stuff for Snake game

So the concept is when the snake is not eating any food the new tail block goes onto the current first block moving all the other tail blocks down and deleting the last tail block (so nothing really happens but it allows for the tail to follow the snake head). Then if a piece of food is eaten the new tail block goes in front of the current first block (hence the i+1 in the for loop). Here is the full code btw. and I should probably simplify this if possible but I’m struggling.

PVector food;
float scl=20;
Snake s;

void setup()
{
  size(800,800);
  background(255);
  s= new Snake();
  frameRate(10);
  pickLocation();
}

void draw()
{
  background(200);
  s.update();
  s.show();
  if(s.eat(food))
  {
    pickLocation();
  }
  
  fill(255,0,0);
  rect(food.x,food.y,scl,scl);
}

void pickLocation()
{
  float cols=floor(width/scl);
  float rows=floor(height/scl);
  food= new PVector(floor(random(cols)),floor(random(rows)));
  food.mult(scl);
}

class Snake
{
  float x=0;
  float y=0;
  float xspeed=1;
  float yspeed=0;
  int total=0;
  ArrayList<PVector> tail = new ArrayList<PVector>();
  
  void dir(float x, float y)
  {
    xspeed=x;
    yspeed=y;
  }
  
  boolean eat(PVector pos)
  {
    float d=dist(x,y,pos.x,pos.y);
    if(d<1)
    {
     total++;
      return true;
    }
    else return false;
  }
  
  void update()
  {
    if(total==tail.size())
    {
      for(int i=0; i<tail.size()-1; i++)
      {
        tail.set(i, tail.get(i+1));
      }
    }
    tail.add(total, new PVector(x,y));
    
    println(tail.size());
   
    x=x + xspeed*scl;
    y=y + yspeed*scl;
    x=constrain(x,0,width-scl);
    y=constrain(y,0,height-scl);
  }
  
  void show()
  {
    fill(0);
    for(int i=0; i<tail.size(); i++)
      {
       rect(tail.get(i).x,tail.get(i).y,scl,scl);
      }
    stroke(255);
    fill(0);
    rect(x,y,20,20);
  }    
}

void keyPressed()
{
  if(keyCode==UP)
  {
    s.dir(0,-1);
  }
  else if(keyCode==DOWN)
  {
    s.dir(0,1);
  }
  else if(keyCode==RIGHT)
  {
    s.dir(1,0);
  }
  else if(keyCode==LEFT)
  {
    s.dir(-1,0);
  }
}

Update: I got it to kind of work by changing the if(total==tail.size()) to if(total<tail.size()) now it does add a new block when food is eaten but it stays within the snake until it gets to the end( I explained that badly but if you run the code you can see what I mean) Also it immediately drops off one snake block and starts as 2 pieces instead of 1.

I fixed your errors and tried to improve it a bit. :slight_smile:

PVector food;
float scl=20;
Snake s;

void setup()
{
  size(800, 800);
  background(255);
  s= new Snake();
  frameRate(10);
  pickLocation();
}

void draw()
{
  background(200);
  s.update();
  s.show();
  if (s.eat(food))
  {
    pickLocation();
    s.grow();
  }

  fill(255, 0, 0);
  rect(food.x, food.y, scl, scl);
}

void pickLocation()
{
  float cols=floor(width/scl);
  float rows=floor(height/scl);
  food= new PVector(floor(random(cols)), floor(random(rows)));
  food.mult(scl);
}

class Snake
{
  float x=0;
  float y=0;
  float xspeed=1;
  float yspeed=0;
  int total=0;
  ArrayList<PVector> tail = new ArrayList<PVector>();

  void dir(float x, float y)
  {
    xspeed=x;
    yspeed=y;
  }

  boolean eat(PVector pos)
  {
    float d=dist(x, y, pos.x, pos.y);
    if (d<1)
    {
      return true;
    } else return false;
  }

  void grow() {
    tail.add(total, new PVector(x, y));
  }

  void update()
  {

    for (int i=0; i<tail.size(); i++)
    {
      if (i == 0) {
        tail.set(i, new PVector(x, y));
      } else {
        tail.set(i, tail.get(i+1));
      }
    }    

    x=x + xspeed*scl;
    y=y + yspeed*scl;
    x=constrain(x, 0, width-scl);
    y=constrain(y, 0, height-scl);
  }

  void show()
  {
    fill(0);
    for (int i=0; i<tail.size(); i++)
    {
      rect(tail.get(i).x, tail.get(i).y, scl, scl);
    }
    stroke(255);
    fill(0);
    rect(x, y, 20, 20);
  }
}

void keyPressed()
{
  if (keyCode==UP)
  {
    s.dir(0, -1);
  } else if (keyCode==DOWN)
  {
    s.dir(0, 1);
  } else if (keyCode==RIGHT)
  {
    s.dir(1, 0);
  } else if (keyCode==LEFT)
  {
    s.dir(-1, 0);
  }
}

I created a new function called grow, which adds a tail to the current position. I fix the bug where the first block didn’t follow the snake. If you have any other questions feel free to ask.

1 Like

I ended up taking jb4x’s advice and just reworked everything to make it easier for myself to understand and was able to finish the game. Thanks so much for your help throughout this process!

1 Like

This probably is unwanted advice, but consider defining a class for the segments of the snake, held together in an Array that could be called segs or snake, and another class for Food, held together in an ArrayList the could be called foods. I did this in my book, Programming 101 (published recently by Apress), most probably as an example for programmer defined classes and also to show the differences between Array and ArrayList. Segments (Seg objects) are added to the segs array using a statement such as
segs = (Seg[]) append(segs, newseg);
I think that was the trickiest thing. The append function works for arrays and the result needs to be cast into the proper data type.