0 votes

Hello,

I am having trouble with some 2D topdown 8 directional movements.

When my player hits a corner and the player is moving towards it the sprite can have some visual flickering (I suspect the collision shape is trying to squeeze between two collision boxes forming the corner) I have tried to come up with some solutions to stop this, but so far have only had minor success.

using Input.actionrelease("PlayerLeft") is the closest solution I have found, however, this means the held input is lost until it is released and makes the controls seem clunky and releasing a held movement key is not intuitive.

The other solution I thought of, was to set the speed to 0 as long as the player is colliding, but I can't figure out how to set the speed back once you try to move away from the wall.

Has anyone encountered this problem and do you have any alternative solutions?

Thanks in advance.

in Engine by (21 points)

Hi, what is your setting for physics fps? What is your fps while running the game? More important: how do you move the player e.g. which _process? You should be able to solve it somehow without workarounds. E.g. try _physics_process for updating the player position.

I followed a Zelda like tutorial from fornclakes on youtube with modification to include diagonal movements, the physics process is using delta. Let me paste the code, my edits are not very pretty but this is my first week learning to code so apologies in advance.

Also sorry I haven't included comments to make navigating easier.

extends KinematicBody2D

var SPEED = 60

var movedir = Vector2(0,0)
var spritedir = "Down"
var currentposition = Vector2()


func _input(event):
    if event.is_action_pressed("ui_cancel"):
        get_tree().quit()

func _physics_process(delta):
    controls_loop()
    movement_loop()
    spritedir_loop()

if is_on_wall():
    if movedir.x !=0 and movedir.y !=0:
            anim_switch("Walk")
            if move_and_collide(Vector2(0,0)) and movedir.x !=0 or movedir.y !=0:
                anim_switch("Idle")
                Input.action_release("Player_Left")
                Input.action_release("Player_Right")
    else:
        anim_switch("Idle")
elif movedir !=Vector2(0,0):
    anim_switch("Walk")
else:
    anim_switch("Idle")


func controls_loop():
    var LEFT    = Input.is_action_pressed("Player_Left")
    var RIGHT   = Input.is_action_pressed("Player_Right")
    var UP      = Input.is_action_pressed("Player_Up")
    var DOWN    = Input.is_action_pressed("Player_Down")

movedir.x = -int(LEFT) + int(RIGHT)
movedir.y = -int(UP) + int(DOWN)

func movement_loop():
    var motion = movedir.normalized() * SPEED
    move_and_slide(motion, Vector2(0,0))

func spritedir_loop():
    match movedir:
        Vector2(0,-1):
            spritedir = "Up"
        Vector2(1,-1):
            spritedir = "DiagUR"
        Vector2(1,0):
            spritedir = "Right"
        Vector2(1,1):
            spritedir = "DiagDR"
        Vector2(0,1):
            spritedir = "Down"
        Vector2(-1,1):
            spritedir = "DiagDL"
        Vector2(-1,0):
            spritedir = "Left"
        Vector2(-1,-1):
            spritedir = "DiagUL"

func anim_switch(animation):
    var newanimation = str(animation, spritedir)
    if $PlayerAnim.current_animation !=newanimation:
        $PlayerAnim.play(newanimation)

Hmm I don't really know. Does the flicker look like the player is quickly changing animations or sprites (spritedir_loop changes the sprite, right)? Or is it just movement? If it's animations or sprite change, you could look into modifying something about assigning those when moving diagonally. (e.g. move_and_slide returns a Vector2 and you can use that to get if the player actually moved, or you may use move_and_collide and that stops the movement when colliding, but it is more a workaround rather than a solution).

So I am pretty sure the issue is due to move_and_slide() I noticed if I hold a single direction eventually I start to see my player character sliding a tiny amount over and causing a similar effect.

I suppose I can switch to move_and_collide() but I do want to slide along the wall when holding diagonal directions. Not sure what my next step will be

Strange, it works for me well, though I only use a polygon2d triangle as a player.
Here's my movement code, maybe you can compare and find something:
actually, I use _process, which I would not recommend :D

func _process(delta):
    if not can_move():
        return
    var direction = Vector2()
    if Input.is_action_pressed("ui_up"):
        direction.y -= 1
    if Input.is_action_pressed("ui_down"):
        direction.y += 1
    if Input.is_action_pressed("ui_left"):
        direction.x -= 1
    if Input.is_action_pressed("ui_right"):
        direction.x += 1
    direction = direction.normalized()
    move_and_slide(direction * speed)
    rotation_target = direction

and I rotate the triangle smoothly based on rotation_target in another script

Please log in or register to answer this question.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.