0

I created a rectangle array to store my snake body. In the grow method, I create a local ArrayList and initialize it, adding the content of the rectangle array. Then I try to add new rectangle to the ArrayList, however at this point, I receive NullPointerException, and I'm not sure why and how to fix it. I've tried searching it up on google and on this website, however I did not find a topic with this problem.

public class Snake extends GameObject
{
    private Rectangle[] snake;
    private int speed;

    public Snake(int locX, int locY, int width, int height, int speed, ID id) 
    {
        super(locX, locY, width, height, id);
        snake = new Rectangle[3];
        snake[0] = new Rectangle(locX, locY, width, height);
        this.speed = speed;
        grow();
    }

    public void render(Graphics g) 
    {
        g.setColor(Color.GREEN);
        drawSnake(g);               
    }   

    public Rectangle getBounds()
    {
        return new Rectangle(locX, locY, width, height);
    }   

    private void drawSnake(Graphics g)
    {       
        for(int i = 0; i < snake.length - 1; i++)
        {
            g.fillRect(locX, locY, width, height);
        }
    }

    private void grow()
    {
        ArrayList<Rectangle> tempBody = new ArrayList<Rectangle>(Arrays.asList(snake));

        tempBody.add(new Rectangle(snake[snake.length - 1].x, snake[snake.length - 1].y, width, height));   

        snake = tempBody.toArray(snake);
    }   
}
Mortem
  • 1
  • 1

2 Answers2

4

Here why :

  • snake = new Rectangle[3]; : you create an array for 3 Rectangle
    1. so snake is[null, null, null]
  • snake[0] = new Rectangle(locX, locY, width, height); : you fill the first box with an object

    1. so snake is[rect, null, null]
  • snake[snake.length - 1].x you want to get the Rectangle of the last box, but refer to 2. : this box contains null, so you call null.x-> NPE


To improve, you can add an attribute size, and when you want to grow() you'll add a Rectangle at this place like :

private void grow(){
    ArrayList<Rectangle> tempBody = new ArrayList<Rectangle>(Arrays.asList(snake));

    tempBody.add(new Rectangle(snake[size].x, 
                               snake[size].y, width, height));   

    snake = tempBody.toArray(snake);
    size++;
}  

# But a real better way would be to use List<Rectangle> snake and never use an array (if possible) because you need a size-mutable element so List is perfect

I would suggest that the Rectangle you add won't have the same position ? But here you'll have to decide

azro
  • 53,056
  • 7
  • 34
  • 70
  • perhaps offer OP a way to fine what index to use when trying to grow the body (search the array for the first null and use the that index found - 1 to find the tail of the snake) – RAZ_Muh_Taz May 16 '18 at 18:54
  • One more mistake that I can see is that when he is adding a new Rectangle in tempBody where is he getting the width and height? He is not passing it as a parameter to the grow() function, its not defined in the grow() function, neither are they global variables. – Haril Satra May 16 '18 at 18:55
  • @HarilSatra look constructor, there are from superclass `GameObject` – azro May 16 '18 at 19:00
  • I suggest getting rid of the array and using a list instead. Futher just starting with one element not three, where two are null. – Florian p.i. May 16 '18 at 19:15
1

I wanted to offer a solution to the grow() method that will add a body (rectangle) to the current tail of the snake by adding it to the next null location in the snake array without going out of the bounds of the array. I am assuming OP converted the snake array into the arraylist to get the current size of the snake, and then you wanted to use that size - 1 as your index to grab the tail of your snake to use its member variables for the new body being added to the snake.

public void grow()
{
    ArrayList<Rectangle> tempBody = new ArrayList<Rectangle>(Arrays.asList(snake));
    if(tempBody.size() < snake.length())
    {
        tempBody.add(new Rectangle(snake[tempBody.size() - 1].x, snake[tempBody.size() - 1].y, width, height));   
        snake = tempBody.toArray(snake);
    }
    else
        System.out.println("Snake at full size: " + snake.length());
}
RAZ_Muh_Taz
  • 4,059
  • 1
  • 13
  • 26
  • The goadl to use the List, is to increase size indefinitly, after 2 times grow you'll go always in else but you still can grow – azro May 16 '18 at 19:09