Libgdx: change ImageButton image on click - libgdx

In my game in Libgdx I want to change ImageButton image on click. I think this should be easy, but I have lost hours on this. :)
public void show() {
buttonSound = new ImageButton(skin.getDrawable("sound_off"));
buttonSound.addListener(new onSoundListener());
}
class onSoundListener extends 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) {
buttonSound.setBackground(skin.getDrawable("btn_sound"));
}
}
This doesn't work. Can someone help me with this?
Thanks

I found solution for my problem by setting checked image
ImageButton (Drawable imageUp, Drawable imageDown, Drawable imageChecked)
and then
if (gameData.isSound())
buttonSound.setChecked(false);
else
buttonSound.setChecked(true);

Related

How to display a text while hovering on image or texture in libgdx?

I am trying to implement a map of the universe. When mouse on a pic of the planet simply hovering on the picture, I want to see some information. How to handle this in libgdx?
In the following example, I am trying to give mouseClick sound while hovering, still does not work.
ImageButton imageButton = new ImageButton(drawable);
imageButton.setSize(100,100);
imageButton.setPosition(100,100);
imageButton.addListener(new FocusListener() {
#Override
public boolean handle(Event event) {
mouseClick.play();
return true;
}
});
Here how my override methods #enter and #exit looks`, I created HoverListener and override both methods.
#Override
public void enter(InputEvent event, float x, float y, int pointer, Actor fromActor) {
super.enter(event, x, y, pointer, fromActor);
fromActor.setName("Hello");
}
#Override
public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) {
super.exit(event, x, y, pointer, toActor);
toActor.setName("Bye");
}
Then btn_station.addListener(new HoverListener());
Still no interaction :/
Check the following:
You stage is the input processor: Gdx.input.setInputProcessor(stage)
Your Actor is on the stage: stage.addActor(actor)
The size of your actor is set: actor.setSize(100f, 100f)
You handle input events correctly (implement and override relevant interfaces)
As per your response to my comments, it sounds like in this case you did not set the stage as the input processor.

How to priorize eventhandling (LIBGDX)

I have a Screen:
WorldScreen implements Screen, InputProcessor{
....
stageGui.addActor(storyActor);
....
#Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
}
}
and I have an Actor :
public class StoryActor extends Group {
private InputListener listener = new InputListener() {
#Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
event.handle();
}
}
}
When Clicking on the actor, then first the touchup from the WorldScreen is handled. Then later the touchUp from the StoryActor is handled.
How can I achieve that first the actors will be handled ?
Instead of implementing InputProcessor in your WorldScreen. Create a new class for InputProcessor for example: WorldScreenInputProcessor implements InputProcessor
After that, you can use the InputMultiplexer to handle several InputProcessors:
InputMultiplexer multiplexer = new InputMultiplexer();
//What you add first has higher priority
multiplexer.addProcessor(stageGui); //Input of your Actor
multiplexer.addProcessor(new WorldScreenInputProcessor());
Gdx.input.setInputProcessor(multiplexer);
Take a look at https://github.com/libgdx/libgdx/wiki/Event-handling#inputmultiplexer on how to use input multiplexers it should solve your problem.

Using Actions on a Button-LibGdx

I have a play button like this;
private void drawPlayButton() {
playButton = new ImageButton(new TextureRegionDrawable(playTexture), new TextureRegionDrawable(pressTexture));
stage.addActor(playButton);
playButton.setPosition(UIConstants.PLAY_X, UIConstants.PLAY_Y, Align.center);
playButton.addListener(new ActorGestureListener() {
#Override
public void tap(InputEvent event, float x, float y, int count, int button) {
super.tap(event, x, y, count, button);
game.setScreen(new GameScreen(game));
}
});
}
I want to add scale in and out effect to this button using Actions.
I am not that familiar with Actions,I tried something like this;
float duationsec= 0.5f;
playButton.addAction(Actions.sequence(Actions.scaleBy(0.2f,0.2f,duationsec),
Actions.scaleTo(1f, 1f, duationsec)));
img.setOrigin(Align.center);
stage.addActor(playButton);
But this is not giving any effect to the button also same code works for an Image.Is this because button uses drawable texture?
How can I give this effect to a button using Actions?
Also my code is working for one time only.I am calling it in show().If I call it in render(),it works in an abnormal manner.I want this effect to be displaying forever.
Is it possible to achieve this?
Any help would be appreciated.
For performance reason most scene2d.ui groups have transform set to false by default and ImageButton is part of that ui group so you've to enable transform by using setTransform(..) method.
For more detail you can check
https://github.com/libgdx/libgdx/wiki/Scene2d.ui#rotation-and-scale
float duationsec= 0.5f;
playButton.setOrigin(Align.center);
playButton.setTransform(true); // <-- Enable Transform
stage.addActor(playButton);
playButton.addAction(Actions.sequence(Actions.scaleBy(0.2f,0.2f,duationsec),Actions.scaleTo(1f, 1f, duationsec)));
EDIT
If you want to scale up/down on user Click, Do in this way :
playButton.addListener(new ClickListener(){
#Override
public void clicked(InputEvent event, float x, float y) {
playButton.addAction(Actions.sequence(Actions.scaleBy(0.2f,0.2f,duationsec),Actions.scaleTo(1f, 1f, duationsec), Actions.run(new Runnable() {
#Override
public void run() {
game.setScreen(new GameScreen(game));
}
})));
super.clicked(event, x, y);
}
});

How to detect when drag input is end in libgdx

I don't know how to detect when the user drag event is end or not so I decide to do like this
protected class Input extends DragListener{
boolean dragging=false;
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
return true;
}
#Override
public void touchDragged(InputEvent event, float x, float y, int pointer) {
if(!dragging)dragging=true;
*my game logic*
.
.
.
}
#Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
Gdx.app.log("touch up","");
if (dragging) {
*my game logic*
.
.
.
}
}
}
I try my class by drag and touch up ,nothing happen.
I drag again and nothing happen. then I tap and the console is print "touchUp" two time.
Is there anything else to detect it
In the interface GestureListener that resides in GestureDetector there is a method pan and panStop. You should implement that interface, add all the methods from it and use pan for your dragging behaviour and panStop for the solution to your question. The methods register for both touch and mouse as well as multiple finger touches.

LibGdx Stage/Actor InputListener (Appropriate Area for InputListener)

I have a class Bubble that extends Actor.
public Bubble(MyGdxGame game,Texture texture){
this.game=game;
setPosition(0,0);
setSize(32,32);
gameObject=new GameObject("","bubble");
direction=new MovementDirection();
sprite=new Sprite(texture);
setTouchable(Touchable.enabled);
setWidth(sprite.getWidth());
setHeight(sprite.getHeight());
setBounds(0,0,sprite.getWidth(),sprite.getHeight());
addListener(new InputListener() {
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
Gdx.app.log("BUBBLE", "touchdown");
return true; // must return true for touchUp event to occur
}
public void touchUp (InputEvent event, float x, float y, int pointer, int button) {
Gdx.app.log("BUBBLE", "touchup");
}
});
}
This is in a class that implements Screen
public void show() {
// TODO Auto-generated method stub
super.show();
//2 bubbles test
gameStage=new Stage(MyGdxGame.WIDTH,MyGdxGame.HEIGHT,true);
Gdx.input.setInputProcessor(gameStage);
for (int i=0; i<10; i++){
Bubble b=new Bubble(game,Assets.bubbleTexture);
b.randomize();
gameStage.addActor(b);
}
//if (bubbleList==null)
// createBubbles();
}
Am I going about this the wrong way by adding the listener # the bubble level? (It seems creating an InputListener for every bubble I spawn is a little crazy).
According to : http://libgdx.l33tlabs.org/docs/api/com/badlogic/gdx/scenes/scene2d/Actor.html
Actor has a touchUp() and touchDown event - but complains when i try to override them (which lead me to believe they dont exist). Overriding these I feel would be a better approach
The docs you linked to are outdated.
Those methods were deprecated and removed in favor of using InputListeners.
In your example if you want to use the same InputListener instance for all instances of your Actor class (Bubble) then you can just implement the InputListener to refer to the Actor class instance using inputEvent.getRelatedActor() and then instantiate one such InputListener as a static member of Bubble and pass it in the constructor to addListener.
class Bubble extends Actor{
private static InputListener bubbleListener= new InputListener() {
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
Bubble b = (Bubble) event.getRelatedActor();
b.doSomething();
...
return true; //or false
}
}
public Bubble(){
addListener(bubbleListener);
...
}
...
}