Step-by-step movement tutorial for player

Godot Version

4.5.1

Question

I have a task to implement the player’s training in the basics of movement. For example, when the message “Press W to go forward” appears, the player should not be able to perform any other action. When performing an action, the following prompt appears for moving to the side, jumping, and so on.

My decision looks like a solid “if” and, to be honest, I’m ashamed to show it, but I do not know how to do otherwise. Can you tell me if there is a simple solution?

Post your code. No need to be ashamed.

I have created global variables:

var tutor_count = 0
var tutor = false
extends CharacterBody3D

func _physics_process(delta: float) -> void:
	if not is_on_floor():
		velocity += get_gravity() * delta
	
	var input_dir
	
	if auto.tutor == false:
		if auto.tutor_count == 0:
			if Input.is_action_just_pressed("tutorial") and is_on_floor():
				velocity.y = JUMP_VELOCITY
			input_dir = Input.get_vector("tutorial", "tutorial", "forward", "tutorial")
		
		if auto.tutor_count == 1:
			if Input.is_action_just_pressed("tutorial") and is_on_floor():
				velocity.y = JUMP_VELOCITY
			input_dir = Input.get_vector("tutorial", "tutorial", "forward", "backward")
		
		if auto.tutor_count == 2:
			if Input.is_action_just_pressed("tutorial") and is_on_floor():
				velocity.y = JUMP_VELOCITY
			input_dir = Input.get_vector("left", "tutorial", "forward", "backward")
		
		if auto.tutor_count == 3:
			if Input.is_action_just_pressed("tutorial") and is_on_floor():
				velocity.y = JUMP_VELOCITY
			input_dir = Input.get_vector("left", "right", "forward", "backward")
		
		if auto.tutor_count == 4:
			if Input.is_action_just_pressed("jump") and is_on_floor():
				velocity.y = JUMP_VELOCITY
			input_dir = Input.get_vector("left", "right", "forward", "backward")
		
	elif auto.tutor == true: 
		if Input.is_action_just_pressed("jump") and is_on_floor():
			velocity.y = JUMP_VELOCITY
		input_dir = Input.get_vector("left", "right", "forward", "backward")
	
	var direction = (Head.transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
	if direction:
		velocity.x = -direction.x * SPEED
		velocity.z = -direction.z * SPEED
	else:
		velocity.x = move_toward(velocity.x, 0, SPEED)
		velocity.z = move_toward(velocity.z, 0, SPEED)
	
	move_and_slide()

I also have a separate “CanvasLayer” scene in which the “Label” output is processed and the “tutor_count” is calculated depending on the level of progress.

extends CanvasLayer

func _input(event: InputEvent) -> void:
	if event.is_action_pressed("forward") && auto.tutor_count == 0:
		movement_w.visible = false
		movement_s.visible = true
		auto.tutor_count += 1

	if event.is_action_pressed("jump") && auto.tutor_count == 4:
		movement_jump.visible = false
		auto.tutor = true
		auto.tutor_count = 0
		visible = false
		queue_free()

Of course, I didn’t insert all the code, but parts of it, but I hope this doesn’t interfere with understanding.
UPD: The “tutorial” is an empty action, meaning its InputMap is empty.

Yes, there’s a much simpler solution. Give me a few minutes.

1 Like

Yeah, avoid doing it like this. Your code should be driven by structured data, resulting in much smaller amount of non-repetitive code.

I suspect @dragonforge-dev will present an example of just that, so let’s wait for their response :wink:

2 Likes
extends CharacterBody3D

func _physics_process(delta: float) -> void:
	if not is_on_floor():
		velocity += get_gravity() * delta
	
	var input_dir

	match auto.tutor_count:
		0:
			input_dir = Input.get_vector(0.0, 0.0, "forward", 0.0)
		1:
			input_dir = Input.get_vector(0.0, 0.0, "forward", "backward")
		2:
			input_dir = Input.get_vector("left", "0.0", "forward", "backward")
		3:
			input_dir = Input.get_vector("left", "right", "forward", "backward")
		_: #Default option, once you hit 4 or higher, it'll just stay here. As you add more steps, just put them in.
			if Input.is_action_just_pressed("jump") and is_on_floor():
				velocity.y = JUMP_VELOCITY
			input_dir = Input.get_vector("left", "right", "forward", "backward")
	
	var direction = (Head.transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
	if direction:
		velocity.x = -direction.x * SPEED
		velocity.z = -direction.z * SPEED
	else:
		velocity.x = move_toward(velocity.x, 0, SPEED)
		velocity.z = move_toward(velocity.z, 0, SPEED)
	
	move_and_slide()

I got rid of the auto.tutor check. You can put it back if you want, but it’s extraneous info that isn’t needed.

1 Like

Thanks a lot)
UPD:
Cannot pass a value of type “float” as “StringName”.
Invalid argument for “get_vector()” function: argument 1 should be “StringName” but is “float”.

But there is a “tutorial” with an empty InputMap for this.

1 Like

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