Primary player-versus-enemy interaction is firing and/or dodging discrete moving objects.
Lasers fired as instanced Area2D scenes; area_entered detects hits and pops the descending enemy ships.
The projectile body itself when you want overlap detection without a physics bounce. Connect body_entered / area_entered to apply damage, then free it.
func _ready():
body_entered.connect(_on_hit)
func _on_hit(body):
if body.has_method("take_damage"):
body.take_damage(DAMAGE)
queue_free()The projectile prefab. Export it, then instantiate() a fresh copy each shot and add it to the running scene so bullets live independently of the gun.
@export var bullet_scene: PackedScene
func fire():
var b = bullet_scene.instantiate()
b.global_position = $Muzzle.global_position
get_tree().current_scene.add_child(b)An empty positional node parented to the weapon — a clean muzzle point that rotates and moves with the gun so spawn position and aim come for free.
# Muzzle moves with the gun, so the shot inherits its position and aim
bullet.global_position = $Muzzle.global_position
bullet.rotation = $Muzzle.global_rotationEnforces fire rate. Gate firing on a cooldown timer so holding the button doesn't spawn a bullet every frame.
@onready var cooldown = $FireCooldown # wait_time = seconds/shot
func try_fire():
if cooldown.is_stopped():
fire()
cooldown.start()In short: Projectile scene instantiated on fire input; velocity-driven movement in _physics_process(); Area2D collision triggers damage
…and 43 more in the interactive database →
123 catalogued game(s) use this mechanic, spanning 1984–1999.
▶ Explore Projectile System interactively — see every game + the Godot system