From 53412c09689768f520cc4f3c0e93fa42eaff7220 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: Thu, 5 Feb 2026 20:04:39 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E6=AD=A6=E5=99=A8=E7=B3=BB=E7=BB=9F):=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=8F=AF=E8=93=84=E5=8A=9B=E9=92=A2=E7=AE=A1?= =?UTF-8?q?=E6=AD=A6=E5=99=A8=E5=8F=8A=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 实现钢管武器的蓄力攻击机制,包括: - 添加 Pipe 武器和 PipeBullet 子弹脚本及场景 - 在 Weapon 类中增加蓄力相关属性和方法 - 修改 Rooster 角色以支持武器蓄力功能 - 添加武器蓄力时间计算和伤害加成逻辑 --- components/Bullets/Pipe.tscn | 32 +++++++++++++ components/Characters/Rooster.tscn | 5 +- components/Weapons/Pipe.tscn | 6 ++- scripts/Contents/Bullets/PipeBullet.gd | 9 ++++ scripts/Contents/Bullets/PipeBullet.gd.uid | 1 + scripts/Contents/Characters/Rooster.gd | 54 ++++++++++++++++------ scripts/Contents/Weapons/Pipe.gd | 21 +++++++++ scripts/Contents/Weapons/Pipe.gd.uid | 1 + scripts/Structs/Weapon.gd | 13 ++++-- 9 files changed, 121 insertions(+), 21 deletions(-) create mode 100644 components/Bullets/Pipe.tscn create mode 100644 scripts/Contents/Bullets/PipeBullet.gd create mode 100644 scripts/Contents/Bullets/PipeBullet.gd.uid create mode 100644 scripts/Contents/Weapons/Pipe.gd create mode 100644 scripts/Contents/Weapons/Pipe.gd.uid diff --git a/components/Bullets/Pipe.tscn b/components/Bullets/Pipe.tscn new file mode 100644 index 0000000..9e1a980 --- /dev/null +++ b/components/Bullets/Pipe.tscn @@ -0,0 +1,32 @@ +[gd_scene load_steps=6 format=3 uid="uid://07lpwkusvvy4"] + +[ext_resource type="PackedScene" uid="uid://crtdkysmnkith" path="res://components/Abstracts/BulletBase.tscn" id="1_3h25n"] +[ext_resource type="Texture2D" uid="uid://ds5htlg14wm3y" path="res://resources/bullets/pipe/pipe.png" id="2_3ntcm"] +[ext_resource type="Script" uid="uid://c4w0f18nj4qhk" path="res://scripts/Contents/Bullets/PipeBullet.gd" id="2_vcs8c"] + +[sub_resource type="SpriteFrames" id="SpriteFrames_vcs8c"] +animations = [{ +"frames": [{ +"duration": 1.0, +"texture": ExtResource("2_3ntcm") +}], +"loop": true, +"name": &"default", +"speed": 5.0 +}] + +[sub_resource type="RectangleShape2D" id="RectangleShape2D_j5ir5"] +size = Vector2(162, 12) + +[node name="Pipe" instance=ExtResource("1_3h25n")] +script = ExtResource("2_vcs8c") +penerate = 1.0 +lifeTime = 1000.0 + +[node name="texture" parent="." index="0"] +rotation = -1.5707964 +scale = Vector2(0.27, 0.27) +sprite_frames = SubResource("SpriteFrames_vcs8c") + +[node name="hitbox" parent="." index="1"] +shape = SubResource("RectangleShape2D_j5ir5") diff --git a/components/Characters/Rooster.tscn b/components/Characters/Rooster.tscn index 491996f..b00f0ed 100644 --- a/components/Characters/Rooster.tscn +++ b/components/Characters/Rooster.tscn @@ -1,7 +1,8 @@ -[gd_scene load_steps=12 format=3 uid="uid://dky8574uqc18r"] +[gd_scene load_steps=13 format=3 uid="uid://dky8574uqc18r"] [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://dyanyf044boxp" path="res://components/Weapons/Pipe.tscn" id="3_da2ca"] [ext_resource type="AudioStream" uid="uid://cdrevrq7n6yqa" path="res://resources/sounds/effect/Boing.mp3" id="4_66s6c"] [ext_resource type="AudioStream" uid="uid://benyec5bqni0b" path="res://resources/sounds/effect/Chomp.wav" id="4_k0yme"] [ext_resource type="AudioStream" uid="uid://dmxh3bpk8vyy5" path="res://resources/sounds/effect/Coin.mp3" id="5_xnbhq"] @@ -57,6 +58,8 @@ metadata/_edit_vertical_guides_ = [71.0] [node name="weaponStore" parent="." index="1"] process_mode = 4 +[node name="Pipe" parent="weaponStore" index="0" instance=ExtResource("3_da2ca")] + [node name="sprint" parent="sounds" index="0"] stream = ExtResource("4_66s6c") diff --git a/components/Weapons/Pipe.tscn b/components/Weapons/Pipe.tscn index f044bf7..abe84cf 100644 --- a/components/Weapons/Pipe.tscn +++ b/components/Weapons/Pipe.tscn @@ -1,12 +1,15 @@ -[gd_scene load_steps=3 format=3 uid="uid://jq8oatmpoesj"] +[gd_scene load_steps=4 format=3 uid="uid://dyanyf044boxp"] [ext_resource type="PackedScene" uid="uid://ckq2cq6m23hq3" path="res://components/Abstracts/WeaponCardBase.tscn" id="1_sqbqm"] [ext_resource type="Texture2D" uid="uid://7yeb0e4ahcee" path="res://resources/weapons/pipe.png" id="2_mmtf8"] +[ext_resource type="Script" uid="uid://l1v3boq8ei12" path="res://scripts/Contents/Weapons/Pipe.gd" id="2_p67v7"] [node name="Pipe" instance=ExtResource("1_sqbqm")] +script = ExtResource("2_p67v7") avatarTexture = ExtResource("2_mmtf8") displayName = "钢管" costBeachball = 350 +chargable = true store = { "atk": 5, "charge": 0.1 @@ -17,7 +20,6 @@ storeType = { } descriptionTemplate = "按住蓄力扔出钢管,蓄力越久伤害越高。 基础伤害:$atk,蓄力倍率:$charge" -debugRebuild = true [node name="avatar" parent="container/info" index="0"] texture = ExtResource("2_mmtf8") diff --git a/scripts/Contents/Bullets/PipeBullet.gd b/scripts/Contents/Bullets/PipeBullet.gd new file mode 100644 index 0000000..2ef04c6 --- /dev/null +++ b/scripts/Contents/Bullets/PipeBullet.gd @@ -0,0 +1,9 @@ +extends BulletBase +class_name PipeBullet + +var energy: float = 0 + +func ai(): + PresetBulletAI.forward(self, rotation) + texture.rotation += energy * (1 - lifeTimePercent()) / 100 + speed = initialSpeed * (1 - lifeTimePercent()) diff --git a/scripts/Contents/Bullets/PipeBullet.gd.uid b/scripts/Contents/Bullets/PipeBullet.gd.uid new file mode 100644 index 0000000..94aeac7 --- /dev/null +++ b/scripts/Contents/Bullets/PipeBullet.gd.uid @@ -0,0 +1 @@ +uid://c4w0f18nj4qhk diff --git a/scripts/Contents/Characters/Rooster.gd b/scripts/Contents/Characters/Rooster.gd index 43c9e8d..df72da2 100644 --- a/scripts/Contents/Characters/Rooster.gd +++ b/scripts/Contents/Characters/Rooster.gd @@ -11,11 +11,8 @@ func register(): elif bullet is FoxZhua: EffectController.create(ComponentManager.getEffect("BloodFall"), texture.global_position).shot() ) - # if !WorldManager.isRelease(): - # getItem({ - # ItemStore.ItemType.BEACHBALL: INF, - # ItemStore.ItemType.SOUL: INF - # }) +var chargeStartTime = {} + func ai(): texture.play("walk") var direction = Vector2( @@ -25,17 +22,27 @@ func ai(): move(direction) if direction.length() == 0: texture.play("idle") - if Input.is_action_pressed("attack"): - tryAttack(0) - if Input.is_action_pressed("attack2"): - tryAttack(1) - if Input.is_action_pressed("smallSkill"): - tryAttack(2) - if Input.is_action_pressed("superSkill"): - tryAttack(3) + if Input.is_action_just_pressed("attack"): + startCharge(0) + if Input.is_action_just_released("attack"): + endCharge(0) + if Input.is_action_just_pressed("attack2"): + startCharge(1) + if Input.is_action_just_released("attack2"): + endCharge(1) + if Input.is_action_just_pressed("smallSkill"): + startCharge(2) + if Input.is_action_just_released("smallSkill"): + endCharge(2) + if Input.is_action_just_pressed("superSkill"): + startCharge(3) + if Input.is_action_just_released("superSkill"): + endCharge(3) for i in range(3): - if Input.is_action_pressed("cardSkill" + str(i)): - tryAttack(4 + i) + if Input.is_action_just_pressed("cardSkill" + str(i)): + startCharge(4 + i) + if Input.is_action_just_released("cardSkill" + str(i)): + endCharge(4 + i) if Input.is_action_just_pressed("sprint"): trySprint() if Input.is_action_just_pressed("heal"): @@ -49,3 +56,20 @@ func sprint(): Input.get_axis("m_left", "m_right"), Input.get_axis("m_up", "m_down") ) * sprintMultiplier, true) + +func startCharge(weaponIndex: int): + if len(weapons) > weaponIndex: + var weapon = weapons[weaponIndex] + if weapon.chargable: + chargeStartTime[weaponIndex] = Time.get_ticks_msec() +func endCharge(weaponIndex: int): + 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.chargable: + weapon.chargedTime = chargedTime + tryAttack(weaponIndex) diff --git a/scripts/Contents/Weapons/Pipe.gd b/scripts/Contents/Weapons/Pipe.gd new file mode 100644 index 0000000..66d8b05 --- /dev/null +++ b/scripts/Contents/Weapons/Pipe.gd @@ -0,0 +1,21 @@ +@tool +extends Weapon + +func update(to: int, origin: Dictionary, _entity: EntityBase): + origin["atk"] += 2 * to * soulLevel + origin["charge"] += 0.02 * to * soulLevel + return origin +func attack(entity: EntityBase): + var weaponPos = entity.findWeaponAnchor("normal") + for bullet in BulletBase.generate( + ComponentManager.getBullet("Pipe"), + entity, + weaponPos, + weaponPos.angle_to_point(get_global_mouse_position()) + ): + if bullet is PipeBullet: + var e = charged(readStore("atk"), readStore("charge")) + bullet.baseDamage = e + bullet.energy = e + bullet.speed = e + return true diff --git a/scripts/Contents/Weapons/Pipe.gd.uid b/scripts/Contents/Weapons/Pipe.gd.uid new file mode 100644 index 0000000..e970f3c --- /dev/null +++ b/scripts/Contents/Weapons/Pipe.gd.uid @@ -0,0 +1 @@ +uid://l1v3boq8ei12 diff --git a/scripts/Structs/Weapon.gd b/scripts/Structs/Weapon.gd index 7061ce8..525a21e 100644 --- a/scripts/Structs/Weapon.gd +++ b/scripts/Structs/Weapon.gd @@ -8,6 +8,7 @@ class_name Weapon @export var typeTopic: WeaponName.TypeTopic = WeaponName.TypeTopic.IMPACT @export var soulLevel: int = 1 @export var costBeachball: int = 500 +@export var chargable: bool = false @export var store: Dictionary = { "atk": 10 } @@ -35,6 +36,7 @@ class_name Weapon var cooldownTimer: CooldownTimer = null var originalStore: Dictionary = {} +var chargedTime: float = 0 func _ready(): cooldownTimer = CooldownTimer.new() @@ -166,9 +168,14 @@ func playSound(sound: String): cloned.queue_free() func tryAttack(entity: EntityBase): cooldownTimer.speedScale = entity.fields.get(FieldStore.Entity.ATTACK_SPEED) - if cooldownTimer.start(): - if entity.useEnergy(needEnergy): - return await attack(entity) + if cooldownTimer.isCooldowned(): + var result = await attack(entity) + if result: + cooldownTimer.start() + entity.useEnergy(needEnergy) + return result +func charged(base: float, percent: float): + return base * (1 + chargedTime / 50 * percent) # 抽象 func update(_to: int, origin: Dictionary, _entity: EntityBase):