0

I'm new to Java and I'm trying to make a simple snake game, but the paint method only gets called once and never again, even though the thread keeps running. I tried another fix on this site that used another class, but that did not work.

public class Snake extends JPanel implements Runnable {

 boolean gamerunning = true;
    int snake_x = 50, snake_y = 50, snake_dir = 2;  //for snake_dir 1=up 2=right 3=down 4=left
    int[] snake_xt, snake_yt;

    public static void main(String args[]) {

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(600,600);
        frame.setVisible(true);
        frame.add(new Snake());

        (new Thread(new Snake())).start();
        System.out.println("Running");
    }

    @Override
    public void run() {
        try {
            while (gamerunning) {
                Thread.sleep(500);
                System.out.println(snake_x);
                tick();
                repaint();
            }
        } catch (InterruptedException e) {}
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        System.out.println("painting");
        g.setColor(Color.black);
        g.fillRect(snake_x, snake_y, 10,10);
    }

    public void tick() { 
        System.out.println("tick");
        switch(snake_dir) {
            case 1:
                snake_y -= 10;
                break;
            case 2:
                snake_x += 10;
                break;
            case 3:
                snake_y += 10;
                break;
            case 4:
                snake_x -= 10;
                break;
        }
    }
}
Stefan Neubert
  • 1,053
  • 8
  • 22
  • 1
    Be carful with this type of model. It's possible that component could be in the process of been painted while you are updating the values it relies on... – MadProgrammer Jan 05 '14 at 10:25
  • your setup is incorrect: properties of a swing component **must** be accessed on the EDT - that rule applies to custom properties (like the snake_x/y) just the same as to "normal" properties (like background). Calling tick() from another thread violates the rule. – kleopatra Jan 05 '14 at 14:45

1 Answers1

1

Your problem is: You are not adding the same snake you are drawing!

frame.add(new Snake());

(new Thread(new Snake())).start();

Each of this lines creates a new Snake, the fist one gets drawn, the second one gets moved.

Try

Snake s = new Snake();
frame.add(s);

(new Thread(s)).start();

instead.

Stefan Neubert
  • 1,053
  • 8
  • 22
  • 3
    Even if it works after this fix, it is still a misguided approach to the solution. A Swing `Timer` should have been used here. – Marko Topolnik Jan 05 '14 at 10:35
  • Well, there are a lot of other issues such as an empty catch block, magic numbers for directions, use of int[] instead of a Point, ... But as the OP is new to java, it might not be a bad idea, to do some good old try&error. – Stefan Neubert Jan 05 '14 at 10:41
  • 1
    I left the comment in the hope of arousing OP's interest :) – Marko Topolnik Jan 05 '14 at 10:50
  • Where my code is at now I have fixed some of the other issues that you stated. What would be a better way to define direction? and all the tutorials i have looked at leave the catch block empty. What should i be putting there? – user3162049 Jan 05 '14 at 20:33
  • Depends on how the snake should be controlled. For a fixed Number of possibilities (up/down/right/left), i usually use enums, but there are many ways of doing this... Concerning the empty catch block, you might want to read http://stackoverflow.com/questions/1234343/why-are-empty-catch-blocks-a-bad-idea and think about what reaction should happen in case of an error. `e.printStackTrace()` could be a valid error handling, there could be a message box, ... – Stefan Neubert Jan 06 '14 at 14:31