In an AndEngine game, I have implemented onAreaTouched() so that when an sprite is tapped, I detect and respond accordingly. Also, I have implemented onSceneTouchEvent() so that when user taps screen, I move the character. But I am having an issue. When user taps on some sprite, the onAreaTouched() is called but after that onSceneTouchEvent() is also being called resulting in two actions against one tap. I want that when sprite is tapped, only onAreaTouched() should be called and vice versa. I also tried to return true/false from onAreaTouched() but it did not worked. Any idea what do am am missing?
If the onAreaTouched() function is being called before the onSceneTouchEvent() function, you could just have a member boolean to control whether or not you want run the code in onSceneTouchEvent()
OnAreaTouched()
{
mIsSpriteTouched = true;
// then run all relevant code when the sprite is touched
}
onSceneTouchEvent()
{
if (!mIsSpriteTouched)
{
//execute code that should run when the sprite isn't touched
}
mIsSpriteTouched = false; //reset for next event;
}
Related
I add UI object Button and add the C# script with public function.
To button I add component Event Trigger, do events(Pointer Click and Pointer Down) and redirect to my function public void onClick()
On PC code works, but when I upload game to android and touch the object, code not works.
How to do onTouch event?
I think OnMouseDown will check every frame if there is a mouse input it's like update so you have to cheek touch in Update & with touch you will have more control like Touch Phase to detect if the touch begins or lifted or moved etc...
you need to check
if(input.touchCount > 0)
void Update() {
if (Input.touchCount > 0){
print("exist a touch");
if(Input.GetTouch(0).phase == TouchPhase.Began){
print("Touch begans");
}
if(Input.GetTouch(0).phase == TouchPhase.Ended){
print("Touch Ended");
}
}
}
chCount > 0)& inside this you can cheek for touch Phase
Touches aren't Clicks
In order to handle touch input you need to check Input.touchCount and then query each touch with Input.GetTouch. Note that each Touch has an an ID that will be unique per finger and consistent across frames.
There are no easy OnClick like methods for touches, as touches can be a lot more complex (tap, long tap, drag, etc), so you will have to check inside Update() and handle the conversion from touch data to mouse analogs yourself.
I have created a button in my 2d game using Unity3d, added box collider 2d with name PADBASE to detect touch events this way:
if(Input.touchCount > 0)
{
for(int i = 0; i < Input.touchCount; i++)
{
Vector3 mouseWorldPos3D = Camera.main.ScreenToWorldPoint(Input.GetTouch(i).position);
Vector2 mousePos2D = new Vector2(mouseWorldPos3D.x, mouseWorldPos3D.y);
Vector2 dir = Vector2.zero;
RaycastHit2D hit = Physics2D.Raycast(mousePos2D, dir);
Touch t = Input.GetTouch(i);
if (hit.transform != null)
{
if(Physics2D.Raycast (hit.transform.position , hit.transform.forward))
{
GameObject recipient = hit.transform.gameObject;
if(t.phase == TouchPhase.Began) //poczatek dotyku
{
// button clicked
// change colour to red to visually show that button is being pressed
}
else if (t.phase == TouchPhase.Ended)
{
// change collor to its default colour to visually show that its no longer pressed
}
}
}
}
}
And lets assume I will change button colour to red when player touched the button, and back to its default colour when he released his finger (for example)
Now it will obviously work only when player will release his finger, as long as his finger is actually inside bounds of the box collider, what I am trying to do is "bind touch events(?)" to still catch touch event (slide or ended) even if player moved his finger outside of the collider without releasing his finger (for example accidentally)
I am looking forward for some suggestions, thanks.
In my game I will have multiple buttons so multi touch is necessary.
Solved, it actually turns to be really easy, you need to store and compare touch finger ID.
Solution:
- on touch began:
check if touch is withing game objects box collider like in the code attached above.
get touch finger ID and pass it to your button or keep reference of it
- on touch ended:
compare touch finger ID with your stored touch id, if they are equal, set your stored finger id to -1 and perform your code that should execute on touch edned
- on touch moved or (||) stationary:
do the same comparison of the touch id like in the touch ended, and perform your code that should be executed if player will slide/move his finger, but do not modify your finger id variable.
That`s it, works well with multiple buttons with multi touch.
Im making a very simple game and have started making each menu. There will be 3 menus in a row - Main menu - Playher select Menu - Gamemode Menu but the problem i am facing atm is adding a delay between the touches. the code i have uses Sprites for the buttons and detects whether a touch point is within the bounding rectangle.
Like so:
if(Gdx.input.isTouched()){
cam.unproject(PlayerMenuTP.set(Gdx.input.getX(), Gdx.input.getY(), 0));
if(Sprites[1].getBoundingRectangle().contains(PlayerMenuTP.x, PlayerMenuTP.y)){
Game.ChangeScreen(2);
}
}
This works for the first menu but since the buttons are in the exact same position on each menu if you hold you finger on the screen i skips through all the menus.
I don't know how to modify this to wait until the previous touch is no longer occurring then continue to scan for this one.
Any help will be appreciated.
Thanks
I strongly suggest you to use Scene2D for UI related stuff, it's not hard to implement or learn, and its very easy to mantain.
Anyway if you want to keep going in that way, you can do this:
Make your screens implement InputProcessor.
Set Gdx.input.setInputProcessor() to that screen (in the show() create() or the name of the method called when the screen is set)
Override touchUp()
Replace your code with
#Override public boolean touchUp (int screenX, int screenY, int pointer, int button) {
cam.unproject(PlayerMenuTP.set(screenX, screenY, 0));
if (Sprites[1].getBoundingRectangle().contains(PlayerMenuTP.x, PlayerMenuTP.y)){
Game.ChangeScreen(2);
}
return true;
}
I am attempting my first game using a custom view extended from view that ,as it stands, is just a background image that can pan by dragging with the ACTION_Move.
It also has a zoom image that gets drawn on the canvas and when an ACTION_UP occurs on this region, a zoom in is registered and the image is scaled up.
The problem I now experience is that although the drag works well with the ontouch function returning true, the ACTION_UP is very sensitive and a single touch executes the code in the ACTION_UP case statement a few hundred times. Instead of just incrementing the zoom up by 10% it rapidly zooms to 100%.
If I return false to the function, the zoom works normally by 10% per touch but as stated in previous posts, the function must return true for ACTION_MOVE to respond.
Things I've tried
Thread.sleep() - it does exactly the same thing by incrementing the zoom 100 times with a delay in between.
Changing the returned value in the case statements so it returns true only for ACTION_MOVE but move does not respond.
You could try using a boolean variable to control the zoom, for example:
private boolean zoom = true;
final Handler handler = new Handler();
// ACTION_UP
if(zoom) {
doZoom();
zoom = false;
}
handler.postDelayed(new Runnable() {
#Override
public void run() {
zoom = true;
}
}, 100); // Delay 100 ms, adjust for ideal zoom speed
Now it won't zoom again until the 100ms delay is completed.
I'm creating a chess Game, I am using flag variable to check white or black turn.
First i am creating a chess board by using surface view and drawing bitmap on that canvas to show element of chess.
But my problem is that when I touch canvas every time it call onDraw()-method even i am not calling invalidate(), and returning false in onTouch()
#Override
public boolean onTouchEvent(MotionEvent event) {
if(white){
// Code for select
// Code for move element
// IF Invalid move ( Donot want to call onDraw() so i return here -
false and i did not call invalidate() but it redraw view)
}else if(black){
// same code for balck
}
}
I notice that you always(?) return false by default. In general, if you have no idea what to return (returning true means you consumed that touch event), use return super.onTouchEvent(event); instead. However, this might not be relevant to your issue.