mirror of
https://github.com/Rundll86/Dog-Lynx-And-HCN.git
synced 2026-06-04 10:47:13 +08:00
feat(战斗系统): 添加小鸡冲刺攻击技能及相关特效
实现小鸡的冲刺攻击能力,包括: 1. 新增ChickSprint子弹类型及场景 2. 为EntityBase添加拖尾粒子效果 3. 添加攻击蓄力特效和音效 4. 调整小鸡的攻击冷却时间和冲刺倍率 5. 优化TickTool工具类添加until方法 6. 修改世界背景z-index避免遮挡 调整战斗平衡性: 1. 降低默认冲刺倍率 2. 修改测试波次配置 3. 增加新的攻击方式选项
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
extends BulletBase
|
||||
class_name ChickSprint
|
||||
|
||||
func register():
|
||||
speed = 0
|
||||
damage = 30
|
||||
penerate = 1
|
||||
func ai():
|
||||
PresetsAI.lockLauncher(self, launcher, true)
|
||||
if !launcher.sprinting:
|
||||
tryDestroy()
|
||||
@@ -8,9 +8,11 @@ const laserCount = 4
|
||||
func register():
|
||||
fields[FieldStore.Entity.MAX_HEALTH] = 2000
|
||||
fields[FieldStore.Entity.MOVEMENT_SPEED] = 0.35
|
||||
attackCooldownMap[0] = 2000
|
||||
attackCooldownMap[0] = 500
|
||||
attackCooldownMap[1] = 6000
|
||||
attackCooldownMap[2] = 100
|
||||
attackCooldownMap[3] = 500
|
||||
sprintMultiplier = 60
|
||||
func spawn():
|
||||
texture.play("walk")
|
||||
|
||||
@@ -21,7 +23,8 @@ func ai():
|
||||
elif currentFocusedBoss.position.distance_to(position) < 700:
|
||||
tryAttack(1)
|
||||
else:
|
||||
tryAttack(0)
|
||||
var method = MathTool.randc_from([0, 3])
|
||||
tryAttack(method, method == 3)
|
||||
func attack(type):
|
||||
if type == 0:
|
||||
var weaponPos = findWeaponAnchor("normal")
|
||||
@@ -36,4 +39,11 @@ func attack(type):
|
||||
firepot.global_rotation = target
|
||||
firepot.shot()
|
||||
BulletBase.generate(preload("res://components/Bullets/FireScan.tscn"), self, weaponPos, target)
|
||||
elif type == 3:
|
||||
trailing = true
|
||||
BulletBase.generate(preload("res://components/Bullets/ChickSprint.tscn"), self, position, 0)
|
||||
await trySprint()
|
||||
trailing = false
|
||||
return true
|
||||
func sprint():
|
||||
move((currentFocusedBoss.position - position).normalized() * sprintMultiplier, true)
|
||||
|
||||
@@ -11,8 +11,9 @@ var per: int = 0
|
||||
static var current: int = 0
|
||||
static var data: Array[Wave] = [
|
||||
# entity, minCount, maxCount, isBoss, from, to, per
|
||||
create(preload("res://components/Characters/Hen.tscn"), 1, 5, false, 0, INF, 1),
|
||||
create(preload("res://components/Characters/Chick.tscn"), 0, 0, true, 8, INF, 6),
|
||||
# create(preload("res://components/Characters/Hen.tscn"), 1, 5, false, 0, INF, 1),
|
||||
# create(preload("res://components/Characters/Chick.tscn"), 0, 0, true, 8, INF, 6),
|
||||
create(preload("res://components/Characters/Chick.tscn"), 1, 1, true, 0, INF, 1),
|
||||
]
|
||||
|
||||
static func create(
|
||||
|
||||
@@ -2,12 +2,17 @@ extends Node2D
|
||||
class_name EffectController
|
||||
|
||||
@export var oneShot: bool = true
|
||||
@export var spawnSound: String = ""
|
||||
|
||||
@onready var particles: GPUParticles2D = $"%particles"
|
||||
@onready var sounds = $"%sounds"
|
||||
|
||||
func _ready():
|
||||
particles.emitting = false
|
||||
particles.one_shot = oneShot
|
||||
var sound = sounds.get_node_or_null(spawnSound)
|
||||
if sound and sound.stream:
|
||||
sound.play()
|
||||
func shot():
|
||||
var cloned = particles.duplicate() as GPUParticles2D
|
||||
cloned.emitting = true
|
||||
|
||||
@@ -55,7 +55,7 @@ var inventoryMax = {
|
||||
@export var defaultCooldownUnit: float = 100
|
||||
@export var isBoss: bool = false
|
||||
@export var displayName: String = "未知实体"
|
||||
@export var sprintMultiplier: float = 4
|
||||
@export var sprintMultiplier: float = 3
|
||||
@export var drops: Array[ItemStore.ItemType] = []
|
||||
@export var dropCounts: Array[Vector2] = []
|
||||
@export var appleCount: Vector2i = Vector2(0, 2) # 死亡后掉落的苹果数量
|
||||
@@ -67,15 +67,18 @@ var inventoryMax = {
|
||||
@onready var sounds: Node2D = $"%sounds"
|
||||
@onready var hurtAnimator: AnimationPlayer = $"%hurtAnimator"
|
||||
@onready var damageAnchor: Node2D = $"%damageAnchor"
|
||||
@onready var trailParticle: GPUParticles2D = $"%trailParticle"
|
||||
var statebar: EntityStateBar
|
||||
|
||||
var health: float = 0
|
||||
var energy: float = 0
|
||||
var sprinting: bool = false
|
||||
var trailing: bool = false
|
||||
|
||||
var lastDirection: int = 1
|
||||
var lastAttack: int = 0
|
||||
var currentFocusedBoss: EntityBase = null
|
||||
var charginup: bool = false
|
||||
|
||||
func _ready():
|
||||
register()
|
||||
@@ -127,10 +130,11 @@ func _physics_process(_delta: float) -> void:
|
||||
sprinting = false
|
||||
else:
|
||||
velocity = Vector2.ZERO
|
||||
if isPlayer() or is_instance_valid(currentFocusedBoss):
|
||||
if (isPlayer() or is_instance_valid(currentFocusedBoss)) and not charginup:
|
||||
ai()
|
||||
move_and_slide()
|
||||
storeEnergy(0.01 * fields.get(FieldStore.Entity.ENERGY_REGENERATION))
|
||||
trailParticle.emitting = trailing
|
||||
|
||||
# 通用方法
|
||||
func applyLevel():
|
||||
@@ -187,16 +191,22 @@ func startCooldown(type: int):
|
||||
if state:
|
||||
lastAttack = WorldManager.getTime()
|
||||
return state
|
||||
func tryAttack(type: int):
|
||||
func tryAttack(type: int, needChargeUp: bool = false):
|
||||
var state = startCooldown(type)
|
||||
if state:
|
||||
if attack(type):
|
||||
if needChargeUp:
|
||||
charginup = true
|
||||
await EffectController.create(preload("res://components/Effects/AttackStar.tscn"), damageAnchor.global_position).shot()
|
||||
charginup = false
|
||||
else:
|
||||
playSound("attack" + str(type))
|
||||
attack(type)
|
||||
return state
|
||||
func trySprint():
|
||||
playSound("sprint")
|
||||
sprint()
|
||||
sprinting = true
|
||||
await TickTool.until(func(): return !sprinting)
|
||||
func tryDie(by: BulletBase):
|
||||
for drop in range(min(len(drops), len(dropCounts))):
|
||||
var item = drops[drop]
|
||||
|
||||
@@ -5,3 +5,6 @@ static func millseconds(ms: int):
|
||||
static func frame(count: int = 1):
|
||||
for i in range(count):
|
||||
await WorldManager.tree.physics_frame
|
||||
static func until(predicate: Callable):
|
||||
while not predicate.call():
|
||||
await frame()
|
||||
|
||||
Reference in New Issue
Block a user