Button not responding after a few clicks lib-gdx - java

I cant seem to find an answer to this. Why does my start button freeze after a certain amount of clicks(3)? It works for the first 3 clicks and then decides to stop working. I can still see that the screen is responding(the button becomes red when clicked), but the text on it doesn't change. It's like the click listener stopped responding.
public class MainMenu implements Screen{
private Game game;
private Stage stage;
private TextButton Start_btn;
private TextButton LocalWifi_btn;
private TextButton Internet_btn;
private TextButton Settings_btn;
private boolean Start_clicked = false;
private boolean LocalWifi_clicked = false;
private boolean Internet_clicked = false;
private boolean Settings_clicked = false;
public MainMenu(Game g){
game = g; //The Wasteland
stage = new Stage(new ExtendViewport(Gdx.graphics.getWidth(),
Gdx.graphics.getHeight())); //create a new stage with viewport to draw 2d stuff on
Gdx.input.setInputProcessor(stage); //all input set to stage
Skin skin = new Skin(Gdx.files.internal("gui/uiskin.json"), new TextureAtlas(Gdx.files.internal("gui/uiskin.atlas"))); //need this before you can make a gui
Start_btn = new TextButton("" + Start_clicked, skin);
Start_btn.setPosition(500, 500);
Start_btn.setSize(200, 200);
Start_btn.getLabel().setFontScale(10, 10); //change text size
Start_btn.addListener(new ClickListener(){
#Override
public void touchUp(InputEvent e, float x, float y, int point, int button){
onStartClicked();
}
});
stage.addActor(Start_btn);
}
private void onStartClicked(){
if(!Start_clicked){
Start_clicked = true;
Start_btn.setText("" + Start_clicked);
Gdx.app.log("Button", "" + Start_clicked);
}
else{
Start_clicked = false;
Start_btn.setText("" + Start_clicked);
Gdx.app.log("Button", "" + Start_clicked);
}
}
#Override
public void render(float delta) {
//this has to be before anything or else it will be drawn on top of everything else
Gdx.gl.glClearColor(0, 0, 0, 1); //set background color
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); //clears the screen
stage.act(delta); //send ammount of time since last render call, tells it to keep a steady fps
stage.draw();
}
#Override
public void resize(int width, int height) {
// use true here to center the camera
// that's what you probably want in case of a UI
stage.getViewport().update(width, height, true);
}
}
What am I doing wrong?!?!?!

Don't override touchUp() without calling super.touchUp(), because its messing up the functionality of ClickListener. But that's not what you want to override anyway. You should override clicked() so it only triggers if you release the click while still over the button. Or better yet, use a ChangeListener. Buttons already have a ClickListener built in that fires a change event when the button is clicked. Adding another ClickListener is redundant when you can just use a ChangeListener.

Related

how can I add Action to a texture packer in libgdx?

I'm trying to create eventListner on each image (playIcon,pauseIcon) but its not working using touchUp and touchDown
here is my code:
TextureAtlas buttonsPlayPause = new TextureAtlas("uiii/uiii.pack");
skin.addRegions(buttonsPlayPause);
TextButton.TextButtonStyle textButtonStyle = new TextButton.TextButtonStyle();
textButtonStyle.font = font;
textButtonStyle.up = skin.getDrawable("pauseIcon");
textButtonStyle.checked = skin.getDrawable("playIcon");
TextButton button = new TextButton("", textButtonStyle);
button.setY(pauseY);
button.setX(Gdx.graphics.getWidth()/6);
button.setSize(150,150);
stage.addActor(button);
//pause/playAction
button.addListener(new ClickListener() {
#Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {resume();
}
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
pause();
return true;
}
});
What happens now is that the button listener behaves as 'istouched()' rather than 'justtouched()'. When I click the button, the game is paused but whenever I remove my finger, there's no pause, the game runs.
If I understand correctly, you want this button to toggle between Play and Pause, calling either pause() or resume() based on current state.
The Button class already has a built-in internal InputListener, so all you need is a ChangeListener to react to button presses:
//pause/playAction
button.addListener(new ChangeListener() {
#Override
public void changed (ChangeEvent event, Actor actor) {
if (button.isChecked())
resume();
else
play();
}
});
Make sure you mark it final when you first declare it, so the listener can reference it:
//...
final TextButton button = new TextButton("", textButtonStyle);
//...

Setting the Cursor Position

So I have a game I am working on and once you finish playing I want to be able for the user to tap on the "Play Again" button and be able to reset at the start.
To do this I create a Rectangle over the Texture and use the contains() method.
if(cloud.contains((float)Gdx.input.getX(),(float)(Gdx.graphics.getHeight()-Gdx.input.getY()))){
reset();
}
Reset method:
public void reset(){
speed=0;
paraY = Gdx.graphics.getHeight() - para[parachuteState].getHeight();
gameState=0;
backY = 0-Gdx.graphics.getHeight();
bach=0;
Gdx.input.setCursorPosition(Gdx.graphics.getWidth()/2,Gdx.graphics.getHeight()/2);
}
So what is happening is the program recognizes the button being pressed and resets but when the game is over again it automatically resets without displaying the end screen. I think that the cursor is not being moved to the center and is instead remaining on top of the button. Am I incorrectly using the setCursorPosition() method or is there another way to do this?
The button would be just right. It might looks more complex, but it's recommended way to do what you want to do.
So, to create a button you should do something like this:
Skin skin = new Skin();
skin.addRegions(uiTextureAtlas);
TextButton.TextButtonStyle buttonStyle = new TextButton.TextButtonStyle();
buttonStyle.up = skin.getDrawable("textureName");
buttonStyle.font = font;
Button button = new Button(buttonStyle);
button.addListener(new InputListener() {
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
reset();
return true;
}
});
button.setSize(100, 100);
button.setPosition(300, 400);
then in your Screen class you create
Stage stage = new Stage();
stage.addActor(button);
Gdx.input.setInputProcessor(stage);

(LibGDX) Displaying a screenshot from previous FrameBuffer on a Stage

I'm trying to get a screenshot to display on the background of a pause menu.
My screenshot method uses ScreenUtils.getFrameBufferPixmap() to get the screenshot; I got it from here.
My code for the pause screen is as follows:
public class CEscapeScreen implements CScreen {
private final Stage stage;
private class BGActor extends Actor {
Pixmap pixmap = CUtil.getScreenshot(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), false);
Texture t = new Texture(pixmap);
#Override
public void draw(Batch batch, float alpha) {
batch.draw(t, 0, 0);
}
}
public CEscapeScreen(CGame g) {
Actor bgActor = new BGActor();
stage = new Stage();
final TextButton quitButton = new TextButton("Quit to Main Menu", CUi.getUISkin(), "default");
...
table.add(quitButton);
stage.addActor(bgActor);
stage.addActor(table);
}
#Override
public void display() {
stage.draw();
}
}
The display method is called every frame by the current Screen the program is on.
What I'm trying to accomplish is to get a screenshot of the screen before the pause screen stage is drawn, and then draw that screenshot behind the quitButton.
Every other Screen clears and makes a new Stage like this one.
The problem I'm having, is that only the quitButton appears on the Escape Menu. Why does this happen?

LibGDX - how do I make my text centered?

I'm new to LibGDX and I am taking it slowly. I'm still trying to understand most things which is why typically google searches don't help due to the fact that their too complicated. I have a main menu that has text that I want centered no matter what the screen size is. Here is the code that I have for that menu.
public class Menu implements Screen {
SlingshotSteve game;
OrthographicCamera camera;
public Menu(final SlingshotSteve gam) {
this.game = gam;
camera = new OrthographicCamera();
camera.setToOrtho(false, 800, 480);
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0.2f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
game.batch.setProjectionMatrix(camera.combined);
game.batch.begin();
game.font.draw(game.batch, "Welcome to Slingshot Steve!!! ", 100, 150);
game.font.draw(game.batch, "Tap anywhere to begin!", 100, 100);
game.batch.end();
if (Gdx.input.isTouched()) {
game.setScreen((Screen) new GameScreen(game));
dispose();
}
}
#Override
public void resize(int width, int height) {
}
#Override
public void show() {
}
#Override
public void hide() {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void dispose() {
}
}
I'm here to save you!
To get width / height from a String drawn with your BitmapFont you can utilize this super nice method:
game.font.getBounds(String string)
And to use it in your case, it would be something like this:
game.font.getBounds("Tap anywhere to begin!").width / 2;
Cheers!
It is possible to do it the way Nine Magics suggested, however one would usually do it via a Stage, which is part of scene2d.
More specifically one would use scene2d.ui which is a bunch of Actors like Button, Image, Label etc. You can attach a ClickListener to a Button for example and react on this event.
Furthermore, for layouting there is one very powerful Actor, namely Table which you can very easily use to center things on the screen.
Some very minimalistic code:
// do this once, in create() or show()
Skin skin = new Skin("uiskin.json"); // get the demo skin from the libgdx test resources
Stage stage = new Stage();
Table table = new Table(skin);
table.add("Welcome to Slingshot Steve!!!");
table.row();
table.add("Tap anywhere to begin!");
stage.addActor(table);
// do this in your render loop
stage.act();
stage.draw();
You can find the "default" skin resources here. You need to get all the uiskin.* files.

Stage draws over everything

public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0.2f, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
stage.act(delta);
batch.setProjectionMatrix(camera.combined);
batch.begin();
if (lifeCount > 0) {
/*
When stage.draw is called here, it only displays the exit button.
The game still operates, but everything is invisible.
If I leave the game on, the game over screen is shown,
*/
stage.draw();
text.setColor(1.0f, 1.0f, 1.0f, 1.0f);
text.draw(batch, score + scoreCount, 25, 100);
text.draw(batch, lives + lifeCount, 25, 120);
text.draw(batch, speed + raindropSpeed, 25, 80);
batch.draw(bucketTexture, bucket.x, bucket.y);
for (Rectangle clearDrop : clearDrops) {
batch.draw(clearDropTexture, clearDrop.x, clearDrop.y);
}
for (Rectangle healthDrop : healthDrops) {
batch.draw(healthDropTexture, healthDrop.x, healthDrop.y);
/*
If I place stage.draw here, health drops are invisible.
This also happens if I place it in the raindrop for-loop and the
cleardrop for-loop
*/
}
for (Rectangle raindrop : raindrops) {
batch.draw(raindropTexture, raindrop.x, raindrop.y);
}
/*
If I place stage.draw here, the bucket, score, life, and speed
display correctly. The drops are still invisible.
*/
} else {
pause();
raindrops.clear();
game.setScreen(new GameOver(game));
}
batch.end();
What I have been trying to do is have an exit button in the top right corner of the GameScreen, although drawing the stage which the button resides in gives me difficulties (see comments in code).
Here is my code for the exit button and stage (resize()):
if (stage == null)
stage = new Stage(width, height, true);
stage.clear();
Gdx.input.setInputProcessor(stage);
TextButtonStyle styleQuit = new TextButtonStyle();
styleQuit.up = skin.getDrawable("buttonnormal");
styleQuit.down = skin.getDrawable("buttonpressed");
styleQuit.font = text;
quitButton = new TextButton(" ", styleQuit);
quitButton.setWidth(128);
quitButton.setHeight(128);
quitButton.setX(800 - 128);
quitButton.setY(480 - 100);
quitButton.addListener(new InputListener() {
public boolean touchDown(InputEvent event, float x, float y,
int pointer, int button) {
return true;
}
public void touchUp(InputEvent event, float x, float y,
int pointer, int button) {
Gdx.app.log(RainCatcher.LOG, "Quit Button Pressed");
game.setScreen(new MainMenu(game));
}
});
stage.addActor(quitButton);
And the rest (in show())
atlas = new TextureAtlas("gamebuttons.pack");
skin = new Skin();
skin.addRegions(atlas);
text = new BitmapFont();
Is there any special trick to allow a stage to be rendered alongside with the falling raindrops, bucket, and text? My friends and I have been stumped and couldn't find a solution anywhere.
Move stage.draw() after batch.end() or before batch.begin()
This is not the right approach you're taking in my opinion. If you're using a stage in libgdx, then you should benefit from other components of Scene2d. So, rather than drawing your raindrops and other game entities separately (and making your job complicated), you should make them actors and add them to stage wherever you need and then draw the stage in the render.
For example:
public class RaindDrop extends Actor {
TextureRegion region;
public RaindDrop () {
region = new TextureRegion(...);
}
public void draw (SpriteBatch batch, float parentAlpha) {
Color color = getColor();
batch.setColor(color.r, color.g, color.b, color.a * parentAlpha);
batch.draw(...);
}
}
So on for other entities. Initialise and add them to your stage.
Here's the official wiki to read more:
https://code.google.com/p/libgdx/wiki/scene2d

Categories