How to flip the hitbox of a projectile?

Godot Version
4.3 Stable

I’m currently making a mario clone of sorts and I managed to make this plant
enemy shoot these peas every 2 seconds. If I flip the plant to the other side,
the projectile goes the other way. Problem is the hitboxes don’t flip as well.
I’ve managed to flip the hitboxes of my enemies, like the mushroom enemy and
even the plant enemy itself, but the projectile itself I can’t seem to flip.


In this image shown, only the right hitbox is shown. When the plant on the
right shoots, the hitboxes align correctly, but the one on left reverses it. So
the right hitbox is on the left and the left hitbox is on the right. It ends up looking a bit wonky when the player gets hit on the left and flies to the right.

I’m not sure how to write the code for this, so any help would be greatly appreciated

It seems like the hitbox is flipped correctly from that image. Maybe you could draw an arrow to show which direction the projectiles are moving?

In the video, when the plant on the right shoots me, the player bounces away from the pea, but when the plant on the left shoots me, the player will bounce towards the pea.


Here’s a close up of the pea projectile. Only the right hitbox is visible.
The pea coming from the right plant’s right hitbox aligns correctly and in the
video, the player bounces away, but not from the plant on the left, since the
right hitbox is on the left side of the pea and vice versa

the way i did it for my plant’s hitboxes was like this
func flip():
if scale.x == -1:
HBleft.position.x = 38.5
HBleft.position.y = 18
HBRight.position.x = -25.5
HBRight.position.y = 17.5

It needs to be something like that for the pea, so that the hitboxes stay consistent. Problem is, my brain and I aren’t really cooperating, and I’m not
sure how to write the code for this.

If the plant’s scale.x = -1, then the pea’s right and left hitboxes need to swap, so
that the player bounces the right ways

Also editors note. I realized in my previous message that i said the hitboxes of the pea don’t flip,
when in reality they do, so that’s a whoopsie from my part. I need them to stay in the same place
when the plant is facing to the right. So sorry if that caused some confusion

I think you could do hitbox sides through code, without two hitboxes.

From the difference in pea’s position and player’s position, you can tell which side they hit. The signf function converts this into a positive or negative one so we can flip the standard knockback on the x axis.

# projectile script
func on_hitbox_body_entered(body: Node2D) -> void:
    if body is Player:
        var difference: float = self.global_position.x - body.global_position.x
        var knockback := Vector2(signf(difference), 1) * STANDARD_KNOCKBACK
        body.apply_knockback(knockback)

If you show your own code I could help adapt this math into it.

1 Like

sure thing

here’s the code for the projectile itself

extends Node2D
class_name pea

@onready var plant: Plant

var direction
var speed = 200
var lifetime = 5.0
var hit = false
@onready var sprites = $AnimationPlayer
@onready var HBLeft = $“Hitbox Left/CollisionShape2D”
@onready var HBRight = $“Hitbox Right/CollisionShape2D”

func _ready() → void:
await get_tree().create_timer(lifetime).timeout
die()

func _physics_process(delta: float) → void:
position.x += abs(speed * delta) * direction

func fliphb():
if get_parent() is Plant:
if scale.x == -1:
HBLeft.position.x = 6
HBRight.position.x = -6

func die():
hit = true
speed = 0
sprites.play(“Pea”)

func _on_hitbox_area_entered(area: Area2D) → void:
if area.get_parent() is player && !hit:
area.get_parent().take_damage(1)
area.get_parent().jump_side_right()
area.get_parent().frameFreeze(0.5, 0)
die()

func _on_hitbox_left_area_entered(area: Area2D) → void:
if area.get_parent() is player && !hit:
area.get_parent().take_damage(1)
area.get_parent().jump_side_left()
area.get_parent().frameFreeze(0.5, 0)
die()

The knockback comes from my main character script, which is the jump_side_left and jump_side_right

func jump_side_left():
velocity.y = jump_height
velocity.x = -jump_side

func jump_side_right():
velocity.y = jump_height
velocity.x = jump_side

Cool, so the player code needs to take another parameter, we can reduce the jump_side functions into one

func jump_side_apply(side: float) -> void:
	velocity.y = jump_height
	velocity.x = jump_side * signf(side)

Now we can reduce the hitbox from left/right into one full hitbox

func _on_hitbox_area_entered(area: Area2D) -> void:
	if area.get_parent() is player && !hit:
		area.get_parent().take_damage(1)

		var diff: float = self.global_position.x - area.get_parent().global_position.x
		area.get_parent().jump_side_apply(diff)

		area.get_parent().frameFreeze(0.5, 0)
		die()
2 Likes

works like a charm!
Thank you so much for the help!

I’ll definitely look into doing this for some of the enemies as well.
You’re a life saver :slight_smile:

Hope you have an awesome day!

1 Like

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