Have node slide a little further after Iinput movement stops

In my game, I am moving a node up and down with an InputEventMouseMotion / InputEventScreenDrag.

(these activate the same method, but makes it work on more devices.)

After I release the input of dragging, the node immediately comes to a halt as it does according to the code.

How do I make it slide a little further with a decreasing speed for a bit more immersion?

my code looks like this, $crt/images is the node being moved.:

func _on_crt_gui_input(event):

#for testing in the editor
	if (event is InputEventMouseMotion):
		if (event.pressure == 1.00):
			_drag_event(event)

#for the export, and testing on my phone
	elif (event is InputEventScreenDrag):
		_drag_event(event)
func _drag_event(event):
#make the node only move vertically
	direction = event.relative.y
	
	$crt/images.position = Vector2($crt/images.position.x , $crt/images.position.y + direction)

I’m assuming you just want to give the node a bit of momentum.

To give a node momentum, you have to implement a system where the node (or the owner of the node) is aware of the node’s velocity. You’re essentially trying to create a primitive physics simulation.

Creating a basic physics system (for this)

Currently, you are moving your node based on the delta of your input (event.relative.y). When no input is detected, the node’s position is not updated. For physically-based systems, the physical object (your node) must be continually updated because the state of the node describes how the node should move.

Examples of state variables in a physically-based system:

  • Position
  • Velocity
  • Acceleration
  • Angular velocity
  • Center of mass (this is usually constant)

As such, you need to implement a system that constantly updates the state of your node. Below is a simple implementation of such a system.
NOTE: The example is one-dimensional based on the code you supplied. If you wish the system to handle motion on more than one axes, you must correct the code below.

var acceleration: float
var speed: float # In higher dimensions, this would be named 'velocity'
var drag_coefficient = 1.0 # This controls how far the node "slides"

func _physics_process(delta):
    # Acceleration
    speed += acceleration * delta
    # Drag
    speed -= drag_coefficient * speed * delta
    # Positional change
    position += speed * delta

Because your use-case wants the speed (‘velocity’ in higher dimensions) to be controlled directly by your input, you may remove the #Acceleration part - it’s not needed in this case.

To allow your drag to control the physical system, simply set the speed to event.relative.y / delta. Alternatively, you can use event.velocity; it will avoid the need for delta which isn’t directly accessible in _input().

How to get the physics delta outside _physics_process()
var delta = 1.0 / ProjectSettings.get_setting("physics/common/physics_ticks_per_second")
For smoother motion

If you want the system above to update at a higher rate, you may substitute _physics_process() for _process(). However, do note that the variable update rate of _process() may introduce instability for systems like this that greatly depend on delta. If such instability is experienced, please constrain the simulation to avoid unwanted states.

1 Like

This works.

only change I needed to add was adding speed to the positional change, else wise you only have the slide occur, not the manual input the slide needs to come from

$crt/images.position.y += ( speed * delta ) + speed 

That doesn’t look entirely correct, actually.

Since speed should describe the difference in position over 1 second, you have to divide event.relative.y with delta to achieve the same unit.

Speed/Velocity SI unit is metres per second (m/s)


Upon further inspection of the InputEventMouseMotion class, there is a velocity variable available which is very useful for your use case.

Please use the following code instead and see if that works better for you.

func _drag_event(event):
    speed = event.velocity.y

func _physics_process(delta):
    $crt/images.position.y += speed * delta

If you’re having trouble with this, please show me how you interpreted my solution in your own script.

1 Like

I’ve got an extreme example of this in one of my test games…it’s on the edge of unplayable on purpose.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.