refactor: improving code

This commit is contained in:
Varylios 2025-08-30 20:08:12 +02:00
parent 6f815d9cae
commit 1dc4fe9131
8 changed files with 127 additions and 157 deletions

View file

@ -2,4 +2,3 @@ extends Resource
class_name Wave
@export var troops : Array[Troop]
@export var wait_for_enemy_kills : bool = true

View file

@ -10,8 +10,6 @@ var current_troop : Troop
var enemies_to_spawn : int = 0
var wave : int = 0
var enemies_alive : int = 0
var wave_on_going : bool = false
@onready var troopTimer := $TroopTimer
@ -60,35 +58,31 @@ func spawnEnemy(delay : float) -> void:
func createEnemy() -> PathFollow3D :
var fp3D : PathFollow3D = current_troop.enemy.instantiate()
var enemy : Enemy = fp3D.find_children("*", "Enemy")[0]
var PF3D : PathFollow3D = current_troop.enemy.instantiate()
var enemy : Enemy = PF3D.find_children("*", "Enemy")[0]
enemy.died.connect(func(): enemies_alive -= 1)
return fp3D
return PF3D
func spawn_manager() -> void:
#Send next troop
if !troopTimer.is_stopped():
if not troopTimer.is_stopped():
return
if !current_wave:
if not current_wave || enemies_alive == 0 && current_wave.troops.is_empty():
spawn_next_wave()
return
if !current_wave.troops.is_empty():
current_troop = current_wave.troops.pop_front()
if (current_troop.spawn_delay == 0):
spawn_troop()
else:
troopTimer.start(current_troop.spawn_delay)
current_troop = current_wave.troops.pop_front()
if not current_troop:
return
if current_troop.spawn_delay == 0:
spawn_troop()
else:
troopTimer.start(current_troop.spawn_delay)
wave_on_going = true
if enemies_alive == 0 && current_wave.troops.is_empty():
wave_on_going = false
spawn_next_wave()
elif !current_wave.wait_for_enemy_kills:
spawn_next_wave()
func clearLevel() -> void:

View file

@ -1 +0,0 @@
extends Node

View file

@ -1 +0,0 @@
uid://dno7nph2s6ad0

View file

@ -1,8 +1,9 @@
@tool
extends LineEdit
class_name CustomLineEdit
signal valueHasChanged(newValue)
enum TYPE { INT, TEXT, FLOAT }
@export var inputType : TYPE
@ -13,6 +14,7 @@ var value:
get:
return getTypedValue(text)
func _ready() -> void:
text_changed.connect(valueUpdated)
@ -47,5 +49,3 @@ func getTypedValue(valueToType: String):
TYPE.INT: return int(valueToType)
TYPE.FLOAT: return float(valueToType)
_: return valueToType
signal valueHasChanged(newValue)

View file

@ -2,46 +2,48 @@
extends OptionButton
class_name CustomOptionButton
@export_dir var resourcePath : String
@export var regexPattern : String
@export var reloadOnOpen : bool = false
signal onValueChanged(value : String)
var selectedValue : String
var options : Dictionary
func _ready() -> void:
loadData(true)
item_selected.connect(itemHasBeenSelected)
pressed.connect(loadData)
allow_reselect = true
item_selected.connect(itemHasBeenSelected)
func loadData(force : bool = false) -> void:
if !force && !reloadOnOpen:
return
var regex := RegEx.create_from_string(regexPattern)
var dir := DirAccess.open(resourcePath)
func setOptions(options : Dictionary, defaultSelectedValue : String = "") -> void:
self.options = options
clear()
for file in dir.get_files():
var fileMatch := regex.search(file)
if fileMatch:
add_item(fileMatch.strings[1])
if selectedValue == fileMatch.strings[1]:
selected = item_count - 1
options.keys().map(add_item)
selectItemByValue(defaultSelectedValue)
func addOption(value : String, displayName : String, autoSelect := false) -> void:
add_item(displayName)
options.set(value, displayName)
if autoSelect:
selected = options.size() - 1
selectedValue = value
if !selectedValue && item_count > 0:
selected = 0
func itemHasBeenSelected(index : int) -> void:
if selectedValue != get_item_text(index):
selectedValue = get_item_text(index)
var value := options.get(get_item_text(index))
if selectedValue != value:
selectedValue = value
onValueChanged.emit(selectedValue)
func selectItemByName(name : String) -> void:
func selectItemByValue(value : String) -> void:
var name := options.find_key(value)
for i in item_count:
if get_item_text(i) == name:
selected = i
selectedValue = value
return
signal onValueChanged(value : String)
if options:
selected = 0
itemHasBeenSelected(0)

View file

@ -2,8 +2,7 @@
extends Control
const LEVEL_PATH : String = "res://Levels"
const LEVEL_NAME_PATERN : String = "level_{id}.tres"
const LEVEL_NAME_PATH_PATERN : String = LEVEL_PATH + "/{name}.tres"
const LEVEL_REGEX_PATERN : String = "(level_.*)\\.tres"
const ENEMY_PATH : String = "res://enemies"
const ENEMY_REGEX_PATERN : String = "(enemy.*)\\.tscn"
@ -15,29 +14,37 @@ const TROOP_LABEL_SETTINGS = preload("res://addons/LevelEditor/UI/troopLabel.tre
const space_multiplicator : int = 10
enum DIRECTION { UP, DOWN, TOP, LEFT, VERTICAL, HORIZONTAL}
var enemies : Dictionary
@onready var autoLaunchLevel := $VBoxContainer2/ButtonContainer2/AutoLaunchLevel
@onready var waitForKill := $VBoxContainer2/ButtonContainer4/WaitForKill
@onready var levelSelect := $VBoxContainer2/HBoxContainer/LevelSelect
@onready var waveTabContainer := $VBoxContainer2/ScrollContainer/WaveContainer
@onready var towerSelector := $VBoxContainer2/ButtonContainer5/TowerSelector
var level : Level
var currentWave : int = -1
func _ready() -> void:
enemies = getOptionsFromFile(ENEMY_PATH, ENEMY_REGEX_PATERN)
levelSelect.setOptions(getOptionsFromFile(LEVEL_PATH, LEVEL_REGEX_PATERN))
towerSelector.clear()
towerSelector.max_columns = Tower.TYPES.size()
for towerType : String in Tower.TYPES:
if Tower.TYPES.NONE != Tower.TYPES.get(towerType):
towerSelector.add_item(" " + towerType + " ")
func _input(event: InputEvent) -> void:
if !has_focus() || event is not InputEventKey || !event.pressed:
if event is not InputEventKey || !event.pressed:
return
if event.keycode == KEY_RIGHT && waveTabContainer.get_tab_count() > waveTabContainer.current_tab:
waveTabContainer.current_tab += 1
waveTabContainer.select_next_available()
elif event.keycode == KEY_LEFT && waveTabContainer.current_tab > 0:
waveTabContainer.current_tab -= 1
waveTabContainer.select_previous_available()
func _ready() -> void:
towerSelector.clear()
for towerType : String in Tower.TYPES:
if Tower.TYPES.NONE != Tower.TYPES.get(towerType):
towerSelector.add_item(towerType)
func buildTree() -> void:
if !level:
@ -46,11 +53,7 @@ func buildTree() -> void:
manageAllowedTowers()
autoLaunchLevel.button_pressed = level.auto_start
for i in level.waves.size():
var troopContainer := VBoxContainer.new()
waitForKill.button_pressed = level.waves[i].wait_for_enemy_kills
buildWave(level.waves[i], troopContainer)
waveTabContainer.add_child(troopContainer)
waveTabContainer.set_tab_title(i, "Vague N°" + str(i + 1))
buildWave(level.waves[i])
func manageAllowedTowers() -> void:
@ -60,7 +63,9 @@ func manageAllowedTowers() -> void:
towerSelector.select(towerAllowed - 1, false)
func buildWave(wave : Wave, troopContainer : VBoxContainer) -> void:
func buildWave(wave : Wave) -> void:
var troopContainer := VBoxContainer.new()
for i in wave.troops.size():
var troop : Troop = wave.troops[i]
@ -112,6 +117,9 @@ func buildWave(wave : Wave, troopContainer : VBoxContainer) -> void:
addTroopBtn.text = "Ajouter une troupe"
addTroopBtn.pressed.connect(addTroop.bind(wave))
troopContainer.add_child(addTroopBtn)
waveTabContainer.add_child(troopContainer)
var tabCount : int = waveTabContainer.get_tab_count()
waveTabContainer.set_tab_title(tabCount - 1, "Vague N°" + str(tabCount))
@ -124,12 +132,9 @@ func buildTroop(troop : Troop, ennemyContainer : VBoxContainer) -> void:
)
var enemySelector := CustomOptionButton.new()
enemySelector.resourcePath = ENEMY_PATH
enemySelector.regexPattern = ENEMY_REGEX_PATERN
var regex = RegEx.create_from_string(ENEMY_REGEX_PATERN)
enemySelector.onValueChanged.connect(func(enemyFileName): addEnemy(troop, enemyFileName))
if troop.enemy:
enemySelector.selectItemByName(regex.search(troop.enemy.resource_path).strings[0])
enemySelector.onValueChanged.connect(func(resourcePath): troop.enemy = load(resourcePath))
var enemy := troop.enemy.resource_path if troop.enemy else ""
enemySelector.setOptions(enemies, enemy)
qtyEdit.add_child(enemySelector)
ennemyContainer.add_child(qtyEdit)
@ -155,6 +160,7 @@ func buildInputLabel(updateCallback : Callable, delay : float, type : CustomLine
return container
func createSection(sectionName : String, BtnCallback : Callable, settings : LabelSettings = BASE_LABEL_SETTINGS) -> HSplitContainer :
var container := HSplitContainer.new()
@ -173,19 +179,35 @@ func createSection(sectionName : String, BtnCallback : Callable, settings : Labe
func cleanMenu() -> void:
if waveTabContainer.get_child_count() > 0:
for child in waveTabContainer.get_children():
child.queue_free()
for child in waveTabContainer.get_children():
child.free()
func addTroop(toWave : Wave) -> void:
toWave.troops.append(Troop.new())
cleanAndBuildMenu()
func removeTroop(troop : Troop, fromWave : Wave) -> void:
fromWave.troops.erase(troop)
cleanAndBuildMenu()
func cleanAndBuildMenu() -> void:
cleanMenu()
buildTree()
func removeWave() -> void:
level.waves.remove_at(currentWave)
waveTabContainer.get_child(currentWave).queue_free()
waveTabContainer.get_child(currentWave).free()
func addWave() -> void:
level.waves.append(Wave.new())
cleanAndBuildMenu()
var wave := Wave.new()
level.waves.append(wave)
buildWave(wave)
waveTabContainer.select_next_available()
func changeWaveOrder(newPos : int) -> void:
@ -202,52 +224,28 @@ func changeWaveOrder(newPos : int) -> void:
level.waves = newWaveOrder
func addTroop(toWave : Wave) -> void:
toWave.troops.append(Troop.new())
func selectLevel(levelPath : String) -> void :
level = load(levelPath)
cleanAndBuildMenu()
func addEnemy(toTroop : Troop, enemyResourcePath : String) -> void:
var enemy = load(enemyResourcePath)
toTroop.enemy = enemy
func removeTroop(troop : Troop, fromWave : Wave) -> void:
fromWave.troops.erase(troop)
cleanAndBuildMenu()
func selectLevel(levelName : String) -> void :
level = load(LEVEL_NAME_PATH_PATERN.format([["name", levelName]]))
func tabFocusHaschanged(idx : int) -> void:
currentWave = idx
func cleanAndBuildMenu() -> void:
cleanMenu()
buildTree()
func _on_auto_launch_wave_toggled(toggled_on: bool) -> void:
level.auto_start = toggled_on
func _on_wait_for_kill_toggled(toggled_on: bool) -> void:
level.waves[currentWave].wait_for_enemy_kills = toggled_on
func _on_new_level_pressed() -> void:
level = Level.new()
levelSelect.add_item(LEVEL_NAME_PATERN.format([["id", levelSelect.item_count + 1]]))
levelSelect.select(levelSelect.item_count - 1)
var levelName = "level_" + str(levelSelect.item_count + 1)
levelSelect.addOption(LEVEL_PATH + "/" + levelName + ".tres", levelName, true)
_on_save_pressed()
func _on_save_pressed() -> void:
ResourceSaver.save(level, LEVEL_PATH + "/" + levelSelect.selectedValue, ResourceSaver.FLAG_BUNDLE_RESOURCES)
ResourceSaver.save(level, levelSelect.selectedValue, ResourceSaver.FLAG_BUNDLE_RESOURCES)
func onSelectedTowerChange(index: int, selected: int) -> void:
@ -257,3 +255,15 @@ func onSelectedTowerChange(index: int, selected: int) -> void:
level.allowedTowers.append(index)
else:
level.allowedTowers.erase(index)
func getOptionsFromFile(path : String, regexPattern : String) -> Dictionary :
var files = {}
var regex := RegEx.create_from_string(regexPattern)
var dir := DirAccess.open(path)
for file in dir.get_files():
var fileMatch := regex.search(file)
if fileMatch:
files.set(fileMatch.strings[1], path + "/" + file)
return files

View file

@ -36,32 +36,16 @@ popup/item_0/id = 0
popup/item_1/text = "level_2"
popup/item_1/id = 1
script = ExtResource("2_xjxpq")
resourcePath = "res://Levels"
regexPattern = "(level_.*)\\.tres"
reloadOnOpen = true
metadata/_custom_type_script = "uid://b47p2u458hsn0"
[node name="NewLevel" type="Button" parent="VBoxContainer2/HBoxContainer"]
layout_mode = 2
text = "Nouveau Niveau"
[node name="Show" type="Button" parent="VBoxContainer2/HBoxContainer"]
layout_mode = 2
text = "Afficher"
[node name="Clean" type="Button" parent="VBoxContainer2/HBoxContainer"]
layout_mode = 2
text = "Effacer"
[node name="Save" type="Button" parent="VBoxContainer2/HBoxContainer"]
layout_mode = 2
text = "Sauvegarder"
[node name="Test" type="Button" parent="VBoxContainer2/HBoxContainer"]
visible = false
layout_mode = 2
text = "TESTER !!!!"
[node name="ButtonContainer" type="HBoxContainer" parent="VBoxContainer2"]
layout_mode = 2
@ -69,6 +53,10 @@ layout_mode = 2
layout_mode = 2
text = "Ajouter une vague"
[node name="RemoveWave" type="Button" parent="VBoxContainer2/ButtonContainer"]
layout_mode = 2
text = "Suprimer la vague"
[node name="ButtonContainer2" type="HBoxContainer" parent="VBoxContainer2"]
layout_mode = 2
@ -79,28 +67,6 @@ layout_mode = 2
layout_mode = 2
text = "Lancer le niveau auto. "
[node name="MarginContainer2" type="MarginContainer" parent="VBoxContainer2/ButtonContainer2"]
custom_minimum_size = Vector2(20, 0)
layout_mode = 2
[node name="RemoveWave" type="Button" parent="VBoxContainer2/ButtonContainer2"]
layout_mode = 2
text = "Suprimer la vague"
[node name="ButtonContainer4" type="HBoxContainer" parent="VBoxContainer2"]
layout_mode = 2
[node name="WaitForKill" type="CheckButton" parent="VBoxContainer2/ButtonContainer4"]
layout_mode = 2
[node name="Label" type="Label" parent="VBoxContainer2/ButtonContainer4"]
layout_mode = 2
text = "Attendre la mort des enemies pour lancer la vague suivante"
[node name="MarginContainer2" type="MarginContainer" parent="VBoxContainer2"]
custom_minimum_size = Vector2(0, 30)
layout_mode = 2
[node name="ButtonContainer5" type="HBoxContainer" parent="VBoxContainer2"]
custom_minimum_size = Vector2(0, 30)
layout_mode = 2
@ -112,13 +78,15 @@ select_mode = 2
allow_search = false
auto_width = true
auto_height = true
item_count = 6
item_0/text = "PIERRE"
item_1/text = "ALINE"
item_2/text = "MAXENCE"
item_3/text = "VICTORIA"
item_4/text = "EVAN"
item_5/text = "ALEX"
item_count = 7
max_columns = 8
item_0/text = " PIERRE "
item_1/text = " ALINE "
item_2/text = " MAXENCE "
item_3/text = " VICTORIA "
item_4/text = " EVAN "
item_5/text = " ALEX "
item_6/text = " GERALDINE "
[node name="MarginContainer4" type="MarginContainer" parent="VBoxContainer2"]
custom_minimum_size = Vector2(0, 30)
@ -131,18 +99,17 @@ size_flags_vertical = 3
[node name="WaveContainer" type="TabContainer" parent="VBoxContainer2/ScrollContainer"]
layout_mode = 2
size_flags_vertical = 3
current_tab = 0
clip_tabs = false
drag_to_rearrange_enabled = true
[connection signal="onValueChanged" from="VBoxContainer2/HBoxContainer/LevelSelect" to="." method="selectLevel"]
[connection signal="pressed" from="VBoxContainer2/HBoxContainer/NewLevel" to="." method="_on_new_level_pressed"]
[connection signal="pressed" from="VBoxContainer2/HBoxContainer/Show" to="." method="cleanAndBuildMenu"]
[connection signal="pressed" from="VBoxContainer2/HBoxContainer/Clean" to="." method="cleanMenu"]
[connection signal="pressed" from="VBoxContainer2/HBoxContainer/Save" to="." method="_on_save_pressed"]
[connection signal="pressed" from="VBoxContainer2/ButtonContainer/Add wave" to="." method="addWave"]
[connection signal="pressed" from="VBoxContainer2/ButtonContainer/RemoveWave" to="." method="removeWave"]
[connection signal="toggled" from="VBoxContainer2/ButtonContainer2/AutoLaunchLevel" to="." method="_on_auto_launch_wave_toggled"]
[connection signal="pressed" from="VBoxContainer2/ButtonContainer2/RemoveWave" to="." method="removeWave"]
[connection signal="toggled" from="VBoxContainer2/ButtonContainer4/WaitForKill" to="." method="_on_wait_for_kill_toggled"]
[connection signal="multi_selected" from="VBoxContainer2/ButtonContainer5/TowerSelector" to="." method="onSelectedTowerChange"]
[connection signal="active_tab_rearranged" from="VBoxContainer2/ScrollContainer/WaveContainer" to="." method="changeWaveOrder"]
[connection signal="tab_changed" from="VBoxContainer2/ScrollContainer/WaveContainer" to="." method="tabFocusHaschanged"]
[connection signal="tab_hovered" from="VBoxContainer2/ScrollContainer/WaveContainer" to="." method="test"]