Pressing key for smooth sprite movement, ignoring typematic delay

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

Hi all,

I have figured out how to do a press so the event only occurs once. I’ve learned how to read a keypress event that allows repeated events.

The problem is, it uses my systems typematic delay. So I press the Right Arrow and it moves 1 pixel to the right, then waits a second, then starts moving the rest of the pixels to the right.

How can I get Godot to start and keep moving my sprite whilst the key is down, smoothly, regardless of typematic delays etc?

Thanks a tonne…

:bust_in_silhouette: Reply From: avencherus

You’ll want to poll input in the fixed_processing loop.

extends Node2D
func _ready(): 
	set_fixed_process(true)

func _fixed_process(delta):
	if(Input.is_key_pressed(KEY_UP)): print("key up")

Thank you for the answer. It’s a great way to work it out. I’ve done the following:

func update(delta):
		#let's check for keyboard input on a frame by frame basis
		if(Input.is_key_pressed(KEY_UP)):
			game.direction = -1 #moving up
			move(delta)
		elif(Input.is_key_pressed(KEY_DOWN)):
			game.direction = 1 #moving down
			move(delta)
		else:
			game.direction = 0 #not moving

I’ll put this in response to Zylann also as you both gave me what’s required. I sort of blended both approaches.

Robster | 2017-02-03 02:48

You may want to stay away from naming the function update if you’re using Node2D. They inherit CanvasItem, which has an update() method. It’s used to call a canvas redraw.

avencherus | 2017-02-03 11:43

Well spotted, but it’s deliberate.

This function is inside a class and back in the func _ready(): method I have this:

func _fixed_process(delta):
	state.update(delta)

So the idea is, to call the update function within the state class. Very cool thing I learned from the state machine lessons in the flappy bird tutorials. It doesn’t matter which state we’re in, as we change states this will call the function with the same name in each class that is “state” as per the onready above.

As long as the function in each state is called update then it’s fine. Cool huh.

Robster | 2017-02-03 22:11

:bust_in_silhouette: Reply From: Zylann

I guess you get this delay because you are using _input, which is an event-based method.
If you want movement at every frame, you need to also use _fixed_process.
So you can create a boolean variable which you set to true when the key is pressed, and false when it’s released. Then, in _fixed_process(delta) (which is called every frame), you move whatever you want if the boolean is true.
Or you can also use Input.is_action_pressed("action_name") or Input.is_key_pressed(KEY_*) instead of a boolean, depends on what is better for you :slight_smile:

Note: _process is also called every frame but it’s recommended to do movement and physics in _fixed_process due to it being in sync with the physics engine.

Thank you for the answer. It’s a great way to work it out. I’ve done the following:

func update(delta):
		#let's check for keyboard input on a frame by frame basis
		if(Input.is_key_pressed(KEY_UP)):
			game.direction = -1 #moving up
			move(delta)
		elif(Input.is_key_pressed(KEY_DOWN)):
			game.direction = 1 #moving down
			move(delta)
		else:
			game.direction = 0 #not moving

I’ll put this identical response in response to avencherus also as you both gave me what’s required. I sort of blended both approaches. You guys are really great. Thanks again

Robster | 2017-02-03 02:49