How can I shoot an arrow without diagonal direction?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Meyerjc

I’d like to shoot an arrow based only on four directional movement.

Currently I have the Player scene which instances the arrow:

extends KinematicBody2D

export var speed = 100

var last_direction = Vector2.ZERO
var packed_arrow = preload("res://projectile/Arrow.tscn")

func _process(delta):
	var move_x = Input.get_action_strength("right") - Input.get_action_strength("left")
	var move_y = Input.get_action_strength("down") - Input.get_action_strength("up")
	
	var direction = Vector2(move_x, move_y).normalized()
	
	if (direction != Vector2.ZERO):
		last_direction = direction
	
	if (Input.is_action_just_pressed("shoot")):
		var arrow = packed_arrow.instance()
		arrow.global_position = global_position
		arrow.rotation = last_direction.angle()
		get_parent().add_child(arrow)
	
	
	move_and_slide(direction * speed)

and the arrow scene itself:

extends Area2D 

var pushback_strength = 50 var speed = 200

func _process(delta): 	position += Vector2.RIGHT.rotated(rotation) * speed * delta

Any help is appreciated! Thanks!

:bust_in_silhouette: Reply From: Gluon

So to clarify I am assuming from your question that you only want the arrow to go straight up, down, left or right? If thats the case you can do this;

func _process(delta):
    var move_x = Input.get_action_strength("right") - Input.get_action_strength("left")
    var move_y = Input.get_action_strength("down") - Input.get_action_strength("up")

    if move_x != 0:
        move_y = 0

    var direction = Vector2(move_x, move_y).normalized()

I wouldnt say this was the best way to do it but unless you rewrite the code this is the easiest I think.

I’m not sure I understand. If I put this script in the Arrow scene then the arrow doesn’t move when instanced.

Meyerjc | 2022-05-24 00:28

I may have misunderstood what you were trying to do or what code outside that shown here is doing. I thought you were saying you only want the arrow to move straight up, down, left or right? Not diagonal?

The code I added is not pretty and not the best way to do it but it should mean that if there is any movement in the x axis that there will be no movement in the y axis. It wouldnt stop any movement in the x axis or remove movement in the y axis if there was no movement on the x axis.

Let me know if I have misunderstood your requirements

Gluon | 2022-05-24 10:09

You are absolutely right about what I am trying to accomplish. However, the problem is that I would still like the player to move diagonally.

Meyerjc | 2022-05-25 04:16

enter code here Oh I see that is the player code not the arrow code. In that case in your arrow code you want to specify from the players code which direction the arrow is to go?

On that assumption you will need a direction var to specify so something like this

var ArrowDirection = Vector2.ZERO

then in the player code you will need a var to pass to it so a change like this:

var last_direction = Vector2.ZERO
var packed_arrow = preload("res://projectile/Arrow.tscn")
var holdArrDirection = Vector2.ZERO

func _process(delta):
    var move_x = Input.get_action_strength("right") - Input.get_action_strength("left")
    var move_y = Input.get_action_strength("down") - Input.get_action_strength("up")
  
var direction = Vector2(move_x, move_y).normalized()

if (direction != Vector2.ZERO):
    last_direction = direction

if (Input.is_action_just_pressed("shoot")):
    if move_x != 0:
        holdArrDirection.x = move_x
    elif move_y != 0:
        holdArrDirection.y = move_y 
    var arrow = packed_arrow.instance()
    arrow.global_position = global_position
    arrow.rotation = last_direction.angle()
    arrow.ArrowDirection = holdArrDirection
    get_parent().add_child(arrow)


move_and_slide(direction * speed)

You may have to also reset the holdArrDirection somewhere in your code but this should work.

Gluon | 2022-05-25 08:46