hello everyone , i was wondering if there was a way to make a player just move in 4 directions (as in up down left right one at a time)
without the use of a grid-based movement system.
this is my current code
var SPEED = 300
func _physics_process(delta):
var direction = Input.get_vector("left","right","up","down")
if direction:
velocity = direction*SPEED
else :
velocity = Vector2.ZERO

i also tried placing each direction in its own if statment but that didnt seem to help

  • Folivora Simple mutual exclusion always feels wonky. Here's how it should be done in the most player-friendly way:

    var pressed_actions = []
    const directions = { &"ui_left": Vector2(-1, 0), &"ui_right": Vector2(1, 0), &"ui_up": Vector2(0, -1), &"ui_down": Vector2(0, 1) }
    
    func _process(delta):
    	for d in directions:
    		if Input.is_action_just_pressed(d):
    			pressed_actions.push_back(d)
    		if Input.is_action_just_released(d):
    			pressed_actions.erase(d)
    	var direction = Vector2.ZERO if pressed_actions.is_empty() else directions[pressed_actions[-1]]
    	print(direction)

    If multiple actions are pressed is will use the one that was pressed last, and if one of the actions is released while one or more actions are still held, it will use the one that was pressed last among the still held actions. This feels very natural and pleasant to the player.

One method is to convert the direction vector to an angle, and then round it to the nearest multiple of 90 degrees. Then convert the result back to a vector for the velocity calculation.

    You could just logic a new Vector2 from the inputs.

    var ndir : Vector2 = Vector2.ZERO
    if direction.x > 0.0:
        ndir = Vector2.RIGHT
    elif direction.x < 0.0:
        ndir = Vector2.LEFT
    elif direction.y > 0.0:
        ndir = Vector2.UP
    elif direction.y < 0.0:
        ndir = Vector2.DOWN

    It's not elegant but not everything has to be.

      Jesusemora
      so like this
      func _physics_process(delta):
      var direction = Input.get_vector("left","right","up","down")
      if direction:
      velocity = direction*SPEED
      else :
      velocity = Vector2.ZERO
      var ndir : Vector2 = Vector2.ZERO
      if direction.x > 0.0:
      ndir = Vector2.RIGHT
      elif direction.x < 0.0:
      ndir = Vector2.LEFT
      elif direction.y > 0.0:
      ndir = Vector2.UP
      elif direction.y < 0.0:
      ndir = Vector2.DOWN
      move_and_slide()

      player still moves diagonally tho

        var direction = Input.get_vector("left","right","up","down")

        This gets all the input vectors when you simply don't want that; if you want to move in a single direction, it needs to be mutually-exclusive, e.g. if the player is going left, then only move them left. If they're not going left, then you can check the other input vectors. You can get input vectors one-at-a-time.

        The code posted above is almost there. Do you think this:

        if direction:
            velocity = direction * SPEED
        else:

        Is necessary?

          DaveTheCoder
          how do you do that exactly ?

          if Input.is_action_pressed("right"):
          velocity = snapped(Vector2.RIGHT.angle() , 90)* SPEED

          something like this?

            spaceyjase
            var direction = Input.get_vector("left") or Input.get_vector("right")
            this is not something i can do right?
            or maybe
            var direction = Input.get_axis("left") or Input.get_axis("right")

            • xyz replied to this.

              Folivora Simple mutual exclusion always feels wonky. Here's how it should be done in the most player-friendly way:

              var pressed_actions = []
              const directions = { &"ui_left": Vector2(-1, 0), &"ui_right": Vector2(1, 0), &"ui_up": Vector2(0, -1), &"ui_down": Vector2(0, 1) }
              
              func _process(delta):
              	for d in directions:
              		if Input.is_action_just_pressed(d):
              			pressed_actions.push_back(d)
              		if Input.is_action_just_released(d):
              			pressed_actions.erase(d)
              	var direction = Vector2.ZERO if pressed_actions.is_empty() else directions[pressed_actions[-1]]
              	print(direction)

              If multiple actions are pressed is will use the one that was pressed last, and if one of the actions is released while one or more actions are still held, it will use the one that was pressed last among the still held actions. This feels very natural and pleasant to the player.

                xyz
                hello mind explaining this line to me more

                const directions = { &"ui_left": Vector2(-1, 0), &"ui_right": Vector2(1, 0), &"ui_up": Vector2(0, -1), &"ui_down": Vector2(0, 1) }

                • xyz replied to this.

                  xyz
                  is this what i should be left with
                  `var pressed_actions = []
                  const directions = { "left" : Vector2(-1, 0), "right": Vector2(1, 0), "up": Vector2(0, -1), "down": Vector2(0, 1) }

                  func _process(delta):
                    for d in directions:
                  	if Input.is_action_just_pressed(d):
                  		pressed_actions.push_back(d)
                  	if Input.is_action_just_released(d):
                  		pressed_actions.erase(d)
                  var direction = Vector2.ZERO if pressed_actions.is_empty() else directions[pressed_actions[-1]]
                  print(direction)
                  
                  
                  
                  
                  
                  
                  func _physics_process(delta):
                  if directions:
                  	velocity = directions * SPEED
                  	
                  else :
                  	velocity = Vector2.ZERO
                  move_and_slide()
                  if velocity == Vector2.ZERO:`
                  • xyz replied to this.

                    Folivora You can put everything into _physics_process()

                    And use ~~~ to properly format a code block.

                    xyz
                    never mind it works now
                    thak you and sorry for the inconvinence

                    Folivora you were supposed to use ndir for movement instead of direction.
                    Well it is solved now.

                    DaveTheCoder One method is to convert the direction vector to an angle, and then round it to the nearest multiple of 90 degrees. Then convert the result back to a vector for the velocity calculation.

                    Folivora how do you do that exactly ?

                    const HALF_PI: float = PI / 2.0
                    var new_direction: Vector2 = Vector2.from_angle((roundf(direction.angle() / HALF_PI)) * HALF_PI)

                    DaveTheCoder That's grid based. I think OP asked specifically for non-grid, continuous movement.

                    It's not grid-based, unless I misunderstand what that means.

                    • xyz replied to this.

                      DaveTheCoder Looks pretty grid-y to me 🙂 When I press the key once the circle instantly steps for a distance that's roughly its size.

                      The distance moved is determined by a speed constant.

                      That's only a quick demo for using the code I posted above. I guess it could be made smoother, but I wasn't trying to do that.

                      The full code is here: https://github.com/daveTheOldCoder/zigzag

                      • xyz replied to this.