I have a problem when the player is flipped to the left and I try to shoot, the bullets go only one direction, "Right', and not the same direction the player/character is facing in. How to fix this ?
This is the bullet script
extends Area2D
@export var speed = 750
@onready var bullet: Area2D = $Bullet
@onready var sprite_2d: Sprite2D = $Sprite2d
@onready var bullet_effect: AnimatedSprite2D = $BulletEffect
var pBulletEffect := preload("res://BulletEffect.tscn")
func _physics_process(delta):
position += transform.x * speed * delta
func _on_body_entered(body: Node2D) -> void:
if body.has_method("enemy_hit"):
var bulletEffect := pBulletEffect.instantiate()
bulletEffect.position = position
get_parent().add_child(bulletEffect)
body.enemy_hit()
queue_free()
this is the player script
extends CharacterBody2D
var health = 30
@onready var player: CharacterBody2D = $Player
@export var bullet_scene : PackedScene
@onready var sprite_2d: AnimatedSprite2D = $Sprite2d
@onready var bowShoot =$bowShoot
@onready var typhon: AudioStreamPlayer2D = $typhon
@onready var player_walk: AudioStreamPlayer2D = $player_walk
@onready var player_jump: AudioStreamPlayer2D = $PlayerJump
const SPEED = 400
const JUMP_VELOCITY = -700.0
func _physics_process(delta: float) -> void:
# Add the gravity.
if not is_on_floor():
velocity += get_gravity() * delta
# Handle jump.
if Input.is_action_just_pressed("jump") and is_on_floor():
velocity.y = JUMP_VELOCITY
sprite_2d.animation = "jump"
player_jump.play()
if Input.is_action_just_released("jump"):
sprite_2d.animation = "idle"
# Get the input direction and handle the movement/deceleration.
# As good practice, you should replace UI actions with custom gameplay actions.
var direction := Input.get_axis("left", "right")
if direction:
velocity.x = direction * SPEED
else:
velocity.x = move_toward(velocity.x, 0, SPEED)
move_and_slide()
if Input.is_action_just_pressed("shoot"):
shoot()
bowShoot.play()
sprite_2d.animation = "shoot"
if Input.is_action_just_released("shoot"):
sprite_2d.animation = "idle"
# Animations
if Input.is_action_just_pressed("left"):
sprite_2d.animation = "left"
player_walk.play()
if Input.is_action_just_released("left"):
sprite_2d.animation = "idle"
if Input.is_action_just_pressed("right"):
sprite_2d.animation = "right"
player_walk.play()
if Input.is_action_just_released("right"):
sprite_2d.animation = "idle"
var isLeft = velocity.x < 0
sprite_2d.flip_h = isLeft
func shoot():
var b = preload ("res://bullet.tscn").instantiate()
get_tree().root.add_child(b)
b.transform = $Muzzle.global_transform
The bullet goes to the right because you’re never telling it to change its direction. This line: position += transform.x * speed * delta is responsible for that.
What you could do is adding a direction parameter to the bullet, which would be 1 or -1, indicating if the bullet goes right or left. You can then simply add this direction to your instruction to adjust the position increment, like this:
var direction: int = 1
func _physics_process(delta):
position += transform.x * speed * delta * direction
You then need to set the direction, based on where the player is looking. To do that, go into your shoot function, and set the value in the bullet variable:
func shoot():
var b = preload ("res://bullet.tscn").instantiate()
get_tree().root.add_child(b)
b.transform = $Muzzle.global_transform
# Demo code, may need adjustements based on your likings, but the logic can be done like this.
b.direction = -1 if sprite_2d.flip_h else 1
You can then change the bullet sprite flip_h/scale based on the direction variable too!
Hope that helps.
Applying the direction to the translation does not flip the sprite automatically, as those two things are decorrelated. As I said, you need to also flip the bullet based on the direction. You could add a line like this:
b.direction = -1 if sprite_2d.flip_h else 1
b.sprite_2d.flip_h = sprite_2d.flip_h # You may want to revert the boolean, depending on your sprite.
But note that a more proper way would be to add a function in your arrow script to set its direction, something like this:
func set_direction(dir: int):
direction = dir
sprite_2d.flip_h = dir > 0 # Again, you may want to use "< 0" instead, depending on your sprite.
And call it like this:
func shoot():
var b = preload ("res://bullet.tscn").instantiate()
get_tree().root.add_child(b)
b.transform = $Muzzle.global_transform
b.set_direction(-1 if sprite_2d.flip_h else 1)
–
And just to make things clear:
I mean the png texture file / image
The .png file is not flipped. When using flip_h or flip_v, you simply tell the Sprite2D to draw the .png file a different way, but the image itself isn’t affected. That’s why you can shoot multiple arrows with different directions, using the same initial image (as you have one .png, but multiple Sprite2D).
That errors means you are trying to set the value of a variable called direction although it does not exist.
You need to declare it in your script, like that:
var direction: int
func set_direction(dir: int):
direction = dir
sprite_2d.flip_h = dir > 0 # Again, you may want to use "< 0" instead, depending on your sprite.
Thanks, now the Arrow and other bullets is flipped when shooting to the left with the player direction
but its position is wrong and its place, a bit far behind the Player/bow/gun
this happens only when shooting to left but shooting to the right it’s good no problem
Doing 16 * direction doesn’t work here because you need to use the bullet direction: 16 * b.direction (using the player direction may work, but I don’t know if the value is correct).
Also, if you’re just offseting by 16 pixels whether you shoot left or right, you should make sure the default position is centered (else, you’d need to offset more on one side than another).