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);
}
Related
I have global variables called:
private int currentLevel;
private int mapHeight;
I have a constructor for my game, where currentLevel = level entered when setScreen() method is called:
public ElevatorLevel(Game g, int level)
{
super(g, level);
currentLevel = level;
}
In my create() method, I set mapHeight to 750 * currentLevel (which starts as one), however when I try to spawn in the blades as seen below, they spawn between -200 and 300. This is because the program is not recognizing currentLevel (I am assuming), so it is multiplying it by nothing, resulting with -200.
public void create()
{
world = new World(new Vector2(0, -9.8f), true);
timeElapsed = 0;
mapHeight = 750 * currentLevel;
blade = new PhysicsActor();
blade.storeAnimation( "", exTex );
blade.setOriginCenter();
blade.circularBoundary();
blade.setMaxSpeed(50);
blade.setDeceleration(50);
bladesList = new ArrayList<PhysicsActor>();
for (int i = 0; i < 3 ; i++)
{
blades = blade.clone();
float xCoord = randomFloatGenerator(440, 20);
float yCoord = randomFloatGenerator(mapHeight - 200, 300);
blades.setPosition(xCoord, yCoord);
mainStage.addActor(blades);
bladesList.add(blades);
}
I also have a Label in my update(float dt) method that is set to:
timeLabel.setText("Level: " + currentLevel);
As seen in the image above, currentLevel is recognized by the label, but not by mapHeight in create().
How do I get currentLevel to be recognized by the create() method?
Below is the standart portrait app code that i use almost in every libgdx project. I never use create method. Instead I use constructor, this code is the most bugfree one that i could have found.
GAME OR MENU SCREEN:
public class TutorialScreen implements Screen {
private OrthographicCamera camera;
public static final float WORLD_HEIGHT = 240;
public static final float WORLD_WIDTH = 135;
private Viewport viewport;
private Stage stage;
private EntryPoint game;
private AdsController adsController;
public TutorialScreen(final EntryPoint game, final AdsController adsController){
this.adsController = adsController;
this.game = game;
adsController.hideBannerAd();
float aspectRatio = (float) (Gdx.graphics.getHeight() / Gdx.graphics.getWidth());
camera = new OrthographicCamera(aspectRatio * WORLD_WIDTH, WORLD_HEIGHT);
camera.setToOrtho(false);
viewport = new FitViewport(WORLD_WIDTH , WORLD_HEIGHT,camera );
stage = new Stage(viewport, game.batch);
}
#Override
public void show() {
}
#Override
public void render(float delta) {
stage.draw();
stage.act();
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() {
}
}
ENTRY POINT THAT YOUR APP WILL OPEN FIRST:
package some.package;
public class EntryPoint extends Game {
SpriteBatch batch;
final AdsController adsController;
public EntryPoint(final AdsController adsController ){
this.adsController = adsController; //Interface for admob
}
#Override
public void create () {
batch = new SpriteBatch();
this.setScreen(new YourScreenClass(this,adsController)); //Above is tutorial so this would be new TutorialScreen(this,adsController)
}
#Override
public void render () {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.end();
super.render();
}
#Override
public void dispose () {
batch.dispose();
}
}
Might have missed some curly brackets or ";" but you get the idea. This way you would not encounter any reference issues.
When I run the android version of my app, the text that is drawn using Bitmap is displayed in a (way) different position in my desktop version than in my android version of the app. I have already looked this issue up and read that I had to set the Projectmatrix to combined, but this hasn't helped. No clue what could be the reason that it displays the texts in different positions crossplatform-wise.
public class HighScoresScreen implements Screen{
private CrossplatformApp game;
private Stage stage;
private TextButton backButton;
private OrthographicCamera camera;
private Table table;
BitmapFont font = new BitmapFont();
private Skin skin;
private Texture background;
private String[] data;
private String[] playerscores;
String nm = "";
String sc = "";
public HighScoresScreen (CrossplatformApp game) {
this.game = game;
this.camera = new OrthographicCamera(Constants.WIDTH, Constants.HEIGHT);
this.camera.position.set(Constants.WIDTH/2, Constants.HEIGHT/2, 0);
this.camera.update();
game.batch.setProjectionMatrix(this.camera.combined);
this.skin = new Skin(Gdx.files.internal("skin/uiskin.json"));
this.background = new Texture("Screens/HighscoresScreen/highscores.png");
}
#Override
public void show() {
backButton = new TextButton("back", skin);
backButton.addListener(new ClickListener(){
#Override
public void clicked(InputEvent event, float x, float y) {
game.setScreen(new MenuScreen(game));
MenuScreen.musicHandler.stopMusic();
}
});
Gdx.input.setInputProcessor(stage);
JSONfunctions json = new JSONfunctions();
parseJSON parse = new parseJSON(json.doInBackground());
for (String i : parse.getNames()){
if(i != null) {
nm += i;
nm += "\n\n";
} else {
break;
}
}
System.out.println(nm);
//
for (String i : parse.getScores()){
if(i != null) {
sc += i;
sc += "\n\n";
} else {
break;
}
}
table = new Table();
table.setFillParent(true);
table.bottom();
table.add(backButton).size(100, 100);
stage.addActor(table);
}
#Override
public void render(float delta) {
game.batch.begin();
game.batch.draw(background, 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
font.draw(game.batch, nm, 100, 300);
font.draw(game.batch, sc, 480, 300);
game.batch.end();
}
#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();
}
}
You need to update viewport of camera and then update projectionmatrix of SpriteBatch with updated viewport.
#Override
public void resize(int width, int height) {
camera.setToOrtho(false, width, height);
game.batch.setProjectionMatrix(camera.combined);
}
Also you need to update Stage's viewport with screen with and height.
You should use Label for nm and sc text.
It's better to use ExtendViewprot instead of FillViewport, take a look of this answer.
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);
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);
...
}
I have created multiple Screens for my Libgdx game.
Whenever I exit the game (Desktop Version), I am getting a red sentence in eclipse console, showing Deleting Buffers(1).
The number is changing according to the Screen, which is active when I quit the game.
What is this "Deleting Buffers"?
Do I have to worry about that?
Also the android version of my game crashes at the second Screen, while the desktop version is running perfectly.
Thanks in advance.
Screen1
public class Splash implements Screen {
private SpriteBatch batch;
private Sprite titleSprite;
private Input input;
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL30.GL_COLOR_BUFFER_BIT);
batch.begin();
titleSprite.draw(batch);
batch.end();
Gdx.input.setInputProcessor(input);
}
#Override
public void show() {
batch = new SpriteBatch();
titleSprite = new Sprite(new Texture("img/Title.jpg"));
titleSprite.setSize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
titleSprite.setOrigin(titleSprite.getWidth() / 2f,
titleSprite.getHeight() / 2f);
titleSprite.setPosition(
Gdx.graphics.getWidth() / 2f - titleSprite.getWidth() / 2f,
Gdx.graphics.getHeight() / 2f - titleSprite.getHeight() / 2f);
input = new Input() {
public boolean keyDown(int keycode) {
if (keycode == Keys.ENTER) {
((Game) Gdx.app.getApplicationListener())
.setScreen(new MainMenu());
Gdx.audio.newMusic(Gdx.files.internal("sounds/button.mp3"))
.play();
dispose();
}
if (keycode == Keys.ESCAPE) {
Gdx.app.exit();
}
return false;
}
#Override
public boolean touchDown(int screenX, int screenY, int pointer,
int button) {
((Game) Gdx.app.getApplicationListener())
.setScreen(new MainMenu());
dispose();
return super.touchDown(screenX, screenY, pointer, button);
}
};
}
#Override
public void dispose() {
batch.dispose();
titleSprite.getTexture().dispose();
}
}
Screen2
public class MainMenu implements Screen {
private Stage stage;
private Table table;
private TextButton playButton, exitButton;
private Skin skin;
private BitmapFont white, black;
private TextureAtlas atlas;
private TextButtonStyle textButtonStyle;
private SpriteBatch batch;
private Sprite sprite;
#Override
public void render(float delta) {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL30.GL_COLOR_BUFFER_BIT);
batch.begin();
sprite.draw(batch);
batch.end();
stage.act(delta);
stage.draw();
Gdx.input.setInputProcessor(stage);
if (Gdx.input.isKeyPressed(Keys.ESCAPE)) {
Gdx.app.exit();
}
}
#Override
public void show() {
batch = new SpriteBatch();
sprite = new Sprite(new Texture("img/Title.jpg"));
sprite.setOrigin(sprite.getWidth() / 2f, sprite.getHeight() / 2f);
sprite.setSize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
sprite.setPosition(Gdx.graphics.getWidth() / 2f - sprite.getWidth()
/ 2f, Gdx.graphics.getHeight() / 2f - sprite.getHeight() / 2f);
sprite.setRotation(0);
white = new BitmapFont(Gdx.files.internal("fonts/White.fnt"), false);
black = new BitmapFont(Gdx.files.internal("fonts/Black.fnt"), false);
black.setScale(Gdx.graphics.getWidth() / 1440f,
Gdx.graphics.getHeight() / 900f);
stage = new Stage();
atlas = new TextureAtlas("ui/Button.pack");
skin = new Skin(atlas);
table = new Table(skin);
table.setBounds(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
textButtonStyle = new TextButtonStyle();
textButtonStyle.up = skin.getDrawable("ButtonUp9");
textButtonStyle.down = skin.getDrawable("ButtonDown9");
textButtonStyle.pressedOffsetX = 1;
textButtonStyle.pressedOffsetY = -1;
textButtonStyle.font = black;
exitButton = new TextButton("Exit", textButtonStyle);
exitButton.pad(10);
playButton = new TextButton("Play", textButtonStyle);
playButton.pad(10);
playButton.addListener(new ClickListener() {
#Override
public void clicked(InputEvent event, float x, float y) {
((Game) Gdx.app.getApplicationListener())
.setScreen(new Scenarios());
Gdx.audio.newSound(Gdx.files.internal("sounds/button.mp3"))
.play(1);
Gdx.input.vibrate(50);
dispose();
}
});
exitButton.addListener(new ClickListener() {
#Override
public void clicked(InputEvent event, float x, float y) {
Gdx.app.exit();
dispose();
}
});
table.add(playButton);
table.row();
table.add(exitButton);
table.getCell(exitButton).spaceTop(50f);
stage.addActor(table);
}
#Override
public void dispose() {
stage.dispose();
black.dispose();
white.dispose();
skin.dispose();
batch.dispose();
sprite.getTexture().dispose();
}
}
Screen3
public class Scenarios implements Screen {
private TextButtonStyle buttonStyle;
private TextButton[] scene;
private BitmapFont black;
private Stage stage;
private Table table;
private TextureAtlas atlas;
private Skin skin;
#Override
public void render(float delta) {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL30.GL_COLOR_BUFFER_BIT);
stage.act(delta);
stage.draw();
Gdx.input.setInputProcessor(stage);
if (Gdx.input.isKeyPressed(Keys.BACKSPACE)) {
((Game) Gdx.app.getApplicationListener()).setScreen(new MainMenu());
} else if (Gdx.input.isKeyPressed(Keys.ESCAPE)) {
Gdx.app.exit();
}
}
#Override
public void show() {
atlas = new TextureAtlas("ui/Button.pack");
skin = new Skin(atlas);
stage = new Stage();
table = new Table(skin);
black = new BitmapFont(Gdx.files.internal("fonts/Black.fnt"), false);
black.setScale(Gdx.graphics.getWidth() / 1280f,
Gdx.graphics.getHeight() / 720f);
table.setBounds(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
buttonStyle = new TextButtonStyle();
buttonStyle.up = skin.getDrawable("ButtonUp9");
buttonStyle.down = skin.getDrawable("ButtonDown9");
buttonStyle.pressedOffsetX = 1;
buttonStyle.pressedOffsetY = -1;
buttonStyle.font = black;
scene = new TextButton[3];
scene[0] = new TextButton("Scenario 1", buttonStyle);
scene[1] = new TextButton("Scenario 2", buttonStyle);
scene[2] = new TextButton("Scenario 3", buttonStyle);
scene[0].addListener(new ClickListener() {
#Override
public void clicked(InputEvent event, float x, float y) {
((Game) Gdx.app.getApplicationListener())
.setScreen(new Intro1());
Gdx.audio.newSound(Gdx.files.internal("sounds/button.mp3"))
.play(1);
Gdx.input.vibrate(50);
dispose();
}
});
scene[1].addListener(new ClickListener() {
#Override
public void clicked(InputEvent event, float x, float y) {
((Game) Gdx.app.getApplicationListener())
.setScreen(new Intro2());
Gdx.audio.newSound(Gdx.files.internal("sounds/button.mp3"))
.play(1);
Gdx.input.vibrate(50);
dispose();
}
});
scene[2].addListener(new ClickListener() {
#Override
public void clicked(InputEvent event, float x, float y) {
((Game) Gdx.app.getApplicationListener())
.setScreen(new Intro3());
Gdx.audio.newSound(Gdx.files.internal("sounds/button.mp3"))
.play(1);
Gdx.input.vibrate(50);
dispose();
}
});
scene[0].pad(10);
scene[1].pad(10f);
scene[2].pad(10f);
table.add(scene[0]);
table.add(scene[1]);
table.getCell(scene[1]).space(20f);
table.add(scene[2]);
stage.addActor(table);
}
#Override
public void dispose() {
stage.dispose();
skin.dispose();
atlas.dispose();
black.dispose();
}
}
You forgot to dispose sound/music objects. You may do it in dispose method of your Game class.