Hi i'm kind of new to libGDX and I'm just creating a simple game app. I have a main menu screen and a level screen for my game. I have initialised the startup screen to the main menu. When i click the 'Play' button in the main menu screen, I want to switch the screen to the level select screen but what happens is that it does change the screen but the old one is rendering behind that as well. This is what is happening when i click the play button: http://prntscr.com/57teri
Game class:
public class BallJump extends Game {
MainMenu menu;
LevelSelect levelSelect;
#Override
public void create () {
menu = new MainMenu(this);
levelSelect = new LevelSelect(this);
setScreen(menu);
}
#Override
public void render () {
super.render();
}
#Override
public void resize(int width, int height) {
super.resize(width, height);
}
#Override
public void dispose() {
super.dispose();
}
}
Main menu screen:
public class MainMenu implements Screen{
BallJump game;
Stage stage;
GameButton playButton, exitButton;
Texture title;
Sprite test;
SpriteBatch batch;
OrthographicCamera camera;
public MainMenu(BallJump game) {
this.game = game;
}
#Override
public void render(float delta) {
Gdx.gl20.glClearColor(0, 0, 0, 1);
Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT);
System.out.println("main menu");
stage.act();
stage.draw();
batch.begin();
test.draw(batch);
batch.end();
}
#Override
public void show() {
camera = new OrthographicCamera();
title = new Texture(Gdx.files.internal("images/title.png"));
test = new Sprite(title);
batch = new SpriteBatch();
stage = new Stage();
test.setPosition(Gdx.graphics.getWidth()/7f, Gdx.graphics.getHeight()/1.75f);
playButton = new GameButton("PLAY");
playButton.setPosition(Gdx.graphics.getWidth()/2.5f, Gdx.graphics.getHeight()/2);
playButton.setHeight(50f);
playButton.setWidth(150f);
playButton.addListener(new InputListener() {
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
game.setScreen(game.levelSelect);
dispose();
return true;
}});
stage.addActor(playButton);
exitButton = new GameButton("EXIT");
exitButton.setPosition(Gdx.graphics.getWidth()/2.5f, Gdx.graphics.getHeight()/3);
exitButton.setHeight(50f);
exitButton.setWidth(150f);
exitButton.addListener(new InputListener() {
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
return true;
}});
stage.addActor(exitButton);
Gdx.input.setInputProcessor(stage);
}
#Override
public void hide() {
}
#Override
public void resize(int width, int height) {
camera.viewportWidth = width;
camera.viewportHeight = height;
camera.update();
}
#Override
public void dispose() {
batch.dispose();
stage.clear();
stage.dispose();
title.dispose();
}
Level select screen :
public class LevelSelect implements Screen{
BallJump game;
Stage stage;
TextButton l1, buttonExit;
Texture title;
Sprite test;
SpriteBatch batch;
OrthographicCamera camera;
public LevelSelect(BallJump game) {
this.game = game;
}
#Override
public void show() {
batch = new SpriteBatch();
stage = new Stage();
title = new Texture(Gdx.files.internal("images/level_select.png"));
test = new Sprite(title);
test.setPosition(Gdx.graphics.getWidth()/7f, Gdx.graphics.getHeight()/1.75f);
stage.addActor(l1);
}
#Override
public void render(float delta) {
stage.act();
stage.draw();
batch.begin();
test.draw(batch);
batch.end();
System.out.println("level select");
}
Your LevelSelect screen needs to clear the buffer before drawing. If you don't do it, the last rendered frame from the Menu will always be on the buffer.
#Override
public void render(float delta) {
Gdx.gl20.glClearColor(0, 0, 0, 1);
Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT);
...
}
Related
I'm trying to create an android game using libgdx with a Titlescreen, you just press start and your game startes. However I'm having difficulty trying to get these buttons to work. The title-screen works, but as soon as I press 'start game' the game crashes with the error:
Exception in thread "LWJGL Application" java.lang.NullPointerException
at com.dinab.onepiecev2.TitleScreen$1.clicked(TitleScreen.java:47) at
com.badlogic.gdx.scenes.scene2d.utils.ClickListener.touchUp(ClickListener.java:88)
at
com.badlogic.gdx.scenes.scene2d.InputListener.handle(InputListener.java:59)
at com.badlogic.gdx.scenes.scene2d.Stage.touchUp(Stage.java:351) at
com.badlogic.gdx.backends.lwjgl.LwjglInput.processEvents(LwjglInput.java:360)
at
com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:221)
at
com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:128)
I don't understand what I'm doing wrong and whether the problem is in my TitleScreen.java or in my GameScreen.java
These are my codes:
Main class
public class Onepiecev2 extends Game {
static public Skin gameSkin;
public void create () {
gameSkin = new Skin(Gdx.files.internal("skin/glassy-ui.json"));
this.setScreen(new TitleScreen(this));
}
public void render () {
super.render();
}
public void dispose () {
}
}
TitleScreen
public class TitleScreen implements Screen {
Stage stage;
Game game;
SpriteBatch batch;
Texture img;
TextureRegion mainBackground;
public TitleScreen(Game aGame){
batch = new SpriteBatch();
img = new Texture("start_screen.jpg");
mainBackground = new TextureRegion(img, 0, 0, 1920, 1080);
stage = new Stage(new ScreenViewport());
Gdx.input.setInputProcessor(stage);
Skin mySkin = new Skin(Gdx.files.internal("skin/glassy-ui.json"));
Button start_btn = new TextButton("START GAME", mySkin);
start_btn.setSize(Constantes.screenWidth/4, Constantes.screenHeight/12);
start_btn.setPosition(Constantes.col_width*3,Constantes.row_height/3);
start_btn.addListener( new ClickListener() {
#Override
public void clicked(InputEvent event, float x, float y) {
game.setScreen( new GameScreen(game) );
}
} );
stage.addActor(start_btn);
}
#Override
public void show() {
Gdx.input.setInputProcessor(stage);
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.draw(mainBackground, 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
batch.end();
stage.act();
stage.draw();
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() {
stage.dispose();
batch.dispose();
img.dispose();
}
}
GameScreen
public class GameScreen implements Screen {
Stage stage;
Game game;
SpriteBatch batch;
Texture img;
TextureRegion mainBackground;
public GameScreen(Game aGame){
batch = new SpriteBatch();
img = new Texture("start_screen.jpg");
mainBackground = new TextureRegion(img, 0, 0, 1920, 1080);
stage = new Stage(new ScreenViewport());
Gdx.input.setInputProcessor(stage);
Skin mySkin = new Skin(Gdx.files.internal("skin/glassy-ui.json"));
Button start_btn = new TextButton("GO BACK", mySkin);
start_btn.setSize(Constantes.screenWidth/4, Constantes.screenHeight/12);
start_btn.setPosition(Constantes.col_width*3,Constantes.row_height/3);
start_btn.addListener( new ClickListener() {
#Override
public void clicked(InputEvent event, float x, float y) {
game.setScreen( new TitleScreen(game));
}
} );
stage.addActor(start_btn);
}
#Override
public void show() {
Gdx.input.setInputProcessor(stage);
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.draw(mainBackground, 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
batch.end();
stage.act();
stage.draw();
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() {
stage.dispose();
batch.dispose();
img.dispose();
}
}
From the crash log, it looks like the problem is in your TitleScreen where you are adding a click listener. I am referring to the following line.
game.setScreen(new GameScreen(game));
Looks like the game object is not initialized before and hence you are getting a NullPointerException.
Trying to create a simple loading Screen. The below code prints the correct progress, so I know that part works. But the rectangle is not being drawn. Not sure what is wrong.
Full LoadingScreen:
public class LoadingScreen implements Screen {
private static final float PROGRESS_BAR_WIDTH = MyGdxGame.WIDTH / 2f;
private static final float PROGRESS_BAR_HEIGHT = 50f;
GdxAssetManager assetManager;
Stage stage;
//Table mainTable;
private ShapeRenderer shapeRenderer;
private MyGdxGame game;
public LoadingScreen(MyGdxGame game){
this.game = game;
assetManager = game.getAssetManager();
shapeRenderer = new ShapeRenderer();
stage = new Stage(new StretchViewport(MyGdxGame.WIDTH, MyGdxGame.HEIGHT));
}
#Override
public void show() {
assetManager.loadGeneral();
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
renderProgressBar();
if (assetManager.getManager().update()) {
game.setScreen(new LoginScreen(game));
}
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
}
private void renderProgressBar() {
float progress = assetManager.getManager().getProgress();
System.out.println(PROGRESS_BAR_WIDTH * progress);
shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
shapeRenderer.setColor(Color.RED);
shapeRenderer.rect(
(MyGdxGame.WIDTH - PROGRESS_BAR_WIDTH) / 2f,
(MyGdxGame.HEIGHT - PROGRESS_BAR_HEIGHT) / 2f,
PROGRESS_BAR_WIDTH * progress,
PROGRESS_BAR_HEIGHT
);
shapeRenderer.end();
}
#Override
public void resize(int width, int height) {
stage.getViewport().update(width, height);
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
dispose();
}
#Override
public void dispose() {
stage.dispose();
shapeRenderer.dispose();
}
}
I guess methods of interest are render and renderProgressBar. Like I said, all I get is a white background until the loading is finished, but the print inside renderProgressBar prints the correct values.
Set projectionMatrix of ShapeRenderer using stage camera.
shapeRenderer.setProjectionMatrix(stage.getCamera().combined);
I'm using libgdx 1.9.0 for game development.
I have one stage in main screen that includes multiple buttons.
I have another screen code that shows game objects.
when the back button in android device is pressed the stage in main screen gets disabled
and listener functions for buttons don't work.
In Main Screen I have :
public class MainMenuScreen extends ScreenAdapter {
TextButton button_start;
TextButtonStyle textButtonStyle;
BitmapFont font;
FitViewport viewp;
Stage stage;
public MainMenuScreen(IndependentArch game) {
this.game = game;
/* add GUI controls */
stage = new Stage(new StretchViewport(game.SCREEN_WIDTH,
game.SCREEN_Height), game.batcher);
Gdx.input.setInputProcessor(stage);
textButtonStyle = new TextButtonStyle();
textButtonStyle.font = Assets.font_btitr;
textButtonStyle.up = Assets.skin.getDrawable("button");
textButtonStyle.down = Assets.skin.getDrawable("button-down");
button_start = new TextButton(Reshape.doReshape_mirror("start"),
textButtonStyle);
button_start.setBounds(0, 0, 200, 50);
button_start.setPosition(140, 255);
button_about.addListener(new ChangeListener() {
#Override
public void changed(ChangeEvent event, Actor actor) {
MyTextInputListener listener = new MyTextInputListener();
Gdx.input.getTextInput(listener, "name", "",
"please enter your name.");
}
});
stage.addActor(button_start);
}
public void update() {
if (Gdx.input.justTouched()) {
stage.getCamera().unproject(
touchPoint.set(Gdx.input.getX(), Gdx.input.getY(), 0));
}
}
public void draw(float delta) {
Gdx.gl.glClearColor(0.09f, 0.28f, 0.2f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
game.batcher.disableBlending();
game.batcher.begin();
game.batcher.draw(Assets.backgroundRegion[0], 0, 0, game.SCREEN_WIDTH,
game.SCREEN_Height);
game.batcher.end();
stage.act(delta);
stage.draw();
game.batcher.enableBlending();
game.batcher.begin();
game.batcher.draw(Assets.uiskin.findRegion("music"),
game.SCREEN_WIDTH - 90, 10, 80, 80);
game.batcher.end();
}
#Override
public void render(float delta) {
update();
draw(delta);
}}
and in Game Screen I have :
public class GameScreen implements Screen, InputProcessor {
OrthographicCamera guiCam;
Vector3 touchPoint;
World world;
WorldRenderer renderer;
CameraController camController;
InputMultiplexer multiplexer;
GestureDetector gestureDetector;
/** for debug rendering **/
ShapeRenderer debugRenderer = new ShapeRenderer();
int lastScore;
String scoreString;
float totalGameTime;
GlyphLayout glyphLayout = new GlyphLayout();
public GameScreen(IndependentArch game) {
this.game = game;
Gdx.input.setCatchBackKey(true);
state = GAME_READY;
guiCam = new OrthographicCamera(game.SCREEN_WIDTH, game.SCREEN_Height);
guiCam.position.set(game.SCREEN_WIDTH / 2, game.SCREEN_Height / 2, 0);
touchPoint = new Vector3();
world = new World();
renderer = new WorldRenderer(game.batcher, world);
Gdx.input.setInputProcessor(this);
camController = new CameraController(world);
multiplexer = new InputMultiplexer();
multiplexer.addProcessor(new GestureDetector(20, 0.5f, 2, 0.15f,
camController));
multiplexer.addProcessor(this);
Gdx.input.setInputProcessor(multiplexer);
}
// * InputProcessor methods ***************************//
#Override
public boolean keyDown(int keycode) {
if (keycode == Keys.BACK) {
game.setScreen(new MainMenuScreen(game));
// Gdx.app.exit();
}
return false;
}}
Override the show() method in the main menu screen and set the input processor to stage there
#Override
public void show() {
Gdx.input.setInputProcessor(stage);
}
I'm trying to make a simple main menu with clickable play and exit labels, but clickable area is always above labels. To click "play" label I need to click about 20 pixels above it.
How can I align clickable area with labels?
There is my MainMenuButton class
public class MainMenuButtons {
private MainGame game;
private Stage stage;
private Viewport gameViewport;
private Label mainGameLabel, playLabel, exitLabel;
public MainMenuButtons(MainGame game) {
this.game = game;
gameViewport = new FillViewport(GameInfo.WIDTH, GameInfo.HEIGHT, new OrthographicCamera());
stage = new Stage(gameViewport, game.getBatch());
Gdx.input.setInputProcessor(stage);
createLabelsAndButtons();
addAllListeners();
Table menuTable = new Table();
menuTable.center().center();
menuTable.setFillParent(true);
menuTable.add(playLabel);
menuTable.row();
menuTable.add(exitLabel).padTop(40);
Table gameTitle = new Table();
gameTitle.center().top();
gameTitle.setFillParent(true);
gameTitle.add(mainGameLabel).padTop(40);
menuTable.debug();
stage.addActor(menuTable);
stage.addActor(gameTitle);
}
void createLabelsAndButtons() {
FreeTypeFontGenerator generator = new FreeTypeFontGenerator(Gdx.files.internal("Fonts/PressStart2P.ttf"));
FreeTypeFontGenerator.FreeTypeFontParameter parameter = new FreeTypeFontGenerator.FreeTypeFontParameter();
parameter.size = 45;
BitmapFont font = generator.generateFont(parameter);
mainGameLabel = new Label("Road Racer", new Label.LabelStyle(font, Color.WHITE));
parameter.size = 25;
font = generator.generateFont(parameter);
playLabel = new Label("Play", new Label.LabelStyle(font, Color.WHITE));
exitLabel = new Label("Exit", new Label.LabelStyle(font, Color.WHITE));
}
void addAllListeners() {
playLabel.addListener(new ClickListener(){
#Override
public void clicked(InputEvent event, float x, float y) {
super.clicked(event, x, y);
System.out.println("Play label clicked " + y);
// game.setScreen(new GamePlay(game));
}
});
exitLabel.addListener(new ClickListener(){
#Override
public void clicked(InputEvent event, float x, float y) {
super.clicked(event, x, y);
System.out.println("Exit label clicked " + y);
// Gdx.app.exit();
}
});
}
public Stage getStage() {
return this.stage;
}
}
And I call it in the MainMenu class
/**
* Created by vladk on 24/09/16.
*/
public class MainMenu implements Screen {
private MainGame game;
private OrthographicCamera mainCamera;
private Viewport gameViewport;
private MainMenuButtons btns;
public MainMenu(MainGame game) {
this.game = game;
mainCamera = new OrthographicCamera();
mainCamera.setToOrtho(false, GameInfo.WIDTH, GameInfo.HEIGHT);
mainCamera.position.set(GameInfo.WIDTH / 2f, GameInfo.HEIGHT / 2f, 0);
gameViewport = new StretchViewport(GameInfo.WIDTH, GameInfo.HEIGHT, mainCamera);
// background ??
// buttons
btns = new MainMenuButtons(game);
}
#Override
public void show() {
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
// game.getBatch().begin();
// game.getBatch().end();
game.getBatch().setProjectionMatrix(btns.getStage().getCamera().combined);
btns.getStage().draw();
btns.getStage().act();
}
#Override
public void resize(int width, int height) {
gameViewport.update(width, height);
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() {
// bg
// buttons
btns.getStage().dispose();
}
}
I found a solution. I needed to update view port for the MainMenuButtons, so I created a new method
// in the MainMenuButtons class
public void viewportUpdate(int width, int height) {
gameViewport.update(width, height);
}
and call if from the MainMenu class
#Override
public void resize(int width, int height) {
gameViewport.update(width, height);
btns.viewportUpdate(width, height);
}
I need to know how I can add a sprite from a texture atlas so I can implement it as a sprite for my main menu.
Here is my code for the main menu:
public class MainMenu implements Screen {
CrazyZombies game;
Stage stage;
TextureAtlas atlas;
Skin skin;
SpriteBatch batch;
TextureRegion firstLayer;
TextureRegion secondLayer;
TextureRegion thirdLayer;
TextureRegion fourthLayer;
TextureRegion fifthLayer;
TextureRegion sixthLayer;
TextureRegion seventhLayer;
TextureRegion eighthLayer;
TextureRegion ninthLayer;
TextureRegion tenthLayer;
TextureRegion eleventhLayer;
public MainMenu(CrazyZombies game){
this.game = game;
}
#Override
public void render(float delta) {
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
Gdx.gl.glClearColor(0.09f, 0.28f, 0.2f, 1);
batch.begin();
batch.end();
}
#Override
public void resize(int width, int height) {
Gdx.input.setInputProcessor(stage);
}
#Override
public void show() {
batch = new SpriteBatch();
skin = new Skin();
}
#Override
public void hide() {
dispose();
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void dispose() {
batch.dispose();
skin.dispose();
atlas.dispose();
stage.dispose();
}
public void loadLayers() {
TextureAtlas atlas = new TextureAtlas(Gdx.files.internal("data/mainmenu/MainMenu.pack"));
firstLayer = atlas.findRegion("1layer");
}
}
So I need to go about getting firstLayer onto the screen and every way I have tried ended with a crash.
You are not doing it right. Your render method doesn't have any draw. Take a look at the SuperJumper demo in libgdx.
To answer on how to create a sprite-
Sprite mySprite;
...
...
mySprite = new Sprite(someTextureRegion);
mySprite.setSize(SOME_WIDTH, SOME_HEIGHT);
mySprite.setOrigin(SOME_WIDTH/2f, SOME_HEIGHT/2f);
mySprite.setPosition(world.sprite.bounds.x, world.sprite.bounds.y);
...
...
mySprite.draw(batch);