ConvexProjects
ConvexProjects

Reputation: 21

Is there a way to make this 4 diagonal sprite 8 direction movement work?

Basically, I'm trying to make a character move in 8 directions, while only having diagonal sprites. How I plan for this to work is that the character has sprites facing the 4 diagonal cardinal directions, and if say, the character was facing southeast and starts moving south, the sprite wouldn't change. If the character was facing southwest, the same applies. If the character starts moving up from facing southeast, the sprite would face northeast, and if the character moves left from facing northeast, the sprite will face northwest. Same goes from southeast to southwest.

I tried implementing a sort-of vector-based solution, but It didn't actually change the sprites and just showed the UpLeft walking animation. I could still control it, but it didn't do what I wanted it to. Can someone show me a solution to this? Because I'm still a beginner at Godot, and as of now, I have no clue what else to do.

extends CharacterBody2D

const max_speed = 50
const accel = 1500
const friction = 400

var input = Vector2.ZERO

@onready var animation = $AnimationPlayer

func get_input():
    input.x = int(Input.is_action_pressed("ui_right")) - int(Input.is_action_pressed("ui_left"))
    input.y = int(Input.is_action_pressed("ui_down")) - int(Input.is_action_pressed("ui_up"))
    return input.normalized()
    
func player_movement(delta):
    input = get_input()
    
    if input == Vector2.ZERO:
        if velocity.length() > (friction * delta):
            velocity -= velocity.normalized() * (friction * delta)
        else:
            velocity = Vector2.ZERO
    else:
        velocity += (input * accel * delta)
        velocity = velocity.limit_length(max_speed)
        
    move_and_slide()

func updateAnimation():
    var direction = "_DownRight"
    
    if Vector2(1, -1): direction = "_UpRight" 
    if Vector2.ONE: direction = "_DownRight"
    if Vector2(-1, 1): direction = "_DownLeft"
    if Vector2(-1, -1): direction = "_UpLeft"
    if Vector2.ZERO:
        animation.play("walk" + direction + "Idle")
    else:
        animation.play("walk" + direction)
        
func _physics_process(delta):
    player_movement(delta)
    updateAnimation()

Can anybody help me with this?

Upvotes: 0

Views: 941

Answers (1)

Theraot
Theraot

Reputation: 40295

Let me get something out of the way: You are using constants in the conditionals of some of your if statements. Since they are constants we don't need to execute the code to know what will happen.

In particular, know that if you pass a zero value to if, it will evaluate as false. That works for null, but also for Vector2.ZERO and any other zero value.

So here:

    if Vector2.ZERO:
        animation.play("walk" + direction + "Idle")
    else:
        animation.play("walk" + direction)

The execution flow will enter the else branch.

And here:

if Vector2(1, -1): direction = "_UpRight" 

The execution flow will never enter.

In general, you want to use variables in if statements.


Now, since you read Input, convert it to integer, returned normalized, and set input to the return value... There are nine possible values for input:

(-0.707107, -0.707107)
(1.0, 0.0)
(-0.707107, 0.707107)
(0.0, -1.0)
(0.0, 0.0)
(0.0, 1.0)
(0.707107, -0.707107)
(1.0, 0.0)
(0.707107, 0.707107)

Now, the direction needs to be updated based on that.

Since you only have the diagonals, we can only be sure of those:

(-0.707107, -0.707107) -> "_UpLeft"
(1.0, 0.0)
(-0.707107, 0.707107)  -> "_DownLeft"
(0.0, -1.0)
(0.0, 0.0)
(0.0, 1.0)
(0.707107, -0.707107) -> "_UpRight"
(1.0, 0.0)
(0.707107, 0.707107)  -> "_DownRight"

For the cases a 0.0 zero component, from your description, you do not want to change the direction... But the direction might still change based on the other component.

That means two things:

  • We are going to handle this by component.
  • We need to store the direction.

So, declare, near the top of the script, two variables:

var direction_h := ""
var direction_v := ""

Here I'm using _h and _v for horizontal and vertical, respectively.

I'll go with "Down" and "Right" for their default value, since they seem to be the default for you:

var direction_h := "Right"
var direction_v := "Down"

And now we can write this in updateAnimation:

if input.x < 0.0:
    direction_h = "Left"
elif input.x > 0.0:
    direction_h = "Right"

if input.y < 0.0:
    direction_v = "Up"
elif input.y > 0.0:
    direction_v = "Down"

var direction := "_" + direction_v + direction_h

if input == Vector2.ZERO:
    animation.play("walk" + direction + "Idle")
else:
    animation.play("walk" + direction)

Upvotes: 0

Related Questions