I am making a LibGdx game. I have a main menu with a button that sends the user to the play screen. When at play screen though, the game reacts as it would when the user clicks in the spot that the button is located in from the previous screen. Here is the code that defines the button and switches screens:
button = new TextButton("Play", button_text);
button.setWidth(Gdx.graphics.getWidth() / 4);
button.setHeight(Gdx.graphics.getHeight() / 8);
button.setPosition((Gdx.graphics.getWidth() / 2) - (button.getWidth() / 2), (Gdx.graphics.getHeight() / 2) - (button.getHeight() / 2));
stage.addActor(button);
Gdx.input.setInputProcessor(stage);
button.addListener(new InputListener(){
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button){
game.setScreen(new PlayScreen(game));
dispose();
return true;
}
});
Here is the dispose method for this screen:
#Override
public void dispose() {
stage.dispose();
}
So how do I clear all input before moving from one screen to the next?
Add on the dispose method
Gdx.input.setInputProcessor(null);
and will be fixed
Upon further research I have discovered a solution to my problem.
To solve this problem, in the constructor of the new screen I set the input proccessor to a new instance of an implementation of the GestureListener interface.
private MyGestureListener myGestureListener;
public PlayScreen(Game game) {
this.game = game;
myGestureListener = new MyGestureListener();
Gdx.input.setInputProcessor(new GestureDetector(myGestureListener));
}
Giving each screen its own instance of a GestureListener will avoid the problem of input being carried on from one screen to the next.
Related
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.
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);
I am making a game where you have two buttons to rotate the player, one to left and the other one to right. I'm using a TextButton in LibGDX. My problem is that the method clicked(InputEvent event, float x, float y) in ClickListener is only called once it's clicked. I want an event to be called repeatedly as long as it's held down. Here is my code:
TextButton btnLeft = new TextButton("<", styleButton);
TextButton btnRight = new TextButton(">", styleButton);
btnLeft.setSize(100, 100);
btnRight.setSize(100, 100);
btnLeft.setPosition(25, 25);
btnRight.setPosition(200, 25);
btnLeft.addListener(new ClickListener() {
#Override
public void clicked(InputEvent event, float x, float y) {
player.rotate(-1);
System.out.println("Left");
}
});
btnRight.addListener(new ClickListener() {
Override
public void clicked(InputEvent event, float x, float y) {
player.rotate(1);
System.out.println("Right");
}
});
stage.addActor(btnLeft);
stage.addActor(btnRight);
The listener is not good place to perform continuous actions since it is by definition asynchronous mechanism. The place to perform some action like this is render() method of Screen or act() method of actor.
Although you can use listener to check a state of actor (is it pressed or not) in this way:
//Global instance
ClickListener listenerLeft;
//show() method
...
listenerLeft= new ClickListener();
btnLeft.addListener(listenerLeft);
...
//render() method
...
if(listenerLeft.isPressed())
//perform turning left
...
The second option is to implement ClickListener's touchUp and touchDown methods to change some flag and then check it in render but it would not be doing anything new.
Worth to notice is than both ClickListener and DragListener have touchDragged method that is something about what you want but works only if the mouse/finger is moving when touching actor
listener = new DragListener(){
#Override
public void touchDragged(InputEvent event, float x, float y, int pointer)
{
System.out.println("Left");
}
};
Keeping touching is not an action - no action = nothing to listen
I am new to libGDX. I am trying to create a custom button by extending com.badlogic.gdx.scenes.scene2d.ui.Button.
I want all the button related logic in this class. But I am not getting how to make the click work. I read many tutorials regarding adding Event Listeners but nothing is working.
public class RestartButton extends Button {
public RestartButton(ButtonStyle style) {
super(style);
}
#Override
public void draw(SpriteBatch batch, float parentAlpha) {
batch.draw(TextureProvider.getInstance().getRestart(), 175, 100);
}
}
And i am trying to add my button in the screen(i.e in show method) like this
RestartButton restartButton;
restartButton=new RestartButton(new ButtonStyle());
Stage stage;
stage.addActor(restartButton);
I am able to see my button on the screen. Now what i want to do is add some code which gets invoked when button is clicked or touched. Can someone please help ?
restartButton = new RestartButton(new ButtonStyle());
button.addListener(new ClickListener() {
#Override
public void clicked(InputEvent event, float x, float y) {
System.out.println("Restart clicked!");
}
});
stage.addActor(restartButton);
It does not work because you need to setBounds for your Button. If you wanted to draw the button in the position (175, 100) you could just create a Button directly from Button Class and call
button.setBounds(x, y, width, height);
Then adding the listener will work because now your button will actually have a position and an area in the stage. If you still need to extend the button class for your own reasons, you can set the bounds in the extended class ditectly or you can pass another argument in your RestartButton class. Similar to:
public RestartButton(ButtonStyle style, Vector2 position, Vector2 size) {
super(style);
this.setBounds(position.x, position.y, size.x, size.y);
}
Then the button will automatically be drawn to the position you want without the need of overriding draw method. add the listener by using this.addListener(yourListener);
Hope it helps.
I have a platform button the game screen, and I'm trying to make it so the user presses it once, clicks somewhere on the screen to draw one platform, and then if they clicked the screen again, nothing would happen.
Right now, before I click the platform button, nothing happens which is what I want. When I press the platform button, the user can click the screen to draw a platform, but, after pressing the platform button once, every time they click the screen, a platform gets drawn so I'm having trouble making it so they can only draw one. I thought using removeProcessor() would've worked, but it's not.
InputController inputProcessor;
InputMultiplexer multiplexer;
public GameScreen(FallDown game) {
this.game = game;
GAMESCREEN_STATE = WORLD_STATE_READY;
this.cam = new OrthographicCamera(FRUSTUM_WIDTH, FRUSTUM_HEIGHT);
this.cam.position.set(FRUSTUM_WIDTH / 2, FRUSTUM_HEIGHT / 2, 0);
this.cam.setToOrtho(false, FRUSTUM_WIDTH, FRUSTUM_HEIGHT);
batch = new SpriteBatch();
world = new World();
renderer = new WorldRenderer(batch, world);
cam.position.set(FRUSTUM_WIDTH / 2, 105, 0);
inputProcessor = new InputController(game, world, cam);
multiplexer = new InputMultiplexer();
}
Then, at the end of my render method I have
multiplexer.addProcessor(stage);
Gdx.input.setInputProcessor(multiplexer);
These are the listeners for my buttons and I'm just using the reset button as an alternate way to stop the user from drawing platforms.
reset_button.addListener(new InputListener() {
public boolean touchDown(InputEvent event, float x, float y,
int pointer, int button) {
multiplexer.removeProcessor(inputProcessor);
return true;
}
});
platform_button.addListener(new InputListener() {
public boolean touchDown(InputEvent event, float x, float y,
int pointer, int button) {
if (GAMESCREEN_STATE != WORLD_STATE_RUNNING) {
multiplexer.addProcessor(new InputController(game, world, cam));
}
return true;
}
});
Well, I would advice you not to add and remove processors that many times (especially the one in the render method.. move that to the constructor/create method).
An easy way to achieve what you are looking for is just have a boolean variable:
boolean createplatform = false;
And then set it to true when the button is pressed and to false when the first platform is created.
(So when you touch the screen, that boolean decides if a platform is created).