Creating Snake using Java

corecase picture corecase · Jun 9, 2012 · Viewed 11k times · Source

I decided to re-create Snake using Java, but I'm sort of stuck. At the moment, I have a square that the user can move around the screen using the arrow keys. When you press LEFT once, the square begins to move left using a timer.. You don't need to hold down the key or keep pressing it; it changes direction when you press any of the other keys that are set(Right, Up, Down). My goal is to use an ArrayList to hold the squares that make up the snake. At the moment, I've created an ArrayList with just one Snake object inside, if I add a second Snake object to the list and add it to the frame(with the first), only one Snake object is visible and the keys to move it don't function. I'm looking for some ideas as to how I can progress with this project - please don't give me the full answer, because I'd like to figure out most of it on my own; I just need some direction. Thanks in advance - code is below.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Snake extends JPanel implements KeyListener, ActionListener
{
int x = 0, y = 0, velx = 0, vely = 0;
Timer t = new Timer(250, this);


public Snake(int num1, int num2)
{
    t.start();
    addKeyListener(this);
    setFocusable(true);
    setFocusTraversalKeysEnabled(true);
    x = num1;
    y = num2;
}
public void paintComponent(Graphics g)
{   
    super.paintComponent(g);

    g.setColor(Color.blue);
    g.fillRect(x, y, 20, 20);
}
public void actionPerformed(ActionEvent e)
{
    repaint();
    x += velx;
    y += vely;
}
public void up()
{
    vely = -20;
    velx = 0;
}
public void down()
{
    vely = 20;
    velx = 0;
}
public void left()
{
    vely = 0;
    velx = -20;
}
public void right()
{
    vely = 0;
    velx = 20;
}
public void keyPressed(KeyEvent e)
{
    int code = e.getKeyCode();

    if(code == KeyEvent.VK_UP)
        up();
    else if(code == KeyEvent.VK_DOWN)
        down();
    else if(code == KeyEvent.VK_RIGHT)
        right();
    else if(code == KeyEvent.VK_LEFT)
        left();

}
public void keyReleased(KeyEvent e)
{

}
public void keyTyped(KeyEvent e)
{

}
}
//Driver Class
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.util.*;

public class UserClass
{
private static JFrame frame = new JFrame("Snake");
private static ArrayList<Snake> mySnake = new ArrayList<Snake>();

public static void main(String[] args)
{
    frame.setSize(500,500);
    frame.setBackground(Color.black);
    frame.setVisible(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    mySnake.add(new Snake(20,20));
    frame.add(mySnake.get(0));
}
}

P.S When I put this same exact code in Eclipse on my Mac, the background of my frame is black, but on Windows it's light gray... Anyone know why? Thanks.

Answer

Hovercraft Full Of Eels picture Hovercraft Full Of Eels · Jun 10, 2012

Your paintComponent(...) only draws one rectangle. Instead if you want to draw multiple rectangles or ovals, or whatever, give your class a List<Point> or List<Rectangle2D>, and in your Swing Timer, remove the tail from the list and add a new head. then have paintComponent() use a for loop to iterate through a list, drawing all the rectangles held by the list.

Also you will probably want to use key bindings rather than a KeyListener to get the user's key presses as this will work better when other components steal the focus.