From 2dd47a4f3ed304699b7e46d9d598355a717e110f 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: Sat, 18 Apr 2026 08:12:27 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E6=AD=A6=E5=99=A8=E7=B3=BB=E7=BB=9F):=20?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=AD=94=E6=B3=95=E5=AF=BC=E5=BC=B9=E6=AD=A6?= =?UTF-8?q?=E5=99=A8=E5=8F=8A=E9=85=8D=E5=A5=97=E5=AD=90=E5=BC=B9=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 实现魔法导弹武器系统,包括: 1. 新增HOLD_LOOP发射类型武器 2. 添加魔法导弹子弹类实现追踪和分裂逻辑 3. 修改武器基类支持循环攻击模式 4. 更新角色控制器支持新武器类型 5. 添加相关资源文件和配置 --- components/Bullets/MagicMissle.tscn | 65 ++++++++++++++++++++ components/Characters/Rooster.tscn | 10 +-- components/Weapons/MagicMissle.tscn | 20 +++--- resources/bullets/magic-missle/ninesols.png | Bin 4422 -> 6743 bytes scripts/Contents/Bullets/MagicMissle.gd | 34 ++++++++++ scripts/Contents/Bullets/MagicMissle.gd.uid | 1 + scripts/Contents/Characters/Rooster.gd | 22 ++++--- scripts/Contents/Weapons/MagicMissle.gd | 36 +++++++++++ scripts/Contents/Weapons/MagicMissle.gd.uid | 1 + scripts/Statemachine/BulletBase.gd | 4 +- scripts/Structs/Weapon.gd | 37 ++++++++--- 11 files changed, 196 insertions(+), 34 deletions(-) create mode 100644 components/Bullets/MagicMissle.tscn create mode 100644 scripts/Contents/Bullets/MagicMissle.gd create mode 100644 scripts/Contents/Bullets/MagicMissle.gd.uid create mode 100644 scripts/Contents/Weapons/MagicMissle.gd create mode 100644 scripts/Contents/Weapons/MagicMissle.gd.uid diff --git a/components/Bullets/MagicMissle.tscn b/components/Bullets/MagicMissle.tscn new file mode 100644 index 0000000..b550b51 --- /dev/null +++ b/components/Bullets/MagicMissle.tscn @@ -0,0 +1,65 @@ +[gd_scene format=3 uid="uid://db2jwaqphd1cx"] + +[ext_resource type="PackedScene" uid="uid://crtdkysmnkith" path="res://components/Abstracts/BulletBase.tscn" id="1_4sjx4"] +[ext_resource type="Script" uid="uid://b1y8r5xrhhso" path="res://scripts/Contents/Bullets/MagicMissle.gd" id="2_lrw10"] +[ext_resource type="Texture2D" uid="uid://bl1i26ovfpxwc" path="res://resources/bullets/magic-missle/tr.webp" id="2_ross6"] +[ext_resource type="Texture2D" uid="uid://drikpnrvqisb0" path="res://resources/bullets/magic-missle/ninesols.png" id="2_rugh7"] + +[sub_resource type="Curve" id="Curve_lrw10"] +_data = [Vector2(0, 0), 0.0, 0.0, 0, 0, Vector2(0.2, 1), 0.0, 0.0, 0, 0, Vector2(1, 0), 0.0, 0.0, 0, 0] +point_count = 3 + +[sub_resource type="CurveTexture" id="CurveTexture_3jny5"] +curve = SubResource("Curve_lrw10") + +[sub_resource type="Curve" id="Curve_grb5l"] +_data = [Vector2(0, 1), 0.0, 0.0, 0, 0, Vector2(1, 0), 0.0, 0.0, 0, 0] +point_count = 2 + +[sub_resource type="CurveTexture" id="CurveTexture_jigkj"] +curve = SubResource("Curve_grb5l") + +[sub_resource type="Curve" id="Curve_rugh7"] +_data = [Vector2(0, 0), 0.0, 0.0, 0, 0, Vector2(0.2, 1), 0.0, 0.0, 0, 0] +point_count = 2 + +[sub_resource type="CurveTexture" id="CurveTexture_lrw10"] +curve = SubResource("Curve_rugh7") + +[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_mgg76"] +particle_flag_disable_z = true +angle_min = 1.0728835e-05 +angle_max = 360.00003 +angle_curve = SubResource("CurveTexture_jigkj") +direction = Vector3(-1, 0, 0) +spread = 15.0 +initial_velocity_min = 100.0 +initial_velocity_max = 200.0 +gravity = Vector3(0, 0, 0) +scale_min = 0.5 +scale_max = 0.9 +scale_curve = SubResource("CurveTexture_lrw10") +alpha_curve = SubResource("CurveTexture_3jny5") + +[sub_resource type="CapsuleShape2D" id="CapsuleShape2D_rugh7"] +height = 76.0 + +[node name="MagicMissle" unique_id=5571707 instance=ExtResource("1_4sjx4")] +script = ExtResource("2_lrw10") +penerate = 1.0 +penerateDamageReduction = 0.1 + +[node name="static" type="Sprite2D" parent="texture" parent_id_path=PackedInt32Array(162977358) index="2" unique_id=1008850333] +texture = ExtResource("2_rugh7") + +[node name="trail" type="GPUParticles2D" parent="texture/static" index="0" unique_id=1403224943] +z_index = -1 +position = Vector2(-35, 1) +amount = 50 +texture = ExtResource("2_ross6") +visibility_rect = Rect2(-1000, -1000, 2000, 2000) +process_material = SubResource("ParticleProcessMaterial_mgg76") + +[node name="hitbox" parent="." index="1" unique_id=175349408] +rotation = 1.5707964 +shape = SubResource("CapsuleShape2D_rugh7") diff --git a/components/Characters/Rooster.tscn b/components/Characters/Rooster.tscn index 22c7646..b816c8c 100644 --- a/components/Characters/Rooster.tscn +++ b/components/Characters/Rooster.tscn @@ -2,11 +2,9 @@ [ext_resource type="PackedScene" uid="uid://cvogxi7mktumf" path="res://components/Abstracts/EntityBase.tscn" id="1_e5pl8"] [ext_resource type="Script" uid="uid://cthtupc6dtbav" path="res://scripts/Contents/Characters/Rooster.gd" id="2_oqdqd"] -[ext_resource type="PackedScene" uid="uid://c0n3igy4hucrg" path="res://components/Weapons/PurpleCrystal.tscn" id="3_joj4g"] +[ext_resource type="PackedScene" uid="uid://c6d23yqjhe0ju" path="res://components/Weapons/MagicMissle.tscn" id="3_da2ca"] [ext_resource type="AudioStream" uid="uid://cdrevrq7n6yqa" path="res://resources/sounds/effect/Boing.mp3" id="4_66s6c"] -[ext_resource type="PackedScene" uid="uid://cx7nogfnv7s8t" path="res://components/Weapons/Tree.tscn" id="4_jluqw"] [ext_resource type="AudioStream" uid="uid://benyec5bqni0b" path="res://resources/sounds/effect/Chomp.wav" id="4_k0yme"] -[ext_resource type="PackedScene" uid="uid://dyanyf044boxp" path="res://components/Weapons/Pipe.tscn" id="5_fkh3f"] [ext_resource type="AudioStream" uid="uid://dmxh3bpk8vyy5" path="res://resources/sounds/effect/Coin.mp3" id="5_xnbhq"] [ext_resource type="AudioStream" uid="uid://4wuuf1osk0yv" path="res://resources/sounds/effect/Low Boing.wav" id="6_m5px1"] [ext_resource type="Texture2D" uid="uid://fn8qx72clh38" path="res://resources/characters/cock/rooster-a.svg" id="8_da2ca"] @@ -103,13 +101,9 @@ process_material = SubResource("ParticleProcessMaterial_joj4g") [node name="weaponStore" parent="." index="2"] process_mode = 4 -[node name="PurpleCrystal" parent="weaponStore" index="0" unique_id=1478939386 instance=ExtResource("3_joj4g")] +[node name="MagicMissle" parent="weaponStore" index="0" unique_id=2085048785 instance=ExtResource("3_da2ca")] debugRebuild = false -[node name="Tree" parent="weaponStore" index="1" unique_id=185228402 instance=ExtResource("4_jluqw")] - -[node name="Pipe" parent="weaponStore" index="2" unique_id=946948425 instance=ExtResource("5_fkh3f")] - [node name="sprint" parent="sounds" index="0"] stream = ExtResource("4_66s6c") diff --git a/components/Weapons/MagicMissle.tscn b/components/Weapons/MagicMissle.tscn index 0ddb16e..356c687 100644 --- a/components/Weapons/MagicMissle.tscn +++ b/components/Weapons/MagicMissle.tscn @@ -2,13 +2,16 @@ [ext_resource type="PackedScene" uid="uid://ckq2cq6m23hq3" path="res://components/Abstracts/WeaponCardBase.tscn" id="1_c3bm3"] [ext_resource type="Texture2D" uid="uid://dce1da2qm24pb" path="res://resources/weapons/magic-missle.webp" id="2_3sdrm"] +[ext_resource type="Script" uid="uid://clec7nrtesipu" path="res://scripts/Contents/Weapons/MagicMissle.gd" id="2_r857c"] [node name="MagicMissle" unique_id=2085048785 instance=ExtResource("1_c3bm3")] +script = ExtResource("2_r857c") avatarTexture = ExtResource("2_3sdrm") displayName = "导弹法杖" +emitType = 3 store = { "G": 197392.0, -"atk": 14, +"atk": 10, "count": 3.0, "cursor-m": 100.0, "missle-m": 10.0, @@ -23,14 +26,15 @@ storeType = { "track": 0 } descriptionTemplate = "召唤1~$count枚[b]魔法导弹[/b],围绕鼠标指针做由鼠标指针提供向心力的圆周运动。 -鼠标指针质量:$cursor-m, -魔法导弹质量:$missle-m, -初始轨道半径:$track, +鼠标指针质量:$cursor-mkg, +魔法导弹质量:$missle-mkg, +初始轨道半径:$trackm, 万有引力常数:$G。 魔法导弹碰撞时造成$atk点伤害, 分裂出$count枚[b]次级导弹[/b], 可继承分裂最多$count次。" sources = Array[String](["万有引力", "宇宙航行"]) +cooldown = 1000.0 debugRebuild = true [node name="avatar" parent="container/info" parent_id_path=PackedInt32Array(1625294072) index="0" unique_id=1021985889] @@ -44,11 +48,11 @@ text = "万有引力 × 宇宙航行" [node name="description" parent="container" parent_id_path=PackedInt32Array(575698869) index="2" unique_id=566230682] text = "[center]召唤1~[color=cyan]3[/color]枚[b]魔法导弹[/b],围绕鼠标指针做由鼠标指针提供向心力的圆周运动。 -鼠标指针质量:[color=cyan]100.00[/color], -魔法导弹质量:[color=cyan]10.00[/color], -初始轨道半径:[color=cyan]200.00[/color], +鼠标指针质量:[color=cyan]100.00[/color]kg, +魔法导弹质量:[color=cyan]10.00[/color]kg, +初始轨道半径:[color=cyan]200.00[/color]m, 万有引力常数:[color=cyan]197392[/color]。 -魔法导弹碰撞时造成[color=cyan]14[/color]点伤害, +魔法导弹碰撞时造成[color=cyan]10[/color]点伤害, 分裂出[color=cyan]3[/color]枚[b]次级导弹[/b], 可继承分裂最多[color=cyan]3[/color]次。[/center]" diff --git a/resources/bullets/magic-missle/ninesols.png b/resources/bullets/magic-missle/ninesols.png index 3e3bb22c170c10b3743838002eb50f0ba82b7aa0..79feed07bf746cd6a0719f8fff32722289a9c338 100644 GIT binary patch literal 6743 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 M&1_9CZ`mFFKT7)4ga7~l literal 4422 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 0 && accelerating && roundBullets.count(self ) > 0: + for i in randi_range(1, powerScale): + for bullet in BulletBase.generate( + ComponentManager.getBullet("MagicMissle"), + launcher, + position, + entity.position.angle_to_point(position) + PI + randf_range(-1, 1) * deg_to_rad(60) + ): + if bullet is MagicMissleBullet: + bullet.position += Vector2.from_angle(bullet.rotation) * 100 + bullet.speedV2 += Vector2.from_angle(bullet.rotation) * 30 + bullet.roundBullets = roundBullets + bullet.powerScale = powerScale - 1 + roundBullets.append(bullet) + powerScale = 0 diff --git a/scripts/Contents/Bullets/MagicMissle.gd.uid b/scripts/Contents/Bullets/MagicMissle.gd.uid new file mode 100644 index 0000000..db49d28 --- /dev/null +++ b/scripts/Contents/Bullets/MagicMissle.gd.uid @@ -0,0 +1 @@ +uid://b1y8r5xrhhso diff --git a/scripts/Contents/Characters/Rooster.gd b/scripts/Contents/Characters/Rooster.gd index a588584..5c2e0e9 100644 --- a/scripts/Contents/Characters/Rooster.gd +++ b/scripts/Contents/Characters/Rooster.gd @@ -54,24 +54,26 @@ func tryLaunch(action: String, weaponIndex: int): chargeStartTime[weaponIndex] = Time.get_ticks_msec() chargeParticle.emitting = true chargeParticle.speed_scale = 1 - elif weapon.emitType == Weapon.EmitType.CLICK_SHOOT: + elif weapon.emitType == Weapon.EmitType.CLICK_SHOOT || weapon.emitType == Weapon.EmitType.HOLD_LOOP: tryAttack(weaponIndex) if Input.is_action_pressed(action): if len(weapons) > weaponIndex: var weapon = weapons[weaponIndex] if chargeStartTime.has(weaponIndex): chargeParticle.speed_scale += 0.01 * self.fields.get(FieldStore.Entity.CHARGE_SPEED) - elif weapon.emitType == Weapon.EmitType.HOLD_SHOOT: + elif weapon.emitType == Weapon.EmitType.HOLD_SHOOT || weapon.emitType == Weapon.EmitType.HOLD_LOOP: tryAttack(weaponIndex) if Input.is_action_just_released(action): - if chargeStartTime.has(weaponIndex): - var startTime = chargeStartTime[weaponIndex] - var endTime = Time.get_ticks_msec() - var chargedTime = endTime - startTime - chargeStartTime.erase(weaponIndex) - if len(weapons) > weaponIndex: - var weapon = weapons[weaponIndex] - if weapon.emitType == Weapon.EmitType.CHARGE: + if len(weapons) > weaponIndex: + var weapon = weapons[weaponIndex] + if weapon.emitType == Weapon.EmitType.CHARGE: + if chargeStartTime.has(weaponIndex): + var startTime = chargeStartTime[weaponIndex] + var endTime = Time.get_ticks_msec() + var chargedTime = endTime - startTime + chargeStartTime.erase(weaponIndex) weapon.chargedTime = chargedTime * self.fields.get(FieldStore.Entity.CHARGE_SPEED) tryAttack(weaponIndex) chargeParticle.emitting = false + elif weapon.emitType == Weapon.EmitType.HOLD_LOOP: + weapon.exitLoop(self ) diff --git a/scripts/Contents/Weapons/MagicMissle.gd b/scripts/Contents/Weapons/MagicMissle.gd new file mode 100644 index 0000000..24153ea --- /dev/null +++ b/scripts/Contents/Weapons/MagicMissle.gd @@ -0,0 +1,36 @@ +@tool +extends Weapon + +var roundBullets: Array[MagicMissleBullet] = [] + +func update(to: int, origin: Dictionary, _entity: EntityBase): + origin["atk"] += 1 * to * soulLevel + origin["cursor-m"] += 0.2 * to * soulLevel + origin["missle-m"] += 0.02 * to * soulLevel + origin["track"] += 1 * to * soulLevel + origin["G"] *= 1.25 ** (soulLevel - 1) + origin["count"] += 1 * (soulLevel - 1) + return origin + +func loopStart(entity: EntityBase): + for i in randi_range(1, readStore("count")): + for bullet in BulletBase.generate( + ComponentManager.getBullet("MagicMissle"), + entity, + get_global_mouse_position() + Vector2.from_angle(randf_range(0, 2 * PI)) * readStore("track"), + 0 + ): + if bullet is MagicMissleBullet: + bullet.look_at(get_global_mouse_position()) + bullet.rotation += PI / 2 + bullet.speedV2 += Vector2.from_angle(bullet.rotation) * sqrt((readStore("G") * readStore("cursor-m") / readStore("track") ** 2) * readStore("track")) / 120 + bullet.roundBullets = roundBullets + bullet.baseDamage = readStore("atk") + bullet.powerScale = readStore("count") + roundBullets.append(bullet) + return true +func loopExit(_entity: EntityBase): + for bullet in roundBullets: + if is_instance_valid(bullet): + bullet.accelerating = false + roundBullets.clear() diff --git a/scripts/Contents/Weapons/MagicMissle.gd.uid b/scripts/Contents/Weapons/MagicMissle.gd.uid new file mode 100644 index 0000000..397acef --- /dev/null +++ b/scripts/Contents/Weapons/MagicMissle.gd.uid @@ -0,0 +1 @@ +uid://clec7nrtesipu diff --git a/scripts/Statemachine/BulletBase.gd b/scripts/Statemachine/BulletBase.gd index ae63458..3c94303 100644 --- a/scripts/Statemachine/BulletBase.gd +++ b/scripts/Statemachine/BulletBase.gd @@ -38,6 +38,7 @@ var initialDamage: float = 0 var speedScale: float = 1 var isFirstFrame: bool = true var cycleStateAngle: float = 0 +var lastDelta: float = 0 func _ready(): initialSpeed = speed @@ -83,7 +84,8 @@ func _process(_delta: float) -> void: if lifeDistance > 0: if position.distance_to(spawnInWhere) >= lifeDistance: tryDestroy() -func _physics_process(_delta: float) -> void: +func _physics_process(delta: float) -> void: + lastDelta = delta if destroying: return if is_instance_valid(launcher) and (launcher.isPlayer() or is_instance_valid(launcher.currentFocusedBoss)): launcher.position -= Vector2.from_angle(rotation) * recoil diff --git a/scripts/Structs/Weapon.gd b/scripts/Structs/Weapon.gd index 04d6d25..e35f3dd 100644 --- a/scripts/Structs/Weapon.gd +++ b/scripts/Structs/Weapon.gd @@ -6,7 +6,7 @@ enum EmitType { HOLD_SHOOT, CLICK_SHOOT, CHARGE, - HOLD_ONCE + HOLD_LOOP } @export var avatarTexture: Texture2D = null @@ -49,6 +49,7 @@ var cooldownTimer: CooldownTimer = null var originalStore: Dictionary = {} var chargedTime: float = 0 var attackSpeed: float = 1 +var looping: bool = false func _ready(): cooldownTimer = CooldownTimer.new() @@ -188,19 +189,41 @@ func canAttackBy(entity: EntityBase): cooldownTimer.speedScale = entity.fields.get(FieldStore.Entity.ATTACK_SPEED) * attackSpeed return cooldownTimer.isCooldowned() and entity.isEnergyEnough(needEnergy) and checkAttack(entity) func tryAttack(entity: EntityBase): - if canAttackBy(entity): - var result = await attack(entity) - if result: - cooldownTimer.start() - entity.useEnergy(needEnergy) - return result + if looping: + if checkAttack(entity): + return await attack(entity) + else: + exitLoop(entity) + else: + if canAttackBy(entity): + if emitType == EmitType.HOLD_LOOP: + var result = await loopStart(entity) + if result: + looping = true + cooldownTimer.start() + entity.useEnergy(needEnergy) + return result + else: + var result = await attack(entity) + if result: + cooldownTimer.start() + entity.useEnergy(needEnergy) + return result func charged(base: float, percent: float): return base * sqrt(1 + chargedTime / 15 * percent) +func exitLoop(entity: EntityBase): + if !looping: return + looping = false + loopExit(entity) # 抽象 func update(_to: int, origin: Dictionary, _entity: EntityBase): return origin +func loopStart(_entity: EntityBase): + pass func checkAttack(_entity: EntityBase) -> bool: return true func attack(_entity: EntityBase): pass +func loopExit(_entity: EntityBase): + pass