Search code examples
javanullpointerexceptionlibgdxtexturessprite

LibGdx Custom Tile Class NullPointer issues


Question: I have begun trying to create a custom tile engine for practice purposes. However out of the gate I've hit a problem. If anyone could please read over everything below and at least point me in the right direction, it would be much appreciated.

Goal: The Tile class takes a string as an argument in its constructor, which is given from an array of the strings for the .PNG files stored in the assets folder. This is then used to create a sprite, which i then try and render to the screen.

Troubleshooting Done:

1) I've used breakpoints to step through the code, and have not found anything that checks out to Null once the code that initializes it has been reached.

2) I've Googled tutorials on how to create Sprites and use Textures in LibGdx and as far as I can tell I am doing it correctly.

3) I've read over the LibGdx documentation to see if there was anything I wasn't understanding about this process, and nothing seems to be going wrong with what I'm doing here.

4) I've read over different NullPointer related questions here to see if anything jumped out that I was doing too, and didn't find anything similar or close to what I am doing here.

What happens: Here is a picture of the log: Log

And here is the Tile class and the TileMap class:

Tile Class:

package com.tilemap.saphiric;

import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Sprite;

/**
 * Base Tile Class for TileMap generation
 */

public class Tile extends Sprite{

    protected Texture texture;
    protected Sprite sprite;

    public Tile(String texture){
        this.texture = new Texture(texture);
        this.sprite = new Sprite(this.texture);
    }


    @Override
    public void setPosition(float x, float y) {
        super.setPosition(x, y);
    }

    @Override
    public float getX() {
        return super.getX();
    }

    @Override
    public float getY() {
        return super.getY();
    }
}

TileMap Class:

package com.tilemap.saphiric;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;

public class TileMap extends ApplicationAdapter {

    private String[] mTextures = new String[4];
    SpriteBatch batch;
    Tile water;

    @Override
    public void create () {
        // Runs setup method to create texture array
        setup(1);

        batch = new SpriteBatch();

        water = new Tile(mTextures[3]);
        System.out.print(String.valueOf(water.texture));

        water.setPosition(Gdx.graphics.getWidth()/2 - water.getWidth()/2,
                Gdx.graphics.getHeight()/2  - water.getHeight()/2);
    }

    @Override
    public void render () {
        Gdx.gl.glClearColor(0, 0, 0, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        batch.begin();
        batch.draw(water, water.getX(), water.getY());
        batch.end();
    }

    // This method recursively initializes the mTextures array with the necessary assets, called on creation
    private int setup(int runCount){
        // Initializes the texture array for tile creation
        mTextures[0] = "dirt_tile.png";
        mTextures[1] = "grass_tile.png";
        mTextures[2] = "stone_tile.png";
        mTextures[3] = "water_tile.png";

        runCount --;

        if(runCount == 0){
            return 0;
        }

        return setup(runCount);
    }
}

Solution

  • The problem is that your Tile needs to be initialized with a Texture. To quote from the Sprite code documentation:

    [the default constructor] Creates an uninitialized sprite. The sprite will need a texture region and bounds set before it can be drawn.

    In other words, your Tile constructor needs to have a call to its super class, Sprite, that initializes it with a Texture or TextureRegion. This should work:

    public Tile(String texture){
        super(new Texture(texture));
    }