I asked this question and implemented the accepted answer. One last piece of the puzzle remains, how to add event listener to the button?
I'm working with a teammate, I suggested to try Gdx.input.justTouched()
but he wonders if it's possible to add event listeners like you would do for normal buttons.
Answer
One way to achieve this could be to extend the existing Button
class and provide an implementation that sets the up
, down
, checked
and disabled
Drawable
s of the ButtonStyle
to whatever the last key-frame of the animation loaded is.
That way you'd get standard button behavior and the only thing that changes is the (somewhat weird) continuously updating style.
Such a Button
might look something like this; package com.bornander.sandbox;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.scenes.scene2d.ui.Button;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
public class AnimatedButton extends Button {
private float elapsed;
// Technically you'll need one of these for each state of the ButtonStyle, but I'll just cover up and down here.
private final Animation upAnimation;
private final Animation downAnimation;
private final ButtonStyle overrideStyle = new ButtonStyle();
private final TextureRegionDrawable upDrawable = new TextureRegionDrawable();
private final TextureRegionDrawable downDrawable = new TextureRegionDrawable();
public AnimatedButton(Animation upAnimation, Animation downAnimation) {
this.upAnimation = upAnimation;
this.downAnimation = downAnimation;
}
@Override
public void act(float delta) {
super.act(delta);
elapsed += delta;
upDrawable.setRegion(upAnimation.getKeyFrame(elapsed));
downDrawable.setRegion(downAnimation.getKeyFrame(elapsed));
overrideStyle.up = upDrawable;
overrideStyle.down = downDrawable;
setStyle(overrideStyle);
}
}
And it would be instantiated with a list of animations (possibly created using a GifDecoder
) for each state. Then it is possible to add listeners for clicked just like any other button owned by a Stage
;
package com.bornander.sandbox;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Button;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.utils.viewport.ScreenViewport;
import com.holidaystudios.tools.GifDecoder;
public class SandboxGame extends ApplicationAdapter {
Stage stage;
@Override
public void create () {
stage = new Stage(new ScreenViewport());
Animation upAnimation = GifDecoder.loadGIFAnimation(Animation.PlayMode.LOOP, Gdx.files.internal("throbber.gif").read());
Animation downAnimation = GifDecoder.loadGIFAnimation(Animation.PlayMode.LOOP, Gdx.files.internal("throbber.gif").read());
// Instanciate an AnimatedButton, providing animations for up and down states
Button button = new AnimatedButton(upAnimation, downAnimation);
button.setPosition(100, 100);
button.setSize(32, 32);
// Here the click listener is added by passing an anonymous type
button.addListener(new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
super.clicked(event, x, y);
//Add click handler here!
}
});
// Add the button to the Stage
stage.addActor(button);
// And set the processor of input to be that stage
Gdx.input.setInputProcessor(stage);
}
@Override
public void render () {
// Make sure to update the state of the stage
stage.act(Gdx.graphics.getDeltaTime());
Gdx.gl.glClearColor(1, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
// Draw the state of the stage
stage.draw();
}
@Override
public void dispose () {
}
}
No comments:
Post a Comment