How to make character move continually with tile-based movement when holding down the button

Godot Version

Godot 4.1.3

Question

How can I make my sprite continually move when holding down the button?
Every guide I find online has it when you press the move button, it only moves 1 tile and then you have to release and press it again to move it again 1 tile, I want to have it so when holding down the movement button, the character continually moves tiles and only stops when you release the button.

extends Area2D


@onready var ray = $RayCast2D

var tile_size = 32
var inputs = {
"right": Vector2.RIGHT,
"left": Vector2.LEFT,
"up": Vector2.UP,
"down": Vector2.DOWN}

func _ready():
	position = position.snapped(Vector2.ONE * tile_size)
	position += Vector2.ONE * tile_size/2

func _unhandled_input(event):
	for dir in inputs.keys():
		if event.is_action_pressed(dir):
			move(dir)

func move(dir):
	ray.position += inputs[dir] * tile_size
	ray.force_raycast_update()
	if !ray.is_colliding():
		position += inputs[dir] * tile_size

^ this is the code I have now which only makes the character move 1 tile when the button get pressed.

You need something ro call the move again. Your best bet is probably a timer- Timer — Godot Engine (stable) documentation in English
You’d want to save the key press to a var for the move to use, and might want to add a key up so you can stop.

1 Like
extends Area2D

var tile_size = 32
var inputs = {
"ui_right": Vector2.RIGHT,
"ui_left": Vector2.LEFT,
"ui_up": Vector2.UP,
"ui_down": Vector2.DOWN}
var hold={
"ui_right": false,
"ui_left": false,
"ui_up": false,
"ui_down": false}
var moving={
"ui_right": false,
"ui_left": false,
"ui_up": false,
"ui_down": false}
const MOVE_DELAY:float=1.0

func _ready():
	position = position.snapped(Vector2.ONE * tile_size)
	position += Vector2.ONE * tile_size/2

func _unhandled_input(event):
	for dir in inputs.keys():
		if event.is_action_pressed(dir):
			hold[dir]=true
			move(dir)
		if event.is_action_released(dir):
			hold[dir]=false

func move(dir):
	if moving[dir]:
		return
	if not moving[dir]:
		moving[dir]=true
	while hold[dir]:
		position += inputs[dir] * tile_size
		await get_tree().create_timer(MOVE_DELAY).timeout
		if not hold[dir]:
			break
	moving[dir]=false

this one i tried without raycast detection, issue found such like if you hold left and right at the same time, it will exactly move left and right every 1 second. at least, this give you an idea how to handle hold input

GIF:
holdinputmovement

1 Like

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