fuzzyworld

godot-shooter / commit

A few tied-up changes:

52220002a7c853d878011a36692e5ab9dde3e331 · Pavel Safronov · 2023-11-05 16:46:58 -0800 · parents 3984bdc73d47

A few tied-up changes:
- added pause functionality, though there's no background in the pause screen yet, for some reason
- once an enemy is killed, its collision shape is disabled
- moved some code around from the world to the HUD, so restart and exit will continue to work even during pause
- added Utils.filter to filter an array of items
- closest living enemy is now targeted
 Enemy.gd      |  5 +++--
 Enemy.tscn    | 12 ++++++++++++
 HUD.gd        | 13 ++++++++++++-
 HUD.tscn      | 10 +++++++---
 Player.gd     |  7 -------
 Utils.gd      |  9 +++++++++
 World.gd      | 47 +++++++++++++++++++++++++++++------------------
 World.tscn    | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 project.godot | 12 ++++++++++++
 9 files changed, 140 insertions(+), 31 deletions(-)

diff --git a/Enemy.gd b/Enemy.gd
index c694f80..27cdc9b 100644
--- a/Enemy.gd
+++ b/Enemy.gd
@@ -11,6 +11,7 @@ export var move_speed = 40
 export var health = -1
 export var max_health = 10
 export var is_targeted = false
+export var is_invincible = false
 signal enemy_killed
 
 var velocity = Vector2.ZERO
@@ -54,7 +55,7 @@ func _physics_process(_delta: float) -> void:
 			kill()
 
 func hurt():
-	if dead:
+	if dead || is_invincible:
 		return
 	health -= 1
 	var smoke = Smoke.instance()
@@ -65,7 +66,7 @@ func hurt():
 		kill()
 
 func kill():
-	if dead:
+	if dead || is_invincible:
 		return
 	dead = true
 	$Graphics/Alive.hide()
diff --git a/Enemy.tscn b/Enemy.tscn
index 42592fb..0a68bb4 100644
--- a/Enemy.tscn
+++ b/Enemy.tscn
@@ -33,6 +33,18 @@ tracks/1/keys = {
 "method": "queue_free"
 } ]
 }
+tracks/2/type = "value"
+tracks/2/path = NodePath("CollisionPolygon2D:disabled")
+tracks/2/interp = 1
+tracks/2/loop_wrap = true
+tracks/2/imported = false
+tracks/2/enabled = true
+tracks/2/keys = {
+"times": PoolRealArray( 0 ),
+"transitions": PoolRealArray( 1 ),
+"update": 1,
+"values": [ true ]
+}
 
 [sub_resource type="Animation" id=2]
 resource_name = "fade_out"
diff --git a/HUD.gd b/HUD.gd
index 02cee1f..287e16f 100644
--- a/HUD.gd
+++ b/HUD.gd
@@ -6,4 +6,15 @@ func _ready() -> void:
 	$AnimationPlayer.play("instructions fade")
 
 func _process(_delta: float) -> void:
-	$VBoxContainer/HBoxContainer/Score.text = "%s" % score
+	$VBoxContainer/HBoxContainer2/HBoxContainer/Score.text = "%s" % score
+	if Input.is_action_just_pressed("exit"):
+		if OS.get_name() == "OSX":
+			get_tree().quit()
+		else:
+			restart()
+	if Input.is_action_just_pressed("restart"):
+		restart()
+
+func restart():
+	var _error = get_tree().reload_current_scene()
+	get_tree().paused = false
diff --git a/HUD.tscn b/HUD.tscn
index c95ba79..7bec601 100644
--- a/HUD.tscn
+++ b/HUD.tscn
@@ -57,16 +57,20 @@ script = ExtResource( 2 )
 margin_right = 40.0
 margin_bottom = 40.0
 
-[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"]
+[node name="HBoxContainer2" type="HBoxContainer" parent="VBoxContainer"]
 margin_right = 617.0
 margin_bottom = 74.0
 
-[node name="ScoreText" type="Label" parent="VBoxContainer/HBoxContainer"]
+[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/HBoxContainer2"]
+margin_right = 278.0
+margin_bottom = 74.0
+
+[node name="ScoreText" type="Label" parent="VBoxContainer/HBoxContainer2/HBoxContainer"]
 margin_right = 192.0
 margin_bottom = 74.0
 text = "Score: "
 
-[node name="Score" type="Label" parent="VBoxContainer/HBoxContainer"]
+[node name="Score" type="Label" parent="VBoxContainer/HBoxContainer2/HBoxContainer"]
 margin_left = 196.0
 margin_right = 278.0
 margin_bottom = 74.0
diff --git a/Player.gd b/Player.gd
index 199a3ad..7a01135 100644
--- a/Player.gd
+++ b/Player.gd
@@ -17,13 +17,6 @@ var destination: Vector2
 var is_destination_set = false
 
 func _process(_delta: float) -> void:
-	if Input.is_action_just_pressed("exit"):
-		if OS.get_name() == "OSX":
-			get_tree().quit()
-		else:
-			restart()
-	if Input.is_action_just_pressed("restart"):
-		restart()
 	if dead:
 		return
 	$Graphics/Alive/Control/HealthLabel.text = "%s / %s" % [health, max_health]
diff --git a/Utils.gd b/Utils.gd
index 5424ca4..c9b3af2 100644
--- a/Utils.gd
+++ b/Utils.gd
@@ -11,3 +11,12 @@ static func log(arg1 = null, arg2 = null, arg3 = null, arg4 = null, arg5 = null,
 			var argText = "%s " % argument
 			text += argText
 	print(text)
+
+static func filter(filter_function: FuncRef, candidate_array: Array)->Array:
+	var filtered_array := []
+
+	for candidate_value in candidate_array:
+		if filter_function.call_func(candidate_value):
+			filtered_array.append(candidate_value)
+
+	return filtered_array
diff --git a/World.gd b/World.gd
index 39ce60a..69717cd 100644
--- a/World.gd
+++ b/World.gd
@@ -39,9 +39,12 @@ func _process(_delta: float) -> void:
 	if Input.is_action_just_pressed("click") and !$Player.dead:
 		var pos = get_global_mouse_position()
 		set_destination(pos)
+	if Input.is_action_just_pressed("pause"):
+		get_tree().paused = true
+		$CanvasLayer/PauseMenu.show()
 
 	if is_destination_set:
-		var diff = destination - $Player.position
+		var diff = destination - $Player.global_position
 		var unit = diff.normalized()
 		$Player.velocity = unit * $Player.move_speed
 		$Destination.visible = true
@@ -53,7 +56,7 @@ func set_destination(pos: Vector2) -> void:
 	Utils.log("setting destination to ", pos)
 	destination = pos
 	is_destination_set = true
-	$Destination.position = pos
+	$Destination.global_position = pos
 	$Destination.visible = true
 	$Player.	global_rotation = global_position.direction_to(get_global_mouse_position()).angle() + PI/2.0
 
@@ -62,25 +65,33 @@ func _on_Destination_body_entered(body: Node) -> void:
 		is_destination_set = false
 
 func sort_enemies_ascending_distance(a: Enemy,b: Enemy):
-	var distA = (a.global_position - $Player.global_position).length()
-	var distB = (b.global_position - $Player.global_position).length()
-	if distA < distB:
-		return true
-	return false
+	var distA = $Player.global_position.distance_to(a.global_position)
+	var distB = $Player.global_position.distance_to(b.global_position)
+	var result = distA < distB
+	return result
+	
+func filter_invalid_enemies(enemy: Enemy) -> bool:
+	if enemy.dead:
+		return false
+	return true
 
 func _on_ShootTimer_timeout() -> void:
 	if $Player.dead:
 		return
 	var enemies = get_tree().get_nodes_in_group("enemies")
-	if enemies.size() > 0:
-#		Utils.log("enemies length", enemies.size())
-		enemies.sort_custom(self, "sort_enemies_ascending_distance")
-		for enemy in enemies:
-#			var diff_to_player: Vector2 = enemy.position - $Player.position
-#			var dist_to_player = diff_to_player.length()
-#			Utils.log("enemy pos", enemy.position, "dist_to_player", dist_to_player)
-			enemy.is_targeted = false
-		var closest_enemy: Enemy = enemies[0]
-		$Player.shoot_at(closest_enemy.global_position)
+	for e in enemies:
+		var enemy: Enemy = e
+		enemy.is_targeted = false
+	
+	var filteredEnemies = Utils.filter(funcref(self,"filter_invalid_enemies"), enemies)
+	if filteredEnemies.size() > 0:
+		filteredEnemies.sort_custom(self, "sort_enemies_ascending_distance")
+		var closest_enemy: Enemy = filteredEnemies[0]
 		closest_enemy.is_targeted = true
-		
+		$Player.shoot_at(closest_enemy.global_position)
+		$PlayerToTarget.points[0] = $Player.global_position
+		$PlayerToTarget.points[1] = closest_enemy.global_position
+
+func _on_Button_pressed() -> void:
+	get_tree().paused = false
+	$CanvasLayer/PauseMenu.hide()
diff --git a/World.tscn b/World.tscn
index fb4b161..09d484a 100644
--- a/World.tscn
+++ b/World.tscn
@@ -41,6 +41,7 @@ visible = false
 
 [node name="Player" parent="." groups=["player"] instance=ExtResource( 2 )]
 position = Vector2( 513, 302 )
+is_invincible = true
 
 [node name="Destination" type="Area2D" parent="."]
 
@@ -54,11 +55,66 @@ shape = SubResource( 1 )
 [node name="CanvasLayer" type="CanvasLayer" parent="."]
 
 [node name="HUD" parent="CanvasLayer" instance=ExtResource( 3 )]
+pause_mode = 2
+margin_left = -4.0
+margin_top = -3.0
+margin_right = -4.0
+margin_bottom = -3.0
+
+[node name="PauseMenu" type="Control" parent="CanvasLayer"]
+pause_mode = 2
+visible = false
+anchor_right = 1.0
+anchor_bottom = 1.0
+margin_right = 40.0
+margin_bottom = 40.0
+mouse_filter = 2
+
+[node name="CenterContainer" type="CenterContainer" parent="CanvasLayer/PauseMenu"]
+anchor_right = 1.0
+anchor_bottom = 1.0
+margin_right = 40.0
+margin_bottom = 40.0
+
+[node name="Panel" type="Panel" parent="CanvasLayer/PauseMenu/CenterContainer"]
+margin_left = 552.0
+margin_top = 340.0
+margin_right = 552.0
+margin_bottom = 340.0
+
+[node name="VBoxContainer" type="VBoxContainer" parent="CanvasLayer/PauseMenu/CenterContainer/Panel"]
+margin_left = 50.0
+margin_top = 50.0
+
+[node name="Label" type="Label" parent="CanvasLayer/PauseMenu/CenterContainer/Panel/VBoxContainer"]
+margin_right = 64.0
+margin_bottom = 14.0
+text = "Paused"
+align = 1
+
+[node name="Button" type="Button" parent="CanvasLayer/PauseMenu/CenterContainer/Panel/VBoxContainer"]
+margin_top = 18.0
+margin_right = 64.0
+margin_bottom = 38.0
+text = "Resume"
 
 [node name="ShootTimer" type="Timer" parent="."]
 process_mode = 0
 wait_time = 0.1
 autostart = true
 
+[node name="PlayerToTarget" type="Line2D" parent="."]
+visible = false
+modulate = Color( 1, 0.984314, 0, 1 )
+points = PoolVector2Array( 2085.69, 283.505, 2067.82, 274.471 )
+width = 3.0
+default_color = Color( 1, 0.976471, 0.4, 1 )
+joint_mode = 1
+begin_cap_mode = 2
+end_cap_mode = 2
+round_precision = 13
+antialiased = true
+
 [connection signal="body_entered" from="Destination" to="." method="_on_Destination_body_entered"]
+[connection signal="pressed" from="CanvasLayer/PauseMenu/CenterContainer/Panel/VBoxContainer/Button" to="." method="_on_Button_pressed"]
 [connection signal="timeout" from="ShootTimer" to="." method="_on_ShootTimer_timeout"]
diff --git a/project.godot b/project.godot
index 784704c..f80d32c 100644
--- a/project.godot
+++ b/project.godot
@@ -62,6 +62,18 @@ click={
 "events": [ Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"button_mask":0,"position":Vector2( 0, 0 ),"global_position":Vector2( 0, 0 ),"factor":1.0,"button_index":1,"pressed":false,"doubleclick":false,"script":null)
  ]
 }
+pause={
+"deadzone": 0.5,
+"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":80,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
+ ]
+}
+
+[network]
+
+limits/debugger_stdout/max_chars_per_second=2048000
+limits/debugger_stdout/max_messages_per_frame=1000
+limits/debugger_stdout/max_errors_per_second=1000
+limits/debugger_stdout/max_warnings_per_second=1000
 
 [physics]