mirror of
https://github.com/Rundll86/Dog-Lynx-And-HCN.git
synced 2026-05-28 06:51:54 +08:00
feat: 新增角色系统及基础功能实现
新增HCN、Lynx和MuyangDog三个可玩角色及其相关资源 实现角色选择界面和角色属性系统 重构玩家生成逻辑以支持角色选择 优化角色卡片UI显示效果
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
extends PlayerBase
|
||||
|
||||
func summoned(entity: SummonBase):
|
||||
entity.died.connect(func(): tryHeal(3))
|
||||
@@ -0,0 +1 @@
|
||||
uid://bevc4f6apql4t
|
||||
@@ -0,0 +1,5 @@
|
||||
extends PlayerBase
|
||||
|
||||
func register():
|
||||
super.register()
|
||||
sprintMultiplier += 3
|
||||
@@ -0,0 +1 @@
|
||||
uid://b8g0hkqvyeptg
|
||||
@@ -0,0 +1,11 @@
|
||||
extends PlayerBase
|
||||
|
||||
var parryCounter: CooldownTimer = CooldownTimer.new(5000)
|
||||
|
||||
func ai():
|
||||
super.ai()
|
||||
if parryCounter.start():
|
||||
var track = getTrackingAnchor()
|
||||
var bullet = BulletTool.findClosetBulletCanDamage(track, get_tree(), self , 400)
|
||||
if is_instance_valid(bullet):
|
||||
BulletBase.generate(ComponentManager.getBullet("Parrier"), self , track, track.angle_to_point(bullet.position))
|
||||
@@ -0,0 +1 @@
|
||||
uid://bbmb572iba42l
|
||||
@@ -0,0 +1,80 @@
|
||||
extends EntityBase
|
||||
class_name PlayerBase
|
||||
|
||||
var chargeStartTime = {}
|
||||
@onready var chargeParticle: GPUParticles2D = $%chargeParticle
|
||||
|
||||
func register():
|
||||
attackCooldownMap[0] = 200
|
||||
attackCooldownMap[1] = 6000
|
||||
hit.connect(
|
||||
func(_damage: float, bullet: BulletBase, _crit: bool):
|
||||
if bullet is DogCircle:
|
||||
EffectController.create(ComponentManager.getEffect("FeatherFall"), texture.global_position).shot()
|
||||
elif bullet is FoxZhua:
|
||||
EffectController.create(ComponentManager.getEffect("BloodFall"), texture.global_position).shot()
|
||||
)
|
||||
chargeParticle.emitting = false
|
||||
|
||||
func ai():
|
||||
currentFocusedPosition = get_global_mouse_position()
|
||||
texture.play("walk")
|
||||
var direction = Vector2(
|
||||
Input.get_axis("m_left", "m_right"),
|
||||
Input.get_axis("m_up", "m_down")
|
||||
)
|
||||
move(direction)
|
||||
if direction.length() == 0:
|
||||
texture.play("idle")
|
||||
tryLaunch("attack", 0)
|
||||
tryLaunch("attack2", 1)
|
||||
tryLaunch("smallSkill", 2)
|
||||
tryLaunch("superSkill", 3)
|
||||
for i in range(3):
|
||||
tryLaunch("cardSkill%d" % i, 4 + i)
|
||||
if Input.is_action_just_pressed("sprint"):
|
||||
trySprint()
|
||||
if Input.is_action_just_pressed("heal"):
|
||||
if health < fields.get(FieldStore.Entity.MAX_HEALTH):
|
||||
if useItem({
|
||||
ItemStore.ItemType.APPLE: 1
|
||||
}):
|
||||
tryHeal(20)
|
||||
func sprint():
|
||||
move(Vector2(
|
||||
Input.get_axis("m_left", "m_right"),
|
||||
Input.get_axis("m_up", "m_down")
|
||||
) * sprintMultiplier, true)
|
||||
|
||||
func tryLaunch(action: String, weaponIndex: int):
|
||||
if Input.is_action_just_pressed(action):
|
||||
if len(weapons) > weaponIndex:
|
||||
var weapon = weapons[weaponIndex]
|
||||
if weapon.emitType == Weapon.EmitType.CHARGE:
|
||||
if weapon.canAttackBy(self ):
|
||||
chargeStartTime[weaponIndex] = Time.get_ticks_msec()
|
||||
chargeParticle.emitting = true
|
||||
chargeParticle.speed_scale = 1
|
||||
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 || weapon.emitType == Weapon.EmitType.HOLD_LOOP:
|
||||
tryAttack(weaponIndex)
|
||||
if Input.is_action_just_released(action):
|
||||
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 )
|
||||
@@ -0,0 +1 @@
|
||||
uid://r5gm7rcya35p
|
||||
@@ -76,14 +76,18 @@ func startMultiplayerGame():
|
||||
MultiplayerState.connection = multiplayer.multiplayer_peer
|
||||
WorldManager.rootNode.multiplayer.multiplayer_peer = multiplayer.multiplayer_peer
|
||||
for i in getPlayerNames():
|
||||
EntityBase.generatePlayer(i)
|
||||
EntityBase.generatePlayer(i, selectedCharacter)
|
||||
UIState.closeCurrentPanel()
|
||||
func startSingleplayerGame():
|
||||
startSingleplayerBtn.disabled = true
|
||||
MultiplayerState.isMultiplayer = false
|
||||
MultiplayerState.playerName = playerNameInput.text
|
||||
Wave.usingWaveData = GAMEMODE_MAP_WAVE[gamemodeOption.selected]
|
||||
UIState.player = EntityBase.generatePlayer(playerNameInput.text)
|
||||
var extras = ArrayTool.mergeDictionary(ArrayTool.dictionaryFromEntries(
|
||||
getCurrentSelectedCharacter().fields,
|
||||
getCurrentSelectedCharacter().fieldValues
|
||||
), OutGameStorage.upgradableFieldsValue)
|
||||
UIState.player = EntityBase.generatePlayer(playerNameInput.text, selectedCharacter, extras)
|
||||
WorldManager.rootNode.spawnWave(Vector2.ZERO)
|
||||
UIState.setPanel("CompilingTip")
|
||||
|
||||
|
||||
@@ -7,16 +7,16 @@ var speedScale: float = 1
|
||||
func _init(cd: float = 100):
|
||||
cooldown = cd
|
||||
|
||||
func centralTime():
|
||||
func centralTime() -> float:
|
||||
return cooldown / speedScale
|
||||
func isCooldowned():
|
||||
func isCooldowned() -> bool:
|
||||
return timeSinceLastStart() >= centralTime()
|
||||
func start():
|
||||
func start() -> bool:
|
||||
var state = isCooldowned()
|
||||
if state:
|
||||
lastStart = WorldManager.getTime()
|
||||
return state
|
||||
func timeSinceLastStart():
|
||||
func timeSinceLastStart() -> float:
|
||||
return WorldManager.getTime() - lastStart
|
||||
func percent():
|
||||
func percent() -> float:
|
||||
return timeSinceLastStart() / centralTime()
|
||||
|
||||
@@ -138,7 +138,7 @@ func _ready():
|
||||
UIState.player = self
|
||||
if WorldManager.isRelease():
|
||||
for i in weaponStore.get_children():
|
||||
i.free()
|
||||
i.queue_free()
|
||||
weaponStore.add_child(ComponentManager.getWeapon("PurpleCrystal").instantiate())
|
||||
for i in weaponStore.get_children():
|
||||
i.hide()
|
||||
@@ -505,6 +505,7 @@ func summon(who: PackedScene, syncFields: bool = true, lockValue: bool = true) -
|
||||
var instance: SummonBase = who.instantiate()
|
||||
instance.position = get_global_mouse_position()
|
||||
instance.myMaster = self
|
||||
summoned(instance)
|
||||
if isPlayer(): instance.add_to_group("players")
|
||||
if syncFields:
|
||||
if lockValue:
|
||||
@@ -550,20 +551,22 @@ func enterStage(_stage: int):
|
||||
pass
|
||||
func kill():
|
||||
pass
|
||||
func summoned(_entity: SummonBase):
|
||||
pass
|
||||
|
||||
static func findPlayer(playerName: String) -> EntityBase:
|
||||
for i in getPlayers():
|
||||
if i.displayName == playerName:
|
||||
return i
|
||||
return null
|
||||
static func generatePlayer(playerName: String) -> EntityBase:
|
||||
var player = generate(ComponentManager.getCharacter("Rooster"), Vector2.ZERO, false)
|
||||
player.displayName = playerName
|
||||
static func generatePlayer(playerName: String, character: String, extraFields: Dictionary = {}) -> EntityBase:
|
||||
var player = generate(ComponentManager.getCharacter(character), Vector2.ZERO, false, false, true, playerName)
|
||||
player.name = "Player_%s" % playerName
|
||||
print(extraFields)
|
||||
var feed = ComponentManager.getAbstract("FeedCardBase").instantiate() as Feed
|
||||
for field in OutGameStorage.upgradableFieldsValue:
|
||||
for field in extraFields:
|
||||
feed.fields.append(field)
|
||||
feed.fieldValues.append(OutGameStorage.upgradableFieldsValue[field])
|
||||
feed.fieldValues.append(extraFields[field])
|
||||
feed.freeToBuy = true
|
||||
feed.apply(player)
|
||||
return player
|
||||
@@ -572,12 +575,15 @@ static func generate(
|
||||
spawnPosition: Vector2,
|
||||
isMob: bool = true,
|
||||
spawnAsBoss: bool = false,
|
||||
addToWorld: bool = true
|
||||
addToWorld: bool = true,
|
||||
disName: String = ""
|
||||
):
|
||||
var instance: EntityBase = entity.instantiate()
|
||||
instance.position = spawnPosition
|
||||
instance.isBoss = spawnAsBoss
|
||||
instance.level = clamp((round(Wave.current * (1 + GameRule.entityLevelOffsetByWave * randf_range(-1, 1)))), 1, INF)
|
||||
if disName:
|
||||
instance.displayName = disName
|
||||
if isMob:
|
||||
instance.add_to_group("mobs")
|
||||
else:
|
||||
|
||||
@@ -5,6 +5,7 @@ class_name CharacterCard
|
||||
signal select()
|
||||
|
||||
@export var displayName: String = "Unknown Character"
|
||||
@export var slogan: String = "Slogan"
|
||||
@export var avatar: Texture2D = null
|
||||
@export_multiline var description: String = ""
|
||||
@export var fields: Array[FieldStore.Entity] = []
|
||||
@@ -14,6 +15,7 @@ signal select()
|
||||
|
||||
@onready var avatarTexture: TextureRect = $%avatarTexture
|
||||
@onready var nameLebel: Label = $%nameLabel
|
||||
@onready var sloganLabel: Label = $%sloganLabel
|
||||
@onready var descriptionLabel: Label = $%descriptionLabel
|
||||
@onready var fieldsBox: Control = $%fields
|
||||
@onready var animator: AnimationPlayer = $%animator
|
||||
@@ -40,6 +42,7 @@ func _process(_delta):
|
||||
func rebuildInfo():
|
||||
avatarTexture.texture = avatar
|
||||
nameLebel.text = displayName
|
||||
sloganLabel.text = "“%s”" % slogan
|
||||
descriptionLabel.text = description
|
||||
for child in fieldsBox.get_children():
|
||||
fieldsBox.remove_child(child)
|
||||
|
||||
@@ -31,3 +31,17 @@ static func fill(origin: Dictionary, filler: Callable) -> Dictionary:
|
||||
return accum,
|
||||
{}
|
||||
)
|
||||
static func dictionaryFromEntries(keys: Array, values: Array) -> Dictionary:
|
||||
var result = {}
|
||||
for index in len(keys):
|
||||
var key = keys[index]
|
||||
var value = values[index]
|
||||
result[key] = value
|
||||
return result
|
||||
static func mergeDictionary(a: Dictionary, b: Dictionary) -> Dictionary:
|
||||
var result := {}
|
||||
for key in a:
|
||||
result[key] = a[key]
|
||||
for key in b:
|
||||
result[key] = result.get(key, 0.0) + b[key]
|
||||
return result
|
||||
|
||||
Reference in New Issue
Block a user