Godot TouchScreen swipe detector - touch

I'm making a simple android mobile game in Godot3.1. I would need to make a swipe detector that would determine if the player swiped and in which direction (left or right).
I tried this:
var swipe_start = null
var minimum_drag = 100
func _unhandled_input(event):
if event.is_action_pressed("click"):
swipe_start = event.get_position()
if event.is_action_released("click"):
_calculate_swipe(event.get_position())
func _calculate_swipe(swipe_end):
if swipe_start == null:
return
var swipe = swipe_end - swipe_start
if abs(swipe.x) > minimum_drag:
if swipe.x > 0:
_right()
else:
_left()
This works when you click with your mouse and swipe but it doesn't work when you play it on your android phone.
Any ideas?

That code only considers clicks and not screen touches, to correct that you have two options:
Go to Project > Project Settings > Input Devices > Pointing and turn on the Emulate Mouse From Touch option.
Or use the following code:
func _unhandled_input(event):
if event is InputEventScreenTouch:
if event.pressed:
swipe_start = event.get_position()
else:
_calculate_swipe(event.get_position())
instead of:
func _unhandled_input(event):
if event.is_action_pressed("click"):
swipe_start = event.get_position()
if event.is_action_released("click"):
_calculate_swipe(event.get_position())
With the last solution the code only accounts for screen touches so you wont be able to test it on PC unless you go to Project > Project Settings > Input Devices > Pointing and turn on the Emulate Touch From Mouse

Related

Handle short and long clicks, drag and drop and sprites overlapping?

My game is going to be using touch controls and I'm having a lot of trouble implementing the following mechanics.
When I make a short click on a sprite, I want it to do a simple click event, in my code, it should highlight the sprite.
But when I make a long click on a sprite, it should at one point anchor to the cursor and be dragged around by it. When I release it, it should then stop following the cursor and stay in place.
Last but not least, I'm actually working with multiple sprites and I want to always influence the top-most sprite (z_index wise).
So right now, my code looks like this:
# Node2D, parent of my sprite
func _process(delta):
# Checks for clicks and hold, calls function based on events
if not owning_hand or not owning_hand.my_hand:
is_holding = false
return
if Input.is_action_just_released("click"):
owning_hand.drop_card()
is_holding = false
if not input_in_sprite:
is_holding = false
return
if Input.is_action_just_pressed("click"):
is_holding = true
if Input.is_action_just_released("click"):
if hold_time < HOLD_TARGET:
owning_hand.clicked_cards.append(self)
is_holding = false
if is_holding:
hold_time += delta
else:
hold_time = 0
if hold_time >= HOLD_TARGET:
owning_hand.held_cards.append(self)
func _input(event):
# If the mouse is in the sprite, set input_in_sprite to true
if not owning_hand or not owning_hand.my_hand:
return
if event is InputEventMouse and sprite.get_rect().has_point(to_local(event.position)) and not played:
input_in_sprite = true
else:
input_in_sprite = false
# Position2D, represents the player's input and methods
func _process(delta): # Gets the top most card z_index wise
# Checks for any clicked cards
print(held_cards)
if dragged_card:
dragged_card.position = get_global_mouse_position()
if clicked_cards:
var top_card = clicked_cards[0]
for Card in clicked_cards:
if Card.z_index > top_card.z_index:
top_card = Card
clicked_cards.clear()
highlight_card(top_card)
if held_cards:
var top_card = held_cards[0]
for Card in held_cards:
if Card.z_index > top_card.z_index:
top_card = Card
held_cards.clear()
drag_card(top_card)
func drag_card(card):
# Drags the card around
dragged_card = card
func drop_card():
# Drops the card
dragged_card = null
func highlight_card(card):
# Highlights the card
card.move_rotate(card.position + transform.y * -HIGHLIGHT_HEIGHT, card.rotation, REORGANISE_TIME)
At the moment, the only issue is that dropping a sprite when there's another sprite under my cursor triggers the click event of the sprite isn't being dropped.
To be frank, the code is pretty much okay for what I'm doing. I'm asking here to see if anyone knows a better way to code those mechanics.
func _process(delta):
# Checks for clicks and hold, calls function based on events
if not owning_hand or not owning_hand.my_hand:
is_holding = false
return
if Input.is_action_just_released("click"):
if hold_time < HOLD_TARGET and input_in_sprite and is_holding:
owning_hand.clicked_cards.append(self)
if owning_hand.dragged_card:
owning_hand.drop_card()
is_holding = false
if Input.is_action_just_pressed("click") and input_in_sprite:
is_holding = true
if is_holding:
hold_time += delta
else:
hold_time = 0
if hold_time >= HOLD_TARGET:
owning_hand.held_cards.append(self)
Coding it like this seems to make it work correctly.
Basically, I used the is_holding bool to gather knowledge on if the sprite has been pressed earlier. If not, the is_action_just_released should completely ignore any action on the sprite.
Feel free to suggest better ways to implement this

How to get touch pad up, down, left and right touches from Samsung gear vr?

I am trying to get touches on left , right , up and down touches of Samsung Gear vr touch pad (which is given at right side of Gear vr)
if (Input.GetMouseButtonDown(button))
{
displayText.text = "Track pad touch down";
}
else if(Input.GetMouseButtonUp(button))
{
displayText.text = "Track pad touch up";
}
When I tried above code for each touch down and touch up I am getting the out put but I need for particular buttons left ,right , up ,down and center.
I want something like this
if(Input.touchpad.left)
{
displayText.text = "left button clicked"
}
else if(Input.touchpad.right)
{
displayText.text = "right button clicked"
}
//and same for up , down and the middle button also.
Any suggestion will be appreciated , thank you!
On the latest GearVR (black one), the headset touchpad doesn't have buttons but rather one single capacitive area.
You can retrieve which area you are touching with OVRInput.Get(OVRInput.Axis2D.PrimaryTouchpad), store it then process the touch with OVRInput.Get(OVRInput.Touch.PrimaryTouchpad).
further documentation about Oculus input is available here.

(Unity) TextMeshPro score-text doesn´t work on android

I've made a simple relfex-dodging game in Unity in which a TextMeshPro text counts up when an obstacle passes by the player. The obstacle drops from above, falls down and gets destroyed when entering the trigger of a Box-collider. I've attached a Picture of the Scene view.
The "scoreText" variable in the example below is a reference to the TextMeshProUGUI component. When I run the game in Unity (with Unity Remote and my android phone as an input device), the score mechanic works as expected and the text property of the TextMeshProUGUI component changes from 0 to 1, from 1 to 2, and so on. When i hit "build and run" or just "build" in the Build Settings and export the apk-file, the game works well, but the text counts up to 1 and then remains like that. The obstacles are being destroyed, so the else if- block is being executed, too. Nothing changes from the Unity-version to Android, the code stays the same. I tried it on multiple devices, but the Problem stays. There are no errors, the app doesn't crash and I don't know what to do! I would very appreciate if you could help me! Here's the Code:
private void OnTriggerEnter2D(Collider2D other)
{
if (int.Parse(scoreText.text) == 0)
{
scoreText.SetText("1");
}
else if (int.Parse(scoreText.text) > 0)
{
int oldNumber = int.Parse(scoreText.text);
int newNumber = oldNumber + 1;
scoreText.SetText(newNumber.ToString());
}
Destroy(gameObject);
}
Have you tried using scoreText.text = newNumber.ToString()? I personally never use SetText

How to operate two ui button hold down at the same time in Unity [duplicate]

I'm writing a script to put on a button that will detect a drag direction to move a player
void OnGUI()
{
if (buttonRect.Contains(Event.current.mousePosition))
{
if (Event.current.type == EventType.MouseDown)
{
buttonPressed = true;
}
if (Event.current.type == EventType.MouseUp)
{
buttonPressed = false;
}
}
if (buttonPressed && Event.current.type == EventType.MouseDrag)
{
}
}
If this script was to be placed on a button, how could I get the buttons bounds as a rectangle?
Also, If anyone has a better solution for controling movement by drag I would be open for suggestions.
You can implement your own Visual Joystick by using the Unity new event callback functions such as OnBeginDrag OnDrag and the OnEndDrag function. There is a already made Visual Joystick package out there for Unity, so implementing your own is like reinventing the wheel.
All you have to do is to import the CrossPlatformInputManager package from Unity's UnityStandardAssets then use CrossPlatformInputManager.GetAxis("Horizontal") and CrossPlatformInputManager.GetAxisRaw("Horizontal") to read the direction of the image/thumb.
To make one from scratch, you can flow this video tutorial.
If you want a mobile solution that is really accurate and natural like a physical joystick, take a look at this asset:
Ultra Precise D-Pad Joystick

Unity - Raycast hit, wrong collider

Here is my code:
using UnityEngine;
public class InputController : MonoBehaviour {
void Update() {
if (Input.GetMouseButtonUp(0)) {
var hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero);
if (hit.collider != null) {
var e = hit.collider.gameObject;
Debug.Log(e.transform.position.x + ":" + e.transform.position.y);
}
}
}
}
When I click/touch a cell, sometimes the hit is good and the cell is revealed, sometimes the hit is always false (it's like I touch the wrong cell) and sometimes it depends of the position of my click (see images below).
I click the left part of the cell, the console says I click the cell on the left.
I click the right part of the cell, the console says I click the right cell (and reveals it). In this case it's left / right but it can be top / bottom, a corner...
I don't know if my problem is very well explained sorry, and my English is not perfect... Don't hesitate to ask me more details!
Ok I find the problem.
The left cell had a scale of 2 so it overlaps the right cell.
I Guess Here is problem with collider overlaping. you have to just reset all the collider and check it, is it overlaping on any object or not?
you can check colider on gamemode , turn on "Gizmo". so you will see all the collider and check it again is it overlaping on there or not ?