So I've recently been abusing Google for an answer, however just can't find one, and my head's starting to ache. I've recently released my second game on the Google Play Store, and only now have I been getting feedback that the people aren't too crazy about the button pressing mechanics (same mechanics as the first game). My game can be found here if you want to give it a go, unfortunately I don't have an HTML version hosted elsewhere.
Making the game, I used LibGDX, and for the UI, I've used Scene2D that comes with LibGDX. My game requires that you press the green "bug" button to get a point (the "bug" buttons cycle around at random), you are forced to play against a timer, so you would obviously want to go faster for a higher score (think Piano Tiles).
Now, to the problem at hand, one of the game modes in my new game is called "Zen", two buttons, one gives you 1 point, the other 2 points. The problem I'm experiencing is that if you hold both "bug" (bottom right and bottom left) buttons down, and release one of the buttons, the released one triggers a score increase, and the other button resets as if it was never pressed on in the first place (even if your finger is still on it). Here's the code for my Scene2D buttons (working off memory, don't have my code near me at the moment):
// All is initialized correctly, no crashes, here's the part about the listener.
leftBugButton.addListener(new ChangeListener()
{
#Override
public void changed(ChangeEvent event, Actor actor)
{
// Run code here when button has been released.
}
}
// And the right hand button's code. Initialization is perfect, no problems.
rightBugButton.addListener(new ChangeListener()
{
#Override
public void changed(ChangeEvent event, Actor actor)
{
// Run code here when button has been released.
}
}
Getting to my question, what I want to go for is that if a button press has been completed (pressing and then releasing), I don't want the other buttons to reset to an unpressed state.
Any tips, or perhaps a different Listener I should use, or even dumping Scene2D for these buttons (using sprites with InputListener for example)? Any help would be greatly appreciated.
Thanks in advance,
TV
Don't use ChangeListener for that, use a ClickListener (button.addClickListener(new ClickListener...)) and handle your process on touchUp event, ChangeListener gonna process if ANYTHING on the button change and it's not a good approach to handle a button release event.
Found my problem, I kept rebuilding the Stack after every button press, resulting in the odd behavior, opted instead for a .setStyle() on my buttons which is working a lot better.
Related
Hi Everyone,
in the game I develop with AndEngine, there are a lot of sprites running around. Now every of this sprites has a TouchArea registered to the scene, because I display some informations about the sprite when it is touched. The Scene itself has a OnSceneTouchListener that I use for moving the camera around and to zoom.
My problem is, that every time the user moves the camera (by touching the display somewhere and moving his finger around) the OnAreaTouched() method of any sprite, that is accidentally under the finger, gets called, when the movement is finished (finger gets lifted). I already limited the triggering events to event.getAction()==UP (before it was a real mess of called touchAreas) but this is not enough. If the user is zooming or moving the camera, the sprites touchAreas should not be activated.
Is there any way I can distinguish between an OnAreaTouched-event and an OnSceneTouched-event? Which one is called first and can I suppress the other?
This is my OnSceneTouched() method (simplified):
public boolean onSceneTouchEvent(Scene scene, final TouchEvent event) {
boolean isZooming = event.getMotionEvent().getPointerCount() >= 2;
if (event.getAction() == MotionEvent.ACTION_DOWN) {
// REMEMBER FIRST TOUCHPOINT, TO KNOW IN WHICH DIRECTION TO MOVE
this.touchPoint = new Point(event.getMotionEvent().getX(), event.getMotionEvent().getY());
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
if (isZooming) {
// DO SOME ZOOM STUFF
} else {
// DO SOME MOVEMENT STUFF
}
return true;
}
OK, actually this is not very interesting - but as you can see I always return true to signal that the touch event was handled. Still the OnAreaTouched() gets called
This is a typical OnAreaTouched() Method of a sprite:
public boolean onAreaTouched(final TouchEvent touchEvent, float touchAreaLocalX, float touchAreaLocalY) {
if (touchEvent.getAction() == TouchEvent.ACTION_UP) {
// DISPLAY INFORMATION ABOUT THE SPRITE
return true;
}
return false;
}
You see, there is nothing special to it. So I hope someone can help me out here to find a solution how to suppress the OnAreaTouch-event when the OnSceneTouch-event should be used. Maybe I can somehow catch the event.getAction()==UP in the OnSceneTouched()-Method??
I hope I could explain the problem good enough for you to understand (sorry, it's not that easy for me : ). Any help is much appreciated, and thank you for you time!
regards
Christoph
edit:
After experimenting with MahdeTo's suggestion to tag the event somehow I found out the following:
the TouchEvent that triggers the OnSceneTouchEvent() Method is not the same as the one triggering the OnAreaTouched() Method.
OnAreaTouched() gets called 20 ms later than OnSceneTouchEvent()
the event calling OnAreaTouched() starts actually when the user puts his finger down on the display (than he moves it around and the OnSceneTouchEvent() gets called multiple times), when he then lifts his finger the first event stops and gets handled. (I tried it out by measuring the time)
So I came up with the solution to measure how long a touch event lasted. If the event is longer than 200 ms, I guess the user wanted not to simply click but move or zoom (because these actions usually take longer). So now the OnAreaTouched() method gets only called when someone really meant to click and not accidentally swiped over the area.
but it's still not a good solution and I would really appreciate if anyone knows more about controlling such events.
thank you
I have recently written a fairly complicated application using touch controls - pressing buttons on the screen, pinch zooming, rotating and moving objects with two fingers and more. What I ended up doing was iteratively improving the application and adding rules controlling how to respond to different combinations of touch events. Whenever something was wrong, I recorded the sequence of TouchEvents and added rules so that the misbehaving action was handled.
You can also create boolean switches that prevent the onAreaTouched to execute, just add a condition that, for example if you want to touch an object, checks whether doNotTouchObject is true or false.
Another thing I found useful were touch mode switchers. I wrote several methods that completely change the behavior when user touches the screen. I believe you can switch them on the go, so it should be possible to call scene.setOnAreaTouchListener(touchListener) while you are touching the screen.
Since un/registering touch areas is blazing fast, simply unregistering certain touch areas while you perform some action is a possibility. After the action is completed, reregister them again.
I used a combination of all of the above and it works rather well, but it is essential to keep the code clean, otherwise debugging or implementing new features will be a pain.
maybe you can use the TouchDetector.
use the clickDetector instead of process TouchUp event, then only the detected click event is processed by the sprites;
use the scroll detector for the Scene Scrolling too;
enable the SceneTouchListenerBinding and TouchAreaBinding will also help you to by pass all the unintended in-progress events.
I've got a button that kicks off a background thread to do some work and I am trying to use a ProgressDialog to prevent the user from double clicking that button (or any other ui elements) while that work is being done. The first thing I do in my buttons onClick code is to display the progress dialog, which takes over the screen. The problem I am seeing is that if I rapidly tap this button, sometimes two or more presses will register before the ProgressDialog is shown. This leads me to assume that ProgressDialog.show() is returning before the ProgressDialog is actually visible.
Can anybody confirm this? Also, is there a way to change this behavior, or at least get a notification of when the dialog is actually visible? I saw Dialog.onStart() but given the javadoc, this appears to be called before the Dialog is actually visible...
UPDATE:
While it appears that there is no good way of solving this problem in general, the following works for my situation where my work is done by an external thread and the amount of work to do takes longer than the time it takes for all the button clicks to be processed:
void myOnClickHandler() {
if(myButton.isEnabled()) {
myButton.setEnabled(False);
// do work here
// setEnabled(true) is invoked at the end of my spawned thread's run().
}
}
No.
The problem is you clicked many times before the click event is delivered. (i.e. it is queued before you run ProgressDialog.show().)
From what I've noticed in Android you can double click on a button rapidly and have the onClick listener fire twice (or even more) regardless of the code in the listener (even if you disable the button immediately).
I reported a bug a while ago here: http://code.google.com/p/android/issues/detail?id=20073 but of course these things tend to go "unnoticed" by Google. Feel free to star it in hopes of getting Google's attention
I'm new to posting, but have been using the site for help for a while now. So thanks for that!
I'm working on a new app, got everything running well. It's a kids' soundboard. 2 pages of imagebuttons in a relative layout, with onclick listeners which triggers SoundPool.
My question is this:
in testing I've discovered if you're finger is anywhere on the screen where a button is not (say pressing on the background) and then you try to touch a button (multitouch) ... the button press doesn't register. Any way to fix this?
Thanks!
You have to cover additional event types for multi-touch, if you are not covering below Actions, you are not covering multi-touch
MotionEvent.ACTION_POINTER_DOWN: This event happens for any additional finger that
touches the screen after the first finger touches
MotionEvent.ACTION_POINTER_UP:This gets
fired when a finger is lifted up from the screen and more than one finger is touching
the screen.
The explanation is quite tedious. I suggest you to google multi-touch for android. One helpful link is: http://android-developers.blogspot.in/2010/06/making-sense-of-multitouch.html
Alright, i'm making a small pong game, and, i'm making a start menu for it. It's like, you start up the game, get a menu, you click on play, and then the game starts, now, everything works exactly as I wanted, except for one thing. When I click the button, everything gets drawn, the ball starts going, everything updates correctly, BUT, I can't move my players anymore. It's like the KeyListener has stopped working, my program suddenly stops reacting to keys. I'll give you guys all of my source code for the game, because, I am puzzled, I have no idea what's causing it, or how to fix it. My menu works by changing a boolean when you press the button, when the boolean is false, draw the start menu, and when it's true, draw the game.
Right, since it's alot of code, I will upload it to pastebin.
PongWindow.java(includes main) http://pastebin.com/S5CpWW5Q
PongDrawing.java(includes drawing,moving,keylisteners,main game loop, and all of that) http://pastebin.com/x2LxkkbP
PongPlayer.java(the player) http://pastebin.com/N8VWTL0P
PongBall.java(the ball) http://pastebin.com/temGc2Yg
If you guys can figure out why it's not listening to my keys anymore, please tell, I have no idea.
It's like the KeyListener has stopped working,
Key events are only passed to components that have focus. If you click on a button then your game panel no longer has focus. You need to use something like:
gamePanel.requestFocusInWindow();
in your ActionListener code.
However the proper way to do this is to forget about using a KeyListener and instead use Key Bindings.
in echo 3 i have a problem setting focus on a specific text field in a new screen. The probelm occurs when a user holds their mouse on the reference button on the previous screen as opposed to just a simple click.
it looks similar to this:
public void display screen {
build window
if window isnt null{
build screen
if screen.textfield isnt null{
Thread t {
thread sleep 10000
screen.textfield.setFocus
}
}
}
}
in the pseudo above the focus would be set if the user user held the reference button down on the screen before for less than 10 seconds, in which case the focus would not be set until the remaining thread time passed. this isnt good because it take too long; and lower wait delay doesnt insure that the focus will set at all because the user might hold the key for longer.
I have tried launching multiple threads and using timers to hammer the focus in but that didnt work... is there something im missing about how the code is built internally because it seems that the whole thing is built despite the fact that the user hasnt let go of the button.
If thats the case is there a way to do it on release?
Thank You
Found a solution. The problem was with using IE6. I presume the order in which it builds is different to that of IE7+.