How to properly implement CheckBox in LibGDX - java

I want to implement a checkbox in my game for switching volume on and off. I have this so far, but it's not working properly:
MusicOnOff.addListener( new InputListener() {
public void touchUp (InputEvent event, float x, float y, int pointer, int button) {
MusicOnOff.toggle();
}
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
System.out.println("Music: " + MusicOnOff.isChecked());
return true;
};
});
EDIT: Ok, never mind. It's toggling with the right mouse button :O. Left is not working though

Never used Checkbox, but I'm guessing it's supposed to automatically toggle, so if you do
MusicOnOff.toggle();
you may actually toggling it twice, giving the feeling that it never toggles.

Related

ClickListener touchDragged pointer always zero

while working on the listener class and implementing handling of multiple touch gesture I came across a possible bug.
The code implementation
public class MyListener extends ClickListener {
private List<Pointer> pointers = new ArrayList<Pointer>();
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointerIndex, int button) {
System.out.println("Listener: touch down" + pointerIndex);
pointers.add(new ListenerPointer(x, y, button));
event.handle();
return super.touchDown(event, x, y, pointerIndex, button);
}
#Override
public void touchDragged(InputEvent event, float x, float y, int pointerIndex) {
System.out.println("Listener: dragged " + pointerIndex);
// Update the current point the user is dragging.
for (ListenerPointer pointer : pointers) {
if (pointer.getPointerIndex() == pointerIndex) {
pointer.update(x, y);
event.handle();
}
}
}
}
While touching down on the screen with a new finger, and still holding the old finger on the screen the indexPointer increases. Resulting in the following log:
Listener: touch down0
Listener: touch down1
If I then move both fingers across the screen, it will only fire the touchDragged event with the pointerIndex always zero. Even though the touchDown gesture said it has a pointerIndex of 1. The log of the touchDragged is always:
Listener: dragged 0
Listener: dragged 0
I think it might be a bug in the code of LibGDX, since such a simple piece of code could not really go wrong.
I thought that I had carefully read the documentation of touchDragged, but what a fool I am. It states the following:
Called when a mouse button or a finger touch is moved anywhere, but only if touchDown previously returned true for the mouse button or touch.
I guess that super.touchDown(event, x, y, pointerIndex, button) only return true if the pointerIndex is 0. Explaining the reason why the touchDragged events did not fire for pointerIndex > 0.
The simple fix is to make touchDown always return true

LibGDX touchDown touchUp on different Actors

In my LibGDX game, I have a raster of clickable Actors. I want the player to be able to swipe across them and get the Actor where the swipe stops.
I don't want a GestureListener, the only thing I need is a touchUp event on the touchDown generated on another Actor. For example: think about Androids login screen where you swipe a pattern to unlock, but I only need an event for the last dot/Actor.
I have tried using touchDown / touchUp, but the event always fires on the Actor where the touchDown occurred.
A fine solution would be to get events for every Actor hit by the swipe, and then get a global touchUp event. Is this possible in a relatively accessible way - eg. without writing a whole new InputListener?
In touchUp() of your listener, call hit on the parent WidgetGroup of all your clickable Actors to see which one the finger is over when it is released. Note that since you're adding the actors to the group, the group needs to be added to the stage instead of adding the widgets to the stage directly. And remember that an Actor's X and Y are relative to its parent.
final WidgetGroup parent = new WidgetGroup();
InputListener inputListener = new InputListener(){
private final Vector2 tmp = new Vector2();
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) {
event.getTargetActor().localToParentCoordinates(tmp.set(x, y));
Actor releaseOverActor = parent.hit(tmp.x, tmp.y, true);
if (releaseOverActor != null){
//doSomethingTo(releaseOverActor);
}
}
}
for (Actor clickable : clickableActors){
parent.add(clickable);
clickable.addListener(inputListener);
}
The above is a little bit simplified. You might want to return true one touchDown only if pointer 0 is used, for example.

Libgdx Listener enter and exit fires multiple times

Im currently trying to implement an clickListener.
I found a great tool with runtime, its called Overlap2D, there i made some nice buttons and loaded them, it all works fine.
Because i wanted to make a "hover" effect for my buttons, i used the ClickListener with the methods enter and exit, it looks so :
#Override
public void enter(InputEvent event, float x, float y, int pointer, Actor fromActor){
playButton.setLayerVisibility("MouseOver", true);
playButton.setLayerVisibility("pressed", false);
playButton.setLayerVisibility("normal", false);
System.out.println("Actor enter : "+fromActor);
}
#Override
public void exit(InputEvent event, float x, float y, int pointer, Actor toActor){
playButton.setLayerVisibility("MouseOver", false);
playButton.setLayerVisibility("pressed", false);
playButton.setLayerVisibility("normal", true);
System.out.println("Actor exit : "+toActor);
}
#Override
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button){
System.out.println("touchdown");
return true;
}
#Override
public void touchUp (InputEvent event, float x, float y, int pointer, int button){
System.out.println("touchup");
}
And heres the problem, touchdown and touchup are called one time, when i touch down the button or up. But the enter and exit methods are also called during the touchdown and touchupo event O.o that looks so:
touchdown
Actor enter : null
Actor exit : Image
Actor enter : Image
touchup
Actor exit : Image
Actor exit : Image
Actor enter : Image
Actor exit : Image
Actor enter : Image
I printed the fromActor and toActor also for debugging ^^
And i still dont know why it fires the exit and enter event so much ...
Any one got an idea?
Thanks :)
You need to check the pointer that's passed into the enter and exit methods. If the pointer is -1, then the mouse cursor just started or stopped hovering over the bounds of the actor. It the pointer is not -1, then the actor just received a click down or click release (for enter and exit respectively).
So if you move the cursor over the button and click and then move away, you get two enter events and two exit events.
Hover -> entered with pointer -1
Click down -> entered with pointer 0
Release click -> exited with pointer 0
Move cursor away -> exited
with pointer -1
Also, when using ClickListener, make sure you are calling through to super methods when overriding methods, so it will behave properly!

libGDX touch in effect after touch

I use the following code to match the user touch to a ball object's position, so when the user touches the ball it bounce back up. Code:
int x1 = Gdx.input.getX();
int y1 = Gdx.input.getY();
Vector3 input = new Vector3(x1, y1, 0);
cam.unproject(input);
if(ball.getBoundingCircle().contains(input.x, input.y)) {
ballBounce();
}
But I have a problem with the touch. If the user touches a certain position on screen for a moment and a ball (after a while more appear) about to reach the position the user touched, the ball will recognize itself as been touched and the ballBounce(); method will start and continue with other balls that reach to the same position until the user touch another position on the screen but then that position will be fixed till the new one... Do someone know how I can bypass that problem so if the user stop touching the screen then where he\she touched won't affect the ball objects?
It seems that you are not using any input processor.
Make your class implement InputProcessor and make your touchDown method look like this.
#Override
touchDown(InputEvent event, float x, float y, int pointer, int button) {
Vector3 input = new Vector3(x, y, 0);
cam.unproject(input);
if (ball.getBoundingCircle().contains(input.x, input.y)) {
ballBounce();
}
}
ClickListener (LibGDX API)

How to drag and drop a LibGDX Image actor

I have a LibGDX scene with a couple of Images (the Actor subclass). I want to drag one Image and drop it on another. I started with the source code located at DragDropTest.java. Since I basically want the source to be the payload I've tried modifying payload.setDragActor to use the source Image. It kind of works, I need to add the code to place the payload actor back in the stage but that isn't my issue.
My problem that that the payload (when it's the source actor or a separate actor) doesn't really get dragged. Instead what happens is the payload actor positions itself slightly down and to the right of the mouse cursor. I want to place the payload, not point to where I want the payload placed. It doesn't feel like dragging at all, it feels like something is following the cursor. I see the same behavior on the Android emulator as I do on the desktop version of the app.
I went digging through the LibGDX source for com.badlogic.gdx.scenes.scene2d.utils.DragAndDrop and found the answer. The code places the payload +14 in the X direction from the cursor and (-20 - payLoadActor.getHeight()) in the Y direction which is why I'm not able to visually drag the payload. There is a setDragActorPosition method that can be used to correct the position. If you always want the dragged payload to be centered under the cursor you can do:
final DragAndDrop dragAndDrop = new DragAndDrop();
dragAndDrop.setDragActorPosition(-(sourceImage.getWidth()/2), sourceImage.getHeight()/2);
If you want the dragged payload to maintain its placement under the cursor/finger than you have to use the cursor position when calling setDragActorPosition in the dragStart method.
final DragAndDrop dragAndDrop = new DragAndDrop();
dragAndDrop.addSource(new DragAndDrop.Source(sourceImage) {
public DragAndDrop.Payload dragStart (InputEvent event, float x, float y, int pointer) {
DragAndDrop.Payload payload = new DragAndDrop.Payload();
payload.setDragActor(sourceImage);
dragAndDrop.setDragActorPosition(-x, -y + sourceImage.getHeight());
return payload;
}
public void dragStop (InputEvent event, float x, float y, int pointer, Target target) {
sourceImage.setBounds(50, 125, sourceImage.getWidth(), sourceImage.getHeight());
if(target != null) {
sourceImage.setPosition(target.getActor().getX(), target.getActor().getY());
}
virtualStage.addActor(sourceImage);
}
});
You're not showing any code, so it's hard to know what you are actually doing. Based on your description, it sounds like you are placing the payload at where the cursor is rather than moving it the same offset as the cursor moved since you started dragging.
Assuming you're using an ActorGestureListener, this is what I do in my app.
float touchX, touchY;
public void touchDown(InputEvent ev, float x, float y, int pointer, int button) {
touchX = x;
touchY = y;
...
}
public void pan(InputEvent ev, float x, float y, float dx, float dy) {
moveBy(x - touchX, y - touchY);
...
}
This way you are moving your actor by the same amount as the mouse cursor moved, so it's like the pointer "glued" itself to whereever you touched your actor. Also, I believe the events in libgdx makes it so that you will not receive the pan events until the cursor has moved a bit inside your actor, so be aware of that when testing (moving the cursor a few pixels only will not trigger the pan events).

Categories

Resources