Hi, I am trying to make a simple snake game, but whenever I try to attach a body piece it appears randomly on the screen rather than behind the head. Also, the body doesn't exactly follow the head either. I checked the code over and over for any problems but nothing seems wrong. I know the code is a bit rough but its just a quick draft. Please help.

import java.awt.*;
import java.applet.*;
import java.awt.event.*;

public class snake extends Applet implements Runnable, KeyListener
{
  Thread t;
  boolean var = true ;
  boolean loop = true ;
  boolean lose = true ;
  boolean win = false ;
  boolean turn = true ;
  String body ;
  int xRandom ;
  int yRandom ;
  int aFood = 20 ;
  int bFood = 20 ;
  int a = 20 ;
  int b = 20 ;
  int size = 20 ;
  int adir ;
  int bdir ;
  int xdir = 10 ;
  int ydir = 10 ;
  int scoreCounter = -1 ;
  int [] xBody = new int [100] ;
  int [] yBody = new int [100] ;
  int xTurn ;
  int yTurn ;


  public void init ()
  {
	  setSize(600,600) ;
	  setBackground(Color.BLACK) ;
	  addKeyListener(this);
  }
  public void start()
  {
	 t = new Thread(this);
     t.start();
  }
  public void stop()
  {
  }
  public void keyTyped (KeyEvent e)
  {
  }
  public void keyPressed ( KeyEvent e)
  {
	  int keyValue = e.getKeyCode();
	  System.out.println(keyValue) ;
	  //down
	  if(keyValue==40)
	  {
		  bdir = 10  ;
		  xTurn = a ;
		  yTurn = b ;
		  loop = false ;
		  turn = false ;
		  body = "down" ;
	  }
	  //up
	  if(keyValue==38)
	  {
		  loop = false ;
		  bdir = -10;
		  xTurn = a ;
		  yTurn = b ;
		  body = "up" ;
		  turn = false ;

	  }
	  //left
	  if(keyValue==37)
	  {
		  loop = true ;
		  adir = -10 ;
		  xTurn = a ;
		  yTurn = b ;
		  turn = false ;
		  body = "left" ;
	  }
	  //right
	  if(keyValue==39)
	  {
		  loop = true ;
		  xTurn = a ;
		  yTurn = b ;
		  adir = 10;
		  turn = false ;
		  body = "right" ;
	  }

  }
  public void keyReleased ( KeyEvent e )
  {
  }
  public void run()
  {
	  Thread thisThread = Thread.currentThread();
	  while (true)
	  {
		  //lose
		  if(a>600 || a<0 || b>600 || b<0)
		  {
			  lose = false ;
			  scoreCounter = 0 ;
		  }
		  //new game
		  if(win==true)
		  {
			  a = ((((int)(Math.random()*10))*10)*6) ;
			  b = ((((int)(Math.random()*10))*10)*6) ;
			  win = false ;
		  }
		  //vertical loop
		  if(loop==false)
		  {
		  	  b = bdir + b ;
			  for(int j=0;j<=scoreCounter;j=j+1)
			  {
				  yBody[j] = yBody[j]+ydir ;
			  }

		  }
		  //horizontal loop
		  if(loop==true)
		  {
	 	      a = adir + a ;
			  for(int k=0;k<=scoreCounter;k=k+1)
			  {
				  xBody[k] = xBody[k]+xdir ;
			  }

		  }
		  //body turn
		  for(int h=0;h<=scoreCounter;h=h+1)
		  {
			  if(xBody[h]==xTurn)
			  {
				  if(yBody[h]==yTurn)
				  {
						if(turn==false)
						{
						    if(body.equals("up"))
							{
								ydir = -10 ;
							}
							if(body.equals("down"))
							{
								ydir = 10 ;
							}
							if(body.equals("left"))
							{
								xdir = -10 ;
							}
							if(body.equals("right"))
							{
								xdir = 10 ;
							}
							turn = true ;

						}
				   }
			  }
		  }
	      xRandom = ((((int)(Math.random()*10))*10)*6) ;
		  yRandom = ((((int)(Math.random()*10))*10)*6) ;
		  //eating food
		  if(a<=aFood+size && a>=aFood)
		  {
			  if(b<=bFood+size && b>=bFood)
			  {
			  	//adds body
			  	if(loop==true)
			  	{
					if(adir==-10)
					{
						xBody[scoreCounter] = a+(scoreCounter*size) ;
						yBody[scoreCounter] = b ;
					}
					if(adir==10)
					{
						xBody[scoreCounter] = a-(scoreCounter*size) ;
						yBody[scoreCounter] = b ;
					}
				}
				if(loop==false)
				{
					if(bdir==-10)
					{
						xBody[scoreCounter] = a ;
						yBody[scoreCounter] = b+(scoreCounter*size) ;
					}
					if(bdir==10)
					{
						xBody[scoreCounter] = a ;
						yBody[scoreCounter] = b-(scoreCounter*size) ;
					}
				}
				var = false ;
			  }
		  }
		  //food location & score count
		  if(var==false)
		  {
			  aFood = xRandom ;
			  scoreCounter = scoreCounter + 1 ;
			  bFood = yRandom ;
			  var = true ;
		  }
		  try
		  {
			  t.sleep(100);
		  }
		  catch (InterruptedException e)
		  {
		  }
          repaint();
      }
	}
  public void paint (Graphics g)
  {
      g.setColor(Color.WHITE) ;
      g.fillOval(a,b,size,size);
      g.drawString("Score: ",250,280) ;
      g.drawString("  "+scoreCounter,290,280) ;
      if(lose==false)
      {
      	g.drawString("YOU LOSE!!!",250,300) ;
      	lose = true ;
      	win = true ;
	  }
      g.setColor(Color.GREEN) ;
      g.fillRect(aFood,bFood,size,size);

	  for(int i=0;i<scoreCounter;i=i+1)
	  {
		  g.setColor(Color.BLUE) ;
		  g.fillOval(xBody[i],yBody[i],size,size);
	  }


  }
  public void update(Graphics g)
  {
		Graphics offgc;
		Image offscreen = null;
		Dimension d = size();

		offscreen = createImage(d.width, d.height);
		offgc = offscreen.getGraphics();
		offgc.setColor(getBackground());
		offgc.fillRect(0, 0, d.width, d.height);
		offgc.setColor(getForeground());
		paint(offgc);
		g.drawImage(offscreen, 0, 0, this);
  }

}

I think it would be better for the body to follow the snake head instead of only reacting to the key pressed by the user

The snake head should have a front like method where you'll know the front of the circle by knowing where the snake is headed
e.g. if the snake head is moving headed towards the right its front side is the circles right side

The tail that will be attached to the snake will have an almost same structure as the head but instead of reacting to the key pressed by the user it will move towards the current location of the head,the head should have a method that return the current head's location where the tail will move close to(distance between head to tail depends on the size of the circle) then the tail will react to the front of the head by moving to the opposite direction(the purpose of knowing the front of the snake)

After eating another fruit,the added tail will move to the last tail of the snake by moving according to the last location and will move around the circle it is attached to(all of the circles has a front where the last circle attached to it will move opposite to)

I hope you can visualize what I'm saying here, by following this suggestion there's going to be major changes in the coding but I think your gonna face the same problems with the body movement if you continue on the current code
Good Luck :)

Edited 4 Years Ago by zeroliken: n/a

Sorry, I don't quite understand. I get the part about every circle having a front. But when you say the tail should move opposite of the head, that doesn't make much sense. It should be moving the same direction, I believe.

The idea behind my code is that when the head eats a fruit it adds a body piece behind it, depending on the direction it was headed. The part I am stuck at is the turn. I am trying to have the computer check when the body piece equals the coordinate where the head changed directions then that body piece will also change directions. But, in the applet, every time the head its a fruit, the body piece appears a bit too far and the directions are inverted. Overall, the game looks like a bunch of circles moving at the same time.

But when you say the tail should move opposite of the head,

I'm sorry if I wasn't clear what I meant is the location of the tail should be opposite to the front of the head so when you press a key the circle head's front will change direction which will make the tail "attached" to it move in the direction opposite of the head circle's front side
ex.
moving to the right: tail->head->front
moving to the left: front<-head<-tail
moving to the upwards:
front
|
head
|
tail

Overall, the game looks like a bunch of circles moving at the same time.

That's what my suggestion is suppose to solve :)

Edited 4 Years Ago by zeroliken: n/a

Oh okay. That makes a bit more sense. How would you code that? I mean that doesn't exactly solve my problems of the body not following.

For the body to follow.... you need a 2 dimentional array that consists of the points to use as a route.

The array consists of cordinations x and y; your computer screen consists of the same dots(cordination) called pixels. That means the food for the snake must register on one of the cordinating x&y axis. Your snake move only via the cordiation you have already made in the 2 dim. Array. I cant give you all these lectures... use google ok?

I'm not quite sure what you're trying to do, I've made a snake game myself...
here

You probably want a 2D array, then something like a LinkedList<Point>.
Each point can represent a (y,x) position in the array, with say the first entry being the head, and the last is the tail.

When the snakes head moves to a new point, add this in to the start of the list, then remove the last element.

Similarly when snake eats food, add the new point in to the start of the list, and thats it.

For me, the only tricky part is getting the timing correct for when you press a key to turn the snake since you want it to be as responsive as possible.

Let me know if I can help any more.

This article has been dead for over six months. Start a new discussion instead.