Hi I’m creating a shoot em up on Godot 4.3. It’s a shoot em up a bit like Space Invader with the difference that the ships never go down. I put an Enemies node for the formation of the enemies which are composed of 15 ships in 3 rows and 5 columns. I added 2 Area2D which are LeftWall and RightWall with their CollissionShape2D. I encounter a problem however. For example when I eliminate the ships for example from the 5th column sometimes the ships return to the left before touching RightWall as if the ships of the 5th column were still present. Here is a short video to show the problem I encounter.
Here is the code that handles ship formation.
extends Node2D
@export var enemyun_scene: PackedScene = preload(“res://ennemyun.tscn”)
@export var ennemydeux_scene: PackedScene = preload(“res://ennemydeux.tscn”)
var rows: int = 3
var cols: int = 5
@export var start_position: Vector2 = Vector2(150, 100)
@export var spacing: Vector2 = Vector2(150, 120)
var columns: Array =
@export var enemy_speed: float = 100.0
var direction: int = -1
func _ready() → void:
columns.resize(cols)
for i in range(cols):
columns[i] =
for row in range(rows):
for col in range(cols):
var enemy_instance: Node
if row == 1:
enemy_instance = ennemydeux_scene.instantiate()
else:
enemy_instance = enemyun_scene.instantiate()
enemy_instance.position = start_position + Vector2(col * spacing.x, row * spacing.y)
add_child(enemy_instance)
columns[col].append(enemy_instance)
for col in range(cols):
var t: Timer = Timer.new()
t.wait_time = float(col + 1)
t.one_shot = false
t.autostart = true
add_child(t)
match col:
0: t.connect("timeout", Callable(self, "_on_column0_timeout"))
1: t.connect("timeout", Callable(self, "_on_column1_timeout"))
2: t.connect("timeout", Callable(self, "_on_column2_timeout"))
3: t.connect("timeout", Callable(self, "_on_column3_timeout"))
4: t.connect("timeout", Callable(self, "_on_column4_timeout"))
var left_wall = get_node("../LeftWall")
var right_wall = get_node("../RightWall")
if left_wall:
var left_callable = Callable(self, "_on_left_wall_entered")
if left_wall.is_connected("area_entered", left_callable):
left_wall.disconnect("area_entered", left_callable)
left_wall.connect("area_entered", left_callable)
else:
push_error("LeftWall non trouvé !")
if right_wall:
var right_callable = Callable(self, "_on_right_wall_entered")
if right_wall.is_connected("area_entered", right_callable):
right_wall.disconnect("area_entered", right_callable)
right_wall.connect("area_entered", right_callable)
else:
push_error("RightWall non trouvé !")
func _physics_process(delta: float) → void:
position.x += enemy_speed * direction * delta
func _on_left_wall_entered(_area: Area2D) → void:
if direction < 0:
print("Collision avec LeftWall – inversion vers la droite.")
direction = 1
func _on_right_wall_entered(_area: Area2D) → void:
if direction > 0:
print("Collision avec RightWall – inversion vers la gauche.")
direction = -1
func fire_from_column(col: int) → void:
var col_enemies = columns[col]
var bottom_enemy = null
for enemy in col_enemies:
if not is_instance_valid(enemy):
continue
if bottom_enemy == null or enemy.position.y > bottom_enemy.position.y:
bottom_enemy = enemy
if bottom_enemy != null:
print("Colonne", col, "-> bottom enemy:", bottom_enemy.name)
if bottom_enemy.has_method("fire_laser"):
bottom_enemy.fire_laser()
else:
print("L'ennemi", bottom_enemy.name, "n'a pas la méthode fire_laser()")
else:
print("Aucun ennemi valide dans la colonne", col)
func _on_column0_timeout() → void:
fire_from_column(0)
func _on_column1_timeout() → void:
fire_from_column(1)
func _on_column2_timeout() → void:
fire_from_column(2)
func _on_column3_timeout() → void:
fire_from_column(3)
func _on_column4_timeout() → void:
fire_from_column(4)
Godot Version
Replace this line with your Godot version
Question
Ask your question here! Try to give as many details as possible