chore: add pause + fixes

This commit is contained in:
Varylios 2025-09-06 22:08:29 +02:00
parent fffb13a27f
commit ca8b39c325
15 changed files with 191 additions and 112 deletions

View file

@ -7,16 +7,6 @@ extends Node
signal tower_selected(towerType : Tower.TYPE)
## [b]Emitter[/b] : [Tower][br]
## [b]Subscriber[/b] [GuiButton], [gui.gd]:
signal tower_changed(tower : Tower)
## [b]Emitter[/b] : [UpgradeButton][br]
## [b]Subscriber[/b] : [Tower]
signal tower_upgraded(towerType : Tower.TYPE, upgrade : TowerUpgrade)
## [b]Emitter[/b] : [TowerManager][br]
## [b]Subscriber[/b] : gui.gd
signal tower_count_changed(count : int)
@ -43,8 +33,8 @@ signal player_has_won
## [b]Emitter[/b] : [WorldManager][br]
## [b]Subscriber[/b] : [code]null[/code]
signal wave_has_change(waveNumber : int)
## [b]Subscriber[/b] : gui.gd
signal wave_has_change(waveNumber : int, timeRemaining : float)
## [b]Emitter[/b] : [gui.gd][br]

View file

@ -12,10 +12,6 @@ signal allowed_tower_has_change
var towerPackedScenes : Dictionary
var enmies : Dictionary
var towers : Dictionary
var allowedTowers : Array[Tower.TYPE] :
set(value):
allowedTowers = value
allowed_tower_has_change.emit()
var max_health : int = 50
@ -25,9 +21,6 @@ var health : int = max_health :
cube_integrity_changed.emit()
if health <= 0:
death()
var healthPercentage : int :
get():
return float(health) / float(max_health) * 100.0
var money : int = 0:
@ -37,21 +30,28 @@ var money : int = 0:
func _ready() -> void:
process_mode = Node.PROCESS_MODE_ALWAYS
EventBus.player_has_won.connect(win)
Helper.preloadSceneInGlobal(towerPackedScenes, Helper.RESOURCE_TYPE.TOWER)
#Helper.preloadSceneInGlobal(towerPackedScenes, Helper.RESOURCE_TYPE.ENEMY)
func initTower(towerType: Tower.TYPE) -> Tower:
var tower : Tower = towerPackedScenes.get(towerType).instantiate()
towers.set(towerType, tower)
return tower
func _input(event: InputEvent) -> void:
if event.is_action_pressed("pause_game"):
get_tree().paused = not get_tree().paused
func initTowers(allowedTowers : Array[Tower.TYPE]) -> void:
towers.clear()
for towerType in allowedTowers:
var tower : Tower = towerPackedScenes.get(towerType).instantiate()
towers.set(towerType, tower)
allowed_tower_has_change.emit()
func resetGame() -> void:
towers.clear()
# DANGER Don't use [method clear] or you will clear the level datas
allowedTowers = []
initTowers([])
money = 0
health = max_health
@ -61,6 +61,15 @@ func win():
resetGame()
func quitLevel() -> void:
Transition.goto("res://UI/start_menu.tscn")
resetGame()
func quitGame() -> void:
get_tree().quit()
func spendMoney(amount : int) -> bool:
if money >= amount:
money -= amount

View file

@ -16,6 +16,11 @@ var progress : Array[float]
var tween : Tween
func _ready() -> void:
process_mode = Node.PROCESS_MODE_ALWAYS
func goto(scene_path : String, _loadState : LOAD_STATE = LOAD_STATE.BASIC_LOAD):
loadState = _loadState
target_scene_path = scene_path

View file

@ -5,6 +5,7 @@ const SCREEN_MARGIN : int = 50
const SCREEN_MOVEMENT_SPEED : float = .05
@export var curve : Curve
var shouldMove : bool = true
func _ready() -> void:
@ -12,6 +13,9 @@ func _ready() -> void:
func _process(_delta: float) -> void:
if not shouldMove:
return
var windowSize : Vector2i = get_window().size
var mousePosition : Vector2 = get_viewport().get_mouse_position()
@ -25,15 +29,22 @@ func _process(_delta: float) -> void:
position.z += SCREEN_MOVEMENT_SPEED
func _notification(what: int) -> void:
match what:
NOTIFICATION_WM_MOUSE_ENTER: shouldMove = true
NOTIFICATION_WM_MOUSE_EXIT: shouldMove = false
func _input(event: InputEvent) -> void:
if not event is InputEventMouseButton:
return
var newPosition : float = position.y
if event.button_index == MOUSE_BUTTON_WHEEL_UP:
newPosition = clampf(newPosition - .2, curve.min_domain, curve.max_domain)
elif event.button_index == MOUSE_BUTTON_WHEEL_DOWN:
newPosition = clampf(newPosition + .2, curve.min_domain, curve.max_domain)
match event.button_index:
MOUSE_BUTTON_WHEEL_UP: newPosition -= .2
MOUSE_BUTTON_WHEEL_DOWN: newPosition += .2
newPosition = clampf(newPosition, curve.min_domain, curve.max_domain)
rotation.x = deg_to_rad(curve.sample(newPosition))
position.y = newPosition

View file

@ -55,7 +55,7 @@ func changeState(newState: STATE) -> void:
func spawnNextWave() -> void:
currentTroopIdx = 0
wave += 1
EventBus.wave_has_change.emit(wave)
EventBus.wave_has_change.emit(wave, level.waves[wave - 1].troops[0].spawn_delay)
spawnNextTroop()
@ -121,7 +121,7 @@ func addMap(mapScene : PackedScene) -> void:
level = map.level
paths = map.paths.get_children()
Game.money = level.startingMoney
Game.allowedTowers = level.allowedTowers
Game.initTowers(level.allowedTowers)
state = STATE.SPAWN if level.auto_start else STATE.IDLE

View file

@ -63,14 +63,17 @@ adjustment_contrast = 1.3
adjustment_saturation = 1.2
[node name="World" type="Node3D"]
process_mode = 1
script = ExtResource("1_tk0a6")
[node name="Camera3D" type="Camera3D" parent="."]
process_mode = 3
transform = Transform3D(1, 0, 0, 0, 0.5, 0.866026, 0, -0.866026, 0.5, 0, 10, 0)
script = ExtResource("2_c1rgm")
curve = SubResource("Curve_c1rgm")
[node name="TowerManager" type="Node3D" parent="."]
process_mode = 3
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 4.73017, 0.728414, 0)
script = ExtResource("2_7pixp")

View file

@ -1,7 +1,12 @@
@tool
extends StaticBody3D
class_name Tower
signal energy_changed
signal changed
# DANGER "NONE" Should always be first
enum TYPE { NONE, PIERRE, ALINE, MAXENCE, VICTORIA, EVAN, ALEX, GERALDINE }
@ -25,7 +30,9 @@ var projectileScene : PackedScene = preload("res://Towers/Projectiles/projectile
@export var max_energy : float = 100.0 :
set(value):
max_energy = value
towerChange.call_deferred()
if not Engine.is_editor_hint() && is_node_ready():
energyBar.max_value = max_energy
changed.emit()
@export var energy_regen : float = 10.0
@export var energy_cost : float = 50.0
@ -43,7 +50,7 @@ var energy : float :
energyBar.value = value
energy = clampf(value, 0.0, max_energy)
is_exhausted = energy < energy_cost
EventBus.tower_changed.emit(self)
energy_changed.emit()
var availableTargets : Array[Enemy]
var target : Enemy
@ -60,11 +67,10 @@ var builded : bool = false
func _ready() -> void:
EventBus.tower_upgraded.connect(apply_upgrade)
energyRecoveryCooldown.timeout.connect(func(): energy += energy_regen)
energy = max_energy
# WARNING : Prevent .tscn file to be modified by the load of the scene in editor
if not Engine.is_editor_hint():
energyRecoveryCooldown.timeout.connect(func(): energy += energy_regen)
collision_layer = 0
collision_mask = 0
$PriceTag.text = str(price) + ""
@ -80,11 +86,6 @@ func get_available_upgrades() -> Array[TowerUpgrade]:
return upgrades.filter(func(u: TowerUpgrade): u.isLevelMax)
func apply_upgrade(towerType : Tower.TYPE, upgrade : TowerUpgrade):
if towerType == type && upgrade.canUpgrade():
upgrade.upgrade(self)
func shoot() -> void:
energy -= energy_cost
var projectile : Projectile = projectileScene.instantiate()
@ -125,20 +126,13 @@ func build() -> bool:
return false
sprite.modulate = "ffffffff"
energyBar.value = energy
energyBar.max_value = max_energy
$EnergyBar3D.visible = true
builded = true
$PriceTag.visible = false
EventBus.tower_changed.emit(self)
changed.emit()
return true
func towerChange() -> void:
energyBar.max_value = max_energy
EventBus.tower_changed.emit(self)
func onBodyEntered(body: Node3D) -> void:
if body is Enemy:
availableTargets.append(body)

View file

@ -115,14 +115,14 @@ func onTowerSelect(towerType: Tower.TYPE):
selected_tower.visible = false
if selected_tower && selected_tower.type == towerType || towerType == Tower.TYPE.NONE:
if selected_tower && not selected_tower.builded:
remove_child(selected_tower)
selected_tower = null
elif Game.towers.has(towerType):
else:
selected_tower = Game.towers.get(towerType)
if not selected_tower.builded:
selected_tower.visible = true
else:
selected_tower = Game.initTower(towerType)
add_child(selected_tower)
add_child(selected_tower)
func selectTower(towerType: Tower.TYPE, force : bool = false) -> void:
@ -145,5 +145,5 @@ func handleTowerShortCuts(event: InputEventKey) -> void:
KEY_D: towerType = Tower.TYPE.GERALDINE
#KEY_F: towerType = Tower.TYPE
if Game.allowedTowers.has(towerType):
if Game.towers.has(towerType):
selectTower(towerType, true)

View file

@ -9,33 +9,41 @@ var tower : Tower
func _ready() -> void:
EventBus.tower_selected.connect(onTowerSelected)
EventBus.tower_changed.connect(onTowerChange)
func onTowerSelected(towerType : Tower.TYPE) -> void:
if tower:
tower.energy_changed.disconnect(onEnergyChange)
tower.changed.disconnect(onTowerChange)
if towerType == Tower.TYPE.NONE:
visible = false
tower = null
return
tower = Game.towers.get(towerType)
tower.energy_changed.connect(onEnergyChange)
tower.changed.connect(onTowerChange)
%UpgradeContainer.visible = false
visible = true
onTowerChange(tower)
onTowerChange()
func onTowerChange(_tower : Tower) -> void:
if _tower == tower:
%TowerIcon.texture = tower.icone
%TowerName.text = tower.tower_name
%TowerDamage.text = "Dmg : %d" % tower.projectileRessource.damage
%TowerCooldown.text = "cooldown : %.1f" % tower.action_cooldown
# TODO Check for better UI to display it
#%TowerBio.text = tower.bio
%TowerEnergy.text = "%d/%d" % [ tower.energy, tower.max_energy ]
func onEnergyChange() -> void:
%TowerEnergy.text = "%d/%d" % [ tower.energy, tower.max_energy ]
if tower.builded && not %UpgradeContainer.visible:
createTowerUpgradeButton()
func onTowerChange() -> void:
onEnergyChange()
%TowerIcon.texture = tower.icone
%TowerName.text = tower.tower_name
%TowerDamage.text = "Dmg : %d" % tower.projectileRessource.damage
%TowerCooldown.text = "cooldown : %.1f" % tower.action_cooldown
# TODO Check for better UI to display it
#%TowerBio.text = tower.bio
if tower.builded && not %UpgradeContainer.visible:
createTowerUpgradeButton()
func createTowerUpgradeButton() -> void:

View file

@ -7,29 +7,49 @@ const guiButton : PackedScene = preload("res://UI/gui_button.tscn")
@onready var buttonContainer = %ButtonContainer
@onready var cubeIntegrity = %CubeIntegrity
var waveCooldown : float
func _ready() -> void:
addTowerButtonNodes()
EventBus.team_in_rest_changed.connect(func(count): %LabelTowerInCube.text = "Zzz : %d" % count)
EventBus.team_in_action_changed.connect(func(count): %LabelTowerOnTerrain.text = " In action : %d" % count)
Game.allowed_tower_has_change.connect(addTowerButtonNodes)
Game.cube_integrity_changed.connect(func(): cubeIntegrity.value = Game.healthPercentage)
Game.cube_integrity_changed.connect(func(): cubeIntegrity.value = Game.health)
cubeIntegrity.max_value = Game.max_health
cubeIntegrity.value = Game.health
Game.money_changed.connect(func(): %LabelMoney.text = "%d" % Game.money)
EventBus.wave_has_change.connect(func(wave): %WaveNumber.text = "Wave N°%d" % wave)
EventBus.wave_has_change.connect(onWaveChange)
%NextWaveBtn.pressed.connect(EventBus.lauch_next_wave.emit)
$WaveCooldown/Timer.timeout.connect(updateWaveCooldownLabel)
%QuitLevelBtn.pressed.connect(Game.quitLevel)
%QuitGameBtn.pressed.connect(Game.quitGame)
$TowerInfoPanel.visible = false
if Engine.is_editor_hint():
var allowedTowers : Array[Tower.TYPE]
allowedTowers.assign(Tower.TYPE.values().filter(func(v): return v))
Game.initTowers(allowedTowers)
func _on_button_cube_pressed() -> void:
pass # Replace with function body.
func quitLevel() -> void:
Transition.goto("res://UI/start_menu.tscn")
func onWaveChange(waveNumber : int, timeRemaining : float) -> void:
%WaveNumber.text = "Wave N°%d" % waveNumber
waveCooldown = timeRemaining
$WaveCooldown/Timer.start()
func quitGame() -> void:
get_tree().quit()
func updateWaveCooldownLabel() -> void:
waveCooldown -= $WaveCooldown/Timer.wait_time
if waveCooldown > 5:
$WaveCooldown.text = "\n\nNext wave : %3.0f" % waveCooldown
elif waveCooldown < 0:
$WaveCooldown/Timer.stop()
$WaveCooldown.text = ""
else:
$WaveCooldown.text = "\n\nNext wave : %3.1f" % waveCooldown
func addTowerButtonNodes() -> void:
@ -37,9 +57,8 @@ func addTowerButtonNodes() -> void:
if node.has_meta("dynamicButton"):
node.queue_free()
for towerType : int in Tower.TYPE.values() :
if towerType && (Engine.is_editor_hint() || Game.allowedTowers.has(towerType)):
createTowerButton(towerType)
for towerType in Game.towers.keys() :
createTowerButton(towerType)
for i in BUTTON_QTY - (buttonContainer.get_children().size() % BUTTON_QTY):
createTowerButton(Tower.TYPE.NONE)
@ -50,10 +69,7 @@ func createTowerButton(towerType : Tower.TYPE) -> void:
btn.set_meta("dynamicButton", true)
if towerType:
var tower : PackedScene = Game.towerPackedScenes.get(towerType)
btn.towerType = towerType
btn.tooltip_text = str(EnhancedResource.getPackedSceneProperty(tower, "name"))
btn.texture = EnhancedResource.getPackedSceneProperty(tower, "icone")
btn.tower = Game.towers.get(towerType)
else:
btn.disabled = true
buttonContainer.add_child(btn)

View file

@ -28,6 +28,7 @@ color = 4
metadata/_custom_type_script = "uid://blnmjxmusrsa7"
[node name="GUI" type="Control"]
process_mode = 3
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
@ -38,6 +39,21 @@ mouse_filter = 2
theme = ExtResource("5_wpcnu")
script = ExtResource("2_sac4j")
[node name="WaveCooldown" type="Label" parent="."]
layout_mode = 1
anchors_preset = 5
anchor_left = 0.5
anchor_right = 0.5
offset_left = -90.0
offset_right = 90.0
offset_bottom = 50.0
grow_horizontal = 2
theme_override_colors/font_color = Color(0.2, 0.2, 0.2, 1)
theme_override_font_sizes/font_size = 40
[node name="Timer" type="Timer" parent="WaveCooldown"]
wait_time = 0.1
[node name="HBoxContainer" type="HBoxContainer" parent="."]
layout_mode = 1
anchors_preset = 3
@ -46,7 +62,7 @@ anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = -562.0
offset_top = -268.0
offset_top = -200.0
grow_horizontal = 0
grow_vertical = 0
theme_override_constants/separation = 0
@ -100,31 +116,27 @@ unique_name_in_owner = true
layout_mode = 2
theme_override_colors/font_color = Color(0.2, 0.2, 0.2, 1)
[node name="WaveCooldown" type="Label" parent="HBoxContainer/InfoPanel/MarginContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
theme_override_colors/font_color = Color(0.2, 0.2, 0.2, 1)
[node name="CubeIntegrity" type="ProgressBar" parent="HBoxContainer"]
unique_name_in_owner = true
custom_minimum_size = Vector2(10, 5)
custom_minimum_size = Vector2(10, 0)
layout_mode = 2
size_flags_vertical = 1
tooltip_text = "Les points d'intégrités du Cube. S'ils arrivent à 0, fin de la partie."
theme_override_styles/background = SubResource("StyleBoxFlat_nxmp4")
theme_override_styles/fill = SubResource("StyleBoxFlat_epgl5")
value = 100.0
max_value = 50.0
value = 50.0
fill_mode = 3
show_percentage = false
[node name="ControlPanelBase" type="PanelContainer" parent="HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 8
theme_override_styles/panel = SubResource("StyleBoxFlat_3lugd")
[node name="MarginContainer" type="MarginContainer" parent="HBoxContainer/ControlPanelBase"]
layout_mode = 2
size_flags_vertical = 0
theme_override_constants/margin_left = 10
theme_override_constants/margin_top = 10
theme_override_constants/margin_right = 10
@ -142,10 +154,12 @@ layout_mode = 2
texture = ExtResource("7_fffne")
[node name="QuitLevelBtn" parent="HBoxContainer/ControlPanelBase/MarginContainer/ButtonContainer" instance=ExtResource("7_parkk")]
unique_name_in_owner = true
layout_mode = 2
texture = ExtResource("8_decjp")
[node name="QuitGameBtn" parent="HBoxContainer/ControlPanelBase/MarginContainer/ButtonContainer" instance=ExtResource("7_parkk")]
unique_name_in_owner = true
layout_mode = 2
texture = ExtResource("9_reygo")
@ -155,6 +169,7 @@ layout_mode = 2
texture = ExtResource("8_ay13l")
[node name="TowerInfoPanel" type="HBoxContainer" parent="."]
visible = false
layout_mode = 1
anchors_preset = 2
anchor_top = 1.0
@ -260,6 +275,3 @@ size_flags_horizontal = 0
size_flags_vertical = 0
[connection signal="pressed" from="HBoxContainer/ControlPanelBase/MarginContainer/ButtonContainer/CubeBtn" to="." method="_on_button_cube_pressed"]
[connection signal="pressed" from="HBoxContainer/ControlPanelBase/MarginContainer/ButtonContainer/QuitLevelBtn" to="." method="quitLevel"]
[connection signal="pressed" from="HBoxContainer/ControlPanelBase/MarginContainer/ButtonContainer/QuitGameBtn" to="." method="quitGame"]
[connection signal="toggled" from="HBoxContainer/ControlPanelBase/MarginContainer/ButtonContainer/TowerButton" to="HBoxContainer/ControlPanelBase/MarginContainer/ButtonContainer/TowerButton" method="buttonToggled"]

View file

@ -3,31 +3,32 @@ extends Button
class_name GuiButton
var towerPrice : int
var towerType : Tower.TYPE = Tower.TYPE.NONE
var tower : Tower : set = towerLinked
@export var texture : Texture2D :
set(value):
texture = value
$TextureRect.texture = texture
func _ready() -> void:
if towerType == Tower.TYPE.NONE:
func towerLinked(value) -> void:
tower = value
if not tower:
return
$LeFond/Label.text = "%d" % tower.price
toggle_mode = true
add_theme_stylebox_override("pressed", GameStyleBoxFlat.createWithColor(GameColor.COLOR.SELECTED))
EventBus.tower_changed.connect(towerChanged)
EventBus.tower_selected.connect(func(_type): set_pressed_no_signal(_type == towerType))
tower.changed.connect(towerChanged)
tower.energy_changed.connect(func(): $EnergyBar.value = tower.energy)
EventBus.tower_selected.connect(func(_type): set_pressed_no_signal(_type == tower.type))
toggled.connect(func(state): EventBus.tower_selected.emit(tower.type if state else Tower.TYPE.NONE))
tooltip_text = tower.name
texture = tower.icone
towerChanged()
func buttonToggled(state : bool) -> void:
if towerType != Tower.TYPE.NONE:
EventBus.tower_selected.emit(towerType if state else Tower.TYPE.NONE)
func towerChanged(tower : Tower) -> void :
if tower.type == towerType && tower.builded:
$EnergyBar.value = tower.energy
$EnergyBar.max_value = tower.max_energy
$EnergyBar.visible = tower.builded
func towerChanged() -> void :
disabled = not tower.builded && Game.money < tower.price
$EnergyBar.max_value = tower.max_energy
$EnergyBar.visible = tower.builded
$LeFond.visible = not tower.builded

View file

@ -1,4 +1,4 @@
[gd_scene load_steps=4 format=3 uid="uid://dqb5o8w7u50hc"]
[gd_scene load_steps=6 format=3 uid="uid://dqb5o8w7u50hc"]
[ext_resource type="Script" uid="uid://dyhtr6g7kd1g2" path="res://UI/gui_button.gd" id="1_snobr"]
[ext_resource type="Script" uid="uid://blnmjxmusrsa7" path="res://UI/GameStyleBoxFlat.gd" id="2_enkiu"]
@ -9,6 +9,15 @@ script = ExtResource("2_enkiu")
color = 1
metadata/_custom_type_script = "uid://blnmjxmusrsa7"
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_snobr"]
bg_color = Color(1, 1, 1, 0.3)
[sub_resource type="LabelSettings" id="LabelSettings_snobr"]
font_size = 26
font_color = Color(1, 0.843137, 0, 1)
outline_size = 3
outline_color = Color(0, 0, 0, 1)
[node name="TowerButton" type="Button"]
custom_minimum_size = Vector2(80, 80)
offset_right = 80.0
@ -38,4 +47,20 @@ offset_bottom = 80.0
theme_override_styles/fill = SubResource("StyleBoxFlat_i47ne")
show_percentage = false
[connection signal="toggled" from="." to="." method="buttonToggled"]
[node name="LeFond" type="PanelContainer" parent="."]
visible = false
layout_mode = 1
anchors_preset = 12
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
offset_top = -36.0
grow_horizontal = 2
grow_vertical = 0
mouse_filter = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_snobr")
[node name="Label" type="Label" parent="LeFond"]
layout_mode = 2
label_settings = SubResource("LabelSettings_snobr")
horizontal_alignment = 1

View file

@ -29,5 +29,5 @@ func upgrade(tower: Tower) -> bool:
upgradeUpgrade()
EventBus.tower_changed.emit(tower)
tower.changed.emit()
return true

View file

@ -92,6 +92,11 @@ spawn_next_wave={
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":32,"key_label":0,"unicode":32,"location":0,"echo":false,"script":null)
]
}
pause_game={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":80,"key_label":0,"unicode":112,"location":0,"echo":false,"script":null)
]
}
[layer_names]