Excluding values from a variable?

Godot Version

4.2.1

Question

Hey all, is it possible to exclude values from a variable? I have an archer enemy that is supposed to shoot an arrow although if the player is right above the enemy the arrow logic kinda stops working

extends Area2D

var direction = null
var on_screen = true
@onready var player = get_tree().get_first_node_in_group("Player_body")
@onready var timer: Timer = $VisibleOnScreenNotifier2D/Timer

func _ready(): # gets direction when arrow is instantiated
	direction = (player.position - self.global_position).normalized()
	if snapped(direction.x,1) == 1:
		$Sprite2D.flip_h = false
	else:
		$Sprite2D.flip_h = true
	print(snappedi(direction.x,1))

func _physics_process(delta): # uses direction to flip

	position.x += direction.x * 100 * delta




When the arrow instantiates the direction is defined but when the player is above the enemy the arrow direction.x is snapped to 0. this affects the arrow speed in a way that is very inconsistent.
I’ve seen other people deal with a similar issue by making a previous_direction_x variable to handle any direction logic when direction.x == 0
which i dont want it to do. Is it possible to modify the snapped method so as to make it snap to the nearest 1 or -1 instead of 0.

Any and all help is appreciated :slight_smile:

Hi!

From what I understand of the code, it seems you’re only using the snap functions to change the flip of the arrow. Can’t you just do something like this?

direction = (player.position - self.global_position).normalized()
if direction.x > 0:
    $Sprite2D.flip_h = false
else:
    $Sprite2D.flip_h = true

No need to snap the x value as you only have to check if it’s positive (looking to the right) or negative (looking to the left).
You can also add a direction.x == 0 case if you need to handle that, but with my code, it will be handled in the else block.

Hope that helps! If not, please attach some screenshots to make the problem more clear :slight_smile:

1 Like

Sorry for the late reply!
The flip script is totally fine. The issue is that when the player is above the enemy the direction.x is defined as 0 which makes the arrow speed really slow. Looking back I should have specified that better and I’m going to edit the post :slight_smile:

There is ceil() and floor() to raise or lower the value:

direction = (player.position - self.global_position).normalized()
if direction.x > 0:
    $Sprite2D.flip_h = false
    direction.x = ceil(direction.x)
else:
    $Sprite2D.flip_h = true
    direction.x = floor(direction.x)

func _physics_process(delta): # uses direction to flip
	position.x += direction.x * 100 * delta
1 Like

Thank you so much! I had no idea ceil() and floor() were a thing :slight_smile:

I forgot: If the value is exactly 0.0 and not 0.000001 or so this doesn’t work. You might add another check to ensure it never is 0.0. :grimacing:

1 Like

Setter functions can be an elegant way to implement what you want

var direction := Vector2(0, 0):
  set(new_direction):
    direction = new_direction if new_direction.x != 0 else Vector2(direction.x, new_direction.y)

Although do note that instead of checking for an exact zero value, you should instead check for a value within a small interval around zero.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.