Problem translating touchscreen joystick to Player's movement

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By ddarkmoto


So I’ve tinkering with this analog joystick that I found in one of the posts here, but it seems to be that I’m having trouble mapping it to one of the nodes. Specifically to my player character. I tried inserting “if conditions” inside the func isPressed(event), but it doesn’t work the way I wanted.

Is there anyway to translate a character’s movement based on this joystick? I have no Idea where, or how to implement it in this code. Thanks in advance for all your help, and assistance.

extends Node2D

const INACTIVE_IDX = -1;
export var isDynamicallyShowing = false
export var listenerNodePath = ""
export var name = ""

var ball
var bg 
var animation_player
var parent
var listenerNode

var centerPoint = Vector2(0,0)
var currentForce = Vector2(0,0)
var halfSize = Vector2()
var ballPos = Vector2()
var squaredHalfSizeLenght = 0
var currentPointerIDX = INACTIVE_IDX;

func _ready():
	bg = get_node("bg")
	ball = get_node("ball")	
	animation_player = get_node("AnimationPlayer")
	parent = get_parent();
	halfSize = bg.get_item_rect().size/2;
	squaredHalfSizeLenght = halfSize.x*halfSize.y;
	if (listenerNodePath != "" && listenerNodePath!=null):
		listenerNodePath = get_node(listenerNodePath)
	elif listenerNodePath=="":
		listenerNodePath = null

	isDynamicallyShowing = isDynamicallyShowing and parent extends Control
	if isDynamicallyShowing:
#		hide()

func get_force():
	return currentForce
func _input(event):
	var incomingPointer = extractPointerIdx(event)
	if incomingPointer == INACTIVE_IDX:
	if need2ChangeActivePointer(event):
		if (currentPointerIDX != incomingPointer) and event.is_pressed():
			currentPointerIDX = incomingPointer;
			showAtPos(Vector2(event.x, event.y));

	var theSamePointer = currentPointerIDX == incomingPointer
	if isActive() and theSamePointer:

func need2ChangeActivePointer(event): #touch down inside analog
	var mouseButton = event.type == InputEvent.MOUSE_BUTTON
	var touch = event.type == InputEvent.SCREEN_TOUCH
	if mouseButton or touch:
		if isDynamicallyShowing:
			return get_parent().get_global_rect().has_point(Vector2(event.x, event.y))
			var lenght = (get_global_pos() - Vector2(event.x, event.y)).length_squared();
			return lenght < squaredHalfSizeLenght
	 return false

func isActive():
	return currentPointerIDX != INACTIVE_IDX

func extractPointerIdx(event):
	var touch = event.type == InputEvent.SCREEN_TOUCH
	var drag = event.type == InputEvent.SCREEN_DRAG
	var mouseButton = event.type == InputEvent.MOUSE_BUTTON
	var mouseMove = event.type == InputEvent.MOUSE_MOTION
	if touch or drag:
		return event.index
	elif mouseButton or mouseMove:
		return 0
func process_input(event):
	calculateForce(event.x - self.get_global_pos().x, event.y - self.get_global_pos().y)
	var isReleased = isReleased(event)
	if isReleased:
	var isPressed = isPressed(event)
	if isPressed:
		#print("is pressed")

func reset():
	currentPointerIDX = INACTIVE_IDX
	calculateForce(0, 0)

	if isDynamicallyShowing:

func showAtPos(pos):
	if isDynamicallyShowing:"alpha_in", 0.2)
func hide():"alpha_out", 0.2) 

#ball position per press
func updateBallPos():
	ballPos.x = halfSize.x * currentForce.x #+ halfSize.x
	ballPos.y = halfSize.y * -currentForce.y #+ halfSize.y

func calculateForce(var x, var y):
	#get direction
	currentForce.x = (x - centerPoint.x)/halfSize.x
	currentForce.y = -(y - centerPoint.y)/halfSize.y
	if currentForce.length_squared()>1:

func sendSignal2Listener():
	if (listenerNodePath != null):
		listenerNodePath.analog_force_change(currentForce, self)

func isPressed(event):
	#print("pressed x")
	#var mouse_pos = get_global_mouse_pos()
	var mouse_pos = get_local_mouse_pos()
	if mouse_pos.x >= 0.1:
		get_node("/root/global").player_direction = "rightm"
	elif mouse_pos.x <= -0.1:
		get_node("/root/global").player_direction = "leftm"
	elif mouse_pos.y <= -0.1:
		get_node("/root/global").player_direction = "upm"
	elif mouse_pos.y >= 0.1:
		get_node("/root/global").player_direction = "downm"
	if event.type == InputEvent.MOUSE_MOTION:
		return (event.button_mask==1)
	elif event.type == InputEvent.SCREEN_TOUCH:
		return event.pressed

func isReleased(event):
	if event.type == InputEvent.SCREEN_TOUCH:
		return !event.pressed
	elif event.type == InputEvent.MOUSE_BUTTON:
		return !event.pressed
:bust_in_silhouette: Reply From: Captain.Susuwatari

The code looks like it’s created out of this plugin…GitHub - gswashburn/Analog-Stick-Demo: Godot 3 - Analog Stick Demo am i right?
So i did these steps to implement that:

  1. Download & install that plugin via Asset Store
  2. In the Scene you have your Player & UI, create a Control Node (with a defined ‘Rectangle’-property, in which the Analog Stick will be showing) then add a instanced child scene from “analog.tscn” and give it properties in the inspector.
  3. Have a look at the “Node” Tab beside the inspector and connect the signal “analog_force_change” with your players code.
  4. The signal passes the vector2D the joystick is pressed, so the receiving function could pass that vector to the movement logic of your player / element you want to move.

I had some errors related to ‘global_position’ of the event, that might be caused by my Godot Version (3.1.2)…if you encounter that: just change the error lines from ‘event.global_position’ to ‘position’ and you should be able to use it.

(Can confirm this plugin works, have implemented & tweaked it for a Twin-Stick-Shooter)

Hi Cap, yes I think so.Only that mine’s the older version prior to 3.0. I’m currently implementing it to a 2d node and I haven’t been successful. I already finished steps one and two. As for step three, I’m not sure yet, but if you could walk me through this, I’d really appreciate it. Perhaps a simple code implementation could really help a lot. Thanks for the reply. Much appreciated.

ddarkmoto | 2020-02-05 14:55