0 votes

when i press up and left/right at same time while my character face down, my character will moonwalk to up right. or when i press left+up then +right and release left, my character start to moonwalk to right , my character play animationplayer moveLeft over moveRight.
sorry for my broken eng.

extends KinematicBody2D

const move_speed = 100
var move_direction = dir.center
var sprite_direction = "_Down"


func _physics_process(delta):
    control_loop()
    move_loop()
    sprite_loop()
    if move_direction != dir.center:
        animation_play("Fmove")
    else:
        animation_play("Fidle")


    pass

func control_loop():#control key
    var RIGHT = Input.is_action_pressed("ui_right")
    var LEFT = Input.is_action_pressed("ui_left")
    var DOWN = Input.is_action_pressed("ui_down")
    var UP = Input.is_action_pressed("ui_up")
    ############Walking##################
    move_direction.x = int(RIGHT) -int(LEFT)
    move_direction.y = int(DOWN)  -int(UP)



func move_loop():
    var motion = move_direction.normalized() * move_speed
    move_and_slide(motion, dir.center)




func sprite_loop():
    match move_direction:
        dir.right:
            sprite_direction ="_Right"
        dir.left:
            sprite_direction = "_Left"
        dir.up:
            sprite_direction = "_Up"
        dir.down:
            sprite_direction = "_Down"
in Engine by (423 points)

1 Answer

+1 vote
Best answer

Judging from your code-snippet, you can walk diagonally too, but you only assigned 4 directions to your spriteloop.
You either add additional conditions for diagonal movement or you completely switch to 4 direction movement.

Conditions for diagonal movement would be (keep everything as is, but add 4 extra conditions to your spriteloop):

if dir.right and dir.up:
    sprite_dir = "up" # or right, depends on your preference
if dir.right and dir.down:
    sprite_dir = "down" # or right, again your preference what you like more

Or you switch to 4 way movement instead of 8 with the following code example (just switch out input code, keep everything else as is):

func get_input():
    velocity = Vector2()
    if Input.is_action_pressed("ui_right"):
        velocity.x += 1
    elif Input.is_action_pressed("ui_left"):
        velocity.x -= 1
    elif Input.is_action_pressed("ui_down"):
        velocity.y += 1
    elif Input.is_action_pressed("ui_up"):
        velocity.y -= 1
    movement = velocity.normalized() * speed

and have your process set up like

func _process(delta):
    get_input()
    move_and_slide(movement)

The second version is what I have switched to in my game. It fits more to the retro arcade style I try to follow, where you only could walk in 4 directions.
Would be nice if you could report back if this helped.

by (143 points)
selected by

thank you for your answer,
if you want to use 4 direction use this code u just need to put if move_direction.y == 0: and if move_direction.x == 0: like this :

func control_loop():#control key
    var RIGHT = Input.is_action_pressed("ui_right")
    var LEFT = Input.is_action_pressed("ui_left")
    var DOWN = Input.is_action_pressed("ui_down")
    var UP = Input.is_action_pressed("ui_up")
    ############Walking##################
    if move_direction.y == 0:
        move_direction.x = int(RIGHT) -int(LEFT)
    if move_direction.x == 0:
        move_direction.y = int(DOWN)  -int(UP)

i understand what your meant in 8 direction, but if i put your code under func physicsprocess my idle always facing down. and i dont how to put "if" in match.

The code you provided for 4-way movement is good too. :)

You can keep the conditions within a match statement too, gets the job done to prevent moonwalking. Or you make it a feature in your game and make it a Michael Jackson game. (just kidding)

Right now the code does the following:
Press Left + Up makes the direction to Vector2(-1,-1), which is not set for spritedirection, so it takes the first one in your spriteloop that fits the criteria, which is spriteleft. If sprite.dir up would be before left in your match statement, the character would walk up instead of left.
If you now press Right and release Left, the Vector becomes Vector2(1,-1), which is again not set as direction, so the sprite_loop keeps the previous direction as is and does not trigger any condition.

To illustrate, I edit your code as an example and keep it as similar as you use it. This way you dont have to change much in your code (no crazy if/elif blocks):

func sprite_loop():
    match move_direction:
        dir.right:
            sprite_direction ="_Right"
        dir.left:
            sprite_direction = "_Left"
        dir.up:
            sprite_direction = "_Up"
        dir.down:
            sprite_direction = "_Down"
        dir.upleft:# equals Vector2(-1,-1) when you press up AND left
            sprite_direction = "_Left"
        dir.upright:# equals Vector2(1,-1)
            sprite_direction = "_Right"
        dir.downleft:# Vector(-1,1) I think you got the idea
            sprite_direction = "_Left"
        dir.downright:# Vector2(1,-1)
            sprite_direction = "_Right"

hope this helps.

omg, thank you so much, lol i totally forgot about Vector2, i spent 5 day to solve this problem yet not even remember Vector2. when you first reply to me i was like this good idea must work then i was like dir.up + dir.left = vector2(-1,-1). lol. you save my day, thanks.

extends Node

const center = Vector2(0,0)
const right = Vector2(1,0)
const left = Vector2(-1,0)
const up = Vector2(0,-1)
const down = Vector2(0,1)
const upLeft = Vector2(-1,-1)
const upRight = Vector2(1,-1)
const downLeft = Vector2(-1,1)
const downRight = Vector2(1,1)

func random():
    var d = randi() % 9 + 1
    match d:
        1:
            return center
        2:
            return right
        3:
            return left
        4: 
            return up
        5:
            return down
        6: 
            return upLeft
        7:
            return upRight
        8: 
            return downRight
        9:
            return downLeft

i have one question, did godot have point direction func like from(x,y) ,to (x,y)?

Glad I could help! :)

i have one question, did godot have point direction func like from(x,y) ,to (x,y)?

Can you rephrase the question or give an example? Do you want a Vector pointing towards an object on the screen? If yes: http://docs.godotengine.org/en/latest/tutorials/math/vector_math.html#practical-applications

You just subtract your position from the desired position and get a Vector in return that points from your position to your target.

Example:
VectorToTarget = MyPosition - TargetPosition
I hope I understood you correctly

yes , Vector pointing towards an object on the screen. thank you.
can i bother future? if i have some with godot?

I'd suggest creating a thread in the forums, so others who have the same issues can find answers. I am a beginner myself and dont know everything. But if you want to chat about game dev stuff, you can message me on twitter. My username is @nooberdev

i will make thread when i finish this project, so i can answer q. ill make twitter then.

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 Frequently asked questions and 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 [email protected] with your username.