Rotate a sprite on mouse drag like a valve handle/crank

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By CraftyManiac
:warning: Old Version Published before Godot 3 was released.

Hey there. I’m super new to Godot and game dev in general. I am trying to find a way to rotate a a sprite when I click and drag in a circular motion and add a value to a var whenever it’s moved a little bit, like you would with a valve handle or a crank. Any help would be appreciated thanks!

Do you want the user having to drag by doing an arc or a straight line?

Zylann | 2016-12-09 18:14

user dragging in an arc/ circle to turn the valve/crank

CraftyManiac | 2016-12-09 18:31

:bust_in_silhouette: Reply From: Zylann

I fiddled a little in the editor and this is what I came up with:

Use an Area2D with a CollisionShape2D that has the shape you want for dragging (be it a circle or a handle), make sure it is set as pickable=true, Then use a script that listens to the Area2D input_event signal so you’ll know when the mouse clicks on it:

  • Sprite (crank.gd)
    • ClickArea (Area2D)
      • CollisionShape2D

After that you need further input processing and a bit of math:
crank.gd

extends Sprite


var dragging = false


func _ready():
	# Connect to the Area2D input signal so we know when the user clicks on it
	get_node("ClickArea").connect("input_event", self, "_on_area_input_event")
	set_process_input(true)


func _on_area_input_event(viewport, event, shape):
	if event.type == InputEvent.MOUSE_BUTTON:
		# Start dragging when the user presses the mouse button over the clickable area
		dragging = event.pressed


func _input(event):
	if dragging:
		if event.type == InputEvent.MOUSE_MOTION:
			var motion = event.relative_pos
			var new_pos = get_global_mouse_pos()
			var prev_pos = new_pos - motion
			var center = get_global_pos()
			# Calculate the angular motion of the crank based on the arc made with the mouse
			var angle = (prev_pos - center).angle_to(new_pos - center)
			rotate(angle)
		
		elif event.type == InputEvent.MOUSE_BUTTON and event.pressed == false:
			# Stop dragging when the user releases the mouse button
			dragging = false

Here is the example project: http://zylannprods.fr/dl/godot/DragRotate.zip
You probably have a more complete setup, you might adapt it for your needs :slight_smile:

Awesome I will give this a shot, Thanks!

CraftyManiac | 2016-12-11 16:51

It works… awesome thanks!

CraftyManiac | 2016-12-11 17:24

Thanks for this!

stevepop | 2017-08-19 19:14