diff --git a/scenes/hud.tscn b/scenes/hud.tscn index 9d6817d..842420d 100644 --- a/scenes/hud.tscn +++ b/scenes/hud.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=6 format=3] +[gd_scene load_steps=7 format=3] [ext_resource type="Texture2D" path="res://assets/game/tilesets/kenney_tiles_atlas.png" id="1_atlas"] [ext_resource type="Texture2D" path="res://assets/game/collectibles/coin_gold_round.png" id="2_coin"] @@ -12,6 +12,10 @@ region = Rect2(72, 36, 18, 18) atlas = ExtResource("1_atlas") region = Rect2(108, 36, 18, 18) +[sub_resource type="AtlasTexture" id="AtlasTexture_diamond"] +atlas = ExtResource("1_atlas") +region = Rect2(126, 54, 18, 18) + [node name="HUD" type="CanvasLayer"] script = ExtResource("3_hud") full_heart_texture = SubResource("AtlasTexture_heart_full") @@ -54,11 +58,27 @@ theme_override_colors/font_color = Color(1, 1, 1, 1) theme_override_font_sizes/font_size = 12 text = "x0" +[node name="DiamondIcon" type="TextureRect" parent="."] +offset_left = 9.0 +offset_top = 45.0 +offset_right = 27.0 +offset_bottom = 63.0 +texture = SubResource("AtlasTexture_diamond") + +[node name="DiamondLabel" type="Label" parent="."] +offset_left = 30.0 +offset_top = 44.0 +offset_right = 130.0 +offset_bottom = 64.0 +theme_override_colors/font_color = Color(1, 1, 1, 1) +theme_override_font_sizes/font_size = 12 +text = "0 / 3" + [node name="ShieldLabel" type="Label" parent="."] offset_left = 8.0 -offset_top = 46.0 -offset_right = 160.0 -offset_bottom = 66.0 +offset_top = 64.0 +offset_right = 170.0 +offset_bottom = 84.0 theme_override_colors/font_color = Color(0.55, 0.9, 1, 1) theme_override_font_sizes/font_size = 12 text = "" diff --git a/scenes/level_clear.tscn b/scenes/level_clear.tscn new file mode 100644 index 0000000..649f398 --- /dev/null +++ b/scenes/level_clear.tscn @@ -0,0 +1,56 @@ +[gd_scene load_steps=4 format=3] + +[ext_resource type="Script" path="res://scripts/level_clear.gd" id="1_clear"] + +[sub_resource type="SystemFont" id="SystemFont_cjk"] +font_names = PackedStringArray("Microsoft YaHei UI", "Microsoft YaHei", "SimHei", "Noto Sans CJK SC", "sans-serif") + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_button"] +bg_color = Color(0.16, 0.62, 0.36, 1) +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 +content_margin_left = 18.0 +content_margin_top = 6.0 +content_margin_right = 18.0 +content_margin_bottom = 6.0 + +[node name="LevelClear" type="CanvasLayer" groups=["level_clear"]] +process_mode = 3 +layer = 20 +script = ExtResource("1_clear") + +[node name="Fade" type="ColorRect" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 +mouse_filter = 2 +color = Color(0, 0, 0, 0) + +[node name="Center" type="CenterContainer" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 +mouse_filter = 2 + +[node name="VBox" type="VBoxContainer" parent="Center"] +theme_override_constants/separation = 10 + +[node name="Title" type="Label" parent="Center/VBox"] +theme_override_colors/font_color = Color(1, 0.85, 0.3, 1) +theme_override_fonts/font = SubResource("SystemFont_cjk") +theme_override_font_sizes/font_size = 26 +text = "过关!" +horizontal_alignment = 1 + +[node name="Subtitle" type="Label" parent="Center/VBox"] +theme_override_colors/font_color = Color(0.8, 0.95, 0.85, 1) +theme_override_fonts/font = SubResource("SystemFont_cjk") +theme_override_font_sizes/font_size = 13 +text = "钻石 3 / 3" +horizontal_alignment = 1 + +[node name="NextButton" type="Button" parent="Center/VBox"] +theme_override_fonts/font = SubResource("SystemFont_cjk") +theme_override_font_sizes/font_size = 14 +theme_override_styles/normal = SubResource("StyleBoxFlat_button") +text = "进入下一关 (R)" diff --git a/scenes/main.tscn b/scenes/main.tscn index e549c73..df84708 100644 --- a/scenes/main.tscn +++ b/scenes/main.tscn @@ -14,6 +14,9 @@ [ext_resource type="PackedScene" path="res://scenes/hud.tscn" id="21_hud"] [ext_resource type="PackedScene" path="res://scenes/death_screen.tscn" id="22_death"] [ext_resource type="PackedScene" path="res://scenes/prefabs/hazards/spikes_grey.tscn" id="23_spikesgrey"] +[ext_resource type="PackedScene" path="res://scenes/prefabs/collectibles/diamond.tscn" id="24_diamond"] +[ext_resource type="PackedScene" path="res://scenes/prefabs/interactables/door.tscn" id="25_door"] +[ext_resource type="PackedScene" path="res://scenes/level_clear.tscn" id="26_clear"] [node name="Main" type="Node2D" unique_id=2061129075] @@ -21,6 +24,8 @@ [node name="DeathScreen" parent="." unique_id=1952687359 instance=ExtResource("22_death")] +[node name="LevelClear" parent="." instance=ExtResource("26_clear")] + [node name="Level" type="Node2D" parent="." unique_id=1678372922] [node name="Background" type="Node2D" parent="Level" unique_id=702011751] @@ -155,7 +160,7 @@ script = ExtResource("19_hidden") [node name="TerrainBase" type="TileMapLayer" parent="Level/TerrainTileMaps" unique_id=91115499] position = Vector2(9, 9) -tile_map_data = PackedByteArray("AAAAAAEAAAABAAUAAAAEAAEAAAABAAUAAAAFAAEAAAACAAUAAAAGAAEAAAADAAUAAAAMAAEAAAARAAAAAAANAAEAAAASAAAAAAAOAAEAAAATAAAAAAAAAAIAAAAEAAUAAAADAAIAAAABAAUAAAAEAAIAAAAEAAUAAAAFAAIAAAAEAAAAAAAGAAIAAAADAAcAAAALAAIAAAARAAAAAAAMAAIAAAASAAEAAAANAAIAAAASAAEAAAAOAAIAAAATAAEAAAAAAAMAAAACAAYAAAADAAMAAAACAAcAAAAEAAMAAAACAAcAAAAFAAMAAAADAAcAAAALAAMAAAARAAIAAAAMAAMAAAASAAEAAAANAAMAAAASAAEAAAAOAAMAAAATAAEAAAAVAAMAAAANAAcAAAAWAAMAAAAPAAcAAAAAAAQAAAACAAYAAAAEAAQAAAAJAAMAAAAMAAQAAAARAAEAAAANAAQAAAASAAEAAAAOAAQAAAATAAEAAAAEAAUAAAAJAAQAAAAMAAUAAAARAAIAAAANAAUAAAARAAQAAAAOAAUAAAATAAIAAAAWAAUAAAALAAUAAAAEAAYAAAAJAAQAAAAIAAYAAAAJAAEAAAANAAYAAAAQAAQAAAAQAAYAAAANAAcAAAARAAYAAAAOAAcAAAASAAYAAAAPAAcAAAAUAAYAAAALAAIAAAAWAAYAAAALAAYAAAAXAAYAAAAFAAcAAAACAAcAAAABAAEAAAAEAAcAAAAJAAUAAAAGAAcAAAAIAAQAAAANAAcAAAAQAAUAAAAUAAcAAAALAAMAAAAVAAcAAAABAAUAAAAWAAcAAAACAAUAAAAXAAcAAAADAAUAAAAYAAcAAAAGAAUAAAAZAAcAAAAGAAUAAAACAAgAAAABAAYAAAADAAgAAAACAAYAAAAEAAgAAAACAAEAAAAFAAgAAAACAAEAAAAGAAgAAAADAAEAAAAKAAgA//8HAAEAAAAMAAgAAAASAAUAAAANAAgAAAARAAUAAAAOAAgAAAATAAQAABAPAAgAAAASAAQAABAUAAgAAAALAAMAAAAVAAgAAAABAAYAAAAWAAgAAAACAAYAAAAXAAgAAAAEAAEAAAAYAAgAAAACAAUAAAAZAAgAAAACAAUAAAAAAAkAAAACAAEAAAABAAkAAAACAAEAAAACAAkAAAAFAAEAAAADAAkAAAACAAYAAAAEAAkAAAACAAYAAAAFAAkAAAACAAYAAAAGAAkAAAADAAYAAAANAAkAAAAQAAUAAAASAAkAAAAGAAcAAAAUAAkAAAABAAUAAAAVAAkAAAAFAAEAAAAWAAkAAAAEAAUAAAAXAAkAAAACAAYAAAAYAAkAAAACAAYAAAAZAAkAAAACAAYAAAAAAAoAAAAEAAUAAAABAAoAAAACAAYAAAACAAoAAAACAAYAAAADAAoAAAACAAYAAAAEAAoAAAAEAAUAAAAFAAoAAAACAAYAAAAGAAoAAAAEAAEAAAAHAAoAAAADAAEAAAAIAAoAAAAGAAUAAAANAAoAAAARAAYAAAAPAAoAAAAHAAYAAAARAAoAAAAKAAUAAAATAAoAAAAEAAcAAAAUAAoAAAABAAYAAAAVAAoAAAACAAYAAAAWAAoAAAACAAYAAAAXAAoAAAACAAYAAAAYAAoAAAACAAYAAAAZAAoAAAACAAYAAAAAAAsAAAAEAAUAAAABAAsAAAACAAYAAAACAAsAAAAEAAUAAAADAAsAAAAEAAUAAAAEAAsAAAACAAYAAAAFAAsAAAAEAAUAAAAGAAsAAAACAAYAAAAHAAsAAAAEAAEAAAAIAAsAAAADAAEAAAAKAAsAAAAEAAYAAAAMAAsAAAABAAEAAAANAAsAAAACAAEAAAAOAAsAAAACAAMAAAAPAAsAAAADAAMAAAARAAsAAAAKAAYAAAATAAsAAAABAAUAAAAUAAsAAAAFAAEAAAAVAAsAAAACAAYAAAAWAAsAAAAEAAUAAAAXAAsAAAAEAAUAAAAYAAsAAAAEAAUAAAAZAAsAAAACAAYAAAAAAAwAAAACAAYAAAABAAwAAAACAAYAAAACAAwAAAACAAYAAAADAAwAAAAEAAUAAAAEAAwAAAACAAYAAAAFAAwAAAAEAAUAAAAGAAwAAAAEAAUAAAAHAAwAAAAEAAUAAAAIAAwAAAAEAAEAAAAJAAwAAAACAAEAAAAKAAwAAAACAAEAAAALAAwAAAACAAEAAAAMAAwAAAAFAAEAAAANAAwAAAAEAAUAAAAOAAwAAAAEAAUAAAAPAAwAAAAEAAEAAAAQAAwAAAACAAMAAAARAAwAAAACAAMAAAASAAwAAAACAAMAAAATAAwAAAAFAAEAAAAUAAwAAAACAAYAAAAVAAwAAAAEAAUAAAAWAAwAAAACAAYAAAAXAAwAAAAEAAUAAAAYAAwAAAAEAAUAAAAZAAwAAAACAAYAAAAAAA0AAAAEAAUAAAABAA0AAAACAAYAAAACAA0AAAAEAAUAAAADAA0AAAACAAYAAAAEAA0AAAACAAYAAAAFAA0AAAAEAAUAAAAGAA0AAAACAAYAAAAHAA0AAAACAAYAAAAIAA0AAAAEAAUAAAAJAA0AAAACAAYAAAAKAA0AAAAEAAUAAAALAA0AAAAEAAUAAAAMAA0AAAACAAYAAAANAA0AAAACAAYAAAAOAA0AAAAEAAUAAAAPAA0AAAAEAAUAAAAQAA0AAAAEAAUAAAARAA0AAAACAAYAAAASAA0AAAACAAYAAAATAA0AAAAEAAUAAAAUAA0AAAACAAYAAAAVAA0AAAACAAYAAAAWAA0AAAACAAYAAAAXAA0AAAAEAAUAAAAYAA0AAAACAAYAAAAZAA0AAAAEAAUAAAAAAA4AAAACAAYAAAABAA4AAAACAAYAAAACAA4AAAAEAAUAAAADAA4AAAACAAYAAAAEAA4AAAAEAAUAAAAFAA4AAAACAAYAAAAGAA4AAAAEAAUAAAAHAA4AAAAEAAUAAAAIAA4AAAAEAAUAAAAJAA4AAAAEAAUAAAAKAA4AAAAEAAUAAAALAA4AAAAEAAUAAAAMAA4AAAACAAYAAAANAA4AAAACAAYAAAAOAA4AAAACAAYAAAAPAA4AAAACAAYAAAAQAA4AAAAEAAUAAAARAA4AAAACAAYAAAASAA4AAAACAAYAAAATAA4AAAACAAYAAAAUAA4AAAACAAYAAAAVAA4AAAACAAYAAAAWAA4AAAAEAAUAAAAXAA4AAAAEAAUAAAAYAA4AAAACAAYAAAAZAA4AAAAEAAUAAAD//wkAAAACAAEAAAD//woAAAAEAAAAAAD//wsAAAAEAAAAAAD//wwAAAAFAAAAAAD//wQAAAAFAAAAAAD//wIAAAAFAAAAAAD//wMAAAAFAAAAAAD//wEAAAACAAUAAAAAAAUAAAACAAcAAAD//wUAAAACAAcAAAD//w0AAAAEAAEAAAD//w4AAAAEAAEAAAD//wYAAAAJAAAAAAD//wcAAAAJAAAAAAD//wgAAAAJAAAAAAAKAAkAAAAJAAEAAAAVAAIAAAAKAAAAAAABAAUAAAADAAcAAAABAAQAAAADAAUAAAADAAcAAAADAAEAAAANAAAAAAAIAAMAAAAOAAAAAAAIAAMAAAA=") +tile_map_data = PackedByteArray("AAAAAAEAAAABAAUAAAAEAAEAAAABAAUAAAAFAAEAAAACAAUAAAAGAAEAAAADAAUAAAAMAAEAAAARAAAAAAANAAEAAAASAAAAAAAOAAEAAAATAAAAAAAAAAIAAAAEAAUAAAADAAIAAAABAAUAAAAEAAIAAAAEAAUAAAAFAAIAAAAEAAAAAAAGAAIAAAADAAcAAAALAAIAAAARAAAAAAAMAAIAAAASAAEAAAANAAIAAAASAAEAAAAOAAIAAAATAAEAAAAAAAMAAAACAAYAAAADAAMAAAACAAcAAAAEAAMAAAACAAcAAAAFAAMAAAADAAcAAAALAAMAAAARAAIAAAAMAAMAAAASAAEAAAANAAMAAAASAAEAAAAOAAMAAAATAAEAAAAVAAMAAAANAAcAAAAWAAMAAAAPAAcAAAAAAAQAAAACAAYAAAAEAAQAAAAJAAMAAAAMAAQAAAARAAEAAAANAAQAAAASAAEAAAAOAAQAAAATAAEAAAAEAAUAAAAJAAQAAAAMAAUAAAARAAIAAAANAAUAAAARAAQAAAAOAAUAAAATAAIAAAAWAAUAAAALAAUAAAAEAAYAAAAJAAQAAAAIAAYAAAAJAAEAAAANAAYAAAAQAAQAAAAQAAYAAAANAAcAAAARAAYAAAAOAAcAAAASAAYAAAAPAAcAAAAUAAYAAAALAAIAAAAWAAYAAAALAAYAAAACAAcAAAABAAEAAAAEAAcAAAAJAAUAAAAGAAcAAAAIAAQAAAANAAcAAAAQAAUAAAAUAAcAAAALAAMAAAAVAAcAAAABAAUAAAAWAAcAAAACAAUAAAAXAAcAAAADAAUAAAAYAAcAAAAGAAUAAAAZAAcAAAAGAAUAAAACAAgAAAABAAYAAAADAAgAAAACAAYAAAAEAAgAAAACAAEAAAAFAAgAAAACAAEAAAAGAAgAAAADAAEAAAAMAAgAAAASAAUAAAANAAgAAAARAAUAAAAOAAgAAAATAAQAABAPAAgAAAASAAQAABAUAAgAAAALAAMAAAAVAAgAAAABAAYAAAAWAAgAAAACAAYAAAAXAAgAAAAEAAEAAAAYAAgAAAACAAUAAAAZAAgAAAACAAUAAAAAAAkAAAACAAEAAAABAAkAAAACAAEAAAACAAkAAAAFAAEAAAADAAkAAAACAAYAAAAEAAkAAAACAAYAAAAFAAkAAAACAAYAAAAGAAkAAAADAAYAAAANAAkAAAAQAAUAAAASAAkAAAAGAAcAAAAUAAkAAAABAAUAAAAVAAkAAAAFAAEAAAAWAAkAAAAEAAUAAAAXAAkAAAACAAYAAAAYAAkAAAACAAYAAAAZAAkAAAACAAYAAAAAAAoAAAAEAAUAAAABAAoAAAACAAYAAAACAAoAAAACAAYAAAADAAoAAAACAAYAAAAEAAoAAAAEAAUAAAAFAAoAAAACAAYAAAAGAAoAAAAEAAEAAAAHAAoAAAADAAEAAAAIAAoAAAAGAAUAAAANAAoAAAARAAYAAAAPAAoAAAAHAAYAAAARAAoAAAAKAAUAAAATAAoAAAAEAAcAAAAUAAoAAAABAAYAAAAVAAoAAAACAAYAAAAWAAoAAAACAAYAAAAXAAoAAAACAAYAAAAYAAoAAAACAAYAAAAZAAoAAAACAAYAAAAAAAsAAAAEAAUAAAABAAsAAAACAAYAAAACAAsAAAAEAAUAAAADAAsAAAAEAAUAAAAEAAsAAAACAAYAAAAFAAsAAAAEAAUAAAAGAAsAAAACAAYAAAAHAAsAAAAEAAEAAAAIAAsAAAADAAEAAAAKAAsAAAAEAAYAAAAMAAsAAAABAAEAAAANAAsAAAACAAEAAAAOAAsAAAACAAMAAAAPAAsAAAADAAMAAAARAAsAAAAKAAYAAAATAAsAAAABAAUAAAAUAAsAAAAFAAEAAAAVAAsAAAACAAYAAAAWAAsAAAAEAAUAAAAXAAsAAAAEAAUAAAAYAAsAAAAEAAUAAAAZAAsAAAACAAYAAAAAAAwAAAACAAYAAAABAAwAAAACAAYAAAACAAwAAAACAAYAAAADAAwAAAAEAAUAAAAEAAwAAAACAAYAAAAFAAwAAAAEAAUAAAAGAAwAAAAEAAUAAAAHAAwAAAAEAAUAAAAIAAwAAAAEAAEAAAAJAAwAAAACAAEAAAAKAAwAAAACAAEAAAALAAwAAAACAAEAAAAMAAwAAAAFAAEAAAANAAwAAAAEAAUAAAAOAAwAAAAEAAUAAAAPAAwAAAAEAAEAAAAQAAwAAAACAAMAAAARAAwAAAACAAMAAAASAAwAAAACAAMAAAATAAwAAAAFAAEAAAAUAAwAAAACAAYAAAAVAAwAAAAEAAUAAAAWAAwAAAACAAYAAAAXAAwAAAAEAAUAAAAYAAwAAAAEAAUAAAAZAAwAAAACAAYAAAAAAA0AAAAEAAUAAAABAA0AAAACAAYAAAACAA0AAAAEAAUAAAADAA0AAAACAAYAAAAEAA0AAAACAAYAAAAFAA0AAAAEAAUAAAAGAA0AAAACAAYAAAAHAA0AAAACAAYAAAAIAA0AAAAEAAUAAAAJAA0AAAACAAYAAAAKAA0AAAAEAAUAAAALAA0AAAAEAAUAAAAMAA0AAAACAAYAAAANAA0AAAACAAYAAAAOAA0AAAAEAAUAAAAPAA0AAAAEAAUAAAAQAA0AAAAEAAUAAAARAA0AAAACAAYAAAASAA0AAAACAAYAAAATAA0AAAAEAAUAAAAUAA0AAAACAAYAAAAVAA0AAAACAAYAAAAWAA0AAAACAAYAAAAXAA0AAAAEAAUAAAAYAA0AAAACAAYAAAAZAA0AAAAEAAUAAAAAAA4AAAACAAYAAAABAA4AAAACAAYAAAACAA4AAAAEAAUAAAADAA4AAAACAAYAAAAEAA4AAAAEAAUAAAAFAA4AAAACAAYAAAAGAA4AAAAEAAUAAAAHAA4AAAAEAAUAAAAIAA4AAAAEAAUAAAAJAA4AAAAEAAUAAAAKAA4AAAAEAAUAAAALAA4AAAAEAAUAAAAMAA4AAAACAAYAAAANAA4AAAACAAYAAAAOAA4AAAACAAYAAAAPAA4AAAACAAYAAAAQAA4AAAAEAAUAAAARAA4AAAACAAYAAAASAA4AAAACAAYAAAATAA4AAAACAAYAAAAUAA4AAAACAAYAAAAVAA4AAAACAAYAAAAWAA4AAAAEAAUAAAAXAA4AAAAEAAUAAAAYAA4AAAACAAYAAAAZAA4AAAAEAAUAAAD//wkAAAACAAEAAAD//woAAAAEAAAAAAD//wsAAAAEAAAAAAD//wwAAAAFAAAAAAD//wQAAAAFAAAAAAD//wIAAAAFAAAAAAD//wMAAAAFAAAAAAD//wEAAAACAAUAAAAAAAUAAAACAAcAAAD//wUAAAACAAcAAAD//w0AAAAEAAEAAAD//w4AAAAEAAEAAAD//wYAAAAJAAAAAAD//wcAAAAJAAAAAAD//wgAAAAJAAAAAAAKAAkAAAAJAAEAAAABAAUAAAADAAcAAAABAAQAAAADAAUAAAADAAcAAAADAAEAAAANAAAAAAAIAAMAAAAOAAAAAAAIAAMAAAAWAAIAAAAHAAMAAAAEAAAAAAAHAAMAAAAOAAcAAAAHAAMAAAA=") tile_set = ExtResource("5_4etix") [node name="TerrainDetailsA" type="TileMapLayer" parent="Level/TerrainTileMaps" unique_id=1513560262] @@ -192,11 +197,11 @@ position = Vector2(270, 216) z_index = 5 position = Vector2(216, 216) -[node name="SpikesGrey_01" parent="Level/PrefabInstances/Hazards" instance=ExtResource("23_spikesgrey")] +[node name="SpikesGrey_01" parent="Level/PrefabInstances/Hazards" unique_id=214833071 instance=ExtResource("23_spikesgrey")] z_index = 5 position = Vector2(252, 18) -[node name="SpikesGrey_02" parent="Level/PrefabInstances/Hazards" instance=ExtResource("23_spikesgrey")] +[node name="SpikesGrey_02" parent="Level/PrefabInstances/Hazards" unique_id=458791480 instance=ExtResource("23_spikesgrey")] z_index = 5 position = Vector2(270, 18) @@ -206,6 +211,15 @@ position = Vector2(270, 18) z_index = 5 position = Vector2(325, 108) +[node name="Door_01" parent="Level/PrefabInstances/Interactables" instance=ExtResource("25_door")] +z_index = 5 +position = Vector2(324, 216) + +[node name="Door_02" parent="Level/PrefabInstances/Interactables" instance=ExtResource("25_door")] +z_index = 5 +position = Vector2(414, 108) +atlas_region = Rect2(198, 90, 18, 18) + [node name="Collectibles" type="Node2D" parent="Level/PrefabInstances" unique_id=2086540192] [node name="CoinGoldRound_01" parent="Level/PrefabInstances/Collectibles" unique_id=926105584 instance=ExtResource("17_rmlt8")] @@ -224,4 +238,16 @@ position = Vector2(315, 63) z_index = 5 position = Vector2(126, 144) +[node name="Diamond_01" parent="Level/PrefabInstances/Collectibles" instance=ExtResource("24_diamond")] +z_index = 5 +position = Vector2(90, 18) + +[node name="Diamond_02" parent="Level/PrefabInstances/Collectibles" instance=ExtResource("24_diamond")] +z_index = 5 +position = Vector2(414, 54) + +[node name="Diamond_03" parent="Level/PrefabInstances/Collectibles" instance=ExtResource("24_diamond")] +z_index = 5 +position = Vector2(270, 144) + [node name="Signs" type="Node2D" parent="Level/PrefabInstances" unique_id=113197076] diff --git a/scenes/prefabs/collectibles/diamond.tscn b/scenes/prefabs/collectibles/diamond.tscn new file mode 100644 index 0000000..2cc0ea0 --- /dev/null +++ b/scenes/prefabs/collectibles/diamond.tscn @@ -0,0 +1,23 @@ +[gd_scene load_steps=5 format=3] + +[ext_resource type="Texture2D" path="res://assets/game/tilesets/kenney_tiles_atlas.png" id="1_atlas"] +[ext_resource type="Script" path="res://scripts/diamond.gd" id="2_diamond"] + +[sub_resource type="AtlasTexture" id="AtlasTexture_diamond"] +atlas = ExtResource("1_atlas") +region = Rect2(126, 54, 18, 18) + +[sub_resource type="CircleShape2D" id="Shape_diamond"] +radius = 7.0 + +[node name="Diamond" type="Area2D" groups=["diamond"]] +collision_layer = 16 +collision_mask = 2 +script = ExtResource("2_diamond") + +[node name="Sprite" type="Sprite2D" parent="."] +texture_filter = 1 +texture = SubResource("AtlasTexture_diamond") + +[node name="PickupArea" type="CollisionShape2D" parent="."] +shape = SubResource("Shape_diamond") diff --git a/scenes/prefabs/interactables/door.tscn b/scenes/prefabs/interactables/door.tscn new file mode 100644 index 0000000..6f668f8 --- /dev/null +++ b/scenes/prefabs/interactables/door.tscn @@ -0,0 +1,23 @@ +[gd_scene load_steps=5 format=3] + +[ext_resource type="Texture2D" path="res://assets/game/tilesets/kenney_tiles_atlas.png" id="1_atlas"] +[ext_resource type="Script" path="res://scripts/door.gd" id="2_door"] + +[sub_resource type="AtlasTexture" id="AtlasTexture_door"] +atlas = ExtResource("1_atlas") +region = Rect2(180, 108, 18, 18) + +[sub_resource type="RectangleShape2D" id="Shape_door"] +size = Vector2(18, 18) + +[node name="Door" type="Area2D" groups=["door"]] +collision_layer = 8 +collision_mask = 2 +script = ExtResource("2_door") + +[node name="Sprite" type="Sprite2D" parent="."] +texture_filter = 1 +texture = SubResource("AtlasTexture_door") + +[node name="TriggerArea" type="CollisionShape2D" parent="."] +shape = SubResource("Shape_door") diff --git a/scripts/diamond.gd b/scripts/diamond.gd new file mode 100644 index 0000000..d1edea3 --- /dev/null +++ b/scripts/diamond.gd @@ -0,0 +1,26 @@ +extends Area2D + +## 钻石:走过去自动收集,集齐后碰门过关 +@export var erase_placeholder_tile: bool = true + + +func _ready() -> void: + body_entered.connect(_on_body_entered) + if erase_placeholder_tile: + _erase_placeholder_tile() + + +func _on_body_entered(body: Node2D) -> void: + if body.has_method("add_diamond"): + body.add_diamond() + queue_free() + + +func _erase_placeholder_tile() -> void: + var root: Node = owner if owner != null else get_parent() + if root == null: + return + for layer in root.find_children("*", "TileMapLayer", true, false): + var cell: Vector2i = layer.local_to_map(layer.to_local(global_position)) + if layer.get_cell_source_id(cell) != -1: + layer.erase_cell(cell) diff --git a/scripts/door.gd b/scripts/door.gd new file mode 100644 index 0000000..1d9676d --- /dev/null +++ b/scripts/door.gd @@ -0,0 +1,54 @@ +extends Area2D + +## 门:集齐钻石后碰到就过关;没集齐则闪一下红色提示。 +@export var required_diamonds: int = 3 +## 门贴图在图集里的区域(不同门可以不一样) +@export var atlas_region: Rect2 = Rect2(180, 108, 18, 18) +## 开场时擦掉脚下的占位地砖 +@export var erase_placeholder_tile: bool = true + +const ATLAS := preload("res://assets/game/tilesets/kenney_tiles_atlas.png") + +var _sprite: Sprite2D = null + + +func _ready() -> void: + body_entered.connect(_on_body_entered) + _sprite = get_node_or_null("Sprite") + if _sprite != null: + var tex := AtlasTexture.new() + tex.atlas = ATLAS + tex.region = atlas_region + _sprite.texture = tex + if erase_placeholder_tile: + _erase_placeholder_tile() + + +func _on_body_entered(body: Node2D) -> void: + if not body.has_method("add_diamond"): + return + if int(body.diamonds) < required_diamonds: + _flash_locked() + return + var clear := get_tree().get_first_node_in_group("level_clear") + if clear != null: + clear.show_clear() + + +func _flash_locked() -> void: + if _sprite == null: + return + _sprite.modulate = Color(1.0, 0.45, 0.45) + await get_tree().create_timer(0.4).timeout + if is_instance_valid(_sprite): + _sprite.modulate = Color.WHITE + + +func _erase_placeholder_tile() -> void: + var root: Node = owner if owner != null else get_parent() + if root == null: + return + for layer in root.find_children("*", "TileMapLayer", true, false): + var cell: Vector2i = layer.local_to_map(layer.to_local(global_position)) + if layer.get_cell_source_id(cell) != -1: + layer.erase_cell(cell) diff --git a/scripts/hud.gd b/scripts/hud.gd index ddf5030..9d0e990 100644 --- a/scripts/hud.gd +++ b/scripts/hud.gd @@ -1,6 +1,6 @@ extends CanvasLayer -## 左上角的状态显示:3 颗心 + 回血道具数量 + 护盾剩余时间。 +## 左上角的状态显示:3 颗心 + 回血道具数量 + 钻石数量 + 护盾剩余时间。 ## 每帧从场景里找带 "player" 组的玩家读取状态。 @export var full_heart_texture: Texture2D @@ -9,6 +9,7 @@ extends CanvasLayer var _player: Node = null var _hearts: Array = [] var _count_label: Label = null +var _diamond_label: Label = null var _shield_label: Label = null @@ -18,6 +19,7 @@ func _ready() -> void: if heart != null: _hearts.append(heart) _count_label = get_node_or_null("CountLabel") + _diamond_label = get_node_or_null("DiamondLabel") _shield_label = get_node_or_null("ShieldLabel") @@ -37,9 +39,15 @@ func _process(_delta: float) -> void: _count_label.text = "x%d" % items _count_label.modulate = Color.WHITE if items > 0 else Color(1.0, 1.0, 1.0, 0.4) + if _diamond_label != null: + var got: int = int(_player.diamonds) + var total: int = maxi(int(_player.diamond_total), got) + _diamond_label.text = "%d / %d" % [got, total] + if total > 0 and got >= total: + _diamond_label.modulate = Color(1.0, 0.9, 0.35) + else: + _diamond_label.modulate = Color.WHITE + if _shield_label != null: var shield: float = float(_player.shield_left) - if shield > 0.0: - _shield_label.text = "SHIELD %.1fs" % shield - else: - _shield_label.text = "" + _shield_label.text = ("SHIELD %.1fs" % shield) if shield > 0.0 else "" diff --git a/scripts/level_clear.gd b/scripts/level_clear.gd new file mode 100644 index 0000000..57dfab7 --- /dev/null +++ b/scripts/level_clear.gd @@ -0,0 +1,72 @@ +extends CanvasLayer + +## 过关界面:集齐钻石后碰到门显示。 +## 显示时把整棵树暂停,所以这一层的 process_mode 设成 ALWAYS(见 .tscn), +## 不然暂停后自己的动画和按钮也会停。 + +@export var fade_time: float = 0.8 +@export var button_delay: float = 0.3 + +var _fade: ColorRect = null +var _center: CenterContainer = null +var _button: Button = null +var _title: Label = null +var _subtitle: Label = null +var _elapsed: float = 0.0 +var _showing: bool = false + + +func _ready() -> void: + visible = false + _fade = get_node_or_null("Fade") + _center = get_node_or_null("Center") + _button = get_node_or_null("Center/VBox/NextButton") + _title = get_node_or_null("Center/VBox/Title") + _subtitle = get_node_or_null("Center/VBox/Subtitle") + if _button != null: + _button.pressed.connect(next_level) + if _fade != null: + _fade.color = Color(0.0, 0.0, 0.0, 0.0) + if _center != null: + _center.visible = false + + +func show_clear() -> void: + if _showing: + return + _showing = true + visible = true + _elapsed = 0.0 + if _title != null: + _title.text = "过关!" + if _subtitle != null: + var player := get_tree().get_first_node_in_group("player") + var n: int = 0 if player == null else int(player.diamonds) + _subtitle.text = "钻石 %d / %d" % [n, n] + get_tree().paused = true + + +func _process(delta: float) -> void: + if not _showing: + return + _elapsed += delta + if _fade != null: + _fade.color = Color(0.0, 0.0, 0.0, clampf(_elapsed / maxf(fade_time, 0.01), 0.0, 1.0)) + if _center != null and _elapsed >= fade_time + button_delay: + _center.visible = true + + +func _unhandled_input(event: InputEvent) -> void: + if not _showing: + return + var key := event as InputEventKey + if key != null and key.pressed and not key.echo: + if key.physical_keycode == KEY_R or key.physical_keycode == KEY_ENTER: + next_level() + + +## 目前项目里只有一关,所以"下一关"先做成重新加载本关。 +## 以后真加了第二关,把这里换成 change_scene_to_file("res://scenes/level2.tscn") 即可。 +func next_level() -> void: + get_tree().paused = false + get_tree().reload_current_scene() diff --git a/scripts/player_controller.gd b/scripts/player_controller.gd index a23ac5b..d9310bd 100644 --- a/scripts/player_controller.gd +++ b/scripts/player_controller.gd @@ -60,6 +60,10 @@ var hurt_count: int = 0 var health: int = 3 ## 身上的回血道具数量(捡到的小球) var heal_items: int = 0 +## 已收集的钻石数量 +var diamonds: int = 0 +## 关卡里钻石总数(开场自动数一遍) +var diamond_total: int = 0 ## 无敌盾剩余时间,给 HUD 显示用 var shield_left: float = 0.0 ## 生命值归零后进入死亡状态:不能操作,交给死亡界面 @@ -84,6 +88,12 @@ func _ready() -> void: _measure_feet_offset() _spawn_point = global_position health = max_health + # 等一帧再数钻石,确保关卡里所有钻石节点都已经 _ready + _count_diamond_total.call_deferred() + + +func _count_diamond_total() -> void: + diamond_total = get_tree().get_nodes_in_group("diamond").size() func _physics_process(delta: float) -> void: @@ -182,6 +192,11 @@ func add_heal_item() -> void: heal_items += 1 +## 由钻石调用 +func add_diamond() -> void: + diamonds += 1 + + ## 按 Z:消耗一个回血道具,回一颗心并获得无敌盾 func use_heal_item() -> bool: if is_dead or heal_items <= 0: