I am slowly learning java/LIBGDX, I have got the following method to change an image from black/white when clicked on, then I call on the touchGem method within render.
What I am having trouble wrapping my head around is putting a condition around calling this method within render to stop it rendering once the new black or white gem is created (as you can undoubtedly tell at the moment once clicked it renders the image over and over.)
public void touchGem() {
Gdx.input.setInputProcessor(stage);
if (touchGemStatus1 < 1) {
touchGem1 = new Image(touchGemTextureWhite);
touchGem1.setColor(1, 1, 1, 1);
touchGem1.setSize(95, 95);
touchGem1.setPosition(5, 0);
touchGem1.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) {
if (touchGemStatus1 < 1) {
touchGemStatus1 = touchGemStatus1 + 1;
} else {
touchGemStatus1 = touchGemStatus1 - 1;
}
}
});
} else {
touchGem1 = new Image(touchGemTextureBlack);
touchGem1.setColor(1, 1, 1, 1);
touchGem1.setSize(95, 95);
touchGem1.setPosition(5, 0);
touchGem1.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) {
if (touchGemStatus1 < 1) {
touchGemStatus1 = touchGemStatus1 + 1;
} else {
touchGemStatus1 = touchGemStatus1 - 1;
}
}
});
}
}
if render() method calls only touchGem(), it doesn't render anything at all. To draw touchGem1, your render() method should look as following:
#Override
public void render(float deltaTime) {
deltaTime = Gdx.graphics.getDeltaTime();
touchGem();
batch.begin();
stage.addActor(touchGem1);
batch.end();
stage.act(deltaTime);
stage.draw();
}
Related
foreword: on desktop everything works just perfect.
Trouble appers when i'm testing my project on phone
I start the game. Here is some buttons on screen: button_1, button_2, button_3. For example i'm touching button_1: with very first touch after app start nothing happing at all. If i'm touching button_1 again, it works fine -> touchDown (button image goes down for 10px) then touchUp (button image goes up for 10px and button code run). But if i touch another button instead, for example button_2, only touchDown of button_1 occurs (button_1 image goes down for 10px and up) and nothing else. It's happens for every button, so i need to touch button twice to make it work.
Button class:
public class myButton {
private float x, y, width, height;
private Texture buttonUp;
public Rectangle bounds;
private boolean isPressed = false;
public myButton(float x, float y, float width, float height, Texture buttonUp) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.buttonUp = buttonUp;
bounds = new Rectangle(x, y, width, height);
}
public boolean isClicked(int screenX, int screenY) {
return bounds.contains(screenX, screenY);
}
public void draw(SpriteBatch batch) {
if (isPressed) {
batch.draw(buttonUp, x, y - 10, width, height);
} else {
batch.draw(buttonUp, x, y, width, height);
}
}
public boolean isTouchDown(int screenX, int screenY) {
if (bounds.contains(screenX, screenY)) {
isPressed = true;
return true;
}
return false;
}
public boolean isTouchUp(int screenX, int screenY) {
if (bounds.contains(screenX, screenY) && isPressed) {
isPressed = false;
return true;
}
isPressed = false;
return false;
}
}
InputHandlerer:
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
screenX = (int) touchPos.x;
screenY = (int) touchPos.y;
playButton.isTouchDown(screenX, screenY);
return true;
}
#Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
screenX = (int) touchPos.x;
screenY = (int) touchPos.y;
if (playButton.isTouchUp(screenX, screenY)) {
start();
return true;
}
}
in create() method i've got:
touchPos = new Vector3();
Gdx.input.setInputProcessor(new InputHandlerer());
camera = new OrthographicCamera();
viewport = new FitViewport(1080, 1920, camera);
in render() method i've got:
touchPos.set(Gdx.input.getX(), Gdx.input.getY(), 0);
camera.unproject(touchPos);
batch.setProjectionMatrix(camera.combined);
I repeat - on desktop every button works properly, but on phone not. What could be the problem?
Maybe on desktop is working because you can do only one click at a time, instead on phone you should manage the pointers, also if you don't want to use the multitouch.
On your InputHandlerer class you have to initilize:
private int button1pointer = -1;
private boolean button1isPressed = false;
Then you have to manage the pointers on your tochDown/Up methods:
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
for (int i = 0; i < 2; i++) { //here you can choose how many touches you can manage
if (Gdx.input.isTouched(i)) {
screenX = (int) touchPos.x;
screenY = (int) touchPos.y;
if (playButton.isTouchDown(screenX, screenY) && (button1pointer != i) && (!button1isPressed)) {
button1pointer = i;
button1isPressed = true;
}
return true;
}
}
#Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
if (!(Gdx.input.isTouched(pointer)) && (button1pointer == pointer) && (button1isPressed)) {
button1pointer = -1;
button1isPressed = false;
start();
return true;
}
}
I'm building a GUI for my game with LibGDX.scene2d.ui and I have a problem when I'm trying to handle inputs. I have the following code to make something happen when button is pressed but it doesn't work:
enterButton.addListener(new InputListener() {
#Override
public boolean touchDown(InputEvent e, float x, float y, int p, int b) {
Gdx.app.log("touched", "down");
return true;
}
#Override
public void touchUp(InputEvent e, float x, float y, int p, int b) {
Gdx.app.log("touched", "up");
if(x > enterButton.getX() && x < enterButton.getRight() && y > enterButton.getY() && y < enterButton.getTop()) {
Gdx.app.log("cond", "cursor on actor");
if(validate(loginField.getText(), passField.getText())) {
Gdx.app.log("cond", "validated");
openMenu();
}
}
Gdx.app.log("untouched", "up");
}
});
But practically same code work correctly:
registerButton.addListener(new InputListener() {
#Override
public boolean touchDown(InputEvent e, float x, float y, int p, int b) {
return true;
}
#Override
public void touchUp(InputEvent e, float x, float y, int p, int b) {
if(x > registerButton.getX() && x < registerButton.getRight() && y > registerButton.getY() && y < registerButton.getTop()) {
registerWindow.setVisible(true);
baseWindow.setVisible(false);
}
}
});
After single click on the enterButton I'm getting this output made with LibGDX logging:
touched: down
touched: up
untouched: up
What can be wrong?
You can try using a ClickListener to check if the touch is within bounds or not, like so:
enterButton.addListener(new ClickListener() {
#Override
public void touchDown(InputEvent event, float x, float y, int pointer, int button) {
return true;
}
#Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
if (isOver()) {
if(validate(loginField.getText(), passField.getText())) {
openMenu();
}
}
}
});
You can also try setting the debug flag on the Actor so that you can see where the click bounds actually are by using enterButton.debug();
I defined a mainmenu class where I am Trying to show some images inside a table and make them respond for touches but when I define the call the class (just call it) inside the constructor of the main screen, the controls don't respond although I defined the mainmenu class in the same way of defining the controls class.
(notice when I use mainmenu object inside the main screen it renders the images and the controls but they don't respond for any click).
the main problem is happened when I call the mainmenu, the game is running but controls don't respond for touch. here is the code of the two classes:
public class Controller {
public Viewport viewport;
public Stage stage;
public boolean upPressed;
public boolean leftPressed;
public boolean rightPressed;
public boolean pausePressed;
public static boolean visiblity;
public Image buttonUp;
public Image buttonDown;
public Image buttonLeft;
public Image buttonRight;
public Image buttonpause;
public OrthographicCamera camera;
public Table table;
public Table table1;
public Table table2;
//Constructor.
public Controller(SpriteBatch spriteBatch) {
camera = new OrthographicCamera();
viewport = new FitViewport(Fruits.V_WIDTH, Fruits.V_HIEGT, camera);
stage = new Stage(viewport, spriteBatch);
Gdx.input.setInputProcessor(stage);
visiblity=false;
//Buttons with images.
buttonUp = new Image(new Texture("Pause.png"));
buttonUp.setSize(30, 30);
buttonUp.addListener(new InputListener() {
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
upPressed = true;
return true;
}
#Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
upPressed = false;
}
});
buttonLeft = new Image(new Texture("buttonleft.png"));
buttonLeft.setSize(65, 65);
buttonLeft.addListener(new InputListener() {
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
leftPressed = true;
return true;
}
#Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
leftPressed = false;
}
});
buttonRight = new Image(new Texture("buttonright.png"));
buttonRight.setSize(65, 65);
buttonRight.addListener(new InputListener() {
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
rightPressed = true;
return true;
}
#Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
rightPressed = false;
}
});
buttonpause = new Image(new Texture("pausing.png"));
buttonpause.setSize(30, 30);
buttonpause.addListener(new InputListener() {
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
pausePressed = true;
return true;
}
#Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
pausePressed = false;
}
});
//Table with buttons.
table = new Table();
table.left().bottom(); //Align to the left bottom.
table.add(buttonLeft).size(buttonLeft.getWidth(), buttonLeft.getHeight()).spaceRight((viewport.getWorldWidth() / 10) * 6.5f);
// table.add(buttonUp).size(buttonUp.getWidth(), buttonUp.getHeight()).spaceRight((viewport.getWorldWidth() / 10) * 6.5f);
table.add(buttonRight).size(buttonRight.getWidth(), buttonRight.getHeight());
stage.addActor(table);
table1=new Table();
table1.right().top();
table1.setFillParent(true);
//table1.add();
table1.row().pad(25, 3, 0, 10);
table1.add(buttonUp).size(buttonUp.getWidth(), buttonUp.getHeight()).spaceRight((viewport.getWorldWidth() / 10) * 6.5f);
stage.addActor(table1);
table2=new Table();
table2.center();
table2.setFillParent(true);
//table1.add();
table2.row().pad(25, 3, 0, 10);
table2.add(buttonpause).size(buttonpause.getWidth(), buttonpause.getHeight()).spaceRight((viewport.getWorldWidth() / 10) * 6.5f);
stage.addActor(table2);
}
public void draw() {
stage.draw();
}
public void resize(int width, int height) {
viewport.update(width, height);
}
public boolean isUpPressed() {
return upPressed;
}
public boolean isLeftPressed() {
return leftPressed;
}
public boolean isRightPressed() {
return rightPressed;
}
public boolean isPausePressed() {
return pausePressed;
}
}
code of mainmenu
public class MainMenu{
/* public Viewport viewport;
public Stage stage;
public boolean pausePressed;
public boolean resumePressed;
public boolean exitPressed;
public Image buttonpause;
public Image buttonDown;
public Image buttonresume;
public Image buttonexit;
public OrthographicCamera camera;
public Table table;
public Table table2;
//Constructor.
public MainMenu(SpriteBatch spriteBatch) {
camera = new OrthographicCamera();
viewport = new FitViewport(Fruits.V_WIDTH, Fruits.V_HIEGT, camera);
stage = new Stage(viewport, spriteBatch);
Gdx.input.setInputProcessor(stage);
//Buttons with images.
buttonpause = new Image(new Texture("pausing.png"));
buttonpause.setSize(30, 30);
buttonpause.addListener(new InputListener() {
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
pausePressed = true;
return true;
}
#Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
pausePressed = false;
}
});
buttonresume = new Image(new Texture("resume.png"));
buttonresume.setSize(65, 65);
buttonresume.addListener(new InputListener() {
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
resumePressed = true;
return true;
}
#Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
resumePressed = false;
}
});
buttonexit = new Image(new Texture("exit.png"));
buttonexit.setSize(65, 65);
buttonexit.addListener(new InputListener() {
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
exitPressed = true;
return true;
}
#Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
exitPressed = false;
}
});
//Table with buttons.
table2=new Table();
table2.center();
table2.setFillParent(true);
//table2.add();
table2.row().pad(25, 3, 0, 10);
table2.add(buttonpause).size(buttonpause.getWidth(), buttonpause.getHeight()).spaceRight((viewport.getWorldWidth() / 10) * 6.5f);
table2.row().pad(25, 3, 0, 10);
table2.add(buttonresume).size(buttonresume.getWidth(), buttonresume.getHeight());
table2.row().pad(25, 3, 0, 10);
table2.add(buttonexit).size(buttonexit.getWidth(), buttonexit.getHeight()).spaceRight((viewport.getWorldWidth() / 10) * 6.5f);
stage.addActor(table2);
}
public void draw() {
stage.draw();
}
public void resize(int width, int height) {
viewport.update(width, height);
}
public boolean isPausePressed() {
return pausePressed;
}
public boolean isResumePressed() {
return resumePressed;
}
public boolean isExitPressed() {
return exitPressed;
}
*/
}
There can only be one input processor set at a time, so only your most recent call to Gdx.input.setInputProcessor has any effect. So move that call to the show() method of your screens (if you're implementing Screen, otherwise do whatever the equivalent is in your structure).
You can also use an InputMultiplexer to combine multiple input processors into one if you want them to be able to work at the same time.
I have a float value that is set from 0 to 100, and I want to register a long click and update a Label progressivly, so that like every 0.25seconds the label's text will be updated. For now I am using a custom made Label that has a method to update the text displayed.
I tried using touchDown like this:
while (Gdx.input.isButtonPressed(Buttons.LEFT)) {
double currentValue = Double.parseDouble(Button.getText()
.toString());
if ((int) currentValue != 0)
currentValue--;
Button.updateText(Double.toString(currentValue));
}
but that doesn't seem to work, how do I update a label while a button is clicked?
Edit: Most of the code for the ClickListener:
#Override
public void enter(InputEvent event, float x, float y, int pointer,
Actor fromActor) {
super.enter(event, x, y, pointer, fromActor);
TextButtonStyle style = ButtonLower.getStyle();
style.font = red;
ButtonLower.setStyle(style);
}
#Override
public void exit(InputEvent event, float x, float y, int pointer,
Actor toActor) {
super.exit(event, x, y, pointer, toActor);
TextButtonStyle style = ButtonLower.getStyle();
style.font = white;
ButtonLower.setStyle(style);
}
#Override
public void clicked(InputEvent event, float x, float y) {
super.clicked(event, x, y);
System.out.println(event.toString());
double currentValue = Double.parseDouble(Button.getText()
.toString());
if ((int) currentValue != 0)
currentValue--;
Button.updateText(Double.toString(currentValue));
}
#Override
public boolean touchDown(InputEvent event, float x, float y,
int pointer, int button) {
if (Gdx.input.isButtonPressed(Buttons.LEFT)) {
double currentValue = Double.parseDouble(Button.getText()
.toString());
if ((int) currentValue != 0)
currentValue--;
Button.updateText(Double.toString(currentValue));
}
return super.touchDown(event, x, y, pointer, button);
}
without knowing which of your classes implements your InputListener, it's a little hard to tell you exactly what to do to fix your problem. However, in the general sense what you probably want to do is have a boolean flag set to true on your touchDown method, set to false on your touchUp method, and then in some method that gets called every frame (act, draw, etc., depending on your implementation), youll want to update your text.
The code would look something like
private boolean flag = false;
#Override
public boolean touchDown(InputEvent event, float x, float y,
int pointer, int button) {
if (button == Buttons.LEFT) {
flag = true;
}
//other stuff
return true; //or whatever you want
}
#Override
public boolean touchUp(InputEvent event, float x, float y,
int pointer, int button) {
if (button == Buttons.LEFT) {
flag = false;
}
//other stuff
return false; //or whatever you want
}
#Override
public void act(float delta) {
if (flag) {
double currentValue = Double.parseDouble(Button.getText()
.toString());
if ((int) currentValue != 0)
currentValue--;
Button.updateText(Double.toString(currentValue));
}
//other stuff
}
depending on your targetted audience, you may also have to deal with pointer id's in some way (this code example wont work if the user clicks on the label with two fingers, then releases one but not the other)
Im trying to add drag and drop functionality to several images in Libgdx. I have looked at this example: https://github.com/libgdx/libgdx/blob/master/tests/gdx-tests/src/com/badlogic/gdx/tests/DragAndDropTest.java but Its still not working. The images do not drag and drop. Would anyone be able to give me some pointers in why its not working?
Thanks
private void createButton() {
stage = new Stage();
Gdx.input.setInputProcessor(stage);
skin = new Skin();
skin.add("up", new Texture(Gdx.files.internal("assets/data/up.png")));
skin.add("def", new Texture(Gdx.files.internal("assets/data/Goal.png")));
final Image up = new Image(skin, "up");
up.setBounds(1090, 630, 40, 40);
stage.addActor(up);
Image def = new Image(skin, "def");
def.setBounds(1090, 585, 40, 40);
stage.addActor(def);
DragAndDrop dragAndDrop = new DragAndDrop();
dragAndDrop.addSource(new Source(up) {
public Payload dragStart (InputEvent event, float x, float y, int pointer) {
Payload payload = new Payload();
payload.setObject(payload);
payload.setDragActor(up);
payload.setDragActor(new Label("up", skin));
Label validLabel = new Label("up", skin);
validLabel.setColor(0, 1, 0, 1);
payload.setValidDragActor(validLabel);
return payload;
}
});
dragAndDrop.addTarget(new Target(def) {
public boolean drag (Source source, Payload payload, float x, float y, int pointer) {
getActor().setColor(Color.GREEN);
return true;
}
public void reset (Source source, Payload payload) {
getActor().setColor(Color.WHITE);
}
public void drop (Source source, Payload payload, float x, float y, int pointer) {
System.out.println("Accepted: " + payload.getObject() + " " + x + ", " + y);
}
});
render();
}
public void render () {
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
Table.drawDebug(stage);
}
I implemented your code on a project of mine.
I removed your render and used the one below. Also, you shouldn't need the assets/ prefix to your image import.
skin.add("up", new Texture(Gdx.files.internal("images/coin.png")));
skin.add("def", new Texture(Gdx.files.internal("images/coin.png")));
#Override
public void render(float delta) {
super.render(delta);
stage.draw();
stage.act(Gdx.graphics.getDeltaTime());
}
Another way to do drag in a better way...
public class CaveInterection implements ApplicationListener {
private OrthographicCamera camera;
private SpriteBatch batch;
private Texture bgTexture;
private Sprite sprite;
private Stage stage;
private Texture mirrTexture;
private MyActor mirrorActor;
Sprite img1,img2;
#Override
public void create() {
camera = new OrthographicCamera(1024, 550);
camera.position.set(1024 / 2, 550 / 2, 0);
batch = new SpriteBatch();
stage = new Stage(1024, 550, false);
//bgTexture = new Texture(Gdx.files.internal("data/cave.jpg"));
//bgTexture = new Texture(Gdx.files.internal("data/bg.jpg"));
mirrTexture = new Texture(Gdx.files.internal("data/mirror.png"));
mirrTexture
.setFilter(TextureFilter.Linear, TextureFilter.Linear);
mirrorActor = new MyActor(new TextureRegion(mirrTexture));
mirrorActor.setPosition(700, 400);
mirrorActor.setOrigin(mirrorActor.getWidth()/2, mirrorActor.getHeight()/2);
stage.addActor(mirrorActor);
// finally stage as the input process
Gdx.input.setInputProcessor(stage);
}
#Override
public void dispose() {
batch.dispose();
//bgTexture.dispose();
}
#Override
public void render() {
// clear the screen, update the camera and make the sprite batch
// use its matrices.
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
camera.update();
batch.setProjectionMatrix(camera.combined);
batch.begin();
//batch.draw(bgTexture, 0,0);
// Gdx.app.log("arvind","X :"+mirrorActor.getX()+ " Y :"+mirrorActor.getY());
//batch.draw(bgTexture, 0, 0);
batch.end();
// tell the stage to act and draw itself
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
}
public class MyActor extends Actor {
TextureRegion region;
float lastX;
float lastY;
public MyActor (TextureRegion region) {
this.region = region;
setWidth(region.getRegionWidth());
setHeight(region.getRegionHeight());
addListener(new InputListener() {
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
Gdx.app.log("arv", "pointer1+"+pointer);
// we only care for the first finger to make things easier
if (pointer != 0) return false;
// record the coordinates the finger went down on. they
// are given relative to the actor's corner (0, 0)
Gdx.app.log("arvind", "touchDown");
Gdx.app.log("arv", "pointer2+"+pointer+""+x+"::::"+y);
lastX = x;
lastY = y;
return true;
}
public void touchDragged (InputEvent event, float x, float y, int pointer) {
// we only care for the first finger to make things easier
if (pointer != 0) return;
Gdx.app.log("arv", "touchDragged");
// adjust the actor's position by (current mouse position - last mouse position)
// in the actor's coordinate system.
translate(x - lastX, y - lastY);
// rotate(2);
// save the current mouse position as the basis for the next drag event.
// we adjust by the same delta so next time drag is called, lastX/lastY
// are in the actor's local coordinate system automatically.
lastX = x - (x - lastX);
lastY = y - (y - lastY);
}
});
}
#Override
public void draw (SpriteBatch batch, float parentAlpha) {
//batch.draw(region, getX(), getY());
batch.draw(region, getX(), getY(), mirrorActor.getOriginX(), mirrorActor.getOriginY(), mirrorActor.getWidth(), mirrorActor.getHeight(), 1, 1,getRotation(), true);
}
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
}