From e47390333f9ee390880e8097be677f5b93a3c3b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=A8=E8=90=BD=E5=9F=BA=E5=9B=B4=E8=99=BE?= <3161880837@qq.com> Date: Sun, 16 Nov 2025 16:01:03 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E5=AD=90=E5=BC=B9):=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E7=8B=90=E7=8B=B8=E7=88=AA=E5=AD=90=E5=BC=B9=E5=8F=8A=E5=85=B6?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加FoxZhua子弹类型,包含追踪功能 修改FireScan子弹伤害计算方式为基于距离百分比 扩展BulletBase添加原始伤害和距离计算功能 更新Chick角色使用新子弹和调整攻击逻辑 调整Wave生成逻辑添加Boss检测功能 优化FirePot粒子效果和参数 --- components/Bullets/FireScan.tscn | 8 +- components/Bullets/FoxZhua.tscn | 223 ++++++++++++++++++++ components/Characters/Chick.tscn | 21 +- components/Effects/FirePot.tscn | 36 ++-- resources/bullets/fox-zhua/zhua.webp | Bin 0 -> 246 bytes resources/bullets/fox-zhua/zhua.webp.import | 40 ++++ scripts/Contents/AIPresets/Bullet.gd | 2 + scripts/Contents/Bullets/FireScan.gd | 5 +- scripts/Contents/Bullets/FoxZhua.gd | 7 + scripts/Contents/Bullets/FoxZhua.gd.uid | 1 + scripts/Contents/Characters/Chick.gd | 12 +- scripts/Contents/Wave.gd | 12 +- scripts/Statemachine/BulletBase.gd | 6 + 13 files changed, 331 insertions(+), 42 deletions(-) create mode 100644 components/Bullets/FoxZhua.tscn create mode 100644 resources/bullets/fox-zhua/zhua.webp create mode 100644 resources/bullets/fox-zhua/zhua.webp.import create mode 100644 scripts/Contents/Bullets/FoxZhua.gd create mode 100644 scripts/Contents/Bullets/FoxZhua.gd.uid diff --git a/components/Bullets/FireScan.tscn b/components/Bullets/FireScan.tscn index dc3873a..6677fee 100644 --- a/components/Bullets/FireScan.tscn +++ b/components/Bullets/FireScan.tscn @@ -1,15 +1,17 @@ [gd_scene load_steps=4 format=3 uid="uid://db2cbgyyjpydp"] [ext_resource type="PackedScene" uid="uid://crtdkysmnkith" path="res://components/Abstracts/BulletBase.tscn" id="1_cqre5"] -[ext_resource type="Script" path="res://scripts/Contents/Bullets/FireScan.gd" id="2_qprdp"] +[ext_resource type="Script" uid="uid://dlg4g03ppdd2x" path="res://scripts/Contents/Bullets/FireScan.gd" id="2_qprdp"] [sub_resource type="RectangleShape2D" id="RectangleShape2D_4qcsn"] -size = Vector2(50, 50) +size = Vector2(10, 200) [node name="FireScan" instance=ExtResource("1_cqre5")] script = ExtResource("2_qprdp") displayName = "狱炎" -lifeDistance = 200.0 +speed = 15.0 +damage = 15.0 +lifeDistance = 500.0 [node name="hitbox" parent="." index="1"] shape = SubResource("RectangleShape2D_4qcsn") diff --git a/components/Bullets/FoxZhua.tscn b/components/Bullets/FoxZhua.tscn new file mode 100644 index 0000000..8c8920f --- /dev/null +++ b/components/Bullets/FoxZhua.tscn @@ -0,0 +1,223 @@ +[gd_scene load_steps=11 format=3 uid="uid://btqtch0v58e7h"] + +[ext_resource type="PackedScene" uid="uid://crtdkysmnkith" path="res://components/Abstracts/BulletBase.tscn" id="1_461id"] +[ext_resource type="Texture2D" uid="uid://ddvmfyk2g4r1m" path="res://resources/bullets/fox-zhua/zhua.webp" id="2_45k2a"] +[ext_resource type="Script" uid="uid://e2doeocb745a" path="res://scripts/Contents/Bullets/FoxZhua.gd" id="2_rl21b"] + +[sub_resource type="SpriteFrames" id="SpriteFrames_rl21b"] + +[sub_resource type="Animation" id="Animation_45k2a"] +length = 0.001 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath(".:scale") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Vector2(0.5, 0.5)] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath(".:modulate") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Color(1, 1, 1, 0)] +} +tracks/2/type = "value" +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/path = NodePath(".:rotation") +tracks/2/interp = 1 +tracks/2/loop_wrap = true +tracks/2/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [-0.7853982] +} +tracks/3/type = "value" +tracks/3/imported = false +tracks/3/enabled = true +tracks/3/path = NodePath("%hitbox:disabled") +tracks/3/interp = 1 +tracks/3/loop_wrap = true +tracks/3/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 1, +"values": [true] +} +tracks/4/type = "value" +tracks/4/imported = false +tracks/4/enabled = true +tracks/4/path = NodePath("hand:position") +tracks/4/interp = 1 +tracks/4/loop_wrap = true +tracks/4/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Vector2(50, 0)] +} +tracks/5/type = "value" +tracks/5/imported = false +tracks/5/enabled = true +tracks/5/path = NodePath("%texture/..:canTrace") +tracks/5/interp = 1 +tracks/5/loop_wrap = true +tracks/5/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 1, +"values": [true] +} + +[sub_resource type="Animation" id="Animation_oinqg"] +resource_name = "destroy" +length = 0.5 +step = 0.1 + +[sub_resource type="Animation" id="Animation_ynxlt"] +resource_name = "loop" +loop_mode = 1 +step = 0.1 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath(".:rotation") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 1), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [0.0, 6.28319] +} + +[sub_resource type="Animation" id="Animation_kmogx"] +resource_name = "spawn" +length = 2.0 +step = 0.05 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath(".:scale") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 0.3, 1.2, 1.4, 1.6, 2), +"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1), +"update": 0, +"values": [Vector2(0.5, 0.5), Vector2(1, 1), Vector2(1, 1), Vector2(3.5, 3.5), Vector2(3.5, 3.5), Vector2(0.5, 0.5)] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath(".:modulate") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0, 0.2, 1.6, 2), +"transitions": PackedFloat32Array(1, 1, 1, 1), +"update": 0, +"values": [Color(1, 1, 1, 0), Color(1, 1, 1, 1), Color(1, 1, 1, 1), Color(1, 1, 1, 0)] +} +tracks/2/type = "value" +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/path = NodePath(".:rotation") +tracks/2/interp = 1 +tracks/2/loop_wrap = true +tracks/2/keys = { +"times": PackedFloat32Array(0, 1.4, 1.6), +"transitions": PackedFloat32Array(1, 1, 1), +"update": 0, +"values": [-0.7853982, -0.7853982, 0.7853981633974483] +} +tracks/3/type = "value" +tracks/3/imported = false +tracks/3/enabled = true +tracks/3/path = NodePath("%hitbox:disabled") +tracks/3/interp = 1 +tracks/3/loop_wrap = true +tracks/3/keys = { +"times": PackedFloat32Array(0, 1.4, 1.6, 2), +"transitions": PackedFloat32Array(1, 1, 1, 1), +"update": 1, +"values": [true, false, false, true] +} +tracks/4/type = "value" +tracks/4/imported = false +tracks/4/enabled = true +tracks/4/path = NodePath("hand:position") +tracks/4/interp = 1 +tracks/4/loop_wrap = true +tracks/4/keys = { +"times": PackedFloat32Array(0, 0.2), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [Vector2(50, 0), Vector2(100, 50)] +} +tracks/5/type = "value" +tracks/5/imported = false +tracks/5/enabled = true +tracks/5/path = NodePath("%texture/..:canTrace") +tracks/5/interp = 1 +tracks/5/loop_wrap = true +tracks/5/keys = { +"times": PackedFloat32Array(0, 1), +"transitions": PackedFloat32Array(1, 1), +"update": 1, +"values": [true, false] +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_45k2a"] +_data = { +&"RESET": SubResource("Animation_45k2a"), +&"destroy": SubResource("Animation_oinqg"), +&"loop": SubResource("Animation_ynxlt"), +&"spawn": SubResource("Animation_kmogx") +} + +[sub_resource type="CapsuleShape2D" id="CapsuleShape2D_45k2a"] +radius = 174.0 +height = 524.0 + +[node name="FoxZhua" instance=ExtResource("1_461id")] +script = ExtResource("2_rl21b") +canTrace = true +displayName = "爪" +damage = 15.0 +penerate = 1.0 +autoSpawnAnimation = true +freeAfterSpawn = true + +[node name="texture" parent="." index="0"] +modulate = Color(1, 1, 1, 0) +rotation = -0.7853982 +scale = Vector2(0.5, 0.5) +sprite_frames = SubResource("SpriteFrames_rl21b") + +[node name="animator" parent="texture" index="0"] +libraries = { +&"": SubResource("AnimationLibrary_45k2a") +} + +[node name="hand" type="Sprite2D" parent="texture" index="1"] +position = Vector2(50, 0) +texture = ExtResource("2_45k2a") + +[node name="hitbox" parent="." index="1"] +position = Vector2(267, -1) +rotation = 1.5707964 +shape = SubResource("CapsuleShape2D_45k2a") +disabled = true diff --git a/components/Characters/Chick.tscn b/components/Characters/Chick.tscn index ce48de3..6dc3283 100644 --- a/components/Characters/Chick.tscn +++ b/components/Characters/Chick.tscn @@ -43,15 +43,15 @@ animations = [{ }] [sub_resource type="RectangleShape2D" id="RectangleShape2D_x766l"] -size = Vector2(57, 62) +size = Vector2(57, 114) [sub_resource type="CircleShape2D" id="CircleShape2D_w0sit"] -radius = 37.054016 +radius = 61.03278 [node name="Chick" instance=ExtResource("1_goqmy")] script = ExtResource("2_r6bub") isBoss = true -displayName = "小鸡" +displayName = "狐狸" drops = Array[int]([0, 1]) dropCounts = Array[Vector2]([Vector2(10, 30), Vector2(15, 50)]) appleCount = Vector2i(2, 4) @@ -78,28 +78,31 @@ sprite_frames = SubResource("SpriteFrames_xji3d") animation = &"walk" [node name="staticAnimation" parent="texture" index="1"] -position = Vector2(0, -39) -scale = Vector2(0.42847547, 0.42847547) +position = Vector2(0, -94) +scale = Vector2(0.72807497, 0.72807497) sprite_frames = SubResource("SpriteFrames_x766l") animation = &"idle" [node name="hitbox" parent="texture/hurtbox" index="0"] -position = Vector2(-0.5, -51) +position = Vector2(-0.5, -113) shape = SubResource("RectangleShape2D_x766l") [node name="hitbox2" type="CollisionShape2D" parent="texture/hurtbox" index="1"] -position = Vector2(73, -76) +position = Vector2(117, -149) shape = SubResource("CircleShape2D_w0sit") [node name="normal" type="Node2D" parent="texture/weapons" index="0"] -position = Vector2(79, -63) +position = Vector2(134, -130) [node name="firepot" parent="texture/weapons/normal" index="0" instance=ExtResource("6_kvx3n")] unique_name_in_owner = true +[node name="foot" type="Node2D" parent="texture/weapons" index="1"] +position = Vector2(56, 28) + [node name="trailParticle" parent="texture" index="7"] position = Vector2(1, -50) [node name="statebar" parent="." index="4" node_paths=PackedStringArray("entity")] -position = Vector2(0, -167) +position = Vector2(0, -294) entity = NodePath("..") diff --git a/components/Effects/FirePot.tscn b/components/Effects/FirePot.tscn index 31171ca..bf710b0 100644 --- a/components/Effects/FirePot.tscn +++ b/components/Effects/FirePot.tscn @@ -1,30 +1,23 @@ -[gd_scene load_steps=13 format=3 uid="uid://dny25qkcvtaa2"] +[gd_scene load_steps=11 format=3 uid="uid://dny25qkcvtaa2"] [ext_resource type="PackedScene" uid="uid://bcvuuy2m0pke0" path="res://components/Abstracts/EffectBase.tscn" id="1_k7ukc"] [sub_resource type="Curve" id="Curve_ohc88"] -_data = [Vector2(0, 1), 0.0, 0.0, 0, 0, Vector2(1, 0), 0.0, 0.0, 0, 0] -point_count = 2 +_data = [Vector2(0, 0), 0.0, 0.0, 0, 0, Vector2(0.2, 1), 0.0, 0.0, 0, 0, Vector2(0.5, 1), 0.0, 0.0, 0, 0, Vector2(1, 0), 0.0, 0.0, 0, 0] +point_count = 4 [sub_resource type="CurveTexture" id="CurveTexture_6awim"] curve = SubResource("Curve_ohc88") [sub_resource type="Gradient" id="Gradient_14cxb"] -colors = PackedColorArray(0.780392, 0.498039, 0, 1, 1, 0, 0, 1) +offsets = PackedFloat32Array(0.5, 1) +colors = PackedColorArray(1, 1, 1, 1, 0, 0.6366434, 1, 1) [sub_resource type="GradientTexture1D" id="GradientTexture1D_2p6rn"] gradient = SubResource("Gradient_14cxb") -[sub_resource type="Gradient" id="Gradient_g8be5"] -offsets = PackedFloat32Array(0, 0.5, 1) -colors = PackedColorArray(1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1) - -[sub_resource type="GradientTexture1D" id="GradientTexture1D_miml8"] -gradient = SubResource("Gradient_g8be5") - [sub_resource type="Curve" id="Curve_iaern"] -min_value = -200.0 -max_value = 200.0 +_limits = [-200.0, 200.0, 0.0, 1.0] _data = [Vector2(0, -200), 0.0, 0.0, 0, 0, Vector2(1, 200), 0.0, 0.0, 0, 0] point_count = 2 @@ -40,24 +33,27 @@ curve = SubResource("Curve_qy5ym") [sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_pah3d"] particle_flag_disable_z = true +emission_shape = 1 +emission_sphere_radius = 50.0 angle_min = 1.07288e-05 angle_max = 360.0 -spread = 15.0 +spread = 5.0 initial_velocity_min = 10.0 initial_velocity_max = 500.0 -gravity = Vector3(0, 0, 0) +gravity = Vector3(980, 0, 0) linear_accel_min = -2.23517e-06 linear_accel_max = -2.23517e-06 linear_accel_curve = SubResource("CurveTexture_1flsn") -scale_min = 2.0 -scale_max = 12.0 +scale_min = 4.0 +scale_max = 16.0 scale_over_velocity_curve = SubResource("CurveTexture_wcx7i") -color_ramp = SubResource("GradientTexture1D_miml8") color_initial_ramp = SubResource("GradientTexture1D_2p6rn") alpha_curve = SubResource("CurveTexture_6awim") [node name="FirePot" instance=ExtResource("1_k7ukc")] +metadata/_edit_vertical_guides_ = [808.0] -[node name="particles" parent="." index="0"] -amount = 50 +[node name="particles" parent="." index="1"] +amount = 100 +local_coords = true process_material = SubResource("ParticleProcessMaterial_pah3d") diff --git a/resources/bullets/fox-zhua/zhua.webp b/resources/bullets/fox-zhua/zhua.webp new file mode 100644 index 0000000000000000000000000000000000000000..7a7e5dce81c0032ba02bbf3574114247f499fc75 GIT binary patch literal 246 zcmVIB&~8`*Al^#G{aHr4+Jgh;l-Hbm}6_=0mPre31*AYX9-%b9rqi;B@kPq7?q>3)J0fW36Pxqy`b zR&M1&uuA5ZJM~fC+D3km_qL6_m#@z*_F8_sgT0nR?7f`Qd%1ysoZ}1m`4+g4vv83A w-GYG&cnK bool: + for wave in data: + if canSpawn(wave): + if wave.isBoss: + return true + return false +static func canSpawn(wave: Wave) -> bool: + return wave.from <= current and wave.to >= current and int(current - wave.from) % wave.per == 0 static func entityCountOf(wave: Wave) -> int: - if wave.from <= current and wave.to >= current and int(current - wave.from) % wave.per == 0: + if canSpawn(wave): if wave.isBoss: return 1 - else: + elif !hasBoss(): return randi_range(ceil(wave.minCount), floor(wave.maxCount * (1 + GameRule.entityCountBoostPerWave * current))) return 0 static func spawn() -> Array: diff --git a/scripts/Statemachine/BulletBase.gd b/scripts/Statemachine/BulletBase.gd index 2474777..199378a 100644 --- a/scripts/Statemachine/BulletBase.gd +++ b/scripts/Statemachine/BulletBase.gd @@ -30,9 +30,11 @@ var destroying: bool = false var isChildSplit: bool = false var isChildRefract: bool = false var initialSpeed: float = 0 +var originalDamage: float = 0 func _ready(): initialSpeed = speed + originalDamage = damage if launcher.isSummon(): launcherSummoned = launcher launcher = launcher.myMaster @@ -99,6 +101,10 @@ func fullPenerate(): return penerate + launcher.fields.get(FieldStore.Entity.PENERATE) + GameRule.penerateRateInfluenceByLuckValue * launcher.fields[FieldStore.Entity.LUCK_VALUE] func timeLived(): return WorldManager.getTime() - spawnInWhen +func distanceLived(): + return position.distance_to(spawnInWhere) +func lifeDistancePercent(): + return distanceLived() / lifeDistance func dotLoop(): if await applyDot(): await TickTool.until(func(): return !UIState.currentPanel)