Problem with player controls at the end of the level

Hi, I’m using Godot 4.3 and I have one last problem with my shootemup minigame. When I destroy all the enemies in the level, the player controls are supposed to be disabled so I can’t move or shoot, but the controls are still usable when all the enemies are killed.

Here is the link to the video that illustrates the problem.

Here is the player ship code.

extends Area2D

@export var speed: float = 300.0
@export var laser_scene: PackedScene
@export var laser_sound: AudioStream = preload("res://musiqueetson/amiral3000lasersound.wav")
@export var boom_texture: Texture = preload("res://alienminigames/boomtexture.png")

var can_fire: bool = true
var controls_enabled: bool = true   # Contrôle local qui conditionne le déplacement et le tir
var initial_y: float = 0.0  # Pour maintenir le joueur sur une ligne fixe

# Gestion des vies
var player_lives: int = 3
var life_sprites: Array = []

# Variables pour gérer l'explosion
var is_exploding: bool = false
var original_texture: Texture   # Pour sauvegarder le sprite normal
var original_scale: Vector2     # Pour sauvegarder l'échelle d'origine

func _ready() -> void:
	# Pour la compatibilité en Godot 4.3, on peut définir la propriété "pause_mode" via le setter générique
	# Mais ici nous allons plutôt désactiver localement le traitement dès que le niveau se termine.
	# Par ailleurs, on conserve _ready() tel quel.
	set("pause_mode", 1)  # On essaie de définir le mode pause pour stopper si la pause globale est activée
	initial_y = position.y
	if not laser_scene:
		laser_scene = preload("res://lasertest.tscn")
	
	var level_scene = get_tree().current_scene
	life_sprites = [
		level_scene.get_node("vievaisseau1"),
		level_scene.get_node("vievaisseau2"),
		level_scene.get_node("vievaisseau3")
	]
	
	original_texture = $Sprite2D.texture
	original_scale = $Sprite2D.scale

	connect("area_entered", Callable(self, "_on_area_entered"))

func _physics_process(delta: float) -> void:
	# Pour déboguer, on affiche l'état de controls_enabled
	# print("Physics process, controls_enabled =", controls_enabled)
	if not is_exploding and controls_enabled:
		var velocity: Vector2 = Vector2.ZERO
		if Input.is_action_pressed("ui_left"):
			velocity.x -= 1
		if Input.is_action_pressed("ui_right"):
			velocity.x += 1
		if velocity.length() > 0:
			velocity = velocity.normalized() * speed
		position.x += velocity.x * delta
		position.x = clamp(position.x, 60, 1220)
		position.y = initial_y

		if Input.is_action_just_pressed("fire") and can_fire and controls_enabled:
			fire_laser()
	# Sinon, ne traite rien.

func fire_laser() -> void:
	var laser_instance = laser_scene.instantiate()
	laser_instance.global_position = $Projectile.global_position
	get_tree().current_scene.add_child(laser_instance)
	laser_instance.add_to_group("player_laser")
	can_fire = false
	laser_instance.connect("laser_removed", Callable(self, "_on_laser_removed"))
	
	if laser_sound:
		$AudioStreamPlayer.stream = laser_sound
		print("Lecture du son du laser")
		$AudioStreamPlayer.play()
	else:
		print("Aucun son de laser assigné!")

func _on_laser_removed() -> void:
	can_fire = true

func _on_area_entered(area: Area2D) -> void:
	if area.is_in_group("enemy_laser"):
		if not is_exploding:
			take_damage()
		area.queue_free()

func take_damage() -> void:
	if is_exploding:
		return
	if player_lives > 0:
		player_lives -= 1
		life_sprites[player_lives].hide()
		print("Joueur touché ! Vies restantes : " + str(player_lives))
		start_explosion()
	else:
		die()

func start_explosion() -> void:
	is_exploding = true
	$Sprite2D.texture = boom_texture
	$Sprite2D.scale = original_scale * 0.7
	$ExplosionPlayer.play()
	if not $ExplosionPlayer.is_connected("finished", Callable(self, "_on_explosion_finished")):
		$ExplosionPlayer.connect("finished", Callable(self, "_on_explosion_finished"))

func _on_explosion_finished() -> void:
	if player_lives == 0:
		die()
	else:
		$Sprite2D.texture = original_texture
		$Sprite2D.scale = original_scale
		is_exploding = false

func die() -> void:
	get_tree().call_deferred("change_scene_to_file", "res://gameover.tscn")

# --- Nouvelle version de disable_controls() ---
func disable_controls() -> void:
	print("disable_controls() appelée - le vaisseau doit être figé.")
	controls_enabled = false
	can_fire = false
	# Désactiver explicitement le processus de ce node
	set_process(false)
	set_physics_process(false)
	set_process_input(false)
	disable_all_lasers()

func disable_all_lasers() -> void:
	for laser in get_tree().get_nodes_in_group("player_laser"):
		laser.queue_free()
	for laser in get_tree().get_nodes_in_group("enemy_laser"):
		laser.queue_free()

Well it looks very thorough, but do you ever call it? How do you call the disable_controls?

2 Likes

Maybe it’s because you never called the disable controls function?

Finally, I found the solution. The function to disable the controls wasn’t present in the ship scene. So, I attached it to the Label so it appears if the player’s ship destroys all enemies.

1 Like