Hello I am currently programming a LibGDX game based on physics with a ball that must stay on a platform, I have set up the physics components for the ball, but when I try updating the sprite for the ball based on the physic body's position it is giving me a null pointer exception.
I have spent 1 whole day trying to fix the problem through researching and looking at other peoples' code but cannot find my error. Thank you for your time and any input that you can give. Below I have typed the code from my Render class, Ball GameObject class, Asset class, and Exception.
Ball GameObject Class:
public class Ball {
public static World physicsWorld;
public static BodyDef ballBodyDef;
public static Body ballBody;
public static CircleShape ballShape;
public static FixtureDef ballFixtureDef;
public static Fixture ballFixture;
public Ball() {
physicsWorld = new World(new Vector2(0, -9.8f), true);
ballBodyDef = new BodyDef();
ballBodyDef.position.set(Assets.ballSprite.getX(),
Assets.ballSprite.getY());
ballBodyDef.type = BodyDef.BodyType.DynamicBody;
ballBody = physicsWorld.createBody(ballBodyDef);
ballShape = new CircleShape();
ballShape.setRadius(6f);
ballFixtureDef = new FixtureDef();
ballFixtureDef.density = 1.0f;
ballFixtureDef.friction = 0.2f;
ballFixtureDef.restitution = 0.4f;
ballFixture = ballBody.createFixture(ballFixtureDef);
}
public void dispose() {
physicsWorld.dispose();
ballShape.dispose();
}
public BodyDef getBallBodyDef() {
return ballBodyDef;
}
public void setBallBodyDef(BodyDef ballBodyDef) {
this.ballBodyDef = ballBodyDef;
}
public Body getBallBody() {
return ballBody;
}
public void setBallBody(Body ballBody) {
this.ballBody = ballBody;
}
public CircleShape getBallShape() {
return ballShape;
}
public void setBallShape(CircleShape ballShape) {
this.ballShape = ballShape;
}
public FixtureDef getBallFixtureDef() {
return ballFixtureDef;
}
public void setBallFixtureDef(FixtureDef ballFixtureDef) {
this.ballFixtureDef = ballFixtureDef;
}
public Fixture getBallFixture() {
return ballFixture;
}
public void setBallFixture(Fixture ballFixture) {
this.ballFixture = ballFixture;
}
}
Render Class:
public class GameRenderer {
private GameWorld myWorld;
private OrthographicCamera cam;
int width = Gdx.graphics.getWidth();
int height = Gdx.graphics.getHeight();
private SpriteBatch batch;
public GameRenderer(GameWorld world, int gameHeight, int midPointY) {
myWorld = world;
cam = new OrthographicCamera();
cam.setToOrtho(true, width, height);
batch = new SpriteBatch();
batch.setProjectionMatrix(cam.combined);
}
public void render(float delta) {
Gdx.app.log("GameRenderer", "render");
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
Ball.physicsWorld.step(Gdx.graphics.getDeltaTime(), 6, 2);
Assets.ballSprite.setPosition(Ball.ballBody.getPosition().x,
Ball.ballBody.getPosition().y);
batch.begin();
batch.draw(Assets.skySprite, 0, 0, 1920, 1080);
batch.draw(Assets.ballSprite, Assets.ballSprite.getX(),
Assets.ballSprite.getY());
batch.draw(Assets.platformSprite, Assets.platformSprite.getX(),
Assets.platformSprite.getY());
batch.end();
}
}
Lastly my Assets Class:
public class Assets {
public static Texture skyTexture;
public static Sprite skySprite;
public static Texture ballTexture;
public static Sprite ballSprite;
public static Texture platformTexture;
public static Sprite platformSprite;
public static Button rightTiltButton;
public static TextureAtlas rightButtonAtlas;
public static TextButtonStyle rightButtonStyle;
public static Skin rightButtonSkin;
public static void Load() {
skyTexture = new Texture(Gdx.files.internal("Assets/skybackground.png"));
skyTexture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
skySprite = new Sprite(skyTexture);
skySprite.flip(false, true);
ballTexture = new Texture(
Gdx.files.internal("Assets/ballcharacter.png"));
ballTexture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
ballSprite = new Sprite(ballTexture);
ballSprite.flip(false, true);
ballSprite.setPosition(
Gdx.graphics.getWidth() / 2 - ballSprite.getWidth()/2,
Gdx.graphics.getHeight() / 2 - ballSprite.getHeight()-4);
platformTexture = new Texture(Gdx.files.internal("Assets/platform.png"));
platformTexture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
platformSprite = new Sprite(platformTexture);
platformSprite.flip(false, true);
platformSprite.setPosition(
Gdx.graphics.getWidth() / 2 - platformSprite.getWidth()/2,
Gdx.graphics.getHeight() / 2 - platformSprite.getHeight()/2);
rightButtonSkin = new Skin();
rightButtonAtlas = new TextureAtlas(
Gdx.files.internal("Assets/right_tilt_button.pack"));
rightButtonSkin.addRegions(rightButtonAtlas);
rightButtonStyle = new TextButtonStyle();
rightButtonStyle.up = rightButtonSkin.getDrawable("right_tilt_button");
rightButtonStyle.up = rightButtonSkin
.getDrawable("right_tilt_button_pressed");
rightButtonStyle.up = rightButtonSkin.getDrawable("right_tilt_button");
rightButtonStyle.over = rightButtonSkin
.getDrawable("right_tilt_button_pressed");
rightButtonStyle.down = rightButtonSkin
.getDrawable("right_tilt_button_pressed");
rightTiltButton = new Button(rightButtonStyle);
}
public static void dispose() {
skyTexture.dispose();
rightButtonAtlas.dispose();
rightButtonSkin.dispose();
ballTexture.dispose();
}
}
NullPointerException:
Exception in thread "LWJGL Application" java.lang.NullPointerException
at com.manumade.tiltr.tiltrhelpers.GameRenderer.render (GameRenderer.java:36)
at com.manumade.tiltr.screens.GameScreen.render(GameScreen.java:39)
at com.badlogic.gdx.Game.render(Game.java:46)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:208)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:114)
Looking at your code and stack trace there seems to be a problem on one of this lines:
batch.draw(Assets.skySprite, 0, 0, 1920, 1080);
batch.draw(Assets.ballSprite, Assets.ballSprite.getX(),
Assets.ballSprite.getY());
batch.draw(Assets.platformSprite, Assets.platformSprite.getX(),
Assets.platformSprite.getY());
From the stack trace that you provided we can see that the error is happening on line 36:
at com.manumade.tiltr.tiltrhelpers.GameRenderer.render (GameRenderer.java:36)
Look at your GameRenderer class and see what object gets called on that line. When you receive a NullPointerException it means that you are trying to call a method or acess a variable on a object that does not point to anything (The object might never be created.)
I would assume that either:
The SpriteBatch is NULL
Assets.skySprite is NULL
Assets.ballSprite is NULL
Assets.platformerSprite is NULL
So look at the way those object get instantiated. Also make sure that you are actually initializing them before performing anything on those objects. Your render() method might be called before you actually initialize the Sprite objects in your Assets class.
It looks like a problem with drawing one of your sprites (based on the exception line number). Try replacing the sprites you have used with other ones (obviously it will look silly), and see if any of them work.
Once you know which sprites work and which ones don't, you can try and narrow down what might be different about them. I have had similar problems caused by using non-power of two textures, for example.
I see that you call:
Assets.ballSprite.setPosition(Ball.ballBody.getPosition().x,
Ball.ballBody.getPosition().y);
batch.begin();
batch.draw(Assets.skySprite, 0, 0, 1920, 1080);
batch.draw(Assets.ballSprite,
Assets.ballSprite.getX(),
Assets.ballSprite.getY());
batch.draw(Assets.platformSprite,
Assets.platformSprite.getX(),
Assets.platformSprite.getY());
batch.end();
Assets.skySprite,
Assets.ballSprite,
Assets.platformSprite
but I can not see that you call Assets.load ();
before using the above why is null, because they are not initialized only declared or I think that's the error.
try calling Assets.Load (); before that used in render method, for example inside of the your public GameRenderer(...); method.
could try to read about it AssetsManager :
https://github.com/libgdx/libgdx/wiki/Managing-your-assets
and create a loading of assets before entering the playing area.(but it's just an idea).
could look at, www some tutorial about it AssetManager.
P.S: which is the line: (GameRenderer.java:36),
sure that the staticas variables used for example in Ball, are initialized before being used in render.
Related
I'm new at Java. I'm writing a simple game like Flappy Bird. I like the add menu screen before starting the game, like
-Start Game -Credits maybe options (maybe), something like that.
Here is my basic code for oncreate:
#Override
public void create () {
batch = new SpriteBatch();
background = new Texture("background.png");
smurf = new Texture("smurf.png");
gargamel1 = new Texture("gargamel.png");
gargamel2 = new Texture("gargamel.png");
gargamel3 = new Texture("gargamel.png");
distance = Gdx.graphics.getWidth() / 2;
random = new Random();
smurfX = Gdx.graphics.getWidth() / 2 - smurf.getHeight() / 2;
smurfY = Gdx.graphics.getHeight() / 3;
shapeRenderer = new ShapeRenderer();
smurfCircle = new Circle();
enemyCircles = new Circle[numberOfEnemies];
enemyCircles2 = new Circle[numberOfEnemies];
enemyCircles3 = new Circle[numberOfEnemies];
font = new BitmapFont();
font.setColor(Color.WHITE);
font.getData().setScale(5);
font2 = new BitmapFont();
font2.setColor(Color.WHITE);
font2.getData().setScale(8);
for (int i = 0; i<numberOfEnemies; i++){
enemyOffSet[i] = (random.nextFloat() - 0.5f) * (Gdx.graphics.getHeight() - 200);
enemyOffSet2[i] = (random.nextFloat() - 0.5f) * (Gdx.graphics.getHeight() - 200);
enemyOffSet3[i] = (random.nextFloat() - 0.5f) * (Gdx.graphics.getHeight() - 200);
enemyX[i] = Gdx.graphics.getWidth() - gargamel1.getWidth() / 2 + i * distance;
enemyCircles[i] = new Circle();
enemyCircles2[i] = new Circle();
enemyCircles3[i] = new Circle();
sound = Gdx.audio.newSound(Gdx.files.internal("lose.ogg"));
}
}
To have several Screens you must extend Game in your Main class.
Default when you create a libGdx project with the "gdx-setup.jar" the Main class extends ApplicationAdapter.
public class MultipleScreen extends Game {
Now you have a method: setScreen(Screen). With this method you can change Screens.
Here is a template which I use often for my projects. It also dispose the old screen:
public class MultipleScreen extends Game {
#Override
public void create () {
}
public void changeScreen(Screen newScreen){
Screen oldScreen = getScreen();
setScreen(newScreen);
//Dispose the old screen to release resources
if(oldScreen != null)
oldScreen.dispose();
}
#Override
public void render () {
//Clear the Screen
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
//Render the current Screen
super.render();
}
#Override
public void dispose () {
//Dispose Assets which you used in the whole Game
}
}
Here I created a new method: changeScreen(Screen). This method uses the setScreen method of the Game to set the screen and additional dispose the old one.
Now to make an example we need two Screens:
public class MenuScreen implements Screen {
//We need MultipleScreen class to change the screen
private MultipleScreen game;
public MenuScreen(MultipleScreen game) {
this.game = game;
}
#Override
public void show() {
}
private float f = 0;
#Override
public void render(float delta) {
//A simple Timer which changes the screen after 10 seconds
f += delta;
if(f > 10000){
//Here you can add for example also the Level to the GameScreen which level the player choose
//game.changeScreen(new GameScreen(game, levelNumber));
game.changeScreen(new GameScreen(game));
}
}
...
}
And a GameScreen which simple displays the badlogic image:
public class GameScreen implements Screen {
private MultipleScreen game;
private SpriteBatch batch;
private Texture img;
public GameScreen(MultipleScreen game) {
this.game = game;
}
#Override
public void show() {
batch = new SpriteBatch();
img = new Texture("badlogic.jpg");
}
#Override
public void render(float delta) {
//Here we don't need to add Gdx.gl.glClear...
//because we already have this in our MultipleScreen which does this for every subScreen
batch.begin();
batch.draw(img, 0, 0);
batch.end();
}
...
#Override
public void dispose() {
//This things will be disposed if we change to another Screen to save resources
batch.dispose();
img.dispose();
}
Now the last thing we must do is to set a Screen if our game Starts. So in the create() method of our Main class (in this case MultipleScreen) we add:
#Override
public void create () {
changeScreen(new MenuScreen(this));
}
Now if the game is over we will go back to MenuScreen. But instead of creating a new MenuScreen everyTime we can add a backToMenu() method in our Main class:
private MenuScreen menuScreen;
#Override
public void create () {
menuScreen = new MenuScreen(this);
backToMenu();
}
public void backToMenu(){
setScreen(menuScreen);
}
In our GameScreen we now can simple call: game.backToMenu(); to change back to MenuScreen without creating a new one.
Important
If we call setScreen() the show() method will be called and not the Constructor of the class.
So every Asset you dispose in the classes dispose() method you must create in the show() method not in the Constructor else you will have no Assets if you show a Screen a second time.
A hope this little guide will help you.
If you need more help you can find some tutorials in the Internet where they change Screen:
https://www.gamedevelopment.blog/full-libgdx-game-tutorial-project-setup/
I have problems to draw an image ( Texture ) on a TiledMap. When I try to call batch.draw(mytexture,x,y) the only image displayed is the map below; I tried to search on web a feasible solution, but i have not solved the problem yet..
i
Here's my code
public class GameTest implements ApplicationListener{
private Player player;
private Batch batch;
private MyTexture texture;
private OrthographicCamera camera;
private OrthogonalTiledMapRenderer renderer;
private TiledMap map;
public GameTest() {
//init camera and player
}
#Override
public void create() {
background = new Background();
batch = new SpriteBatch();
texture = new MyTexture();
map = new TmxMapLoader().load(Asset.FIRST_LEVEL);
renderer = new OrthogonalTiledMapRenderer(map);
camera.setToOrtho(false, 1280,512);
renderer.setView(camera);
camera.update();
}
#Override
public void render() {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
background.update(Gdx.graphics.getDeltaTime());
batch.begin();
if(Gdx.input.isKeyJustPressed(Input.Keys.RIGHT)){
game.movePlayer('r', 1);
camera.position.x += 5;
}
camera.update();
renderer.setView(camera);
renderer.render();
// batch.setProjectionMatrix(camera.combined);
batch.draw(texture.getTexture("100"), (player.getPosition().y) * 64, ((7
- player.getPosition().x) * 64));
batch.end();
}
}
Here's MyTexture class. I create a map where I put a String as a key and a Texture corresponding to the image I want to display
public MyTexture() {
....
map.put("100",new Texture(Gdx.files.internal(Asset.PLAYER)));
}
public static final Texture getTexture(String key){
return map.get(key);
}
And here my Asset class, where I create only static field for imgaes path
public class Asset {
public static Map<String, String> map = new HashMap<String,String>();
public static final String FIRST_LEVEL = "levels/firstLevel.tmx";
public static String BACKGROUND = "asset/Background.png";
public static String PLAYER = "asset/Player.png";
...
}
Are you use you want to draw with a unit-scale of 1.0?
When calling the constructor of OrthogonalTiledMapRenderer that only takes a TmxTileMap as parameter the unit scale is defaulted to 1.0.
That means that a single tile takes up the as many world-units as there are pixels in a tile.
Try calling it with 1.0f / your_tile_size_in_pixels.
So if the tiles for your map are 64 by 64 pixels change
renderer = new OrthogonalTiledMapRenderer(map);
to
renderer = new OrthogonalTiledMapRenderer(map, 1.0f / 64.0f);
Update: Solution at the bottom of this post.
I'm having a problem in which when my game is run, the screen is just black and crashed a couple seconds later. I declare a new SpriteBatch in my main Game class:
public SpriteBatch batch;
And I instantiate it in my Create method() and pass the entire Game class to a Screen called Playscreen:
batch = new SpriteBatch();
setScreen(new PlayScreen(this));
In the constructor of PlayScreen, I set the passed Game class to a private field I set up:
this.game = game;
This is my entire render method for PlayScreen:
#Override
public void render(float delta)
{
update(delta);
Gdx.gl.glClearColor(0, 2, 2, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
game.batch.setProjectionMatrix(hud.stage.getCamera().combined);
// Gdx.gl20.glActiveTexture(GL20.GL_TEXTURE0);
game.batch.begin();
for (Tile[] tileArray : tileMatrix.getTileMatrix())
{
for (Tile tile : tileArray)
{
tile.draw(game.batch);
}
}
game.batch.end();
hud.stage.draw();
}
tileArray is a two dimensional array that contains Tiles. In my create() method, every tile in this array is initialized and assigned a different location. Here is the base class:
public abstract class Tile extends Sprite
{
protected Texture texture;
protected String name;
protected int movementPoints;
protected int foodYield;
protected int productionYield;
protected int tradeYield;
public Tile(int mP, int fY, int pY, int tY, String name, Texture texture)
{
this.movementPoints = mP;
this.foodYield = fY;
this.productionYield = pY;
this.tradeYield = tY;
this.name = name;
this.texture = texture;
setBounds(0, 0, 50, 50);
}
When DesktopLauncher.java is run, I get this error:
Exception in thread "LWJGL Application" java.lang.NullPointerException
at com.badlogic.gdx.graphics.g2d.SpriteBatch.flush(SpriteBatch.java:962)
at com.badlogic.gdx.graphics.g2d.SpriteBatch.end(SpriteBatch.java:183)
at com.marcusorciuch.reciv.screens.PlayScreen.render(PlayScreen.java:108)
at com.badlogic.gdx.Game.render(Game.java:46)
at com.marcusorciuch.reciv.ReCivMain.render(ReCivMain.java:47)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:225)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:126)
#
game.batch.end();
Yeah, I don't know whats going on.
Edit: To those who are having this problem, make sure if you have a class that extends from Sprite, make sure you call super(texture) or else the Sprite parts of your class will not be instantiated.
i'm creating a 2D platform game with Android Studio and LibGDX.
Right now, I'm implementing an on-screen controller to move the character, but when I start the launcher, it closes automatically.
When I run the launcher, this is what the console shows:
Exception in thread "LWJGL Application" java.lang.IllegalArgumentException: batch cannot be null.
at com.badlogic.gdx.scenes.scene2d.Stage.<init>(Stage.java:108)
at com.globapps.supermarioclon.Tools.Controles.<init>(Controles.java:30)
at com.globapps.supermarioclon.Screens.PantallaJuego.<init>(PantallaJuego.java:57)
at com.globapps.supermarioclon.MarioBros.create(MarioBros.java:34)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:147)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:124)
This is the code from the controller class:
public class Controles {
Viewport viewport;
Stage stage;
boolean salto, izquierda, derecha;
OrthographicCamera cam;
public Controles() {
cam = new OrthographicCamera();
viewport = new FitViewport(800, 480, cam);
stage = new Stage(viewport, PantallaJuego.batch);
Gdx.input.setInputProcessor(stage);
Table table1 = new Table();
Table table2 = new Table();
table1.left().bottom();
table2.right().bottom();
Image flechaizquierda = new Image(new Texture("flechaIzquierda.png"));
flechaizquierda.setSize(50, 50);
flechaizquierda.addListener(new InputListener() {
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
izquierda = true;
return true;
}
#Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
izquierda = false;
}
});
final Image flechaderecha = new Image(new Texture("flechaDerecha.png"));
flechaderecha.setSize(50, 50);
flechaderecha.addListener(new InputListener() {
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
derecha = true;
return true;
}
#Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
derecha = false;
}
});
Image flechasalto = new Image(new Texture("flechaIzquierda.png"));
flechasalto.setSize(50, 50);
flechasalto.addListener(new InputListener() {
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
salto = true;
return true;
}
#Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
}
});
table1.add();
table1.add(flechaizquierda).size(flechaizquierda.getWidth(), flechaizquierda.getHeight());
table1.add();
table1.row().pad(0, 5, 0, 5);
table1.add();
table1.add(flechaderecha).size(flechaderecha.getWidth(), flechaderecha.getHeight());
table2.add();
table2.add(flechasalto).size(flechasalto.getWidth(), flechasalto.getHeight());
table2.row().padRight(5);
table2.add();
stage.addActor(table1);
stage.addActor(table2);
}
public void draw() {
stage.draw();
}
public boolean isDerecha() {
return derecha;
}
public boolean isIzquierda() {
return izquierda;
}
public boolean isSalto() {
return salto;
}
public void resize(int ancho, int alto) {
viewport.update(ancho, alto);
}
}
And this is the PlayScreen class:
public class PantallaJuego extends ApplicationAdapter implements Screen {
private MarioBros game;
public static SpriteBatch batch;
private TextureAtlas atlas;
private OrthographicCamera gamecam, cam;
private Viewport gamePort, viewport;
private HUD hud;
private TmxMapLoader maploader;
private TiledMap map;
private OrthogonalTiledMapRenderer renderer;
private World world;
private Box2DDebugRenderer b2dr;
Controles controles;
private Mario player;
private Music musica;
public PantallaJuego(MarioBros game) {
atlas = new TextureAtlas("MarioyEnemigos.pack");
this.game = game;
gamecam = new OrthographicCamera();
gamePort = new FitViewport(MarioBros.V_WIDTH / MarioBros.PPM, MarioBros.V_HEIGHT / MarioBros.PPM, gamecam);
hud = new HUD(game.batch);
controles = new Controles();
batch = new SpriteBatch();
maploader = new TmxMapLoader();
map = maploader.load("nivel1mario.tmx");
renderer = new OrthogonalTiledMapRenderer(map, 1/MarioBros.PPM);
gamecam.position.set(gamePort.getWorldWidth()/2, gamePort.getWorldHeight()/2, 0);
world = new World(new Vector2(0,-10), true);
b2dr = new Box2DDebugRenderer();
player = new Mario(world, this);
new B2WorldCreator(world, map);
world.setContactListener(new WorldContactListener());
musica = MarioBros.manager.get("Audio/Música/Super Mario World - Overworld Theme Music (FULL VERSION).mp3", Music.class);
musica.setLooping(true);
musica.play();
}
public TextureAtlas getAtlas() {
return atlas;
}
#Override
public void show() {
}
public void handleInput(float dt) {
if(controles.isDerecha())
player.b2body.applyLinearImpulse(new Vector2(0.1f, 0), player.b2body.getWorldCenter(), true);
if(controles.isSalto())
MarioBros.manager.get("Audio/Sonidos/Super Mario Bros- Mario Jump Sound Effect.mp3", Sound.class).play();
player.b2body.applyLinearImpulse(new Vector2(0, 4f), player.b2body.getWorldCenter(), true);
if(controles.isIzquierda())
player.b2body.applyLinearImpulse(new Vector2(-0.1f, 0), player.b2body.getWorldCenter(), true);
}
public void update(float dt) {
handleInput(dt);
world.step(1 / 60f, 6, 2);
gamecam.position.x = player.b2body.getPosition().x;
cam.position.set(viewport.getWorldWidth() / 2, viewport.getWorldHeight() / 2, 0);
player.update(dt);
hud.update(dt);
if(Gdx.app.getType() == Application.ApplicationType.Android)
controles.draw();
gamecam.update();
cam.update();
renderer.setView(gamecam);
}
#Override
public void render(float delta) {
update(delta);
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
renderer.render();
b2dr.render(world, cam.combined);
b2dr.render(world, gamecam.combined);
game.batch.setProjectionMatrix(gamecam.combined);
game.batch.begin();
player.draw(game.batch);
game.batch.end();
game.batch.setProjectionMatrix(hud.stage.getCamera().combined);
hud.stage.draw();
}
If someone could help me, I'd be very grateful. Thank you.
I think you should instantiate your batch in PantallaJueago class before instantiating controles field.
public PantallaJuego(MarioBros game) {
atlas = new TextureAtlas("MarioyEnemigos.pack");
this.game = game;
gamecam = new OrthographicCamera();
gamePort = new FitViewport(MarioBros.V_WIDTH / MarioBros.PPM, MarioBros.V_HEIGHT / MarioBros.PPM, gamecam);
hud = new HUD(game.batch);
batch = new SpriteBatch();
controles = new Controles();
Because it is null while you instantiating your "controles". You are getting this error for your line
stage = new Stage(viewport, PantallaJuego.batch);
PantallaJuego.batch is null.
Well you should learn some more of the basics before you continue. This is related to a a NullPointerException and is usually very easy to fix. It tells you that you are trying to access a method or variable in nothing since you did not initialize it. Let's take your stack and find whats wrong.
Exception in thread "LWJGL Application" java.lang.IllegalArgumentException: batch cannot be null.
//Great! So let's fix this.
at com.badlogic.gdx.scenes.scene2d.Stage.<init>(Stage.java:108)
//This is a LibGDX class so there is probably nothing wrong with this
at com.globapps.supermarioclon.Tools.Controles.<init>(Controles.java:30)
//This is your class so let's go to this specific line, you can double click it.
stage = new Stage(viewport, PantallaJuego.batch);
//So either viewport or batch is null in this line.
//You can put a breakpoint here and run a debug,
//your program will stop on this line and you can hover
//to see what is in the variables. You will see that batch
// is null. Why, you may ask.
In the constructor of your main class you first set new Controles()
controles = new Controles();
Now the constructor of Controles will run and comes to this line:
stage = new Stage(viewport, PantallaJuego.batch);
And since your code did not reach batch = new SpriteBatch(); in PantallaJuego batch is still null and since stage does not accept that it will throw a NullPointer. A quick fix is to turn around new SpriteBatch() and new Controles().
The reason I say you should start learning the basics first is because your code is very poorly formed. You should format your code in a neat way and use much smaller methods since right now certain methods and constructors do all kind of stuff and it is very hard to read. Apart from this you are picking up very bad habits like making a global from that SpriteBatch (public static). There is really no need for this and it is partly responsible for your failure here.
Have a look at What is a NullPointerException, and how do I fix it? although your error is not a NullPointerException it is very related. Stage() does a check of it's own for it to be null and throws another exception before it tries to access it and get a nullpointer then.
I started trying to create a TestGame. Currently having an NPE and after spending hours on google and trying everything I could think of I can't seem to understand what I'm overlooking or forgetting. I had everything in one class and all worked perfectly. Though I wanted to create a GUI where I could switch between a MainMenu and PlayScreen. My MainMenu class works fine, though when I hit my neat little "play" button to enter the PlayScreen class I get these errors:
Exception in thread "LWJGL Application" java.lang.NullPointerException
at com.me.game.PlayScreen.render(PlayScreen.java:90)
at com.badlogic.gdx.Game.render(Game.java:46)
at com.me.game.TestGame.render(TestGame.java:27)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:214)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:120)
Playscreen error:
batch.draw(player.getCurrentFrame(), player.getPosition().x , player.getPosition().y);
Game error:
if (screen != null) screen.render(Gdx.graphics.getDeltaTime());
TestGame error:
super.render();
TestMenu class (Game class)
public class TestGame extends Game {
Game game;
#Override
public void create() {
game = this;
setScreen(new MainMenu(game));
public void render() {
super.render();
}
MainMenu class
public class MainMenu implements Screen{
SpriteBatch batch;
Game game;
Stage stage;
public MainMenu(Game game){
this.game = game;
public void render(float delta) {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act();
batch.begin();
stage.draw();
batch.end();
}
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
game.setScreen(new PlayScreen(game));
stage.clear();
return true;
PlayScreen
public class PlayScreen implements Screen {
SpriteBatch batch;
Player player;
Game game;
Texture playerTexture;
public PlayScreen(Game game){
this.game = game;
}
public void render(float delta) {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.draw(player.getCurrentFrame(), player.getPosition().x , player.getPosition().y);
}
player.update();
batch.end();
}
public void show() {
batch = new SpriteBatch();
Player class
public class Player {
Texture playerTexture ;
Vector2 position;
String textureLoc;
public Player(Vector2 position, String textureLoc){
this.position = position;
movement = "";
playerTexture = new Texture(Gdx.files.internal("Character.png"));
public String getTextureLoc() {
return textureLoc;
}
public void setTextureLoc(String textureLoc) {
this.textureLoc = textureLoc;
}
The most helpful was Libgdx Screen NullPointerException when referencing another class where the problem also seems to be that I didn't initialize player in the PlayerScreen class at the show method. Though when I do fill player = new Player(position, textureLoc); in under the show method
public void show() {
batch = new SpriteBatch();
player = new Player(position, textureLoc);
I get other errors
at com.me.game.Player.<init>(Player.java:50)
at com.me.game.PlayScreen.show(PlayScreen.java:90)
at com.badlogic.gdx.Game.setScreen(Game.java:61)
at com.me.game.MainMenu$1.touchDown(MainMenu.java:90)
Which point to:
bounds = new Rectangle(position.x, position.y, currentFrame.getRegionWidth(), currentFrame.getRegionHeight());
player = new Player(position, textureLoc);
game.setScreen(new PlayScreen(game));
Though I assume it has something to do with the player not being initialized correctly? Anyhow for some reason I just can't seem to solve this. Any ideas would be greatly appreciated.
The problem is right here
player = new Player(position, textureLoc);
position and textureLoc are placeholders, these parameters you created are as follows
Vector2 position, String textureLoc
This means you need to create a new Vector2 and place it where position is and a String and place it where textureLoc is.
Try the following code instead, which will place your player approximately in the middle of the screen.
player = new Player(new Vector2(Gdx.graphics.getWidth()/2,Gdx.graphics.getHeight()/2), "I am not sure why you put this parameter here");