Godot version: Godot_v3.2.1-stable_win64

I'm going through godot tutorial, and I got stuck on "Your First Game": https://docs.godotengine.org/en/stable/getting_started/step_by_step/your_first_game.html

Player movement is... weird.

I think the issue is with how clamp() works, and this is why:

My code so far:

extends Area2D

export var speed=400
var screen_size

func _ready():
	screen_size = get_viewport_rect().size

func _process(delta):
	var velocity = Vector2()
	if Input.is_action_pressed("ui_right"):
		velocity.x +=1
	if Input.is_action_pressed("ui_left"):
		velocity.x -=1
	if Input.is_action_pressed("ui_down"):
		velocity.y +=1
	if Input.is_action_pressed("ui_up"):
		velocity.y -=1
	if velocity.length() >0:
		velocity = velocity.normalized() * speed
		$AnimatedSprite.play()
	else:
		$AnimatedSprite.stop()
	
	position += velocity * delta
	position.x = clamp(velocity.x,0,screen_size.x)
	position.y = clamp(velocity.y,0,screen_size.y)

This bit is supposed to allow player to move around, but it doesn't seem to work as intended. The code is same as in tutorial.

I suspect it has something to do with how clamp() works.

Documentation lists two examples on clamp():

speed = 1000
# a is 20
a = clamp(speed, 1, 20)

speed = -10
# a is 1
a = clamp(speed, 1, 20)

First one returns a=20, since speed exceeds the upper limit, and second one returns a=1, since speed is lower than 1. If speed was anywhere between 1 and 20, let's say 15, it would return a=15. That is how I understood clamp() works.

If I remove from code this part at the end:

position.x = clamp(velocity.x, 0, screen_size.x)
position.y = clamp(velocity.y, 0, screen_size.y)

Player can move as intended, but he is not clamped within the confines of the screen, so the player sprite can go beyond its boundaries. Also, player sprite starts at the middle of the screen, where i placed it.

However, without removing that code, player sprite starts at the upper left corner of the screen, instantly teleports across the screen upon button press, and upon button release, returns to starting position at upper left corner.

As I see it, clamp() takes velocity.x (or velocity.y) as first value, 0 as second value, and screen_size.x (or screen_size.y) as third.

screen_size.x is 480 and screen_size.y is 720

Since velocity = velocity.normalized() * speed , velocity.x and velocity.y are both 400 (due to var speed=400)

Thus it seems to me that here:

position.x = clamp(velocity.x, 0, screen_size.x)
position.y = clamp(velocity.y, 0, screen_size.y)

position.x and position.y are being updated to fixed positions, locking player sprite in one position on button press. Also, changing the value of speed also changes to which position player sprite will be locked.

Not sure if I explained this well enough, so ask about anything that needs clarifying.

Thanks in advance!

You need to replace velocity.x and velocity.y in the clamp with position.x and position.y. The clamp is just used to keep the player's position within the bounds of the level.

The stable version of the documentation shows the correct snippet when I looked:

My guess is either there is a typo somewhere in the documentation (I only briefly looked through) or it was a typo when you entered the script. Either way, changing velocity to position in the clamp functions should fix the issue :smile:

Thank you! I must be blind for missing something like this.

@gouserdot said: Thank you! I must be blind for missing something like this.

No problem! I almost missed it myself :smile:

2 years later