0

so I have this little snake game and I get StackOverflow error which looks like so:

 Exception in thread "main" java.lang.StackOverflowError
at java.awt.Component.setBackground(Component.java:1835)
at javax.swing.JComponent.setBackground(JComponent.java:2733)
at javax.swing.LookAndFeel.installColors(LookAndFeel.java:175)
at javax.swing.LookAndFeel.installColorsAndFont(LookAndFeel.java:211)
at javax.swing.plaf.basic.BasicPanelUI.installDefaults(BasicPanelUI.java:66)
at javax.swing.plaf.basic.BasicPanelUI.installUI(BasicPanelUI.java:56)
at javax.swing.JComponent.setUI(JComponent.java:666)
at javax.swing.JPanel.setUI(JPanel.java:153)
at javax.swing.JPanel.updateUI(JPanel.java:126)
at javax.swing.JPanel.<init>(JPanel.java:86)
at javax.swing.JPanel.<init>(JPanel.java:109)
at javax.swing.JPanel.<init>(JPanel.java:117)
at SnakeGame.Animation.<init>(Animation.java:36)
at SnakeGame.Snake.<init>(Snake.java:24)
at SnakeGame.Animation.<init>(Animation.java:38)
at SnakeGame.Snake.<init>(Snake.java:24)

I know there's some infinite recursion going on but I don't get it. It seems like just a constructor. so Here's code for Animation class:

//imports are there
interface Drawable{
public void draw(Graphics g);
}


public class Animation extends JPanel implements ActionListener,   KeyListener{

JFrame frame;
List <Drawable> toDraw;
Snake snake;
Food food;
Timer timer;

public static boolean gameOver = false;
public static int UNIT = 20;
public static int SIZE = 500;


public static void main(String[] args){
   Animation animate = new Animation();
   animate.setUpFrame();
}

Animation(){

    toDraw = new ArrayList<>(); // this is line 38 from exception
    snake = new Snake(SIZE/2,SIZE/2);
    food = new Food();
    toDraw.add(snake);
    toDraw.add(food);
    initTimer();
}

void initTimer(){
    timer = new Timer(200, this);
    timer.setInitialDelay(1000);
    timer.start();
}

void setUpFrame(){
    frame = new JFrame("Snake");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(SIZE, SIZE);
    frame.setFocusable(true);
    frame.setVisible(true);
    frame.add(this);
}

void gameRun() {
       //haven't written here anything yet.  
}  

   @Override
public void paintComponent(Graphics g){
    super.paintComponent(g);
    this.setBackground(new Color(70,130,80));

    for(Drawable d : toDraw){
        d.draw(g);
    }  

}

@Override
public void actionPerformed(ActionEvent e) {
        gameRun();
        repaint();
}


@Override
public void keyTyped(KeyEvent e) {

}

@Override
public void keyPressed(KeyEvent e) {
    int c = e.getKeyCode();
    switch(c){
        case 'L':
           snake.setDirection('L');
            break;
        case 'R':
            snake.setDirection('R');         
            break;
        case 'U':
            snake.setDirection('U');
            break;
        case 'D':
            snake.setDirection('D');
            break;
    }
}

@Override
public void keyReleased(KeyEvent e) {

}

}

And here's snake class:

   public class Snake extends Animation implements Drawable {

int x;
int y;
char direction = 'N';

Snake(int x, int y){ //line 24 from exception
    this.x = x;
    this.y = y;
}


void setDirection(char way){
    direction = way;
}
void move(char direction){

    if(x < 0){
      x = SIZE;  
    } 
    else if(x > SIZE){
        x = 0;
    }
    if(y < 0){
        y= SIZE;
    }else if (y > SIZE){
        y = 0;
    }

    switch(direction){
        case 'L':
            x-= UNIT;
            break;
        case 'R':
            x+= UNIT;              
            break;
        case 'U':
            y-= UNIT;    
            break;
        case 'D':
            y+= UNIT;
            break;
    }  
}

@Override
public void draw(Graphics g) {
    g.setColor(new Color(160,2,42));
    g.fill3DRect(x, y, UNIT, UNIT, true);
  }  
}

Any help would be greatly appreciated!

2
  • Your inheritance makes no sense, why does Snake extend Animation in the first place anyways? Commented Nov 27, 2016 at 19:08
  • @AndrewLi Thanks got it! inheritance is my weak spot. I think I'll just create abstract class for any physical object and extend off of it. Commented Nov 27, 2016 at 19:16

1 Answer 1

2

You've got unintended recursion due to your program's inheritance structure:

Your Snake extends Animation which creates a Snake in its constructor which extends Animation which creates a Snake in its constructor which extends Animation which creates a Snake in its constructor which extends Animation which creates a Snake in its constructor which extends Animation which creates a Snake in its constructor ... etc...

Solution: don't have Snake extend Animation. And this also makes logical sense, since your Snake is not acting as a Swing component such as a JPanel, and so shouldn't inherit from JPanel. Rather it's a logical entity that is drawn by the JPanel -- and so you want to use composition here (which you're already doing) and not inheritance (which you're unfortunately doing as well).

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you! I don't know how inheritance works very well since I read about it at the time when I couldn't do anything in java. I need to refresh my knowledge.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.