From defdf202e6b2a9e3be6b587083865e0971dcf275 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?sijcdu=E7=9A=84=E6=B8=B8=E6=88=8F?= Date: Wed, 7 Oct 2026 22:38:07 +0800 Subject: [PATCH] Bullet field: pierce-through and damaging, rings spaced 3 cells apart Solid bullets were blocking the patrolling enemies, so the field now defaults to solid = false: each bullet is a plain StaticBody2D with no collision layer, plus an Area2D that only detects the player, so nothing is physically obstructed while contact still costs a heart. Ring radii changed from [5, 10, 15] to [3, 6, 9]. Damage is now applied every frame to whatever is overlapping, not only on body_entered, so standing inside a bullet keeps hurting instead of only the first touch. Also picks up the editor change that removed Walker_03. --- scenes/level2.tscn | 6 +---- scenes/main.tscn | 15 +++++-------- scripts/bullet_field.gd | 44 +++++++++++++++++++++++++------------ scripts/bullet_field.gd.uid | 1 + 4 files changed, 37 insertions(+), 29 deletions(-) create mode 100644 scripts/bullet_field.gd.uid diff --git a/scenes/level2.tscn b/scenes/level2.tscn index 3ab348a..2f77426 100644 --- a/scenes/level2.tscn +++ b/scenes/level2.tscn @@ -217,10 +217,6 @@ position = Vector2(216, 216) position = Vector2(306, 216) start_direction = 1 -[node name="Walker_03" parent="Level/PrefabInstances/Enemies" unique_id=1711052130 instance=ExtResource("18_walker")] -position = Vector2(90, 198) -start_direction = 1 - [node name="Laser_01" parent="Level/PrefabInstances/Enemies" unique_id=1298565970 instance=ExtResource("19_laser")] position = Vector2(187, 223) rotation = -1.5707964 @@ -249,7 +245,7 @@ rotation = -1.5707964 length = 108.0 start_delay = 2.4 -[node name="BulletField_01" parent="Level/PrefabInstances/Enemies" instance=ExtResource("20_field")] +[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] diff --git a/scenes/main.tscn b/scenes/main.tscn index bfe28c0..4f55894 100644 --- a/scenes/main.tscn +++ b/scenes/main.tscn @@ -24,7 +24,7 @@ [node name="DeathScreen" parent="." unique_id=1952687359 instance=ExtResource("22_death")] -[node name="LevelClear" parent="." instance=ExtResource("26_clear")] +[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) diff --git a/scripts/bullet_field.gd b/scripts/bullet_field.gd index 51ddc51..9f5e4f1 100644 --- a/scripts/bullet_field.gd +++ b/scripts/bullet_field.gd @@ -1,14 +1,18 @@ extends Node2D ## 静态弹幕障碍:以自己为圆心,一圈一圈地摆上**固定不动、不会发射**的子弹。 -## 默认只是纯障碍(实心,撞得到、能踩上去),把 damage 调大于 0 就变成碰到扣血。 -## 落在实心地砖里的子弹会自动跳过(不然会埋在地里)。 +## +## 两种形态: +## - solid = true :实心障碍,挡路、能踩上去(注意:会连小怪一起挡住) +## - solid = false:可以穿透,只做伤害判定 —— 配合 damage > 0 就是普通弹幕 +## +## 落在实心地砖里、或跑出关卡范围的子弹会自动跳过。 const BULLET_SCRIPT := preload("res://scripts/bullet.gd") @export var enabled: bool = true -## 每一圈的半径(单位:格)。默认 5 格、10 格、15 格 -@export var radii_cells: Array[int] = [5, 10, 15] +## 每一圈的半径(单位:格)。默认 3 格、6 格、9 格 +@export var radii_cells: Array[int] = [3, 6, 9] ## 每圈摆几颗 @export var per_ring: int = 20 ## 一格多少像素(图块是 18) @@ -18,10 +22,10 @@ const BULLET_SCRIPT := preload("res://scripts/bullet.gd") ## 子弹半径 @export var bullet_radius: int = 3 @export var bullet_color: Color = Color(1.0, 0.45, 0.85) -## 实心障碍:玩家撞得到、也能踩上去 -@export var solid: bool = true -## 碰到扣几颗心。0 = 只是障碍不扣血 -@export var damage: int = 0 +## 实心障碍:挡路、能踩上去。关掉的话就是可以穿透的纯弹幕 +@export var solid: bool = false +## 碰到扣几颗心。0 = 不扣血 +@export var damage: int = 1 ## 超出这个范围的子弹不生成(默认整个关卡 468x270) @export var bounds: Rect2 = Rect2(0, 0, 468, 270) ## 最多铺几圈 @@ -33,6 +37,8 @@ var made: int = 0 var skipped_out: int = 0 var skipped_ground: int = 0 +var _hurt_areas: Array = [] + func _ready() -> void: if not enabled: @@ -47,6 +53,7 @@ func _build() -> void: 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: @@ -62,6 +69,19 @@ func _build() -> void: 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: @@ -91,6 +111,7 @@ func _make(pos: Vector2, tex: Texture2D) -> void: body.collision_layer = 1 body.collision_mask = 1 else: + # 不实心:谁都挡不住,只靠下面的伤害区域起作用 body.collision_layer = 0 body.collision_mask = 0 add_child(body) @@ -118,9 +139,4 @@ func _make(pos: Vector2, tex: Texture2D) -> void: hit.shape = circle2 area.add_child(hit) body.add_child(area) - area.body_entered.connect(_on_hit) - - -func _on_hit(body: Node2D) -> void: - if body.has_method("hurt"): - body.hurt(damage) + _hurt_areas.append(area) diff --git a/scripts/bullet_field.gd.uid b/scripts/bullet_field.gd.uid new file mode 100644 index 0000000..a584aee --- /dev/null +++ b/scripts/bullet_field.gd.uid @@ -0,0 +1 @@ +uid://c751srku7fi1h