Simple movement for top down shooter problem

Godot Version

4.4.1

Question

I am trying to make a top down shooter, my first focus is movement. A video below of some mobile top down game is what I am trying to achieve, simple top down movement mechanic where the character slide along the wall properly (Warning: I am not good at speaking English and I am new to Godot and this forum).

goal

Thought its gonna be easy so I put this in script:

var speed := 300
func _physics_process(delta: float) -> void:

    var input_dir = Input.get_vector("move_left", "move_right", "move_up", "move_down").normalized()
    var velo = input_dir * speed
    var motion = velo * delta

    var collision = move_and_collide(motion)
    
    if collision:
        var normal = collision.get_normal()
        
        var vel_to_wall = normal * velo.dot(normal)
        var vel_along = velo - vel_to_wall
        motion = vel_along * delta
        move_and_collide(motion)

But the problem is when I test it by moving along steep angled wall, it boosts the character, moving faster than set speed. Here is the video below (the right wall is 1 degree tilted):

outcome

Turns out move_and_collide (and move_and_slide) should be called once per frame. So I try fix it by declaring collision outside of function and to ensure move_and_collide is called once, like this:

var speed := 300
var collision

func _physics_process(delta: float) -> void:
    
    var input_dir = Input.get_vector("move_left", "move_right", "move_up", "move_down").normalized()
    var velo = input_dir * speed
    var motion = velo * delta

    if collision:
        var normal = collision.get_normal()
        
        var vel_to_wall = normal * velo.dot(normal)
        var vel_along = velo - vel_to_wall
        motion = vel_along * delta
        move_and_collide(motion)
        collision = null
    else:
        collision = move_and_collide(motion)

This works but new issue appears: the character jitters when sliding…
About CharacterBody2D property, I set the Motion Mode to Floating and Wall Min Slide Angle to 0.

Anyone know the solution for this?

have you tried using move_and_slide instead of move_and_collide?

func _physics_process(delta: float) -> void:
    
    var input_dir = Input.get_vector("move_left", "move_right", "move_up", "move_down").normalized()
    velocity = input_dir * speed
    move_and_slide()

If I use move_and_slide only, character will slide along wall… with set speed, so when I facing against a wall (and my speed is 300) and I try strafing left, I will move left with same speed of 300. Video below showcase 4 different moving function:

showcase (and fixing progress I guess)

If you want to see the code, here:

upper part

var speed = 300
var collision

func _physics_process(delta: float) -> void:
	var input_dir = Input.get_vector("move_left", "move_right", "move_up", "move_down").normalized()
	velocity = input_dir * speed
	#and below is different moving mode

“wall boost bug”

	var collision = move_and_collide(velocity * delta)

	if collision:
		var normal = collision.get_normal()
		
		var vel_to_wall = normal * velocity.dot(normal)
		var vel_along = velocity - vel_to_wall
		velocity = vel_along
		move_and_slide()

“jitter bug”

	if collision:
		var normal = collision.get_normal()
		
		var vel_to_wall = normal * velocity.dot(normal)
		var vel_along = velocity - vel_to_wall
		velocity = vel_along
		move_and_slide()
		collision = null
	else:
		collision = move_and_collide(velocity * delta)

weird small gap

	var collision = move_and_collide(velocity * delta, true)
	if collision:
		var normal = collision.get_normal()
		
		var vel_along = velocity - normal * velocity.dot(normal)
		velocity = vel_along

		move_and_slide()
	else:
		move_and_slide()

move_and_slide only

	move_and_slide()

Here the “wall boost bug” and “jitter bug” snippet are those 2 script snippets in the post above, but just little change on the bottom part, the result still same

alright I have figured it out now, solution for this is in “small weird gap” where I change the first move_and_collide part from this

move_and_collide(velocity * delta, true)

to this

var motion = velocity * delta
move_and_collide(motion.normalized(), true)

Basically test collision using move_and_collide and put very small vector in the first argument. The second argument is a test_only, if true then the body won’t move but gives would-be collision info.

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