fuzzyworld

godot-shooter / commit

Moved a lot of UI stuff (like the intro dialog, the pause dialog, etc.) out of the World scene and into the Player scene.

f3c75ae97cbffd5e3bac496ca86192f5951c357d · Pavel Safronov · 2023-11-14 16:28:26 -0800 · parents 9c3981ff4a17

Moved a lot of UI stuff (like the intro dialog, the pause dialog, etc.) out of the World scene and into the Player scene.
 HUD.gd      |   2 +
 Player.gd   | 131 ++++++++++++++----
 Player.tscn | 448 +++++++++++++++++++++++++++++++++++-------------------------
 Rocket.gd   |   1 -
 Settings.gd |  30 +++-
 Utils.gd    |  60 +++++++-
 World.gd    |  82 ++---------
 World.tscn  | 217 +----------------------------
 8 files changed, 459 insertions(+), 512 deletions(-)

diff --git a/HUD.gd b/HUD.gd
index 5888efd..98deb5d 100644
--- a/HUD.gd
+++ b/HUD.gd
@@ -47,6 +47,8 @@ func _input(event: InputEvent) -> void:
 func _process(_delta: float) -> void:
 	score_label.text = "%s" % score
 	objective_label.text = "%s" % objective
+	if Input.is_action_just_pressed("pause"):
+		emit_signal("paused")
 	if Input.is_action_just_pressed("exit"):
 		if OS.get_name() == "OSX":
 			get_tree().quit()
diff --git a/Player.gd b/Player.gd
index 33c3903..c7f4a99 100644
--- a/Player.gd
+++ b/Player.gd
@@ -3,17 +3,33 @@ class_name Player
 
 const Weapons = preload("res://Weapons.gd")
 
+export var score = 0
 export var move_speed = 60
 export var health = 50
 export var max_health = 100
 export var is_invincible = false
 export var turn_rate = 0.03
-export var shield_active = true
 export var radar_min_radius = 350
 export var radar_max_radius = 2000
+signal player_died
+signal destination_set(position)
+signal debug
 
+onready var hud = $UI/HUD
+onready var static_controls = $Graphics/Alive/StaticControls
 onready var radar_sprite = $Graphics/Alive/StaticControls/RadarSprite
 onready var radar_container = $Graphics/Alive/StaticControls/Radar
+onready var scores_container = $UI/PauseMenu/CenterContainer/PanelContainer/VBoxContainer/TabContainer/Scores
+onready var scores_list = $UI/PauseMenu/CenterContainer/PanelContainer/VBoxContainer/TabContainer/Scores/ScoresList
+onready var intro_menu = $UI/IntroMenu
+onready var intro_always_show_intro_check = $UI/IntroMenu/CenterContainer/PanelContainer/VBoxContainer/AlwaysShowIntroCheckBox
+onready var pause_always_show_intro_check = $UI/PauseMenu/CenterContainer/PanelContainer/VBoxContainer/TabContainer/Pref/AlwaysShowIntroCheckBox
+onready var health_label = $Graphics/Alive/StaticControls/HealthLabel
+onready var trails = $Graphics/Alive/Trails
+onready var shot_timer = $ShotTimer
+onready var death_screen = $UI/DeathScreen
+onready var final_score_label = $UI/DeathScreen/CenterContainer/PanelContainer/VBoxContainer/FinalScoreLabel
+
 const Utils = preload("res://Utils.gd")
 const PopupControl = preload("res://Popup.tscn")
 
@@ -22,26 +38,41 @@ var default_weapon: Weapon = Weapons.create_basic_gun()
 var dead = false
 var velocity: Vector2
 var can_fire = true
-var destination: Vector2
-var is_destination_set = false
+var settings: Settings
 
 func _ready() -> void:
 	velocity= Vector2.UP * move_speed
 	weapon = Weapons.create_basic_gun()
-#	weapon = Weapons.create_gattling_gun()
-	if shield_active:
-		enable_shield()
-	else:
-		$Graphics/Alive/Shield/Sprite/AnimationPlayer.play("fade out instant")
+
+	var now = Time.get_datetime_dict_from_system()
+#	Utils.remove_user_settings()
+	settings = Utils.load_user_settings()
+	settings.save_user_settings()
+	pause_always_show_intro_check.pressed = settings.show_intro
+	if settings.show_intro:
+		get_tree().paused = true
+		intro_menu.visible = true
+	if settings.high_scores.size() > 0:
+		Utils.remove_all_children(scores_list)
+		settings.high_scores.sort_custom(self, "sort_high_scores")
+		var index = 0
+		for hs in settings.high_scores:
+			index += 1
+			var label = Label.new()
+			var date_dict = hs.date
+			var date_diff_secs = Utils.time_diff_secs(date_dict, now)
+			var date_diff = Utils.timespan_to_english(date_diff_secs)
+			label.text = "%s - %s points, %s" % [index, hs.score, date_diff]
+			scores_list.add_child(label)
 
 func _process(_delta: float) -> void:
 	if dead:
 		return
-	$Graphics/Alive/StaticControls/HealthLabel.text = "%s / %s" % [health, max_health]
-	$Graphics/Alive/StaticControls.global_rotation = 0
-	$Graphics/Alive/Trails.add_position(global_position)
-	$ShieldCollisionShape.disabled = !shield_active
-	$ShipCollisionShape.disabled = shield_active
+	health_label.text = "%s / %s" % [health, max_health]
+	static_controls.global_rotation = 0
+	trails.add_position(global_position)
+	hud.set_current_weapon(weapon)
+	hud.score = score
 
 func _physics_process(_delta: float) -> void:
 	if dead:
@@ -76,9 +107,12 @@ func kill():
 	if dead or is_invincible:
 		return
 	dead = true
+	emit_signal("player_died")
+	add_high_score(score)
 	$Graphics/Dead.show()
 	$Graphics/Alive.hide()
-	$CanvasLayer/CenterContainer/DeathScreen.show()
+	final_score_label.text = "Final score: %s" % score
+	death_screen.show()
 	z_index = -1
 	get_tree().paused = true
 
@@ -94,19 +128,9 @@ func speed_up(delta: int = 10):
 		return
 	move_speed += delta
 
-func enable_shield() -> void:
-	shield_active = true
-	$Graphics/Alive/Shield/Sprite/AnimationPlayer.play("fade in")
-
-func disable_shield() -> void:
-	shield_active = false
-	$Graphics/Alive/Shield/Sprite/AnimationPlayer.play("fade out")
-
 func hurt(damage_amount: int = 1):
 	if dead or is_invincible:
 		return
-	if shield_active:
-		disable_shield()
 	else:
 		health -= damage_amount
 		if health <= 0:
@@ -123,8 +147,8 @@ func shoot():
 	if !can_fire:
 		return
 	can_fire = false
-	$ShotTimer.wait_time = weapon.shot_period_seconds
-	$ShotTimer.start()
+	shot_timer.wait_time = weapon.shot_period_seconds
+	shot_timer.start()
 	var particle = weapon.particle.instance()
 	owner.add_child(particle)
 	particle.transform = $Barrel.global_transform
@@ -137,8 +161,8 @@ func shoot_at(pos: Vector2):
 		if weapon.ammo <= 0:
 			weapon = default_weapon
 		weapon.ammo -= 1
-	$ShotTimer.wait_time = weapon.cooldown_seconds
-	$ShotTimer.start()
+	shot_timer.wait_time = weapon.cooldown_seconds
+	shot_timer.start()
 	var particle = weapon.particle.instance()
 	particle.damage_amount = weapon.damage_amount
 	owner.add_child(particle)
@@ -151,3 +175,54 @@ func allow_fire():
 func _on_Button_pressed() -> void:
 	get_tree().paused = false
 	restart()
+
+func set_objective(objective: String) -> void:
+	hud.objective = objective
+
+func _on_StartButton_pressed() -> void:
+	get_tree().paused = false
+	intro_menu.visible = false
+	settings.show_intro = intro_always_show_intro_check.pressed
+	settings.save_user_settings()
+
+func set_intro_dialog(enabled: bool) -> void:
+	settings.show_intro = enabled
+	settings.save_user_settings()
+
+func _on_PauseAlwaysShowIntroCheckBox_pressed() -> void:
+	var show_intro = pause_always_show_intro_check.pressed
+	set_intro_dialog(show_intro)
+
+func add_high_score(new_score: int) -> void:
+	var hs = Settings.HighScore.new(new_score, Time.get_datetime_dict_from_system())
+	var hss = settings.high_scores
+	hss.push_back(hs)
+	settings.high_scores.sort_custom(self, "sort_high_scores")
+	while settings.high_scores.size() > 10:
+		settings.high_scores.pop_back()
+	settings.save_user_settings()
+
+func _on_LinkButton_pressed() -> void:
+	get_tree().paused = true
+	var _err = OS.shell_open("https://gitlab.com/PavelSafronov/godot-shooter")
+	get_tree().paused = true
+
+func _on_HUD_position_set(position) -> void:
+	emit_signal("destination_set", position)
+
+func show_message(message: String, duration_seconds: int = 2) -> void:
+	hud.show_message(message, duration_seconds)
+
+func _on_HUD_paused() -> void:
+	get_tree().paused = true
+	$UI/PauseMenu.show()
+
+func _on_ResumeButton_pressed() -> void:
+	get_tree().paused = false
+	$UI/PauseMenu.hide()
+
+func _on_HUD_debug_signal() -> void:
+	emit_signal("debug")
+
+func sort_high_scores(a, b):
+	return (a as Settings.HighScore).score > (b as Settings.HighScore).score
diff --git a/Player.tscn b/Player.tscn
index 7629a80..7954406 100644
--- a/Player.tscn
+++ b/Player.tscn
@@ -6,10 +6,9 @@
 [ext_resource path="res://assets/kenney_simple-space/PNG/Retina/ship_B.png" type="Texture" id=4]
 [ext_resource path="res://CharacterTheme.tres" type="Theme" id=5]
 [ext_resource path="res://Trails.tscn" type="PackedScene" id=6]
-[ext_resource path="res://assets/kenney_crosshair-pack/PNG/White Retina/crosshair120.png" type="Texture" id=7]
-
-[sub_resource type="CircleShape2D" id=7]
-radius = 36.0
+[ext_resource path="res://assets/neuropolitical rg.otf" type="DynamicFontData" id=8]
+[ext_resource path="res://Theme.tres" type="Theme" id=9]
+[ext_resource path="res://HUD.tscn" type="PackedScene" id=10]
 
 [sub_resource type="Gradient" id=2]
 colors = PoolColorArray( 1, 0, 0, 1, 1, 0, 0, 0 )
@@ -17,159 +16,34 @@ colors = PoolColorArray( 1, 0, 0, 1, 1, 0, 0, 0 )
 [sub_resource type="Gradient" id=1]
 colors = PoolColorArray( 0, 0, 0, 0, 0, 1, 0, 1 )
 
-[sub_resource type="Animation" id=3]
-length = 0.001
-tracks/0/type = "value"
-tracks/0/path = NodePath(".:modulate")
-tracks/0/interp = 1
-tracks/0/loop_wrap = true
-tracks/0/imported = false
-tracks/0/enabled = true
-tracks/0/keys = {
-"times": PoolRealArray( 0 ),
-"transitions": PoolRealArray( 1 ),
-"update": 0,
-"values": [ Color( 0, 0, 1, 1 ) ]
-}
-tracks/1/type = "value"
-tracks/1/path = NodePath(".:rotation_degrees")
-tracks/1/interp = 1
-tracks/1/loop_wrap = true
-tracks/1/imported = false
-tracks/1/enabled = true
-tracks/1/keys = {
-"times": PoolRealArray( 0 ),
-"transitions": PoolRealArray( 1 ),
-"update": 0,
-"values": [ 0.0 ]
-}
-tracks/2/type = "value"
-tracks/2/path = NodePath(".:scale")
-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": 0,
-"values": [ Vector2( 1, 1 ) ]
-}
-
-[sub_resource type="Animation" id=4]
-resource_name = "blinking"
-loop = true
-tracks/0/type = "value"
-tracks/0/path = NodePath(".:modulate")
-tracks/0/interp = 1
-tracks/0/loop_wrap = true
-tracks/0/imported = false
-tracks/0/enabled = true
-tracks/0/keys = {
-"times": PoolRealArray( 0, 0.7, 1 ),
-"transitions": PoolRealArray( 1, 1, 1 ),
-"update": 0,
-"values": [ Color( 0, 0, 1, 1 ), Color( 0, 0, 1, 0.509804 ), Color( 0, 0, 1, 1 ) ]
-}
-tracks/1/type = "value"
-tracks/1/path = NodePath(".:rotation_degrees")
-tracks/1/interp = 1
-tracks/1/loop_wrap = true
-tracks/1/imported = false
-tracks/1/enabled = true
-tracks/1/keys = {
-"times": PoolRealArray( 0, 1 ),
-"transitions": PoolRealArray( 1, 1 ),
-"update": 0,
-"values": [ 0.0, 90.0 ]
-}
-tracks/2/type = "value"
-tracks/2/path = NodePath(".:scale")
-tracks/2/interp = 1
-tracks/2/loop_wrap = true
-tracks/2/imported = false
-tracks/2/enabled = true
-tracks/2/keys = {
-"times": PoolRealArray( 0, 0.7, 1 ),
-"transitions": PoolRealArray( 1, 1, 1 ),
-"update": 0,
-"values": [ Vector2( 0.7, 0.7 ), Vector2( 0.6, 0.6 ), Vector2( 0.7, 0.7 ) ]
-}
+[sub_resource type="DynamicFont" id=9]
+size = 24
+font_data = ExtResource( 8 )
 
-[sub_resource type="Animation" id=5]
-resource_name = "fade in"
-tracks/0/type = "value"
-tracks/0/path = NodePath(".:modulate")
-tracks/0/interp = 1
-tracks/0/loop_wrap = true
-tracks/0/imported = false
-tracks/0/enabled = true
-tracks/0/keys = {
-"times": PoolRealArray( 0, 1 ),
-"transitions": PoolRealArray( 1, 1 ),
-"update": 0,
-"values": [ Color( 0, 0, 1, 0 ), Color( 0, 0, 1, 1 ) ]
-}
-tracks/1/type = "method"
-tracks/1/path = NodePath("AnimationPlayer")
-tracks/1/interp = 1
-tracks/1/loop_wrap = true
-tracks/1/imported = false
-tracks/1/enabled = true
-tracks/1/keys = {
-"times": PoolRealArray( 1 ),
-"transitions": PoolRealArray( 1 ),
-"values": [ {
-"args": [ "blinking", -1, 1.0, false ],
-"method": "play"
-} ]
-}
+[sub_resource type="DynamicFont" id=10]
+outline_color = Color( 0, 0.490196, 0.831373, 1 )
+use_mipmaps = true
+use_filter = true
+font_data = ExtResource( 8 )
 
-[sub_resource type="Animation" id=6]
-resource_name = "fade out"
-tracks/0/type = "value"
-tracks/0/path = NodePath(".:modulate")
-tracks/0/interp = 1
-tracks/0/loop_wrap = true
-tracks/0/imported = false
-tracks/0/enabled = true
-tracks/0/keys = {
-"times": PoolRealArray( 0, 1 ),
-"transitions": PoolRealArray( 1, 1 ),
-"update": 0,
-"values": [ Color( 0, 0, 1, 1 ), Color( 0, 0, 1, 0 ) ]
-}
+[sub_resource type="Theme" id=11]
+default_font = SubResource( 10 )
 
-[sub_resource type="Animation" id=8]
-resource_name = "fade out instant"
-length = 0.001
-tracks/0/type = "value"
-tracks/0/path = NodePath(".:modulate")
-tracks/0/interp = 1
-tracks/0/loop_wrap = true
-tracks/0/imported = false
-tracks/0/enabled = true
-tracks/0/keys = {
-"times": PoolRealArray( 0 ),
-"transitions": PoolRealArray( 1 ),
-"update": 0,
-"values": [ Color( 0, 0, 1, 0 ) ]
-}
+[sub_resource type="DynamicFont" id=12]
+use_mipmaps = true
+use_filter = true
+font_data = ExtResource( 8 )
 
 [node name="Player" type="KinematicBody2D" groups=["player"]]
 rotation = -0.000165944
 z_index = 10
 collision_mask = 6
 script = ExtResource( 3 )
-shield_active = false
 radar_max_radius = 3000
 
 [node name="ShipCollisionShape" type="CollisionPolygon2D" parent="."]
 polygon = PoolVector2Array( -0.996349, -22.0002, -8.00133, 7.99867, -7.00166, 9.99884, -11.002, 11.9982, -14.0007, 3.99768, -20.002, 11.9967, -17.0038, 22.9972, -9.00465, 27.9985, -8.00448, 26.9987, -10.0027, 15.9983, -6.00232, 13.999, -0.00398266, 24, 4.99784, 13.0008, 9.99734, 16.0017, 6.99552, 27.0012, 7.99519, 29.0013, 10.9952, 29.0018, 17.996, 24.003, 20.998, 12.0035, 15.9993, 4.00266, 12.9993, 4.00216, 10.9982, 11.0018, 6.99834, 10.0012, 0.00381671, -23 )
 
-[node name="ShieldCollisionShape" type="CollisionShape2D" parent="."]
-shape = SubResource( 7 )
-
 [node name="Graphics" type="Node2D" parent="."]
 
 [node name="Alive" type="Node2D" parent="Graphics"]
@@ -208,81 +82,270 @@ offset = Vector2( 0, -300 )
 modulate = Color( 1, 0, 0, 1 )
 gradient = SubResource( 1 )
 
-[node name="Shield" type="Node2D" parent="Graphics/Alive"]
-
-[node name="Sprite" type="Sprite" parent="Graphics/Alive/Shield"]
-modulate = Color( 0, 0, 1, 1 )
-texture = ExtResource( 7 )
-
-[node name="AnimationPlayer" type="AnimationPlayer" parent="Graphics/Alive/Shield/Sprite"]
-autoplay = "blinking"
-anims/RESET = SubResource( 3 )
-anims/blinking = SubResource( 4 )
-"anims/fade in" = SubResource( 5 )
-"anims/fade out" = SubResource( 6 )
-"anims/fade out instant" = SubResource( 8 )
-
 [node name="Dead" type="Node2D" parent="Graphics"]
 visible = false
 
 [node name="Explosion" parent="Graphics/Dead" instance=ExtResource( 2 )]
 
-[node name="CanvasLayer" type="CanvasLayer" parent="."]
+[node name="UI" type="CanvasLayer" parent="."]
+pause_mode = 2
 layer = 100
 
-[node name="CenterContainer" type="CenterContainer" parent="CanvasLayer"]
+[node name="HUD" parent="UI" instance=ExtResource( 10 )]
+pause_mode = 2
+
+[node name="DeathScreen" type="Control" parent="UI"]
+pause_mode = 2
+visible = false
 margin_left = 109.0
 margin_top = 84.0
 margin_right = 109.0
 margin_bottom = 84.0
 mouse_filter = 2
-
-[node name="DeathScreen" type="Control" parent="CanvasLayer/CenterContainer"]
-pause_mode = 2
-visible = false
-mouse_filter = 2
 size_flags_horizontal = 5
 size_flags_vertical = 5
 
-[node name="ColorRect" type="ColorRect" parent="CanvasLayer/CenterContainer/DeathScreen"]
+[node name="CenterContainer" type="CenterContainer" parent="UI/DeathScreen"]
+anchor_right = 1.0
+anchor_bottom = 1.0
+
+[node name="PanelContainer" type="PanelContainer" parent="UI/DeathScreen/CenterContainer"]
+margin_right = 300.0
+margin_bottom = 200.0
+rect_min_size = Vector2( 300, 200 )
+
+[node name="VBoxContainer" type="VBoxContainer" parent="UI/DeathScreen/CenterContainer/PanelContainer"]
+margin_left = 14.0
+margin_top = 14.0
+margin_right = 286.0
+margin_bottom = 186.0
+
+[node name="Label" type="Label" parent="UI/DeathScreen/CenterContainer/PanelContainer/VBoxContainer"]
+margin_right = 272.0
+margin_bottom = 25.0
+size_flags_horizontal = 3
+theme = ExtResource( 5 )
+text = "Game Over"
+align = 1
+valign = 1
+
+[node name="FinalScoreLabel" type="Label" parent="UI/DeathScreen/CenterContainer/PanelContainer/VBoxContainer"]
 margin_right = 40.0
-margin_bottom = 40.0
-color = Color( 0, 0, 0, 1 )
+margin_bottom = 25.0
 
-[node name="Panel" type="Panel" parent="CanvasLayer/CenterContainer/DeathScreen"]
-margin_right = 250.0
-margin_bottom = 150.0
+[node name="Button" type="Button" parent="UI/DeathScreen/CenterContainer/PanelContainer/VBoxContainer"]
+margin_top = 135.0
+margin_right = 272.0
+margin_bottom = 172.0
+size_flags_vertical = 14
+theme = ExtResource( 5 )
+text = "Restart"
+
+[node name="IntroMenu" type="Control" parent="UI" groups=["pause_menu"]]
+visible = false
+anchor_right = 1.0
+anchor_bottom = 1.0
+
+[node name="CenterContainer" type="CenterContainer" parent="UI/IntroMenu"]
+anchor_right = 1.0
+anchor_bottom = 1.0
+
+[node name="PanelContainer" type="PanelContainer" parent="UI/IntroMenu/CenterContainer"]
+margin_left = 236.0
+margin_top = 386.0
+margin_right = 264.0
+margin_bottom = 414.0
+
+[node name="VBoxContainer" type="VBoxContainer" parent="UI/IntroMenu/CenterContainer/PanelContainer"]
+margin_left = 14.0
+margin_top = 14.0
+margin_right = 447.0
+margin_bottom = 451.0
+theme = ExtResource( 9 )
+alignment = 1
+
+[node name="Label" type="Label" parent="UI/IntroMenu/CenterContainer/PanelContainer/VBoxContainer"]
+margin_right = 433.0
+margin_bottom = 30.0
+custom_fonts/font = SubResource( 9 )
+text = "Welcome to Tactical Shooter!"
+
+[node name="RichTextLabel" type="RichTextLabel" parent="UI/IntroMenu/CenterContainer/PanelContainer/VBoxContainer"]
+margin_top = 38.0
+margin_right = 433.0
+margin_bottom = 324.0
+theme = SubResource( 11 )
+text = "This is a 2D space shooter game.
+
+You choose where to fly in this game.
+
+Your ship will attack for you.
+
+Touch/click + hold anywhere to pause the game and plan your course.
+Let go to set location as the destination.
+
+Your objective count is in the lower-right corner.
+The radar shows enemies and objectives."
+fit_content_height = true
+
+[node name="AlwaysShowIntroCheckBox" type="CheckBox" parent="UI/IntroMenu/CenterContainer/PanelContainer/VBoxContainer"]
+margin_top = 332.0
+margin_right = 433.0
+margin_bottom = 380.0
+custom_fonts/font = SubResource( 12 )
+pressed = true
+text = "Always show intro"
+
+[node name="StartButton" type="Button" parent="UI/IntroMenu/CenterContainer/PanelContainer/VBoxContainer"]
+margin_top = 388.0
+margin_right = 433.0
+margin_bottom = 437.0
+mouse_default_cursor_shape = 2
+text = "Start Game"
+
+[node name="PauseMenu" type="Control" parent="UI" groups=["pause_menu"]]
+visible = false
+anchor_right = 1.0
+anchor_bottom = 1.0
 mouse_filter = 2
 
-[node name="Label" type="Label" parent="CanvasLayer/CenterContainer/DeathScreen/Panel"]
+[node name="CenterContainer" type="CenterContainer" parent="UI/PauseMenu"]
 anchor_right = 1.0
-margin_top = 50.0
-margin_bottom = 14.0
-theme = ExtResource( 5 )
-text = "Game Over"
+anchor_bottom = 1.0
+
+[node name="PanelContainer" type="PanelContainer" parent="UI/PauseMenu/CenterContainer"]
+margin_left = 25.0
+margin_top = 282.0
+margin_right = 475.0
+margin_bottom = 517.0
+rect_min_size = Vector2( 450, 235 )
+
+[node name="VBoxContainer" type="VBoxContainer" parent="UI/PauseMenu/CenterContainer/PanelContainer"]
+margin_left = 14.0
+margin_top = 14.0
+margin_right = 436.0
+margin_bottom = 233.0
+
+[node name="Label" type="Label" parent="UI/PauseMenu/CenterContainer/PanelContainer/VBoxContainer"]
+margin_right = 422.0
+margin_bottom = 37.0
+theme = ExtResource( 9 )
+text = "Paused"
 align = 1
-valign = 1
 
-[node name="Button" type="Button" parent="CanvasLayer/CenterContainer/DeathScreen/Panel"]
-anchor_top = 1.0
+[node name="TabContainer" type="TabContainer" parent="UI/PauseMenu/CenterContainer/PanelContainer/VBoxContainer"]
+margin_top = 45.0
+margin_right = 422.0
+margin_bottom = 174.0
+
+[node name="Scores" type="VBoxContainer" parent="UI/PauseMenu/CenterContainer/PanelContainer/VBoxContainer/TabContainer"]
 anchor_right = 1.0
 anchor_bottom = 1.0
-margin_top = -20.0
-theme = ExtResource( 5 )
-text = "Restart"
+margin_left = 8.0
+margin_top = 61.0
+margin_right = -8.0
+margin_bottom = -8.0
+
+[node name="Label" type="Label" parent="UI/PauseMenu/CenterContainer/PanelContainer/VBoxContainer/TabContainer/Scores"]
+margin_right = 406.0
+margin_bottom = 25.0
+text = "High scores:"
+
+[node name="ScoresList" type="VBoxContainer" parent="UI/PauseMenu/CenterContainer/PanelContainer/VBoxContainer/TabContainer/Scores"]
+margin_top = 33.0
+margin_right = 406.0
+margin_bottom = 33.0
+
+[node name="Label" type="Label" parent="UI/PauseMenu/CenterContainer/PanelContainer/VBoxContainer/TabContainer/Scores/ScoresList"]
+margin_right = 40.0
+margin_bottom = 25.0
+text = "No high scores yet!"
 
-[node name="Camera2D" type="Camera2D" parent="."]
-current = true
+[node name="Pref" type="VBoxContainer" parent="UI/PauseMenu/CenterContainer/PanelContainer/VBoxContainer/TabContainer"]
+visible = false
+anchor_right = 1.0
+anchor_bottom = 1.0
+margin_left = 8.0
+margin_top = 61.0
+margin_right = -8.0
+margin_bottom = -8.0
+
+[node name="AlwaysShowIntroCheckBox" type="CheckBox" parent="UI/PauseMenu/CenterContainer/PanelContainer/VBoxContainer/TabContainer/Pref"]
+margin_right = 406.0
+margin_bottom = 48.0
+text = "Show intro dialog"
 
-[node name="CanvasLayer2" type="CanvasLayer" parent="."]
+[node name="About" type="VBoxContainer" parent="UI/PauseMenu/CenterContainer/PanelContainer/VBoxContainer/TabContainer"]
 visible = false
+anchor_right = 1.0
+anchor_bottom = 1.0
+margin_left = 8.0
+margin_top = 61.0
+margin_right = -8.0
+margin_bottom = -8.0
+
+[node name="RichTextLabel" type="RichTextLabel" parent="UI/PauseMenu/CenterContainer/PanelContainer/VBoxContainer/TabContainer/About"]
+margin_right = 406.0
+margin_bottom = 27.0
+rect_min_size = Vector2( 200, 0 )
+text = "Welcome to my Godot experiment."
+fit_content_height = true
+
+[node name="LinkButton" type="LinkButton" parent="UI/PauseMenu/CenterContainer/PanelContainer/VBoxContainer/TabContainer/About"]
+margin_top = 35.0
+margin_right = 406.0
+margin_bottom = 60.0
+focus_mode = 2
+text = "Source code"
+
+[node name="ResumeButton" type="Button" parent="UI/PauseMenu/CenterContainer/PanelContainer/VBoxContainer"]
+margin_top = 182.0
+margin_right = 422.0
+margin_bottom = 219.0
+theme = ExtResource( 5 )
+text = "Resume"
 
-[node name="Background" type="ColorRect" parent="CanvasLayer2"]
+[node name="GameFinishedMenu" type="Control" parent="UI"]
+pause_mode = 2
+visible = false
 anchor_right = 1.0
 anchor_bottom = 1.0
-margin_top = -2.0
-margin_bottom = -2.0
-color = Color( 0.811765, 0, 0, 1 )
+mouse_filter = 2
+theme = ExtResource( 9 )
+
+[node name="CenterContainer" type="CenterContainer" parent="UI/GameFinishedMenu"]
+anchor_right = 1.0
+anchor_bottom = 1.0
+
+[node name="PanelContainer" type="PanelContainer" parent="UI/GameFinishedMenu/CenterContainer"]
+margin_left = 236.0
+margin_top = 386.0
+margin_right = 264.0
+margin_bottom = 414.0
+
+[node name="VBoxContainer" type="VBoxContainer" parent="UI/GameFinishedMenu/CenterContainer/PanelContainer"]
+margin_left = 14.0
+margin_top = 14.0
+margin_right = 182.0
+margin_bottom = 208.0
+
+[node name="Label" type="Label" parent="UI/GameFinishedMenu/CenterContainer/PanelContainer/VBoxContainer"]
+margin_right = 168.0
+margin_bottom = 118.0
+theme = ExtResource( 9 )
+text = "You've won!"
+align = 1
+valign = 1
+autowrap = true
+
+[node name="Button" type="Button" parent="UI/GameFinishedMenu/CenterContainer/PanelContainer/VBoxContainer"]
+margin_top = 126.0
+margin_right = 168.0
+margin_bottom = 194.0
+text = "Replay!"
+
+[node name="Camera2D" type="Camera2D" parent="."]
+current = true
 
 [node name="ShotTimer" type="Timer" parent="."]
 wait_time = 0.5
@@ -295,5 +358,12 @@ __meta__ = {
 "_gizmo_extents_": 14.2
 }
 
-[connection signal="pressed" from="CanvasLayer/CenterContainer/DeathScreen/Panel/Button" to="." method="_on_Button_pressed"]
+[connection signal="debug_signal" from="UI/HUD" to="." method="_on_HUD_debug_signal"]
+[connection signal="paused" from="UI/HUD" to="." method="_on_HUD_paused"]
+[connection signal="position_set" from="UI/HUD" to="." method="_on_HUD_position_set"]
+[connection signal="pressed" from="UI/DeathScreen/CenterContainer/PanelContainer/VBoxContainer/Button" to="." method="_on_Button_pressed"]
+[connection signal="pressed" from="UI/IntroMenu/CenterContainer/PanelContainer/VBoxContainer/StartButton" to="." method="_on_StartButton_pressed"]
+[connection signal="pressed" from="UI/PauseMenu/CenterContainer/PanelContainer/VBoxContainer/TabContainer/Pref/AlwaysShowIntroCheckBox" to="." method="_on_PauseAlwaysShowIntroCheckBox_pressed"]
+[connection signal="pressed" from="UI/PauseMenu/CenterContainer/PanelContainer/VBoxContainer/TabContainer/About/LinkButton" to="." method="_on_LinkButton_pressed"]
+[connection signal="pressed" from="UI/PauseMenu/CenterContainer/PanelContainer/VBoxContainer/ResumeButton" to="." method="_on_ResumeButton_pressed"]
 [connection signal="timeout" from="ShotTimer" to="." method="allow_fire"]
diff --git a/Rocket.gd b/Rocket.gd
index 3e07107..afc663f 100644
--- a/Rocket.gd
+++ b/Rocket.gd
@@ -9,7 +9,6 @@ export var arm_secs = 1
 export var damage_amount = 2
 
 func _ready() -> void:
-#	$AnimationPlayer.play("arming")
 	pass
 
 func _physics_process(delta: float) -> void:
diff --git a/Settings.gd b/Settings.gd
index 71e0da0..3fc05a2 100644
--- a/Settings.gd
+++ b/Settings.gd
@@ -1,17 +1,39 @@
 class_name Settings
 
 var show_intro = true
+var high_scores: Array = [
+]
+
+class HighScore:
+	var score: int
+	var date: Dictionary
+	func _init(s: int, d: Dictionary):
+		score = s
+		date = d
+	func to_json() -> Dictionary:
+		return {
+			"score": score,
+			"date": date
+		}
 
 const settings_path = "user://settings.json"
 
 func to_json() -> Dictionary:
-	return {
-		"show_intro": show_intro
+	var scores = []
+	for hs in high_scores:
+		var high_score: HighScore = hs
+		var json = high_score.to_json()
+		scores.push_back(json)
+	var final_obj = {
+		"show_intro": show_intro,
+		"high_scores": scores
 	}
+	return final_obj
 
 func save_user_settings(path = settings_path) -> void:
 	var save_game: File = File.new()
-	save_game.open(path, File.WRITE)
+	var _err = save_game.open(path, File.WRITE)
 	var json_data = JSON.print(self.to_json())
-	save_game.store_line(json_data)
+	print("saving settings:", json_data)
+	save_game.store_string(json_data)
 	save_game.close()
diff --git a/Utils.gd b/Utils.gd
index 8458c2a..e9d6e0c 100644
--- a/Utils.gd
+++ b/Utils.gd
@@ -11,13 +11,22 @@ static func load_user_settings(path = SettingsClass.settings_path) -> Settings:
 	var save_game: File = File.new()
 	var settings_exists = save_game.file_exists(path)
 	if settings_exists:
-		save_game.open(path, File.READ)
-		var current_line = save_game.get_line()
-		save_game.close()
-		var json = parse_json(current_line)
-		var data: Settings = Settings.new()
-		data.show_intro = json["show_intro"]
-		return data
+		var _err = save_game.open(path, File.READ)
+		var text = save_game.get_as_text()
+		if text.length() > 0:
+			var json = parse_json(text)
+			var data: Settings = Settings.new()
+			data.show_intro = json["show_intro"]
+			if json.has("high_scores"):
+				data.high_scores = []
+#				print("high scores", high_scores)
+				for hs in json["high_scores"]:
+					var score = hs["score"]
+					var date = hs["date"]
+					var high_score: Settings.HighScore = Settings.HighScore.new(score, date)
+					data.high_scores.push_back(high_score)
+	#		Utils.log("high scores", high_scores)
+			return data
 	
 	var data: Settings = Settings.new()
 	return data
@@ -64,3 +73,40 @@ static func dist_to_ratio(dist: float, min_dist: float, max_dist: float) -> floa
 #	var exponential_decay_curve = 1.0 - exp(-t * 5.0)
 #	var inverse_exponential_curve = 1.0 - (1.0 - exp(-t * 5.0))
 	return linear_curve
+
+static func time_diff_secs(a: Dictionary, b: Dictionary) -> float:
+	var at = Time.get_unix_time_from_datetime_dict(a)
+	var bt = Time.get_unix_time_from_datetime_dict(b)
+	var diff = at - bt
+	return diff
+
+static func timespan_to_english(seconds: float) -> String:
+	var is_past = seconds < 0
+	seconds = abs(seconds)
+	var minutes = seconds / 60
+	var hours = minutes / 60
+	var days = hours / 24
+	var weeks = days / 7
+	var result = ""
+	if weeks > 1 and result == "":
+		result += "%1.f weeks" % weeks
+	if days > 1 and result == "":
+		result += "%1.f days" % days
+	if hours > 1 and result == "":
+		result += "%1.f hours" % hours
+	if minutes > 1 and result == "":
+		result += "%1.f minutes" % minutes
+	if seconds > 1 and result == "":
+		result += "%1.f seconds" % seconds
+	
+	if result == "":
+		result = "just now"
+	elif is_past:
+		result += " ago"
+	return result
+
+static func remove_all_children(node: Node) -> void:
+	var count = node.get_child_count()
+	for i in count:
+		var child = node.get_child(0)
+		node.remove_child(child)
diff --git a/World.gd b/World.gd
index 80275f8..a433217 100644
--- a/World.gd
+++ b/World.gd
@@ -7,8 +7,7 @@ const PowerUp = preload("res://PowerUp.tscn")
 const Settings = preload("res://Settings.gd")
 var width = ProjectSettings.get("display/window/size/width")
 var height = ProjectSettings.get("display/window/size/height")
-
-onready var player = $Player
+onready var player: Player = $Player
 
 var destination: Vector2
 var is_destination_set = false
@@ -17,25 +16,20 @@ var generators = [
 	ConstantItemGenerator.new("create_health", self, "health", 10),
 	ConstantItemGenerator.new("create_weapon", self, "weapon", 10),
 	LevelItemGenerator.new(5, "create_gold", self, "gold", 5),
-#	LevelItemGenerator.new(3, "create_shield", self, "shields", 3),
 ]
 var completed_objectives = 0
 var max_objectives = 5
 var item_replacement_distance = 2000
 var is_dragging = false
-var settings: Settings
 
 func enemy_killed(_position: Vector2):
-	$UI/HUD.score += 5
-	$UI/HUD.show_message("Enemy killed!", 1)
+	player.score += 5
+	player.show_message("Enemy killed!", 1)
 func health_consumed(_data):
 	$Player.heal(10)
-func shield_consumed(_data):
-	Utils.log("consuming a shield and sending a message")
-	$Player.enable_shield()
 func gold_consumed(_data):
 	completed_objectives += 1
-	$UI/HUD.score += 1
+	player.score += 1
 func weapon_consumed(data):
 	var weapon: Weapon = data
 	var is_same_weapon = $Player.weapon.name == weapon.name
@@ -81,21 +75,6 @@ func create_weapon() -> PowerUp:
 		weapon.label = "LZR"
 		weapon.color = Color.pink
 	return weapon
-func create_shield() -> PowerUp:
-	var shield = PowerUp.instance()
-	shield.position = get_new_item_pos(randf() + .5)
-	shield.connect("consumed", self, "shield_consumed")
-	shield.label = "Shield"
-	shield.color = Color.blue
-	return shield
-
-func _ready() -> void:
-	settings = Utils.load_user_settings()
-	var pause_menu_show_intro_check = $UI/PauseMenu/CenterContainer/PanelContainer/VBoxContainer/TabContainer/Settings/CheckBox
-	pause_menu_show_intro_check.pressed = settings.show_intro
-	if settings.show_intro:
-		get_tree().paused = true
-		$UI/IntroMenu.visible = true
 
 func get_new_item_pos(dist_ratio: float = 1.0) -> Vector2:
 	var pos_angle = randi() % 360
@@ -131,16 +110,12 @@ func _input(_event: InputEvent) -> void:
 		return
 
 func _process(_delta: float) -> void:
-	if Input.is_action_just_pressed("pause"):
-		pause()
-		return
-
-	$UI/HUD.objective = "%s / %s" % [completed_objectives, max_objectives]
-	$UI/HUD.set_current_weapon(player.weapon)
+	player.set_objective("%s / %s" % [completed_objectives, max_objectives])
 	var all_done = completed_objectives == max_objectives
 	if all_done:
 		get_tree().paused = true
 		var score = $UI/HUD.score
+		player.add_high_score(score)
 		var final_message = "You won with %s points!" % score
 		var _err = ($UI/GameFinishedMenu.find_node("Button") as Button).connect("pressed", self, "restart")
 		$UI/GameFinishedMenu.find_node("Label").text = final_message
@@ -174,10 +149,6 @@ func _process(_delta: float) -> void:
 	player.update_radar(get_tree().get_nodes_in_group("gold"), Color.yellow)
 	player.update_radar(filteredEnemies, Color.red)
 
-func pause():
-	get_tree().paused = true
-	$UI/PauseMenu.show()
-
 func set_destination(event_pos: Vector2) -> void:
 	var mid = Vector2(width / 2.0, height / 2.0)
 	var pos = event_pos + $Player.position - mid	
@@ -228,43 +199,16 @@ func _on_Game_over_button_pressed() -> void:
 	$UI/GameFinishedMenu.hide()
 	restart()
 
-func _on_Player_shield_changed(shield_active: bool) -> void:
-	var message = "Shield Activated" if shield_active else "Shield Lost!"
-	$UI/HUD.show_message(message)
-
-func _on_HUD_paused() -> void:
-	pause()
-
 func restart() -> void:
 	get_tree().paused = false
 	var _err = get_tree().reload_current_scene()
 
-func _on_HUD_debug_signal() -> void:
-	var p = $Player.global_position
-	
-	set_destination(Vector2(p.x, p.y - 1000))
-	pass
-
-func _on_LinkButton_pressed() -> void:
-	get_tree().paused = true
-	var _err = OS.shell_open("https://gitlab.com/PavelSafronov/godot-shooter")
-	get_tree().paused = true
-
-
-func _on_StartButton_pressed() -> void:
-	get_tree().paused = false
-	$UI/IntroMenu.visible = false
-	settings.show_intro = $UI/IntroMenu/CenterContainer/PanelContainer/VBoxContainer/CheckBox.pressed
-	settings.save_user_settings()
-	var pause_menu_show_intro_check = $UI/PauseMenu/CenterContainer/PanelContainer/VBoxContainer/TabContainer/Settings/CheckBox
-	pause_menu_show_intro_check.pressed = settings.show_intro
-	get_tree().set_input_as_handled()
+func _on_Player_destination_set(position) -> void:
+	set_destination(position)
+	pass # Replace with function body.
 
-func _on_CheckBox_pressed() -> void:
-	var show_intro_check = $UI/IntroMenu/CenterContainer/PanelContainer/VBoxContainer/CheckBox
-	var show_intro = show_intro_check.pressed
-	set_intro_dialog(show_intro)
 
-func set_intro_dialog(enabled: bool) -> void:
-	settings.show_intro = enabled
-	settings.save_user_settings()
+func _on_Player_debug() -> void:
+	player.score += 1
+	player.kill()
+	pass # Replace with function body.
diff --git a/World.tscn b/World.tscn
index bc211d9..123aab8 100644
--- a/World.tscn
+++ b/World.tscn
@@ -1,35 +1,13 @@
-[gd_scene load_steps=14 format=2]
+[gd_scene load_steps=6 format=2]
 
 [ext_resource path="res://assets/kenney_simple-space/PNG/Default/icon_crossLarge.png" type="Texture" id=1]
 [ext_resource path="res://Player.tscn" type="PackedScene" id=2]
-[ext_resource path="res://HUD.tscn" type="PackedScene" id=3]
 [ext_resource path="res://World.gd" type="Script" id=4]
 [ext_resource path="res://StarField.tscn" type="PackedScene" id=5]
-[ext_resource path="res://CharacterTheme.tres" type="Theme" id=6]
-[ext_resource path="res://Theme.tres" type="Theme" id=7]
-[ext_resource path="res://assets/neuropolitical rg.otf" type="DynamicFontData" id=8]
 
 [sub_resource type="CircleShape2D" id=1]
 radius = 29.0172
 
-[sub_resource type="DynamicFont" id=2]
-size = 24
-font_data = ExtResource( 8 )
-
-[sub_resource type="DynamicFont" id=3]
-outline_color = Color( 0, 0.490196, 0.831373, 1 )
-use_mipmaps = true
-use_filter = true
-font_data = ExtResource( 8 )
-
-[sub_resource type="Theme" id=4]
-default_font = SubResource( 3 )
-
-[sub_resource type="DynamicFont" id=5]
-use_mipmaps = true
-use_filter = true
-font_data = ExtResource( 8 )
-
 [node name="World" type="Node2D"]
 script = ExtResource( 4 )
 
@@ -77,190 +55,6 @@ __meta__ = {
 
 [node name="Environment" type="Node2D" parent="."]
 
-[node name="UI" type="CanvasLayer" parent="."]
-pause_mode = 2
-
-[node name="HUD" parent="UI" instance=ExtResource( 3 )]
-pause_mode = 2
-
-[node name="PauseMenu" type="Control" parent="UI" groups=["pause_menu"]]
-visible = false
-anchor_right = 1.0
-anchor_bottom = 1.0
-mouse_filter = 2
-
-[node name="CenterContainer" type="CenterContainer" parent="UI/PauseMenu"]
-anchor_right = 1.0
-anchor_bottom = 1.0
-
-[node name="PanelContainer" type="PanelContainer" parent="UI/PauseMenu/CenterContainer"]
-margin_left = 50.0
-margin_top = 386.0
-margin_right = 450.0
-margin_bottom = 414.0
-rect_min_size = Vector2( 400, 0 )
-
-[node name="VBoxContainer" type="VBoxContainer" parent="UI/PauseMenu/CenterContainer/PanelContainer"]
-margin_left = 14.0
-margin_top = 14.0
-margin_right = 386.0
-margin_bottom = 227.0
-
-[node name="Label" type="Label" parent="UI/PauseMenu/CenterContainer/PanelContainer/VBoxContainer"]
-margin_right = 372.0
-margin_bottom = 37.0
-theme = ExtResource( 7 )
-text = "Paused"
-align = 1
-
-[node name="TabContainer" type="TabContainer" parent="UI/PauseMenu/CenterContainer/PanelContainer/VBoxContainer"]
-margin_top = 45.0
-margin_right = 372.0
-margin_bottom = 168.0
-
-[node name="Settings" type="VBoxContainer" parent="UI/PauseMenu/CenterContainer/PanelContainer/VBoxContainer/TabContainer"]
-anchor_right = 1.0
-anchor_bottom = 1.0
-margin_left = 8.0
-margin_top = 61.0
-margin_right = -8.0
-margin_bottom = -8.0
-
-[node name="CheckBox" type="CheckBox" parent="UI/PauseMenu/CenterContainer/PanelContainer/VBoxContainer/TabContainer/Settings"]
-margin_right = 48.0
-margin_bottom = 48.0
-text = "Show intro dialog"
-
-[node name="About" type="VBoxContainer" parent="UI/PauseMenu/CenterContainer/PanelContainer/VBoxContainer/TabContainer"]
-visible = false
-anchor_right = 1.0
-anchor_bottom = 1.0
-margin_left = 8.0
-margin_top = 61.0
-margin_right = -8.0
-margin_bottom = -8.0
-
-[node name="RichTextLabel" type="RichTextLabel" parent="UI/PauseMenu/CenterContainer/PanelContainer/VBoxContainer/TabContainer/About"]
-margin_right = 356.0
-margin_bottom = 54.0
-rect_min_size = Vector2( 200, 0 )
-text = "Welcome to my Godot experiment."
-fit_content_height = true
-
-[node name="LinkButton" type="LinkButton" parent="UI/PauseMenu/CenterContainer/PanelContainer/VBoxContainer/TabContainer/About"]
-margin_top = 89.0
-margin_right = 200.0
-margin_bottom = 114.0
-text = "Source code"
-
-[node name="Button" type="Button" parent="UI/PauseMenu/CenterContainer/PanelContainer/VBoxContainer"]
-margin_top = 176.0
-margin_right = 372.0
-margin_bottom = 213.0
-theme = ExtResource( 6 )
-text = "Resume"
-
-[node name="GameFinishedMenu" type="Control" parent="UI"]
-pause_mode = 2
-visible = false
-anchor_right = 1.0
-anchor_bottom = 1.0
-mouse_filter = 2
-theme = ExtResource( 7 )
-
-[node name="CenterContainer" type="CenterContainer" parent="UI/GameFinishedMenu"]
-anchor_right = 1.0
-anchor_bottom = 1.0
-
-[node name="PanelContainer" type="PanelContainer" parent="UI/GameFinishedMenu/CenterContainer"]
-margin_left = 236.0
-margin_top = 386.0
-margin_right = 264.0
-margin_bottom = 414.0
-
-[node name="VBoxContainer" type="VBoxContainer" parent="UI/GameFinishedMenu/CenterContainer/PanelContainer"]
-margin_left = 14.0
-margin_top = 14.0
-margin_right = 182.0
-margin_bottom = 208.0
-
-[node name="Label" type="Label" parent="UI/GameFinishedMenu/CenterContainer/PanelContainer/VBoxContainer"]
-margin_right = 168.0
-margin_bottom = 118.0
-theme = ExtResource( 7 )
-text = "You've won!"
-align = 1
-valign = 1
-autowrap = true
-
-[node name="Button" type="Button" parent="UI/GameFinishedMenu/CenterContainer/PanelContainer/VBoxContainer"]
-margin_top = 126.0
-margin_right = 168.0
-margin_bottom = 194.0
-text = "Replay!"
-
-[node name="IntroMenu" type="Control" parent="UI" groups=["pause_menu"]]
-visible = false
-anchor_right = 1.0
-anchor_bottom = 1.0
-
-[node name="CenterContainer" type="CenterContainer" parent="UI/IntroMenu"]
-anchor_right = 1.0
-anchor_bottom = 1.0
-
-[node name="PanelContainer" type="PanelContainer" parent="UI/IntroMenu/CenterContainer"]
-margin_left = 236.0
-margin_top = 386.0
-margin_right = 264.0
-margin_bottom = 414.0
-
-[node name="VBoxContainer" type="VBoxContainer" parent="UI/IntroMenu/CenterContainer/PanelContainer"]
-margin_left = 14.0
-margin_top = 14.0
-margin_right = 447.0
-margin_bottom = 451.0
-theme = ExtResource( 7 )
-alignment = 1
-
-[node name="Label" type="Label" parent="UI/IntroMenu/CenterContainer/PanelContainer/VBoxContainer"]
-margin_right = 433.0
-margin_bottom = 30.0
-custom_fonts/font = SubResource( 2 )
-text = "Welcome to Tactical Shooter!"
-
-[node name="RichTextLabel" type="RichTextLabel" parent="UI/IntroMenu/CenterContainer/PanelContainer/VBoxContainer"]
-margin_top = 38.0
-margin_right = 433.0
-margin_bottom = 324.0
-theme = SubResource( 4 )
-text = "This is a 2D space shooter game.
-
-You choose where to fly in this game.
-
-Your ship will attack for you.
-
-Touch/click + hold anywhere to pause the game and plan your course.
-Let go to set location as the destination.
-
-Your objective count is in the lower-right corner.
-The radar shows enemies and objectives."
-fit_content_height = true
-
-[node name="CheckBox" type="CheckBox" parent="UI/IntroMenu/CenterContainer/PanelContainer/VBoxContainer"]
-margin_top = 332.0
-margin_right = 433.0
-margin_bottom = 380.0
-custom_fonts/font = SubResource( 5 )
-pressed = true
-text = "Always show intro"
-
-[node name="StartButton" type="Button" parent="UI/IntroMenu/CenterContainer/PanelContainer/VBoxContainer"]
-margin_top = 388.0
-margin_right = 433.0
-margin_bottom = 437.0
-mouse_default_cursor_shape = 2
-text = "Start Game"
-
 [node name="ShootTimer" type="Timer" parent="."]
 process_mode = 0
 wait_time = 0.05
@@ -279,11 +73,6 @@ round_precision = 13
 antialiased = true
 
 [connection signal="body_entered" from="Destination" to="." method="_on_Destination_body_entered"]
-[connection signal="debug_signal" from="UI/HUD" to="." method="_on_HUD_debug_signal"]
-[connection signal="paused" from="UI/HUD" to="." method="_on_HUD_paused"]
-[connection signal="position_set" from="UI/HUD" to="." method="set_destination"]
-[connection signal="pressed" from="UI/PauseMenu/CenterContainer/PanelContainer/VBoxContainer/TabContainer/Settings/CheckBox" to="." method="_on_CheckBox_pressed"]
-[connection signal="pressed" from="UI/PauseMenu/CenterContainer/PanelContainer/VBoxContainer/TabContainer/About/LinkButton" to="." method="_on_LinkButton_pressed"]
-[connection signal="pressed" from="UI/PauseMenu/CenterContainer/PanelContainer/VBoxContainer/Button" to="." method="_on_Button_pressed"]
-[connection signal="pressed" from="UI/IntroMenu/CenterContainer/PanelContainer/VBoxContainer/StartButton" to="." method="_on_StartButton_pressed"]
+[connection signal="debug" from="Player" to="." method="_on_Player_debug"]
+[connection signal="destination_set" from="Player" to="." method="_on_Player_destination_set"]
 [connection signal="timeout" from="ShootTimer" to="." method="_on_ShootTimer_timeout"]