mirror of
https://github.com/Rundll86/Dog-Lynx-And-HCN.git
synced 2026-05-28 06:51:54 +08:00
feat(障碍物系统): 添加草墙障碍物及相关功能
实现草墙障碍物系统,包括以下主要变更: - 新增草墙障碍物资源、脚本和场景 - 添加障碍物状态显示UI - 扩展组件管理器支持障碍物类型 - 修改子弹系统以支持对障碍物的碰撞检测 - 调整实体碰撞层设置 - 为公鸡角色添加草墙武器 新增功能允许玩家放置可阻挡敌人的草墙障碍物,并显示其生命值状态
This commit is contained in:
@@ -44,7 +44,8 @@ func _ready():
|
||||
launcherSummoned = launcher
|
||||
launcher = launcher.myMaster
|
||||
register()
|
||||
area_entered.connect(hit)
|
||||
area_entered.connect(hitEntity)
|
||||
body_entered.connect(hitObstacle)
|
||||
spawnInWhen = WorldManager.getTime()
|
||||
spawnInWhere = position
|
||||
spawn()
|
||||
@@ -107,16 +108,31 @@ func setupCuttable(cutSpeed: float):
|
||||
)
|
||||
func getDamage():
|
||||
return baseDamage * damageMultipliers[usingDamageMultiplier]
|
||||
func hit(target: Node):
|
||||
func calculateDamage(crit: bool):
|
||||
var baseDmg = getDamage() * launcher.fields.get(FieldStore.Entity.DAMAGE_MULTIPILER) * randf_range(1 - GameRule.damageOffset, 1 + GameRule.damageOffset)
|
||||
var damage = baseDmg + baseDmg * int(crit) * launcher.fields.get(FieldStore.Entity.CRIT_DAMAGE)
|
||||
return damage
|
||||
func determineCrit():
|
||||
return MathTool.rate(launcher.fields.get(FieldStore.Entity.CRIT_RATE) + GameRule.critRateInfluenceByLuckValue * launcher.fields[FieldStore.Entity.LUCK_VALUE])
|
||||
func hitEntity(target: Node):
|
||||
var entity: EntityBase = EntityTool.fromHurtbox(target)
|
||||
if !BulletTool.canDamage(self, entity): return
|
||||
var resultDamage = entity.bulletHit(self, MathTool.rate(launcher.fields.get(FieldStore.Entity.CRIT_RATE) + GameRule.critRateInfluenceByLuckValue * launcher.fields[FieldStore.Entity.LUCK_VALUE]))
|
||||
var resultDamage = entity.bulletHit(self, determineCrit())
|
||||
succeedToHit(resultDamage, entity)
|
||||
if MathTool.rate(fullPenerate()):
|
||||
penerate -= entity.fields[FieldStore.Entity.PENARATION_RESISTANCE]
|
||||
if MathTool.rate(fullPenerate() - entity.fields[FieldStore.Entity.PENARATION_RESISTANCE]):
|
||||
baseDamage *= 1.0 - penerateDamageReduction
|
||||
else:
|
||||
tryDestroy()
|
||||
func hitObstacle(target: Node):
|
||||
if target is ObstacleBase:
|
||||
var obstacle = target as ObstacleBase
|
||||
if is_instance_valid(obstacle.launcher):
|
||||
if not BulletTool.canDamage(self, obstacle.launcher): return
|
||||
obstacle.takeDamage(calculateDamage(determineCrit()))
|
||||
if MathTool.rate(fullPenerate() - obstacle.penerateResistance):
|
||||
baseDamage *= 1.0 - penerateDamageReduction
|
||||
else:
|
||||
tryDestroy()
|
||||
func forward(direction: Vector2):
|
||||
position += direction.normalized() * speed * GameRule.bulletSpeedMultiplier
|
||||
func fullPenerate():
|
||||
|
||||
@@ -8,6 +8,10 @@ signal died()
|
||||
|
||||
signal energyChanged(energy: float, dontChangeDirection: bool)
|
||||
|
||||
enum Layers {
|
||||
PLAYER = 1 << 2,
|
||||
ENEMY = 1 << 1,
|
||||
}
|
||||
const TITLE_FLAG = INF
|
||||
var fields = {
|
||||
"生存": TITLE_FLAG,
|
||||
@@ -143,8 +147,12 @@ func _ready():
|
||||
)
|
||||
if displayName == MultiplayerState.playerName:
|
||||
rebuildWeaponIcons()
|
||||
collision_layer = Layers.PLAYER
|
||||
collision_mask = Layers.PLAYER
|
||||
else:
|
||||
applyLevel()
|
||||
collision_layer = Layers.ENEMY
|
||||
collision_mask = Layers.ENEMY
|
||||
health = fields.get(FieldStore.Entity.MAX_HEALTH)
|
||||
energy = fields.get(FieldStore.Entity.MAX_ENERGY)
|
||||
if is_instance_valid(statebar):
|
||||
@@ -242,8 +250,7 @@ func takeDamage(baseDamage: float, crit: bool = false, perfectMiss: bool = false
|
||||
func bulletHit(bullet: BulletBase, crit: bool):
|
||||
# 当受伤时
|
||||
hurtAnimator.play("hurt")
|
||||
var baseDamage: float = bullet.getDamage() * bullet.launcher.fields.get(FieldStore.Entity.DAMAGE_MULTIPILER) * randf_range(1 - GameRule.damageOffset, 1 + GameRule.damageOffset)
|
||||
var damage = baseDamage + baseDamage * int(crit) * fields.get(FieldStore.Entity.CRIT_DAMAGE)
|
||||
var damage = bullet.calculateDamage(crit)
|
||||
var perfectMiss = false
|
||||
if sprinting:
|
||||
playSound("miss")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
extends Node
|
||||
extends CanvasItem
|
||||
class_name EntityStateBar
|
||||
|
||||
@export var entity: EntityBase
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
extends StaticBody2D
|
||||
class_name ObstacleBase
|
||||
|
||||
signal healthChanged(newHealth: float)
|
||||
|
||||
@export var healthMax: float = 100
|
||||
@export var penerateResistance: float = 0
|
||||
@export var blockPlayer: bool = false
|
||||
@export var blockEnemy: bool = false
|
||||
|
||||
@onready var statebar: ObstacleStateBar = $%statebar
|
||||
@onready var texture: AnimatedSprite2D = $%texture
|
||||
@onready var hitbox: CollisionShape2D = $%hitbox
|
||||
var health: float = 0
|
||||
var launcher: EntityBase = null
|
||||
|
||||
func _ready():
|
||||
health = healthMax
|
||||
if blockPlayer:
|
||||
collision_layer |= EntityBase.Layers.PLAYER
|
||||
collision_mask |= EntityBase.Layers.PLAYER
|
||||
if blockEnemy:
|
||||
collision_layer |= EntityBase.Layers.ENEMY
|
||||
collision_mask |= EntityBase.Layers.ENEMY
|
||||
healthChanged.connect(
|
||||
func(newHealth):
|
||||
statebar.healthBar.maxValue = healthMax
|
||||
statebar.healthBar.setCurrent(newHealth)
|
||||
)
|
||||
func _process(_delta):
|
||||
statebar.global_rotation = 0
|
||||
statebar.applyText()
|
||||
|
||||
func initHealth(maxHealth: float):
|
||||
healthMax = maxHealth
|
||||
health = healthMax
|
||||
statebar.forceSync()
|
||||
statebar.applyText()
|
||||
func takeDamage(damage: float):
|
||||
health -= damage
|
||||
healthChanged.emit(health)
|
||||
if health <= 0:
|
||||
tryDie()
|
||||
func tryDie():
|
||||
die()
|
||||
queue_free()
|
||||
|
||||
func die():
|
||||
pass
|
||||
|
||||
static func generate(
|
||||
obstacle: PackedScene,
|
||||
spawnPosition: Vector2,
|
||||
spawnRotation: float = 0,
|
||||
itsLauncher: EntityBase = null,
|
||||
addToWorld: bool = true
|
||||
) -> ObstacleBase:
|
||||
var instance: ObstacleBase = obstacle.instantiate()
|
||||
instance.position = spawnPosition
|
||||
instance.rotation = spawnRotation
|
||||
instance.launcher = itsLauncher
|
||||
if addToWorld:
|
||||
WorldManager.rootNode.spawn(instance)
|
||||
return instance
|
||||
@@ -0,0 +1 @@
|
||||
uid://bj26s4i47bw0a
|
||||
@@ -0,0 +1,17 @@
|
||||
extends Node2D
|
||||
class_name ObstacleStateBar
|
||||
|
||||
@export var obstacle: ObstacleBase
|
||||
|
||||
@onready var healthBar: ColorBar = $%health
|
||||
@onready var currentLabel: Label = $%current
|
||||
@onready var maxLabel: Label = $%max
|
||||
@onready var levelLabelContainer: HBoxContainer = $%levelLabel
|
||||
|
||||
func forceSync():
|
||||
healthBar.maxValue = obstacle.healthMax
|
||||
healthBar.currentValue = obstacle.health
|
||||
healthBar.forceSync()
|
||||
func applyText():
|
||||
currentLabel.text = "%d" % obstacle.health
|
||||
maxLabel.text = "%d" % obstacle.healthMax
|
||||
@@ -0,0 +1 @@
|
||||
uid://dkt4yqm0juwic
|
||||
Reference in New Issue
Block a user