Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 13b5a8edc7 | |||
| 4a6f4862de | |||
| f549c03533 | |||
| 44e4c3a751 | |||
| 8127c787f8 | |||
| acc7901c2a | |||
| 8391e1c5da | |||
| defdf202e6 | |||
| 35174b67ab | |||
| 1b3d61793d | |||
| 0d2bccc3a9 | |||
| 74e4bd1e97 | |||
| 84020864cc |
@@ -23,7 +23,7 @@
|
||||
| `S` 松开 | 投出钥匙 |
|
||||
| `W` | 传送到扔出去的钥匙位置,并把它捡回来 |
|
||||
| `Z` | 消耗一个回血道具:回一颗心 + 5 秒无敌盾 |
|
||||
| `F` | 切换飞行(**仅编辑器 / 调试版可用**,见下方说明) |
|
||||
| `F` | 切换飞行(**隐藏技能**,藏在右上角「房★主★有★神★器★」面板里,见下方说明) |
|
||||
| `R` / `Enter` | 死亡后重新开始 |
|
||||
|
||||
---
|
||||
@@ -92,10 +92,12 @@
|
||||
- 按 `W`:瞬移到钥匙所在位置并收回它
|
||||
- 因为预测和实际飞行调用的是**同一个 `simulate_trajectory()` 函数**,"弧线显示能落到的地方"就等于"钥匙真正落到的地方"(实测偏差 0.000 px)
|
||||
|
||||
**技能 B —— 飞行**(`player_controller.gd`)
|
||||
**技能 B —— 飞行(隐藏技能)**(`player_controller.gd`)
|
||||
|
||||
- 按 `F` 切换飞行状态,`W` / `S` 控制升降,`A` / `D` 平移
|
||||
- 为了不影响正式玩法的难度平衡,**只在编辑器 / 调试版生效**(`OS.is_debug_build()`),导出正式版按键无效
|
||||
- 按 `F` 切换飞行状态,`空格` / `S` 控制升降(方向键 ↑ / ↓ 也可以),`A` / `D` 平移
|
||||
- 屏幕上不会有任何提示,它是藏在右上角 **「房★主★有★神★器★」** 按钮里的彩蛋:
|
||||
点开面板就能看到飞行开关和跳关按钮(键盘 `1` / `2` / `3` 跳关,`Esc` 关闭面板)
|
||||
- 这个面板由自动加载单例 `scripts/cheat_panel.gd` 提供,**三个关卡都有,正式版里也能用**
|
||||
- 如果想在导出版里也开放,把 `fly_available()` 里的 `OS.is_debug_build()` 去掉即可:
|
||||
```gdscript
|
||||
func fly_available() -> bool:
|
||||
|
||||
@@ -132,6 +132,7 @@ use_texture_padding = false
|
||||
9:4/0 = 0
|
||||
10:4/0 = 0
|
||||
11:4/0 = 0
|
||||
11:4/0/physics_layer_1/polygon_0/points = PackedVector2Array(-9, -3, 9, -3, 9, 3, -9, 3)
|
||||
12:4/0 = 0
|
||||
13:4/0 = 0
|
||||
14:4/0 = 0
|
||||
@@ -264,4 +265,5 @@ use_texture_padding = false
|
||||
[resource]
|
||||
tile_size = Vector2i(18, 18)
|
||||
physics_layer_0/collision_layer = 1
|
||||
physics_layer_1/collision_layer = 2
|
||||
sources/0 = SubResource("TileSetAtlasSource_afvjv")
|
||||
|
||||
@@ -15,6 +15,10 @@ run/main_scene="res://scenes/main.tscn"
|
||||
config/features=PackedStringArray("4.7", "Forward Plus")
|
||||
config/icon="res://icon.svg"
|
||||
|
||||
[autoload]
|
||||
|
||||
CheatPanel="*res://scenes/cheat_panel.tscn"
|
||||
|
||||
[display]
|
||||
|
||||
window/size/viewport_width=468
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
[gd_scene load_steps=4 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/cheat_panel.gd" id="1_cheat"]
|
||||
|
||||
[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_panel"]
|
||||
content_margin_left = 10.0
|
||||
content_margin_top = 10.0
|
||||
content_margin_right = 10.0
|
||||
content_margin_bottom = 10.0
|
||||
bg_color = Color(0.07, 0.08, 0.13, 0.92)
|
||||
border_width_left = 2
|
||||
border_width_top = 2
|
||||
border_width_right = 2
|
||||
border_width_bottom = 2
|
||||
border_color = Color(1, 0.82, 0.35, 0.85)
|
||||
corner_radius_top_left = 5
|
||||
corner_radius_top_right = 5
|
||||
corner_radius_bottom_right = 5
|
||||
corner_radius_bottom_left = 5
|
||||
|
||||
[node name="CheatPanel" type="CanvasLayer"]
|
||||
process_mode = 3
|
||||
layer = 40
|
||||
script = ExtResource("1_cheat")
|
||||
|
||||
[node name="OpenButton" type="Button" parent="."]
|
||||
anchor_left = 1.0
|
||||
anchor_right = 1.0
|
||||
offset_left = -178.0
|
||||
offset_top = 6.0
|
||||
offset_right = -6.0
|
||||
offset_bottom = 28.0
|
||||
theme_override_colors/font_color = Color(1, 0.88, 0.5, 1)
|
||||
theme_override_fonts/font = SubResource("SystemFont_cjk")
|
||||
theme_override_font_sizes/font_size = 11
|
||||
text = "房★主★有★神★器★"
|
||||
|
||||
[node name="Panel" type="PanelContainer" parent="."]
|
||||
anchor_left = 1.0
|
||||
anchor_right = 1.0
|
||||
offset_left = -178.0
|
||||
offset_top = 32.0
|
||||
offset_right = -6.0
|
||||
offset_bottom = 168.0
|
||||
theme_override_styles/panel = SubResource("StyleBoxFlat_panel")
|
||||
|
||||
[node name="VBox" type="VBoxContainer" parent="Panel"]
|
||||
theme_override_constants/separation = 6
|
||||
|
||||
[node name="Title" type="Label" parent="Panel/VBox"]
|
||||
theme_override_colors/font_color = Color(1, 0.85, 0.4, 1)
|
||||
theme_override_fonts/font = SubResource("SystemFont_cjk")
|
||||
theme_override_font_sizes/font_size = 12
|
||||
text = "神 器"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="FlyButton" type="Button" parent="Panel/VBox"]
|
||||
theme_override_fonts/font = SubResource("SystemFont_cjk")
|
||||
theme_override_font_sizes/font_size = 11
|
||||
text = "飞行:关(F)"
|
||||
|
||||
[node name="Row" type="HBoxContainer" parent="Panel/VBox"]
|
||||
theme_override_constants/separation = 5
|
||||
|
||||
[node name="JumpHint" type="Label" parent="Panel/VBox/Row"]
|
||||
theme_override_fonts/font = SubResource("SystemFont_cjk")
|
||||
theme_override_font_sizes/font_size = 11
|
||||
text = "跳关"
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="CloseButton" type="Button" parent="Panel/VBox"]
|
||||
theme_override_fonts/font = SubResource("SystemFont_cjk")
|
||||
theme_override_font_sizes/font_size = 11
|
||||
text = "关闭(Esc)"
|
||||
@@ -0,0 +1,279 @@
|
||||
[gd_scene format=4 uid="uid://b14qjya7pedi1"]
|
||||
|
||||
[ext_resource type="PackedScene" path="res://scenes/hud.tscn" id="1_g8vcy"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/death_screen.tscn" id="2_cqal4"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/level_clear.tscn" id="3_o3sye"]
|
||||
[ext_resource type="Texture2D" uid="uid://djmk0srfgyafe" path="res://assets/game/backgrounds/cloud_left.png" id="4_24ks5"]
|
||||
[ext_resource type="Texture2D" uid="uid://dptqmtay4plwp" path="res://assets/game/backgrounds/cloud_trees.png" id="5_s4es8"]
|
||||
[ext_resource type="Texture2D" uid="uid://dys7320ghojh6" path="res://assets/game/backgrounds/cloud_hills.png" id="6_63e4f"]
|
||||
[ext_resource type="Texture2D" uid="uid://1b8hp0rm864l" path="res://assets/game/backgrounds/cloud_right.png" id="7_y6lc1"]
|
||||
[ext_resource type="Script" uid="uid://dxwa7fxghp3a2" path="res://scripts/hidden_passages.gd" id="8_ekhvm"]
|
||||
[ext_resource type="TileSet" uid="uid://dkowcf1ljh41j" path="res://assets/game/tilesets/kenney_terrain_tileset.tres" id="9_nflru"]
|
||||
[ext_resource type="PackedScene" uid="uid://c1u8k6ny02t4y" path="res://scenes/player.tscn" id="10_ikw2v"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/hazards/spikes_double.tscn" id="11_cgqhq"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/hazards/spikes_grey.tscn" id="12_ttvjw"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/interactables/door.tscn" id="14_qo7hg"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/collectibles/coin_gold_round.tscn" id="15_odav0"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/collectibles/key_gold.tscn" id="16_3xffc"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/collectibles/diamond.tscn" id="17_icuov"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/enemies/laser.tscn" id="19_laser"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/enemies/bullet_field.tscn" id="20_field"]
|
||||
|
||||
[node name="Main2" type="Node2D" unique_id=2061129075]
|
||||
|
||||
[node name="HUD" parent="." unique_id=215179112 instance=ExtResource("1_g8vcy")]
|
||||
|
||||
[node name="DeathScreen" parent="." unique_id=1952687359 instance=ExtResource("2_cqal4")]
|
||||
|
||||
[node name="LevelClear" parent="." unique_id=1589634220 instance=ExtResource("3_o3sye")]
|
||||
next_level_scene = "res://scenes/level3.tscn"
|
||||
|
||||
[node name="Level" type="Node2D" parent="." unique_id=1678372922]
|
||||
|
||||
[node name="Background" type="Node2D" parent="Level" unique_id=702011751]
|
||||
|
||||
[node name="SkyColor" type="Polygon2D" parent="Level/Background" unique_id=22763597]
|
||||
z_index = -30
|
||||
color = Color(0.8509804, 0.9411765, 0.9372549, 1)
|
||||
polygon = PackedVector2Array(0, 0, 468, 0, 468, 130.0972, 468, 270, 0, 270)
|
||||
|
||||
[node name="CloudBand_01" type="Sprite2D" parent="Level/Background" unique_id=589633713]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(12, 150)
|
||||
texture = ExtResource("4_24ks5")
|
||||
|
||||
[node name="CloudBand_02" type="Sprite2D" parent="Level/Background" unique_id=225493882]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(36, 150)
|
||||
texture = ExtResource("5_s4es8")
|
||||
|
||||
[node name="CloudBand_03" type="Sprite2D" parent="Level/Background" unique_id=646834403]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(60, 150)
|
||||
texture = ExtResource("6_63e4f")
|
||||
|
||||
[node name="CloudBand_04" type="Sprite2D" parent="Level/Background" unique_id=1012727532]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(84, 150)
|
||||
texture = ExtResource("7_y6lc1")
|
||||
|
||||
[node name="CloudBand_05" type="Sprite2D" parent="Level/Background" unique_id=1685434781]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(108, 150)
|
||||
texture = ExtResource("4_24ks5")
|
||||
|
||||
[node name="CloudBand_06" type="Sprite2D" parent="Level/Background" unique_id=1425986424]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(132, 150)
|
||||
texture = ExtResource("5_s4es8")
|
||||
|
||||
[node name="CloudBand_07" type="Sprite2D" parent="Level/Background" unique_id=1333305041]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(156, 150)
|
||||
texture = ExtResource("6_63e4f")
|
||||
|
||||
[node name="CloudBand_08" type="Sprite2D" parent="Level/Background" unique_id=55356860]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(180, 150)
|
||||
texture = ExtResource("7_y6lc1")
|
||||
|
||||
[node name="CloudBand_09" type="Sprite2D" parent="Level/Background" unique_id=379152848]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(204, 150)
|
||||
texture = ExtResource("4_24ks5")
|
||||
|
||||
[node name="CloudBand_10" type="Sprite2D" parent="Level/Background" unique_id=325990577]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(228, 150)
|
||||
texture = ExtResource("5_s4es8")
|
||||
|
||||
[node name="CloudBand_11" type="Sprite2D" parent="Level/Background" unique_id=1505438200]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(252, 150)
|
||||
texture = ExtResource("6_63e4f")
|
||||
|
||||
[node name="CloudBand_12" type="Sprite2D" parent="Level/Background" unique_id=190709163]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(276, 150)
|
||||
texture = ExtResource("7_y6lc1")
|
||||
|
||||
[node name="CloudBand_13" type="Sprite2D" parent="Level/Background" unique_id=349156114]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(300, 150)
|
||||
texture = ExtResource("4_24ks5")
|
||||
|
||||
[node name="CloudBand_14" type="Sprite2D" parent="Level/Background" unique_id=1838903106]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(324, 150)
|
||||
texture = ExtResource("5_s4es8")
|
||||
|
||||
[node name="CloudBand_15" type="Sprite2D" parent="Level/Background" unique_id=169474301]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(348, 150)
|
||||
texture = ExtResource("6_63e4f")
|
||||
|
||||
[node name="CloudBand_16" type="Sprite2D" parent="Level/Background" unique_id=156763289]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(372, 150)
|
||||
texture = ExtResource("7_y6lc1")
|
||||
|
||||
[node name="CloudBand_17" type="Sprite2D" parent="Level/Background" unique_id=161240142]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(396, 150)
|
||||
texture = ExtResource("4_24ks5")
|
||||
|
||||
[node name="CloudBand_18" type="Sprite2D" parent="Level/Background" unique_id=1823235224]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(420, 150)
|
||||
texture = ExtResource("5_s4es8")
|
||||
|
||||
[node name="CloudBand_19" type="Sprite2D" parent="Level/Background" unique_id=2092676382]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(444, 150)
|
||||
texture = ExtResource("6_63e4f")
|
||||
|
||||
[node name="CloudBand_20" type="Sprite2D" parent="Level/Background" unique_id=124375716]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(468, 150)
|
||||
texture = ExtResource("7_y6lc1")
|
||||
|
||||
[node name="TerrainTileMaps" type="Node2D" parent="Level" unique_id=652327492]
|
||||
script = ExtResource("8_ekhvm")
|
||||
|
||||
[node name="TerrainBase" type="TileMapLayer" parent="Level/TerrainTileMaps" unique_id=91115499]
|
||||
position = Vector2(9, 9)
|
||||
tile_map_data = PackedByteArray("AAD//wkAAAACAAEAAAD//woAAAAEAAAAAAABAA0AAAACAAYAAAACAA0AAAAEAAUAAAACAA4AAAAEAAUAAAADAA0AAAACAAYAAAABAAoAAAACAAYAAAAAAAoAAAAEAAUAAAAAAAkAAAACAAEAAAACAAsAAAAEAAUAAAAAAA0AAAAEAAUAAAD//w0AAAAEAAEAAAAFAA0AAAAEAAUAAAAEAA4AAAAEAAUAAAADAA4AAAACAAYAAAAAAA4AAAACAAYAAAABAA4AAAACAAYAAAAHAAwAAAACAAEAAAALAAwAAAACAAEAAAAKAA0AAAAEAAUAAAAIAA4AAAAEAAUAAAALAA4AAAAEAAUAAAAMAA4AAAACAAYAAAANAA0AAAACAAYAAAAOAA0AAAAEAAUAAAAPAA0AAAAEAAUAAAAQAA0AAAAEAAUAAAARAAwAAAACAAUAAAATAAwAAAACAAUAAAAVAAsAAAACAAYAAAAWAAsAAAAEAAUAAAAUAAwAAAACAAYAAAAQAAwAAAACAAMAAAAKAA4AAAAEAAUAAAAJAA4AAAAEAAUAAAAFAA4AAAACAAYAAAAGAA4AAAAEAAUAAAAHAA4AAAAEAAUAAAANAA4AAAACAAYAAAAOAA4AAAACAAYAAAAPAA4AAAACAAYAAAASAA0AAAACAAYAAAATAA0AAAAEAAUAAAAUAA0AAAACAAYAAAAVAA0AAAACAAYAAAAWAA0AAAACAAYAAAAXAA0AAAAEAAUAAAALAA0AAAAEAAUAAAAMAA0AAAACAAYAAAAPAAwAAAACAAMAAAAXAAsAAAAEAAUAAAAYAAsAAAAEAAUAAAAZAAsAAAACAAYAAAAZAAwAAAACAAYAAAAYAAwAAAAEAAUAAAAZAA4AAAAEAAUAAAAXAA4AAAAEAAUAAAAWAA4AAAAEAAUAAAAVAA4AAAACAAYAAAAUAA4AAAACAAYAAAATAA4AAAACAAYAAAASAA4AAAACAAYAAAAYAA4AAAACAAYAAAARAA4AAAACAAYAAAAEAA0AAAACAAYAAAD//w4AAAAEAAEAAAABAAkAAAACAAEAAAAIAAwAAAACAAEAAAAOAAwAAAACAAMAAAANAAwAAAACAAMAAAAMAAwAAAACAAMAAAAUAAkAAAABAAUAAAAUAAoAAAABAAYAAAAPAAgAAAASAAQAABAWAAoAAAACAAYAAAAXAAcAAAACAAUAAAAYAAkAAAACAAYAAAAYAAoAAAACAAYAAAAXAAoAAAACAAYAAAAXAAkAAAACAAYAAAAZAAkAAAACAAYAAAAZAAoAAAACAAYAAAAQAA4AAAAEAAUAAAARAA0AAAACAAYAAAASAAwAAAACAAUAAAAVAAoAAAACAAYAAAAWAAkAAAACAAUAAAAXAAgAAAAEAAEAAAAUAAsAAAAFAAEAAAAVAAwAAAAEAAUAAAAWAAwAAAACAAYAAAAXAAwAAAAEAAUAAAAYAA0AAAACAAYAAAAZAA0AAAAEAAUAAAAAAAwAAAACAAYAAAACAAwAAAACAAYAAAADAAwAAAAEAAUAAAAEAAwAAAACAAYAAAAFAAwAAAAEAAUAAAAGAAwAAAAEAAUAAAAGAA0AAAACAAYAAAAHAA0AAAACAAYAAAAIAA0AAAAEAAUAAAAJAA0AAAACAAYAAAAJAAwAAAACAAEAAAAKAAwAAAACAAEAAAD//wwAAAAFAAAAAAD//wsAAAAEAAAAAAAAAAsAAAAEAAUAAAABAAsAAAACAAYAAAABAAwAAAACAAYAAAAYAAcAAAACAAUAAAAZAAcAAAADAAUAAAAYAAgAAAACAAYAAAAZAAgAAAACAAYAAAAVAAkAAAACAAUAAAADAAsAAAACAAYAAAAEAAsAAAACAAEAAAAFAAsAAAACAAEAAAAGAAsAAAACAAEAAAACAAoAAAACAAEAAAADAAoAAAACAAEAAAARAAcAAAAOAAcAAAASAAcAAAAOAAcAAAAQAAcAAAAOAAcAAAAPAAcAAAANAAcAAAAIAAYAAAANAAcAAAATAAcAAAAPAAcAAAAMAAYAAAAPAAcAAAALAAYAAAAOAAcAAAAKAAYAAAAOAAcAAAABAAgAAAARAAYAAAABAAcAAAAQAAUAAAABAAYAAAARAAUAAAABAAUAAAAQAAUAAAAAAAQAAAASAAIAAAABAAQAAAASAAIAAAACAAQAAAASAAIAAAD//wQAAAARAAIAAAAEAAQAAAATAAIAAAADAAQAAAASAAIAAAAAAAMAAAASAAEAAAABAAMAAAASAAEAAAACAAMAAAASAAEAAAADAAMAAAASAAAAAAAEAAMAAAATAAAAAAD//wMAAAARAAEAAAD//wIAAAARAAEAAAD//wEAAAARAAEAAAAAAAEAAAASAAEAAAAAAAIAAAASAAEAAAABAAEAAAASAAEAAAABAAIAAAASAAEAAAACAAEAAAASAAEAAAACAAIAAAASAAEAAAACAAYAAAATAAQAAAAJAAYAAAAOAAcAAAA=")
|
||||
tile_set = ExtResource("9_nflru")
|
||||
|
||||
[node name="TerrainDetailsA" type="TileMapLayer" parent="Level/TerrainTileMaps" unique_id=1513560262]
|
||||
z_index = 1
|
||||
position = Vector2(9, 9)
|
||||
tile_map_data = PackedByteArray("AAADAA0AAAADAAYAAAABAAwAAAABAAYAAAABAA0AAAABAAYAAAACAAsAAAACAAEAAAADAAsAAAADAAEAAAACAAwAAAACAAYAAAACAA4AAAACAAYAAAAXAAsAAAADAAUAAAAXAAwAAAADAAYAAAAXAA0AAAADAAYAAAAXAA4AAAADAAYAAAAWAAoAAAAEAAcAAAAWAAsAAAACAAUAAAAWAAwAAAAEAAUAAAAWAA0AAAACAAYAAAAWAA4AAAAEAAUAAAAVAAsAAAABAAUAAAAVAAwAAAABAAYAAAAVAA0AAAABAAYAAAAVAA4AAAABAAYAAAAQAA4AAAADAAYAAAAOAA4AAAAEAAUAAAAPAA4AAAACAAYAAAAQAA0AAAADAAMAAAANAA4AAAABAAYAAAAOAAwAAAAEAAYAAAAPAA0AAAACAAMAAAAOAA0AAAACAAMAAAANAA0AAAABAAMAAAAQAAQAAAATAAIAAAAQAAMAAAATAAEAAAAKAAMAAAARAAAAAAALAAMAAAASAAAAAAAOAAIAAAARAAAAAAAPAAIAAAASAAAAAAADAAwAAAADAAYAAAAQAAIAAAATAAAAAAACAA0AAAAEAAUAAAABAA4AAAABAAYAAAADAA4AAAADAAYAAAABAAsAAAABAAEAAAAUAPz/AAASAAcAAAA=")
|
||||
tile_set = ExtResource("9_nflru")
|
||||
|
||||
[node name="TerrainDetailsB" type="TileMapLayer" parent="Level/TerrainTileMaps" unique_id=478648603]
|
||||
z_index = 2
|
||||
position = Vector2(9, 9)
|
||||
tile_map_data = PackedByteArray("AAAGAAwAAAADAAEAAAAGAA0AAAADAAYAAAAFAA4AAAACAAYAAAAFAAsAAAAFAAYAAAAFAAwAAAACAAEAAAAFAA0AAAAEAAUAAAAGAA4AAAADAAYAAAADAAwAAAABAAEAAAADAA0AAAABAAYAAAADAA4AAAABAAYAAAAEAAwAAAACAAEAAAAEAA0AAAACAAYAAAAEAA4AAAAEAAUAAAA=")
|
||||
tile_set = ExtResource("9_nflru")
|
||||
|
||||
[node name="ActorsAndCharacters" type="Node2D" parent="Level" unique_id=2036761714]
|
||||
|
||||
[node name="Player" parent="Level/ActorsAndCharacters" unique_id=1343528246 instance=ExtResource("10_ikw2v")]
|
||||
z_index = 10
|
||||
position = Vector2(144, 215)
|
||||
rotation = -3.1415927
|
||||
scale = Vector2(1, -1)
|
||||
|
||||
[node name="PrefabInstances" type="Node2D" parent="Level" unique_id=2013556771]
|
||||
|
||||
[node name="Structures" type="Node2D" parent="Level/PrefabInstances" unique_id=1811607442]
|
||||
|
||||
[node name="Hazards" type="Node2D" parent="Level/PrefabInstances" unique_id=888595377]
|
||||
|
||||
[node name="Spikes_01" parent="Level/PrefabInstances/Hazards" unique_id=1025977450 instance=ExtResource("11_cgqhq")]
|
||||
z_index = 5
|
||||
position = Vector2(270, 216)
|
||||
|
||||
[node name="Spikes_02" parent="Level/PrefabInstances/Hazards" unique_id=1262276584 instance=ExtResource("11_cgqhq")]
|
||||
z_index = 5
|
||||
position = Vector2(335, 127)
|
||||
|
||||
[node name="SpikesGrey_01" parent="Level/PrefabInstances/Hazards" unique_id=214833071 instance=ExtResource("12_ttvjw")]
|
||||
z_index = 5
|
||||
position = Vector2(109, 199)
|
||||
|
||||
[node name="SpikesGrey_02" parent="Level/PrefabInstances/Hazards" unique_id=458791480 instance=ExtResource("12_ttvjw")]
|
||||
z_index = 5
|
||||
position = Vector2(331, 216)
|
||||
|
||||
[node name="Enemies" type="Node2D" parent="Level/PrefabInstances" unique_id=93211253]
|
||||
|
||||
[node name="Laser_01" parent="Level/PrefabInstances/Enemies" unique_id=1298565970 instance=ExtResource("19_laser")]
|
||||
position = Vector2(187, 223)
|
||||
rotation = -1.5707964
|
||||
|
||||
[node name="Laser_02" parent="Level/PrefabInstances/Enemies" unique_id=1808104165 instance=ExtResource("19_laser")]
|
||||
position = Vector2(298, 233)
|
||||
rotation = -1.5707964
|
||||
length = 108.0
|
||||
start_delay = 2.4
|
||||
|
||||
[node name="Laser_03" parent="Level/PrefabInstances/Enemies" unique_id=1437324170 instance=ExtResource("19_laser")]
|
||||
position = Vector2(387, 137)
|
||||
rotation = -1.5707964
|
||||
length = 108.0
|
||||
start_delay = 2.4
|
||||
|
||||
[node name="Laser_04" parent="Level/PrefabInstances/Enemies" unique_id=1698684283 instance=ExtResource("19_laser")]
|
||||
position = Vector2(125, 125)
|
||||
rotation = -1.5707964
|
||||
length = 108.0
|
||||
start_delay = 2.4
|
||||
|
||||
[node name="Laser_05" parent="Level/PrefabInstances/Enemies" unique_id=231592857 instance=ExtResource("19_laser")]
|
||||
position = Vector2(251, 78)
|
||||
rotation = -1.5707964
|
||||
length = 108.0
|
||||
start_delay = 2.4
|
||||
|
||||
[node name="BulletField_01" parent="Level/PrefabInstances/Enemies" unique_id=978673745 instance=ExtResource("20_field")]
|
||||
position = Vector2(234, 234)
|
||||
|
||||
[node name="Interactables" type="Node2D" parent="Level/PrefabInstances" unique_id=769532488]
|
||||
|
||||
[node name="Door_01" parent="Level/PrefabInstances/Interactables" unique_id=1264725697 instance=ExtResource("14_qo7hg")]
|
||||
z_index = 5
|
||||
position = Vector2(288, 37)
|
||||
|
||||
[node name="Collectibles" type="Node2D" parent="Level/PrefabInstances" unique_id=2086540192]
|
||||
|
||||
[node name="CoinGoldRound_01" parent="Level/PrefabInstances/Collectibles" unique_id=926105584 instance=ExtResource("15_odav0")]
|
||||
z_index = 5
|
||||
position = Vector2(437, 127)
|
||||
|
||||
[node name="CoinGoldRound_02" parent="Level/PrefabInstances/Collectibles" unique_id=1674416025 instance=ExtResource("15_odav0")]
|
||||
z_index = 5
|
||||
position = Vector2(179, 111)
|
||||
|
||||
[node name="CoinGoldRound_03" parent="Level/PrefabInstances/Collectibles" unique_id=1087706364 instance=ExtResource("15_odav0")]
|
||||
z_index = 5
|
||||
position = Vector2(219, 54)
|
||||
|
||||
[node name="KeyGold_01" parent="Level/PrefabInstances/Collectibles" unique_id=2060959680 instance=ExtResource("16_3xffc")]
|
||||
z_index = 5
|
||||
position = Vector2(145, 220)
|
||||
|
||||
[node name="Diamond_01" parent="Level/PrefabInstances/Collectibles" unique_id=909237898 instance=ExtResource("17_icuov")]
|
||||
z_index = 5
|
||||
position = Vector2(399, 161)
|
||||
|
||||
[node name="Diamond_02" parent="Level/PrefabInstances/Collectibles" unique_id=234727210 instance=ExtResource("17_icuov")]
|
||||
z_index = 5
|
||||
position = Vector2(204, 217)
|
||||
|
||||
[node name="Diamond_03" parent="Level/PrefabInstances/Collectibles" unique_id=1261326529 instance=ExtResource("17_icuov")]
|
||||
z_index = 5
|
||||
position = Vector2(288, 125)
|
||||
|
||||
[node name="Signs" type="Node2D" parent="Level/PrefabInstances" unique_id=113197076]
|
||||
@@ -0,0 +1,267 @@
|
||||
[gd_scene format=4 uid="uid://csvqda2jbvh2o"]
|
||||
|
||||
[ext_resource type="PackedScene" path="res://scenes/hud.tscn" id="1_07lh1"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/death_screen.tscn" id="2_6uuvf"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/level_clear.tscn" id="3_x008a"]
|
||||
[ext_resource type="Texture2D" uid="uid://djmk0srfgyafe" path="res://assets/game/backgrounds/cloud_left.png" id="4_atr84"]
|
||||
[ext_resource type="Texture2D" uid="uid://dptqmtay4plwp" path="res://assets/game/backgrounds/cloud_trees.png" id="5_qyu38"]
|
||||
[ext_resource type="Texture2D" uid="uid://dys7320ghojh6" path="res://assets/game/backgrounds/cloud_hills.png" id="6_8vbrh"]
|
||||
[ext_resource type="Texture2D" uid="uid://1b8hp0rm864l" path="res://assets/game/backgrounds/cloud_right.png" id="7_d5gix"]
|
||||
[ext_resource type="Script" uid="uid://dxwa7fxghp3a2" path="res://scripts/hidden_passages.gd" id="8_7hs6g"]
|
||||
[ext_resource type="TileSet" uid="uid://dkowcf1ljh41j" path="res://assets/game/tilesets/kenney_terrain_tileset.tres" id="9_yeq8b"]
|
||||
[ext_resource type="PackedScene" uid="uid://c1u8k6ny02t4y" path="res://scenes/player.tscn" id="10_invaa"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/hazards/spikes_double.tscn" id="11_88b2t"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/hazards/spikes_grey.tscn" id="12_0ydwj"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/interactables/spring_red.tscn" id="15_usk20"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/interactables/door.tscn" id="16_y8u0o"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/collectibles/coin_gold_round.tscn" id="17_16ffm"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/collectibles/key_gold.tscn" id="18_kvrlk"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/collectibles/diamond.tscn" id="19_85fmh"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/enemies/bullet_rain.tscn" id="20_rain"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/prefabs/enemies/walker.tscn" id="21_walker"]
|
||||
|
||||
[node name="Main" type="Node2D" unique_id=2061129075]
|
||||
|
||||
[node name="HUD" parent="." unique_id=215179112 instance=ExtResource("1_07lh1")]
|
||||
|
||||
[node name="DeathScreen" parent="." unique_id=1952687359 instance=ExtResource("2_6uuvf")]
|
||||
|
||||
[node name="LevelClear" parent="." unique_id=1589634220 instance=ExtResource("3_x008a")]
|
||||
|
||||
[node name="Level" type="Node2D" parent="." unique_id=1678372922]
|
||||
|
||||
[node name="Background" type="Node2D" parent="Level" unique_id=702011751]
|
||||
|
||||
[node name="SkyColor" type="Polygon2D" parent="Level/Background" unique_id=22763597]
|
||||
z_index = -30
|
||||
color = Color(0.8509804, 0.9411765, 0.9372549, 1)
|
||||
polygon = PackedVector2Array(0, 0, 468, 0, 468, 130.0972, 468, 270, 0, 270)
|
||||
|
||||
[node name="CloudBand_01" type="Sprite2D" parent="Level/Background" unique_id=589633713]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(12, 150)
|
||||
texture = ExtResource("4_atr84")
|
||||
|
||||
[node name="CloudBand_02" type="Sprite2D" parent="Level/Background" unique_id=225493882]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(36, 150)
|
||||
texture = ExtResource("5_qyu38")
|
||||
|
||||
[node name="CloudBand_03" type="Sprite2D" parent="Level/Background" unique_id=646834403]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(60, 150)
|
||||
texture = ExtResource("6_8vbrh")
|
||||
|
||||
[node name="CloudBand_04" type="Sprite2D" parent="Level/Background" unique_id=1012727532]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(84, 150)
|
||||
texture = ExtResource("7_d5gix")
|
||||
|
||||
[node name="CloudBand_05" type="Sprite2D" parent="Level/Background" unique_id=1685434781]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(108, 150)
|
||||
texture = ExtResource("4_atr84")
|
||||
|
||||
[node name="CloudBand_06" type="Sprite2D" parent="Level/Background" unique_id=1425986424]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(132, 150)
|
||||
texture = ExtResource("5_qyu38")
|
||||
|
||||
[node name="CloudBand_07" type="Sprite2D" parent="Level/Background" unique_id=1333305041]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(156, 150)
|
||||
texture = ExtResource("6_8vbrh")
|
||||
|
||||
[node name="CloudBand_08" type="Sprite2D" parent="Level/Background" unique_id=55356860]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(180, 150)
|
||||
texture = ExtResource("7_d5gix")
|
||||
|
||||
[node name="CloudBand_09" type="Sprite2D" parent="Level/Background" unique_id=379152848]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(204, 150)
|
||||
texture = ExtResource("4_atr84")
|
||||
|
||||
[node name="CloudBand_10" type="Sprite2D" parent="Level/Background" unique_id=325990577]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(228, 150)
|
||||
texture = ExtResource("5_qyu38")
|
||||
|
||||
[node name="CloudBand_11" type="Sprite2D" parent="Level/Background" unique_id=1505438200]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(252, 150)
|
||||
texture = ExtResource("6_8vbrh")
|
||||
|
||||
[node name="CloudBand_12" type="Sprite2D" parent="Level/Background" unique_id=190709163]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(276, 150)
|
||||
texture = ExtResource("7_d5gix")
|
||||
|
||||
[node name="CloudBand_13" type="Sprite2D" parent="Level/Background" unique_id=349156114]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(300, 150)
|
||||
texture = ExtResource("4_atr84")
|
||||
|
||||
[node name="CloudBand_14" type="Sprite2D" parent="Level/Background" unique_id=1838903106]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(324, 150)
|
||||
texture = ExtResource("5_qyu38")
|
||||
|
||||
[node name="CloudBand_15" type="Sprite2D" parent="Level/Background" unique_id=169474301]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(348, 150)
|
||||
texture = ExtResource("6_8vbrh")
|
||||
|
||||
[node name="CloudBand_16" type="Sprite2D" parent="Level/Background" unique_id=156763289]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(372, 150)
|
||||
texture = ExtResource("7_d5gix")
|
||||
|
||||
[node name="CloudBand_17" type="Sprite2D" parent="Level/Background" unique_id=161240142]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(396, 150)
|
||||
texture = ExtResource("4_atr84")
|
||||
|
||||
[node name="CloudBand_18" type="Sprite2D" parent="Level/Background" unique_id=1823235224]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(420, 150)
|
||||
texture = ExtResource("5_qyu38")
|
||||
|
||||
[node name="CloudBand_19" type="Sprite2D" parent="Level/Background" unique_id=2092676382]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(444, 150)
|
||||
texture = ExtResource("6_8vbrh")
|
||||
|
||||
[node name="CloudBand_20" type="Sprite2D" parent="Level/Background" unique_id=124375716]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(468, 150)
|
||||
texture = ExtResource("7_d5gix")
|
||||
|
||||
[node name="TerrainTileMaps" type="Node2D" parent="Level" unique_id=652327492]
|
||||
script = ExtResource("8_7hs6g")
|
||||
|
||||
[node name="TerrainBase" type="TileMapLayer" parent="Level/TerrainTileMaps" unique_id=91115499]
|
||||
position = Vector2(9, 9)
|
||||
tile_map_data = PackedByteArray("AAD//wkAAAACAAEAAAD//woAAAAEAAAAAAABAA0AAAACAAYAAAACAA0AAAAEAAUAAAACAA4AAAAEAAUAAAADAA0AAAACAAYAAAABAAoAAAACAAYAAAAAAAoAAAAEAAUAAAAAAAkAAAACAAEAAAACAAsAAAAEAAUAAAAAAA0AAAAEAAUAAAD//w0AAAAEAAEAAAAFAA0AAAAEAAUAAAAEAA4AAAAEAAUAAAADAA4AAAACAAYAAAAAAA4AAAACAAYAAAABAA4AAAACAAYAAAAHAAwAAAACAAEAAAALAAwAAAACAAEAAAAKAA0AAAAEAAUAAAAIAA4AAAAEAAUAAAALAA4AAAAEAAUAAAAMAA4AAAACAAYAAAANAA0AAAACAAYAAAAOAA0AAAAEAAUAAAAPAA0AAAAEAAUAAAAQAA0AAAAEAAUAAAARAAwAAAACAAUAAAATAAwAAAACAAUAAAAVAAsAAAACAAYAAAAWAAsAAAAEAAUAAAAUAAwAAAACAAYAAAAQAAwAAAACAAMAAAAKAA4AAAAEAAUAAAAJAA4AAAAEAAUAAAAFAA4AAAACAAYAAAAGAA4AAAAEAAUAAAAHAA4AAAAEAAUAAAANAA4AAAACAAYAAAAOAA4AAAACAAYAAAAPAA4AAAACAAYAAAASAA0AAAACAAYAAAATAA0AAAAEAAUAAAAUAA0AAAACAAYAAAAVAA0AAAACAAYAAAAWAA0AAAACAAYAAAAXAA0AAAAEAAUAAAALAA0AAAAEAAUAAAAMAA0AAAACAAYAAAAPAAwAAAACAAMAAAAXAAsAAAAEAAUAAAAYAAsAAAAEAAUAAAAZAAsAAAACAAYAAAAZAAwAAAACAAYAAAAYAAwAAAAEAAUAAAAZAA4AAAAEAAUAAAAXAA4AAAAEAAUAAAAWAA4AAAAEAAUAAAAVAA4AAAACAAYAAAAUAA4AAAACAAYAAAATAA4AAAACAAYAAAASAA4AAAACAAYAAAAYAA4AAAACAAYAAAARAA4AAAACAAYAAAAEAA0AAAACAAYAAAD//w4AAAAEAAEAAAABAAkAAAACAAEAAAAIAAwAAAACAAEAAAAOAAwAAAACAAMAAAANAAwAAAACAAMAAAAMAAwAAAACAAMAAAAUAAkAAAABAAUAAAAUAAoAAAABAAYAAAAWAAoAAAACAAYAAAAXAAcAAAACAAUAAAAYAAkAAAACAAYAAAAYAAoAAAACAAYAAAAXAAoAAAACAAYAAAAXAAkAAAACAAYAAAAZAAkAAAACAAYAAAAZAAoAAAACAAYAAAAQAA4AAAAEAAUAAAARAA0AAAACAAYAAAASAAwAAAACAAUAAAAVAAoAAAACAAYAAAAWAAkAAAACAAUAAAAXAAgAAAAEAAEAAAAUAAsAAAAFAAEAAAAVAAwAAAAEAAUAAAAWAAwAAAACAAYAAAAXAAwAAAAEAAUAAAAYAA0AAAACAAYAAAAZAA0AAAAEAAUAAAAAAAwAAAACAAYAAAACAAwAAAACAAYAAAADAAwAAAAEAAUAAAAEAAwAAAACAAYAAAAFAAwAAAAEAAUAAAAGAAwAAAAEAAUAAAAGAA0AAAACAAYAAAAHAA0AAAACAAYAAAAIAA0AAAAEAAUAAAAJAA0AAAACAAYAAAAKAAwAAAACAAEAAAD//wwAAAAFAAAAAAD//wsAAAAEAAAAAAAAAAsAAAAEAAUAAAABAAsAAAACAAYAAAABAAwAAAACAAYAAAAYAAcAAAACAAUAAAAZAAcAAAADAAUAAAAYAAgAAAACAAYAAAAZAAgAAAACAAYAAAAVAAkAAAACAAUAAAADAAsAAAACAAYAAAAEAAsAAAACAAEAAAAFAAsAAAACAAEAAAAGAAsAAAACAAEAAAACAAoAAAACAAEAAAADAAoAAAACAAEAAAARAAcAAAAOAAcAAAASAAcAAAAOAAcAAAAQAAcAAAAOAAcAAAAIAAYAAAANAAcAAAATAAcAAAAPAAcAAAAMAAYAAAAPAAcAAAALAAYAAAAOAAcAAAAKAAYAAAAOAAcAAAABAAgAAAARAAYAAAABAAcAAAAQAAUAAAABAAYAAAARAAUAAAABAAUAAAAQAAUAAAAAAAQAAAASAAIAAAABAAQAAAASAAIAAAACAAQAAAASAAIAAAD//wQAAAARAAIAAAAEAAQAAAATAAIAAAADAAQAAAASAAIAAAAAAAMAAAASAAEAAAABAAMAAAASAAEAAAACAAMAAAASAAEAAAADAAMAAAASAAAAAAAEAAMAAAATAAAAAAD//wMAAAARAAEAAAD//wIAAAARAAEAAAD//wEAAAARAAEAAAAAAAEAAAASAAEAAAAAAAIAAAASAAEAAAABAAEAAAASAAEAAAABAAIAAAASAAEAAAACAAEAAAASAAEAAAACAAIAAAASAAEAAAACAAYAAAATAAQAAAAJAAYAAAAOAAcAAAAJAAwAAAACAAEAAAAPAAcAAAANAAcAAAA=")
|
||||
tile_set = ExtResource("9_yeq8b")
|
||||
|
||||
[node name="TerrainDetailsA" type="TileMapLayer" parent="Level/TerrainTileMaps" unique_id=1513560262]
|
||||
z_index = 1
|
||||
position = Vector2(9, 9)
|
||||
tile_map_data = PackedByteArray("AAADAA0AAAADAAYAAAABAAwAAAABAAYAAAABAA0AAAABAAYAAAACAAsAAAACAAEAAAADAAsAAAADAAEAAAACAAwAAAACAAYAAAACAA4AAAACAAYAAAAXAAsAAAADAAUAAAAXAAwAAAADAAYAAAAXAA0AAAADAAYAAAAXAA4AAAADAAYAAAAWAAoAAAAEAAcAAAAWAAsAAAACAAUAAAAWAAwAAAAEAAUAAAAWAA0AAAACAAYAAAAWAA4AAAAEAAUAAAAVAAsAAAABAAUAAAAVAAwAAAABAAYAAAAVAA0AAAABAAYAAAAVAA4AAAABAAYAAAAQAA4AAAADAAYAAAAOAA4AAAAEAAUAAAAPAA4AAAACAAYAAAAQAA0AAAADAAMAAAANAA4AAAABAAYAAAAOAAwAAAAEAAYAAAAPAA0AAAACAAMAAAAOAA0AAAACAAMAAAANAA0AAAABAAMAAAAKAAMAAAARAAAAAAALAAMAAAASAAAAAAAMAAMAAAATAAAAAAAOAAIAAAARAAAAAAAPAAIAAAASAAAAAAADAAwAAAADAAYAAAAQAAIAAAATAAAAAAACAA0AAAAEAAUAAAABAA4AAAABAAYAAAADAA4AAAADAAYAAAABAAsAAAABAAEAAAAUAPz/AAASAAcAAAA=")
|
||||
tile_set = ExtResource("9_yeq8b")
|
||||
|
||||
[node name="TerrainDetailsB" type="TileMapLayer" parent="Level/TerrainTileMaps" unique_id=478648603]
|
||||
z_index = 2
|
||||
position = Vector2(9, 9)
|
||||
tile_map_data = PackedByteArray("AAAGAAwAAAADAAEAAAAGAA0AAAADAAYAAAAFAA4AAAACAAYAAAAFAAsAAAAFAAYAAAAFAAwAAAACAAEAAAAFAA0AAAAEAAUAAAAGAA4AAAADAAYAAAADAAwAAAABAAEAAAADAA0AAAABAAYAAAADAA4AAAABAAYAAAAEAAwAAAACAAEAAAAEAA0AAAACAAYAAAAEAA4AAAAEAAUAAAA=")
|
||||
tile_set = ExtResource("9_yeq8b")
|
||||
|
||||
[node name="ActorsAndCharacters" type="Node2D" parent="Level" unique_id=2036761714]
|
||||
|
||||
[node name="Player" parent="Level/ActorsAndCharacters" unique_id=1343528246 instance=ExtResource("10_invaa")]
|
||||
z_index = 10
|
||||
position = Vector2(144, 215)
|
||||
rotation = -3.1415927
|
||||
scale = Vector2(1, -1)
|
||||
|
||||
[node name="PrefabInstances" type="Node2D" parent="Level" unique_id=2013556771]
|
||||
|
||||
[node name="Structures" type="Node2D" parent="Level/PrefabInstances" unique_id=1811607442]
|
||||
|
||||
[node name="Hazards" type="Node2D" parent="Level/PrefabInstances" unique_id=888595377]
|
||||
|
||||
[node name="Spikes_01" parent="Level/PrefabInstances/Hazards" unique_id=1025977450 instance=ExtResource("11_88b2t")]
|
||||
z_index = 5
|
||||
position = Vector2(270, 216)
|
||||
|
||||
[node name="Spikes_02" parent="Level/PrefabInstances/Hazards" unique_id=1262276584 instance=ExtResource("11_88b2t")]
|
||||
z_index = 5
|
||||
position = Vector2(335, 127)
|
||||
|
||||
[node name="SpikesGrey_01" parent="Level/PrefabInstances/Hazards" unique_id=214833071 instance=ExtResource("12_0ydwj")]
|
||||
z_index = 5
|
||||
position = Vector2(109, 199)
|
||||
|
||||
[node name="SpikesGrey_02" parent="Level/PrefabInstances/Hazards" unique_id=458791480 instance=ExtResource("12_0ydwj")]
|
||||
z_index = 5
|
||||
position = Vector2(331, 216)
|
||||
|
||||
[node name="Enemies" type="Node2D" parent="Level/PrefabInstances" unique_id=93211253]
|
||||
|
||||
[node name="BulletRain_01" parent="Level/PrefabInstances/Enemies" unique_id=1814844955 instance=ExtResource("20_rain")]
|
||||
position = Vector2(234, 0)
|
||||
|
||||
[node name="Walker_01" parent="Level/PrefabInstances/Enemies" instance=ExtResource("21_walker")]
|
||||
position = Vector2(216, 216)
|
||||
|
||||
[node name="Walker_02" parent="Level/PrefabInstances/Enemies" instance=ExtResource("21_walker")]
|
||||
position = Vector2(306, 216)
|
||||
start_direction = 1
|
||||
|
||||
[node name="Walker_03" parent="Level/PrefabInstances/Enemies" instance=ExtResource("21_walker")]
|
||||
position = Vector2(90, 198)
|
||||
start_direction = 1
|
||||
|
||||
[node name="Interactables" type="Node2D" parent="Level/PrefabInstances" unique_id=769532488]
|
||||
|
||||
[node name="SpringRed_01" parent="Level/PrefabInstances/Interactables" unique_id=34192139 instance=ExtResource("15_usk20")]
|
||||
visible = false
|
||||
z_index = 5
|
||||
position = Vector2(448, 125)
|
||||
|
||||
[node name="Door_01" parent="Level/PrefabInstances/Interactables" unique_id=1264725697 instance=ExtResource("16_y8u0o")]
|
||||
z_index = 5
|
||||
position = Vector2(288, 37)
|
||||
|
||||
[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_16ffm")]
|
||||
z_index = 5
|
||||
position = Vector2(432, 127)
|
||||
|
||||
[node name="CoinGoldRound_02" parent="Level/PrefabInstances/Collectibles" unique_id=1674416025 instance=ExtResource("17_16ffm")]
|
||||
z_index = 5
|
||||
position = Vector2(67, 184)
|
||||
|
||||
[node name="CoinGoldRound_03" parent="Level/PrefabInstances/Collectibles" unique_id=1087706364 instance=ExtResource("17_16ffm")]
|
||||
z_index = 5
|
||||
position = Vector2(182, 109)
|
||||
|
||||
[node name="KeyGold_01" parent="Level/PrefabInstances/Collectibles" unique_id=2060959680 instance=ExtResource("18_kvrlk")]
|
||||
z_index = 5
|
||||
position = Vector2(145, 220)
|
||||
|
||||
[node name="Diamond_01" parent="Level/PrefabInstances/Collectibles" unique_id=909237898 instance=ExtResource("19_85fmh")]
|
||||
z_index = 5
|
||||
position = Vector2(399, 161)
|
||||
|
||||
[node name="Diamond_02" parent="Level/PrefabInstances/Collectibles" unique_id=234727210 instance=ExtResource("19_85fmh")]
|
||||
z_index = 5
|
||||
position = Vector2(204, 217)
|
||||
|
||||
[node name="Diamond_03" parent="Level/PrefabInstances/Collectibles" unique_id=1261326529 instance=ExtResource("19_85fmh")]
|
||||
z_index = 5
|
||||
position = Vector2(288, 125)
|
||||
|
||||
[node name="Signs" type="Node2D" parent="Level/PrefabInstances" unique_id=113197076]
|
||||
@@ -1,88 +0,0 @@
|
||||
[gd_scene load_steps=9 format=3]
|
||||
|
||||
[ext_resource type="Texture2D" path="res://assets/game/backgrounds/cloud_left.png" id="1_cloud1"]
|
||||
[ext_resource type="Texture2D" path="res://assets/game/backgrounds/cloud_trees.png" id="2_cloud2"]
|
||||
[ext_resource type="Texture2D" path="res://assets/game/backgrounds/cloud_hills.png" id="3_cloud3"]
|
||||
[ext_resource type="Texture2D" path="res://assets/game/backgrounds/cloud_right.png" id="4_cloud4"]
|
||||
[ext_resource type="TileSet" path="res://assets/game/tilesets/kenney_terrain_tileset.tres" id="5_tileset"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/player.tscn" id="6_player"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/hud.tscn" id="7_hud"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/death_screen.tscn" id="8_death"]
|
||||
[ext_resource type="PackedScene" path="res://scenes/level_clear.tscn" id="9_clear"]
|
||||
[ext_resource type="Script" path="res://scripts/hidden_passages.gd" id="10_hidden"]
|
||||
|
||||
[node name="Main" type="Node2D"]
|
||||
|
||||
[node name="HUD" parent="." instance=ExtResource("7_hud")]
|
||||
|
||||
[node name="DeathScreen" parent="." instance=ExtResource("8_death")]
|
||||
|
||||
[node name="LevelClear" parent="." instance=ExtResource("9_clear")]
|
||||
|
||||
[node name="Level" type="Node2D" parent="."]
|
||||
|
||||
[node name="Background" type="Node2D" parent="Level"]
|
||||
|
||||
[node name="SkyColor" type="Polygon2D" parent="Level/Background"]
|
||||
z_index = -30
|
||||
color = Color(0.8509804, 0.9411765, 0.9372549, 1)
|
||||
polygon = PackedVector2Array(0, 0, 468, 0, 468, 270, 0, 270)
|
||||
|
||||
[node name="CloudBand_01" type="Sprite2D" parent="Level/Background"]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(12, 150)
|
||||
texture = ExtResource("1_cloud1")
|
||||
|
||||
[node name="CloudBand_02" type="Sprite2D" parent="Level/Background"]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(36, 150)
|
||||
texture = ExtResource("2_cloud2")
|
||||
|
||||
[node name="CloudBand_03" type="Sprite2D" parent="Level/Background"]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(60, 150)
|
||||
texture = ExtResource("3_cloud3")
|
||||
|
||||
[node name="CloudBand_04" type="Sprite2D" parent="Level/Background"]
|
||||
z_index = -20
|
||||
texture_filter = 1
|
||||
position = Vector2(84, 150)
|
||||
texture = ExtResource("4_cloud4")
|
||||
|
||||
[node name="TerrainTileMaps" type="Node2D" parent="Level"]
|
||||
script = ExtResource("10_hidden")
|
||||
hidden_cells = []
|
||||
|
||||
[node name="TerrainBase" type="TileMapLayer" parent="Level/TerrainTileMaps"]
|
||||
position = Vector2(9, 9)
|
||||
tile_set = ExtResource("5_tileset")
|
||||
|
||||
[node name="TerrainDetailsA" type="TileMapLayer" parent="Level/TerrainTileMaps"]
|
||||
position = Vector2(9, 9)
|
||||
z_index = 1
|
||||
tile_set = ExtResource("5_tileset")
|
||||
|
||||
[node name="TerrainDetailsB" type="TileMapLayer" parent="Level/TerrainTileMaps"]
|
||||
position = Vector2(9, 9)
|
||||
z_index = 2
|
||||
tile_set = ExtResource("5_tileset")
|
||||
|
||||
[node name="ActorsAndCharacters" type="Node2D" parent="Level"]
|
||||
|
||||
[node name="Player" parent="Level/ActorsAndCharacters" instance=ExtResource("6_player")]
|
||||
position = Vector2(102, 132)
|
||||
|
||||
[node name="PrefabInstances" type="Node2D" parent="Level"]
|
||||
|
||||
[node name="Structures" type="Node2D" parent="Level/PrefabInstances"]
|
||||
|
||||
[node name="Hazards" type="Node2D" parent="Level/PrefabInstances"]
|
||||
|
||||
[node name="Interactables" type="Node2D" parent="Level/PrefabInstances"]
|
||||
|
||||
[node name="Collectibles" type="Node2D" parent="Level/PrefabInstances"]
|
||||
|
||||
[node name="Signs" type="Node2D" parent="Level/PrefabInstances"]
|
||||
+6
-11
@@ -24,8 +24,8 @@
|
||||
|
||||
[node name="DeathScreen" parent="." unique_id=1952687359 instance=ExtResource("22_death")]
|
||||
|
||||
[node name="LevelClear" parent="." instance=ExtResource("26_clear")]
|
||||
next_level_scene = "res://scenes/level_2.tscn"
|
||||
[node name="LevelClear" parent="." unique_id=573996737 instance=ExtResource("26_clear")]
|
||||
next_level_scene = "res://scenes/level2.tscn"
|
||||
|
||||
[node name="Level" type="Node2D" parent="." unique_id=1678372922]
|
||||
|
||||
@@ -212,15 +212,10 @@ position = Vector2(270, 18)
|
||||
z_index = 5
|
||||
position = Vector2(325, 108)
|
||||
|
||||
[node name="Door_01" parent="Level/PrefabInstances/Interactables" instance=ExtResource("25_door")]
|
||||
[node name="Door_01" parent="Level/PrefabInstances/Interactables" unique_id=1439478654 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")]
|
||||
@@ -239,15 +234,15 @@ position = Vector2(315, 63)
|
||||
z_index = 5
|
||||
position = Vector2(126, 144)
|
||||
|
||||
[node name="Diamond_01" parent="Level/PrefabInstances/Collectibles" instance=ExtResource("24_diamond")]
|
||||
[node name="Diamond_01" parent="Level/PrefabInstances/Collectibles" unique_id=879831603 instance=ExtResource("24_diamond")]
|
||||
z_index = 5
|
||||
position = Vector2(90, 18)
|
||||
|
||||
[node name="Diamond_02" parent="Level/PrefabInstances/Collectibles" instance=ExtResource("24_diamond")]
|
||||
[node name="Diamond_02" parent="Level/PrefabInstances/Collectibles" unique_id=1537151440 instance=ExtResource("24_diamond")]
|
||||
z_index = 5
|
||||
position = Vector2(414, 54)
|
||||
|
||||
[node name="Diamond_03" parent="Level/PrefabInstances/Collectibles" instance=ExtResource("24_diamond")]
|
||||
[node name="Diamond_03" parent="Level/PrefabInstances/Collectibles" unique_id=2052535476 instance=ExtResource("24_diamond")]
|
||||
z_index = 5
|
||||
position = Vector2(270, 144)
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
[gd_scene load_steps=4 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/bullet.gd" id="1_bullet"]
|
||||
|
||||
[sub_resource type="CircleShape2D" id="Shape_bullet"]
|
||||
radius = 3.0
|
||||
|
||||
[node name="Bullet" type="Area2D" groups=["bullet"]]
|
||||
collision_layer = 4
|
||||
collision_mask = 2
|
||||
script = ExtResource("1_bullet")
|
||||
|
||||
[node name="Sprite" type="Sprite2D" parent="."]
|
||||
texture_filter = 1
|
||||
|
||||
[node name="HitBox" type="CollisionShape2D" parent="."]
|
||||
shape = SubResource("Shape_bullet")
|
||||
|
||||
[node name="Probe" type="RayCast2D" parent="."]
|
||||
collision_mask = 3
|
||||
hit_from_inside = true
|
||||
target_position = Vector2(-12, 0)
|
||||
@@ -0,0 +1,7 @@
|
||||
[gd_scene load_steps=2 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/bullet_field.gd" id="1_field"]
|
||||
|
||||
[node name="BulletField" type="Node2D"]
|
||||
z_index = 5
|
||||
script = ExtResource("1_field")
|
||||
@@ -0,0 +1,6 @@
|
||||
[gd_scene load_steps=2 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/bullet_rain.gd" id="1_rain"]
|
||||
|
||||
[node name="BulletRain" type="Node2D"]
|
||||
script = ExtResource("1_rain")
|
||||
@@ -0,0 +1,19 @@
|
||||
[gd_scene load_steps=3 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/laser.gd" id="1_laser"]
|
||||
|
||||
[sub_resource type="RectangleShape2D" id="Shape_laser"]
|
||||
size = Vector2(90, 6)
|
||||
|
||||
[node name="Laser" type="Area2D" groups=["hazard"]]
|
||||
collision_layer = 4
|
||||
collision_mask = 2
|
||||
script = ExtResource("1_laser")
|
||||
|
||||
[node name="Beam" type="Polygon2D" parent="."]
|
||||
color = Color(1, 0.25, 0.25, 1)
|
||||
polygon = PackedVector2Array(0, -3, 90, -3, 90, 3, 0, 3)
|
||||
|
||||
[node name="HitBox" type="CollisionShape2D" parent="."]
|
||||
position = Vector2(45, 0)
|
||||
shape = SubResource("Shape_laser")
|
||||
@@ -0,0 +1,35 @@
|
||||
[gd_scene load_steps=5 format=3]
|
||||
|
||||
[ext_resource type="Texture2D" path="res://assets/game/vegetation/mushroom_red.png" id="1_tex"]
|
||||
[ext_resource type="Script" path="res://scripts/walker.gd" id="2_walker"]
|
||||
|
||||
[sub_resource type="RectangleShape2D" id="Shape_body"]
|
||||
size = Vector2(12, 16)
|
||||
|
||||
[sub_resource type="RectangleShape2D" id="Shape_touch"]
|
||||
size = Vector2(16, 16)
|
||||
|
||||
[node name="Walker" type="CharacterBody2D" groups=["enemy"]]
|
||||
z_index = 5
|
||||
collision_layer = 4
|
||||
collision_mask = 1
|
||||
script = ExtResource("2_walker")
|
||||
|
||||
[node name="Sprite" type="Sprite2D" parent="."]
|
||||
texture_filter = 1
|
||||
texture = ExtResource("1_tex")
|
||||
|
||||
[node name="Collision" type="CollisionShape2D" parent="."]
|
||||
shape = SubResource("Shape_body")
|
||||
|
||||
[node name="FloorProbe" type="RayCast2D" parent="."]
|
||||
position = Vector2(-6, 7)
|
||||
target_position = Vector2(0, 9)
|
||||
collision_mask = 1
|
||||
|
||||
[node name="TouchArea" type="Area2D" parent="."]
|
||||
collision_layer = 0
|
||||
collision_mask = 2
|
||||
|
||||
[node name="TouchShape" type="CollisionShape2D" parent="TouchArea"]
|
||||
shape = SubResource("Shape_touch")
|
||||
@@ -0,0 +1,86 @@
|
||||
extends Area2D
|
||||
|
||||
## 弹幕子弹:直线飞行,碰到玩家扣血。
|
||||
## 贴图是代码生成的实心圆,不需要额外美术素材。
|
||||
|
||||
@export var speed: float = 70.0
|
||||
@export var damage: int = 1
|
||||
@export var lifetime: float = 8.0
|
||||
@export var radius: int = 3
|
||||
@export var bullet_color: Color = Color(1.0, 0.35, 0.7)
|
||||
## 撞到地形/绳子之类的障碍就消失。
|
||||
## 关掉(默认)的话子弹会**穿过一切**,只靠存活时间和出界来回收
|
||||
@export var stop_on_obstacle: bool = false
|
||||
## 掉到这个世界 y 以下就自动回收(默认在关卡底部之外)
|
||||
@export var despawn_y: float = 340.0
|
||||
|
||||
var direction: Vector2 = Vector2.LEFT
|
||||
|
||||
var _age: float = 0.0
|
||||
var _probe: RayCast2D = null
|
||||
|
||||
static var _cache: Dictionary = {}
|
||||
|
||||
|
||||
## 生成(并缓存)一个实心圆贴图
|
||||
static func circle_texture(r: int, color: Color) -> ImageTexture:
|
||||
var key := "%d|%s" % [r, color.to_html()]
|
||||
if _cache.has(key):
|
||||
return _cache[key]
|
||||
var size: int = r * 2 + 1
|
||||
var img := Image.create_empty(size, size, false, Image.FORMAT_RGBA8)
|
||||
img.fill(Color(0.0, 0.0, 0.0, 0.0))
|
||||
var limit := float(r * r) + float(r) * 0.6
|
||||
for y in size:
|
||||
for x in size:
|
||||
var dx := float(x - r)
|
||||
var dy := float(y - r)
|
||||
if dx * dx + dy * dy <= limit:
|
||||
img.set_pixel(x, y, color)
|
||||
var tex := ImageTexture.create_from_image(img)
|
||||
_cache[key] = tex
|
||||
return tex
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
add_to_group("bullet")
|
||||
var sprite := get_node_or_null("Sprite") as Sprite2D
|
||||
if sprite != null:
|
||||
sprite.texture = circle_texture(radius, bullet_color)
|
||||
var hit := get_node_or_null("HitBox") as CollisionShape2D
|
||||
if hit != null and hit.shape is CircleShape2D:
|
||||
var circle := (hit.shape as CircleShape2D).duplicate() as CircleShape2D
|
||||
circle.radius = float(radius)
|
||||
hit.shape = circle
|
||||
_probe = get_node_or_null("Probe") as RayCast2D
|
||||
if _probe != null:
|
||||
_probe.enabled = stop_on_obstacle
|
||||
body_entered.connect(_on_body_entered)
|
||||
|
||||
|
||||
func launch(dir: Vector2, spd: float = -1.0) -> void:
|
||||
direction = dir.normalized()
|
||||
if spd > 0.0:
|
||||
speed = spd
|
||||
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
_age += delta
|
||||
if _age >= lifetime or global_position.y > despawn_y:
|
||||
queue_free()
|
||||
return
|
||||
|
||||
var step := direction * speed * delta
|
||||
if stop_on_obstacle and _probe != null:
|
||||
_probe.target_position = step * 1.5
|
||||
_probe.force_raycast_update()
|
||||
if _probe.is_colliding():
|
||||
queue_free()
|
||||
return
|
||||
position += step
|
||||
|
||||
|
||||
func _on_body_entered(body: Node2D) -> void:
|
||||
if body.has_method("hurt"):
|
||||
body.hurt(damage)
|
||||
queue_free()
|
||||
@@ -0,0 +1 @@
|
||||
uid://c4v4jls42gsyk
|
||||
@@ -0,0 +1,142 @@
|
||||
extends Node2D
|
||||
|
||||
## 静态弹幕障碍:以自己为圆心,一圈一圈地摆上**固定不动、不会发射**的子弹。
|
||||
##
|
||||
## 两种形态:
|
||||
## - solid = true :实心障碍,挡路、能踩上去(注意:会连小怪一起挡住)
|
||||
## - solid = false:可以穿透,只做伤害判定 —— 配合 damage > 0 就是普通弹幕
|
||||
##
|
||||
## 落在实心地砖里、或跑出关卡范围的子弹会自动跳过。
|
||||
|
||||
const BULLET_SCRIPT := preload("res://scripts/bullet.gd")
|
||||
|
||||
@export var enabled: bool = true
|
||||
## 每一圈的半径(单位:格)。默认 3 格、6 格、9 格
|
||||
@export var radii_cells: Array[int] = [3, 6, 9]
|
||||
## 每圈摆几颗
|
||||
@export var per_ring: int = 20
|
||||
## 一格多少像素(图块是 18)
|
||||
@export var cell_size: float = 18.0
|
||||
## 起始角度偏移(度),用来微调子弹摆在哪个方向
|
||||
@export var angle_offset_deg: float = 0.0
|
||||
## 子弹半径
|
||||
@export var bullet_radius: int = 3
|
||||
@export var bullet_color: Color = Color(1.0, 0.45, 0.85)
|
||||
## 实心障碍:挡路、能踩上去。关掉的话就是可以穿透的纯弹幕
|
||||
@export var solid: bool = false
|
||||
## 碰到扣几颗心。0 = 不扣血
|
||||
@export var damage: int = 1
|
||||
## 超出这个范围的子弹不生成(默认整个关卡 468x270)
|
||||
@export var bounds: Rect2 = Rect2(0, 0, 468, 270)
|
||||
## 最多铺几圈
|
||||
@export var max_rings: int = 3
|
||||
## 跳过埋在地砖里的子弹
|
||||
@export var skip_solid_ground: bool = true
|
||||
|
||||
var made: int = 0
|
||||
var skipped_out: int = 0
|
||||
var skipped_ground: int = 0
|
||||
|
||||
var _hurt_areas: Array = []
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
if not enabled:
|
||||
return
|
||||
# 等一帧,确保 TileMapLayer 都已经就绪
|
||||
_build.call_deferred()
|
||||
|
||||
|
||||
func _build() -> void:
|
||||
var layers := _tile_layers()
|
||||
var tex := BULLET_SCRIPT.circle_texture(bullet_radius, bullet_color)
|
||||
made = 0
|
||||
skipped_out = 0
|
||||
skipped_ground = 0
|
||||
_hurt_areas.clear()
|
||||
for i in mini(radii_cells.size(), max_rings):
|
||||
var radius: float = float(radii_cells[i]) * cell_size
|
||||
for k in per_ring:
|
||||
var ang := deg_to_rad(angle_offset_deg + 360.0 * float(k) / float(per_ring))
|
||||
var pos := global_position + Vector2(cos(ang), sin(ang)) * radius
|
||||
if not bounds.has_point(pos):
|
||||
skipped_out += 1
|
||||
continue
|
||||
if skip_solid_ground and _in_solid(layers, pos):
|
||||
skipped_ground += 1
|
||||
continue
|
||||
_make(pos, tex)
|
||||
made += 1
|
||||
|
||||
|
||||
## 每帧检查一次:站在子弹里也会持续扣血
|
||||
## (不能只靠 body_entered —— 玩家本来就在子弹里的话不会触发)
|
||||
func _physics_process(_delta: float) -> void:
|
||||
if damage <= 0 or _hurt_areas.is_empty():
|
||||
return
|
||||
for area in _hurt_areas:
|
||||
if not is_instance_valid(area):
|
||||
continue
|
||||
for body in area.get_overlapping_bodies():
|
||||
if body.has_method("hurt"):
|
||||
body.hurt(damage)
|
||||
|
||||
|
||||
func _tile_layers() -> Array:
|
||||
var root: Node = owner if owner != null else get_tree().current_scene
|
||||
if root == null:
|
||||
return []
|
||||
return root.find_children("*", "TileMapLayer", true, false)
|
||||
|
||||
|
||||
## 这个点是不是埋在实心地砖里
|
||||
func _in_solid(layers: Array, pos: Vector2) -> bool:
|
||||
for l in layers:
|
||||
var cell: Vector2i = l.local_to_map(l.to_local(pos))
|
||||
var sid: int = l.get_cell_source_id(cell)
|
||||
if sid == -1:
|
||||
continue
|
||||
var source := l.tile_set.get_source(sid) as TileSetAtlasSource
|
||||
if source == null:
|
||||
continue
|
||||
var data: TileData = source.get_tile_data(l.get_cell_atlas_coords(cell), 0)
|
||||
if data != null and data.get_collision_polygons_count(0) > 0:
|
||||
return true
|
||||
return false
|
||||
|
||||
|
||||
func _make(pos: Vector2, tex: Texture2D) -> void:
|
||||
var body := StaticBody2D.new()
|
||||
if solid:
|
||||
body.collision_layer = 1
|
||||
body.collision_mask = 1
|
||||
else:
|
||||
# 不实心:谁都挡不住,只靠下面的伤害区域起作用
|
||||
body.collision_layer = 0
|
||||
body.collision_mask = 0
|
||||
add_child(body)
|
||||
body.global_position = pos
|
||||
|
||||
var sprite := Sprite2D.new()
|
||||
sprite.texture = tex
|
||||
sprite.texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST
|
||||
body.add_child(sprite)
|
||||
|
||||
if solid:
|
||||
var shape := CollisionShape2D.new()
|
||||
var circle := CircleShape2D.new()
|
||||
circle.radius = float(bullet_radius)
|
||||
shape.shape = circle
|
||||
body.add_child(shape)
|
||||
|
||||
if damage > 0:
|
||||
var area := Area2D.new()
|
||||
area.collision_layer = 4
|
||||
area.collision_mask = 2
|
||||
var hit := CollisionShape2D.new()
|
||||
var circle2 := CircleShape2D.new()
|
||||
circle2.radius = float(bullet_radius) + 1.0
|
||||
hit.shape = circle2
|
||||
area.add_child(hit)
|
||||
body.add_child(area)
|
||||
_hurt_areas.append(area)
|
||||
@@ -0,0 +1 @@
|
||||
uid://c751srku7fi1h
|
||||
@@ -0,0 +1,64 @@
|
||||
extends Node2D
|
||||
|
||||
## 子弹雨:从天上随机横坐标往下落子弹,密度可以调。
|
||||
##
|
||||
## 落下来的子弹**不会被任何东西挡住**(bullet 的 stop_on_obstacle 默认关掉),
|
||||
## 会一直穿到关卡底下才回收。
|
||||
|
||||
const BULLET := preload("res://scenes/prefabs/enemies/bullet.tscn")
|
||||
|
||||
@export var enabled: bool = true
|
||||
## 平均多少秒落一颗(数值越大越稀疏)
|
||||
@export var interval: float = 0.2
|
||||
## 间隔随机浮动范围(0 = 完全固定节奏)
|
||||
@export var interval_jitter: float = 0.12
|
||||
## 开场后第一次落下的延迟
|
||||
@export var start_delay: float = 1.0
|
||||
## 生成高度(相对自己的 y,负数 = 从屏幕上方外面)
|
||||
@export var spawn_y: float = -30.0
|
||||
## 水平撒落范围:以自己的 x 为中心,左右各一半
|
||||
@export var span: float = 468.0
|
||||
## 下落速度
|
||||
@export var fall_speed: float = 70.0
|
||||
@export var damage: int = 1
|
||||
@export var bullet_color: Color = Color(0.55, 0.8, 1.0)
|
||||
## 固定随机种子(0 = 每次运行都不同)
|
||||
@export var random_seed: int = 0
|
||||
|
||||
var _timer: float = 0.0
|
||||
var _rng := RandomNumberGenerator.new()
|
||||
var dropped: int = 0
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
add_to_group("bullet_rain")
|
||||
if random_seed != 0:
|
||||
_rng.seed = random_seed
|
||||
else:
|
||||
_rng.randomize()
|
||||
_timer = start_delay
|
||||
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
if not enabled:
|
||||
return
|
||||
_timer -= delta
|
||||
if _timer > 0.0:
|
||||
return
|
||||
_timer = maxf(interval + _rng.randf_range(-interval_jitter, interval_jitter), 0.05)
|
||||
drop()
|
||||
|
||||
|
||||
func drop() -> void:
|
||||
var bullet := BULLET.instantiate()
|
||||
# 这几个属性必须在 add_child 之前设好
|
||||
bullet.bullet_color = bullet_color
|
||||
bullet.speed = fall_speed
|
||||
bullet.damage = damage
|
||||
bullet.stop_on_obstacle = false
|
||||
get_parent().add_child(bullet)
|
||||
bullet.global_position = Vector2(
|
||||
global_position.x + _rng.randf_range(-span * 0.5, span * 0.5),
|
||||
global_position.y + spawn_y)
|
||||
bullet.launch(Vector2(0.0, 1.0), fall_speed)
|
||||
dropped += 1
|
||||
@@ -0,0 +1 @@
|
||||
uid://dbpe6r76gao3w
|
||||
@@ -0,0 +1,111 @@
|
||||
extends CanvasLayer
|
||||
|
||||
## 「房★主★有★神★器★」:把两个调试功能(飞行 / 跳关)藏在一个彩蛋按钮里。
|
||||
##
|
||||
## 平时屏幕上只有右上角一个小小的「房★主★有★神★器★」按钮,
|
||||
## 点一下才弹出面板,里面是飞行开关和跳关按钮。
|
||||
## 面板打开时键盘 1/2/3 也能跳关,Esc 或再点一次按钮关闭。
|
||||
## 正式版里也能用(这是刻意留的彩蛋,不是调试残留)。
|
||||
|
||||
@export var levels: Array[String] = [
|
||||
"res://scenes/main.tscn",
|
||||
"res://scenes/level2.tscn",
|
||||
"res://scenes/level3.tscn",
|
||||
]
|
||||
## 是否显示那个彩蛋按钮(关掉的话就只能靠别的方式打开面板了)
|
||||
@export var show_button: bool = true
|
||||
|
||||
var _panel: Control = null
|
||||
var _open_button: Button = null
|
||||
var _fly_button: Button = null
|
||||
var _player: Node = null
|
||||
var _open: bool = false
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
visible = true
|
||||
_panel = get_node_or_null("Panel")
|
||||
_open_button = get_node_or_null("OpenButton")
|
||||
_fly_button = get_node_or_null("Panel/VBox/FlyButton")
|
||||
|
||||
if _open_button != null:
|
||||
_open_button.visible = show_button
|
||||
_open_button.pressed.connect(toggle_panel)
|
||||
|
||||
var close := get_node_or_null("Panel/VBox/CloseButton")
|
||||
if close != null:
|
||||
close.pressed.connect(toggle_panel)
|
||||
|
||||
if _fly_button != null:
|
||||
_fly_button.pressed.connect(toggle_fly)
|
||||
|
||||
var row := get_node_or_null("Panel/VBox/Row")
|
||||
if row != null:
|
||||
var index := 1
|
||||
for path in levels:
|
||||
var btn := Button.new()
|
||||
btn.text = str(index)
|
||||
btn.custom_minimum_size = Vector2(26.0, 24.0)
|
||||
btn.focus_mode = Control.FOCUS_NONE
|
||||
btn.add_theme_font_size_override("font_size", 12)
|
||||
btn.pressed.connect(jump_to.bind(path))
|
||||
row.add_child(btn)
|
||||
index += 1
|
||||
|
||||
if _panel != null:
|
||||
_panel.visible = false
|
||||
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
if _fly_button == null:
|
||||
return
|
||||
if _player == null or not is_instance_valid(_player):
|
||||
_player = get_tree().get_first_node_in_group("player")
|
||||
if _player == null:
|
||||
_fly_button.text = "飞行(F)"
|
||||
return
|
||||
_fly_button.text = "飞行:开(F)" if bool(_player.flying) else "飞行:关(F)"
|
||||
|
||||
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if not _open:
|
||||
return
|
||||
var key := event as InputEventKey
|
||||
if key == null or not key.pressed or key.echo:
|
||||
return
|
||||
if key.physical_keycode == KEY_ESCAPE:
|
||||
toggle_panel()
|
||||
return
|
||||
var n := 0
|
||||
match key.physical_keycode:
|
||||
KEY_1:
|
||||
n = 1
|
||||
KEY_2:
|
||||
n = 2
|
||||
KEY_3:
|
||||
n = 3
|
||||
KEY_4:
|
||||
n = 4
|
||||
KEY_5:
|
||||
n = 5
|
||||
if n >= 1 and n <= levels.size():
|
||||
jump_to(levels[n - 1])
|
||||
|
||||
|
||||
func toggle_panel() -> void:
|
||||
_open = not _open
|
||||
if _panel != null:
|
||||
_panel.visible = _open
|
||||
|
||||
|
||||
func toggle_fly() -> void:
|
||||
if _player == null or not is_instance_valid(_player):
|
||||
_player = get_tree().get_first_node_in_group("player")
|
||||
if _player == null or not _player.has_method("set_flying"):
|
||||
return
|
||||
_player.set_flying(not bool(_player.flying))
|
||||
|
||||
|
||||
func jump_to(path: String) -> void:
|
||||
get_tree().paused = false
|
||||
get_tree().change_scene_to_file(path)
|
||||
@@ -0,0 +1 @@
|
||||
uid://bexl5365w3qgq
|
||||
@@ -0,0 +1,90 @@
|
||||
extends Area2D
|
||||
|
||||
## 激光。两种模式:
|
||||
## - always_on = true(默认):**固定障碍** —— 一直亮着,碰到就扣血,只能绕开或用钥匙传送穿过去
|
||||
## - always_on = false:循环「蓄力闪烁 -> 发射 -> 熄灭」,需要卡时间通过
|
||||
## 光束从自己的原点沿 +X 方向伸出,想改朝向就转节点本身。
|
||||
|
||||
enum State { WAIT, WARMUP, FIRING }
|
||||
|
||||
## 固定障碍模式(一直亮着)
|
||||
@export var always_on: bool = true
|
||||
@export var length: float = 90.0
|
||||
@export var thickness: float = 6.0
|
||||
@export var damage: int = 1
|
||||
## 蓄力(闪烁警告)时长,只有循环模式用
|
||||
@export var warmup: float = 0.8
|
||||
## 发射持续时长,只有循环模式用
|
||||
@export var fire_time: float = 0.35
|
||||
## 两次发射之间的间隔,只有循环模式用
|
||||
@export var cooldown: float = 1.8
|
||||
## 开场后第一次发射前的延迟,只有循环模式用
|
||||
@export var start_delay: float = 1.0
|
||||
@export var laser_color: Color = Color(1.0, 0.25, 0.25)
|
||||
@export var warn_color: Color = Color(1.0, 0.8, 0.4)
|
||||
|
||||
var _state: int = State.WAIT
|
||||
var _timer: float = 0.0
|
||||
var _first: bool = true
|
||||
var _beam: Polygon2D = null
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
add_to_group("hazard")
|
||||
_beam = get_node_or_null("Beam") as Polygon2D
|
||||
var half := thickness * 0.5
|
||||
if _beam != null:
|
||||
_beam.polygon = PackedVector2Array([
|
||||
Vector2(0.0, -half), Vector2(length, -half),
|
||||
Vector2(length, half), Vector2(0.0, half)])
|
||||
_beam.color = laser_color
|
||||
_beam.visible = always_on
|
||||
var hit := get_node_or_null("HitBox") as CollisionShape2D
|
||||
if hit != null:
|
||||
var rect := RectangleShape2D.new()
|
||||
rect.size = Vector2(length, thickness)
|
||||
hit.shape = rect
|
||||
hit.position = Vector2(length * 0.5, 0.0)
|
||||
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
if always_on:
|
||||
if _beam != null:
|
||||
_beam.visible = true
|
||||
_beam.color = laser_color
|
||||
_hurt_overlaps()
|
||||
return
|
||||
|
||||
_timer += delta
|
||||
match _state:
|
||||
State.WAIT:
|
||||
var wait: float = start_delay if _first else cooldown
|
||||
if _timer >= wait:
|
||||
_first = false
|
||||
_state = State.WARMUP
|
||||
_timer = 0.0
|
||||
State.WARMUP:
|
||||
if _beam != null:
|
||||
_beam.color = warn_color
|
||||
_beam.visible = fmod(_timer, 0.16) < 0.08
|
||||
if _timer >= warmup:
|
||||
_state = State.FIRING
|
||||
_timer = 0.0
|
||||
if _beam != null:
|
||||
_beam.color = laser_color
|
||||
_beam.visible = true
|
||||
State.FIRING:
|
||||
_hurt_overlaps()
|
||||
if _timer >= fire_time:
|
||||
_state = State.WAIT
|
||||
_timer = 0.0
|
||||
if _beam != null:
|
||||
_beam.visible = false
|
||||
|
||||
|
||||
## 每帧检查压在光柱里的东西(不能只靠 body_entered,
|
||||
## 因为玩家可能本来就在光柱里,那样不会触发 entered)
|
||||
func _hurt_overlaps() -> void:
|
||||
for body in get_overlapping_bodies():
|
||||
if body.has_method("hurt"):
|
||||
body.hurt(damage)
|
||||
@@ -0,0 +1 @@
|
||||
uid://de3i3dmyi8bjw
|
||||
@@ -357,7 +357,8 @@ func _build_throw_visuals() -> void:
|
||||
# ---------------------------------------------------------------- 测试用飞行
|
||||
|
||||
func fly_available() -> bool:
|
||||
return debug_fly and OS.is_debug_build()
|
||||
# 这是藏在「房★主★有★神★器★」面板里的隐藏技能,正式版里也能用
|
||||
return debug_fly
|
||||
|
||||
|
||||
func set_flying(on: bool) -> void:
|
||||
@@ -368,10 +369,13 @@ func set_flying(on: bool) -> void:
|
||||
|
||||
|
||||
func handle_fly_movement() -> void:
|
||||
# get_axis(负方向, 正方向),屏幕坐标里 y 向下为正,所以空格(跳跃)要放在负方向
|
||||
# 和以前一样:空格(跳跃键)上升、S 下降。方向键上下也顺便能用
|
||||
var vertical := Input.get_axis("jump", "squat")
|
||||
if is_zero_approx(vertical):
|
||||
vertical = Input.get_axis("ui_up", "ui_down")
|
||||
var direction := Vector2(
|
||||
Input.get_axis("move_left", "move_right"),
|
||||
Input.get_axis("jump", "squat")
|
||||
vertical
|
||||
)
|
||||
if direction == Vector2.ZERO:
|
||||
velocity = Vector2.ZERO
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
extends CharacterBody2D
|
||||
|
||||
## 小怪:只在平台上左右巡逻,**不发射任何东西**,也**打不死**。
|
||||
## 作用纯粹是挡路 + 碰到扣血,逼玩家走位。
|
||||
## 弹幕交给专门的「弹幕源」节点负责。
|
||||
|
||||
@export_category("巡逻")
|
||||
@export var speed: float = 28.0
|
||||
## 巡逻方向:-1 向左,1 向右
|
||||
@export var start_direction: int = -1
|
||||
## 掉头后的冷却时间:防止贴着墙时每帧都掉头、结果原地抖动
|
||||
@export var turn_cooldown: float = 0.25
|
||||
## 速度设成 0 就变成待在原地不动的障碍
|
||||
@export var damage: int = 1
|
||||
|
||||
var direction: int = -1
|
||||
|
||||
var _turn_timer: float = 0.0
|
||||
|
||||
@onready var sprite: Sprite2D = $Sprite
|
||||
@onready var floor_probe: RayCast2D = $FloorProbe
|
||||
@onready var touch_area: Area2D = $TouchArea
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
add_to_group("enemy")
|
||||
direction = -1 if start_direction < 0 else 1
|
||||
_apply_direction()
|
||||
touch_area.body_entered.connect(_on_touch)
|
||||
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
if _turn_timer > 0.0:
|
||||
_turn_timer -= delta
|
||||
|
||||
if not is_on_floor():
|
||||
velocity += get_gravity() * delta
|
||||
velocity.x = float(direction) * speed
|
||||
|
||||
# 撞到墙 或 前方脚下没有地板 -> 掉头(带冷却,掉头后先走一段再说)
|
||||
if _turn_timer <= 0.0:
|
||||
if is_on_wall() or (is_on_floor() and not floor_probe.is_colliding()):
|
||||
direction = -direction
|
||||
_turn_timer = turn_cooldown
|
||||
_apply_direction()
|
||||
|
||||
move_and_slide()
|
||||
|
||||
|
||||
func _apply_direction() -> void:
|
||||
if sprite != null:
|
||||
sprite.flip_h = direction > 0
|
||||
if floor_probe != null:
|
||||
floor_probe.position.x = float(direction) * 6.0
|
||||
|
||||
|
||||
func _on_touch(body: Node2D) -> void:
|
||||
# 打不死:踩上去也一样只是扣血
|
||||
if body.has_method("hurt"):
|
||||
body.hurt(damage)
|
||||
@@ -0,0 +1 @@
|
||||
uid://b0lnhlnkjhxug
|
||||
Reference in New Issue
Block a user