0

I'm trying to get an array of objects to render into a gamescreen. I've looked around and found some similar questions asked by others, but I can't seem to apply the answers they've gotten to my program.

The problem seems to occur in the nested for-loops. In trying to solve this issue, I've gotten Java NullPointerExceptions at the first line within those for loops.

package com.frfanizz.agility;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL30;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;

public class GameScreen implements Screen {

AgilityGame game;
OrthographicCamera camera;

SpriteBatch batch;
Hero hero;
Spark[] sparkArray;
int totalSparks;

public GameScreen(AgilityGame game) {
    this.game = game;
    camera = new OrthographicCamera();
    camera.setToOrtho(true, 1920, 1080);

    batch = new SpriteBatch();

    hero = new Hero(60,540);

    //Variables to set spark array
    int screenX = 1400;
    int screenY = 1200;
    int numOfRow = 11;
    int numOfCol = 8;
    float spacingRow = screenY/(numOfRow + 1);
    float spacingCol = screenX/(numOfCol + 1);
    int totalSparks = numOfRow*numOfCol;
    //Spark array
    Spark[] sparkArray = new Spark[totalSparks];
    //setting bounds for sparks
    int index = 0;
    for (int i=0;i<numOfCol;i++) {
        for (int j=0; j<numOfRow;j++) {
            //sparkArray[index] = new Spark();
            sparkArray[index].bounds.x = (float) (60 + spacingCol + ((i)*spacingCol));
            sparkArray[index].bounds.y = (float) (spacingRow + ((j-0.5)*spacingRow));
            index++;
        }
    }

}

@Override
public void render(float delta) {

    Gdx.gl.glClearColor(1F, 1F, 1F, 1F);
    Gdx.gl.glClear(GL30.GL_COLOR_BUFFER_BIT);
    camera.update();
    generalUpdate();

    batch.setProjectionMatrix(camera.combined);

    batch.begin();

        //Rendering code
        batch.draw(Assets.spriteBackground, 0, 0);
        batch.draw(hero.image,hero.bounds.x,hero.bounds.y);

        for (int i=0; i<totalSparks; i++) {
            batch.draw(sparkArray[i].image,sparkArray[i].bounds.x,sparkArray[i].bounds.y);
        }

    batch.end();

}

//Other gamescreen methods

}

The classes Hero and Spark are as follows:

package com.frfanizz.agility;

import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.math.Rectangle;

public class Hero {

public Sprite image;
public Rectangle bounds;

public Hero(int spawnX, int spawnY) {
    image = Assets.spriteHero;
    image.flip(false, true);
    bounds = new Rectangle(spawnX - 16, spawnY - 16, 32, 32);
}
}

and:

package com.frfanizz.agility;

import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.math.Rectangle;

public class Spark {

public Sprite image;
public Rectangle bounds;

public Spark () {
    image = Assets.spriteSpark;
    image.flip(false, true);
    bounds = new Rectangle();
    bounds.height = 32;
    bounds.width = 32;
}
}

Within the for loops, I've printed the values of sparkArray, so I think I have an issue with values rather than references from the other questions I've read the answers to. (Here are the questions I (unsuccessfully) referenced: Java. Array of objects , Java NullPointerException with objects in array)

Thanks in advance!

Community
  • 1
  • 1

1 Answers1

3

Uncomment the line

//sparkArray[index] = new Spark();

Your array of Spark objects contains null values until you put instances of Spark into it.

Consider using a two-dimensional array of Spark, if it's appropriate to what you're doing.

int numOfRow = 11;
int numOfCol = 8;
Spark[][] sparkArray = new Spark[numOfRow][numOfCol];
//setting bounds for sparks
for (int row=0; row<numOfRow; row++) {
    for (int col=0; col<numOfCol; col++) {
        sparkArray[row][col] = new Spark();
        sparkArray[row][col].bounds.x = 1.23; // example of usage
    }
}
gknicker
  • 5,509
  • 2
  • 25
  • 41
  • When I uncomment that line, I no longer get the NullPointerException, but the array of sprites does not render onto the screen. – frfanizz Dec 19 '14 at 02:41
  • I am getting an ArrayIndexOutOfBoundsException in the line: sparkArray[row][col] = new Spark(); – frfanizz Dec 19 '14 at 02:53
  • You may have reversed the row and col bounds (numOfRow/numOfCol) in the `for` loops. The code I posted does not yield ArrayIndexOutOfBoundsException. – gknicker Dec 19 '14 at 07:22
  • I actually figured out the problem. It was that Java was passing all the definitions for the array based on reference rather than value. (See [link1](http://www.javaworld.com/article/2077424/learn-java/does-java-pass-by-reference-or-pass-by-value.html) and [link2](http://docstore.mik.ua/orelly/java-ent/jnut/ch02_10.htm)). I ended up using .clone() to pass the values in the array as values rather than the reference of variables (from the for loop) that were no longer in scope in the render() method. The hero object was working because I used values to instantiate that object – frfanizz Dec 20 '14 at 15:31
  • I don't remember pass-by-reference causing problems in any other language I've used, so maybe it's something specific to Java. If you know of any better way to set arrays to pass by value (or how my overall code should be structured), let me know, because I plan on using loops again to create movement in the sparkarray, and having to go through a separate method to actually store values seems inefficient. – frfanizz Dec 20 '14 at 15:36
  • Java doesn't pass method arguments by reference, it passes them by value. In the case of objects and arrays, the value being passed is a reference (heap memory address). See diagram here http://stackoverflow.com/questions/7015683/where-is-array-saved-in-memory-in-java – gknicker Dec 21 '14 at 02:41