diff --git a/components/Abstracts/EntityBase.tscn b/components/Abstracts/EntityBase.tscn index 91b43f6..40a5a43 100644 --- a/components/Abstracts/EntityBase.tscn +++ b/components/Abstracts/EntityBase.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=36 format=3 uid="uid://cvogxi7mktumf"] +[gd_scene load_steps=40 format=3 uid="uid://cvogxi7mktumf"] [ext_resource type="Script" path="res://scripts/Statemachine/EntityBase.gd" id="1_mvol6"] [ext_resource type="Texture2D" uid="uid://dwwpkn4q07ja2" path="res://icon.svg" id="2_7lpu0"] @@ -169,6 +169,123 @@ _data = { "hurt": SubResource("Animation_wl2we") } +[sub_resource type="Animation" id="Animation_n7kxn"] +length = 0.001 +tracks/0/type = "bezier" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath(".:scale:x") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"handle_modes": PackedInt32Array(0), +"points": PackedFloat32Array(1, -0.25, 0, 0.25, 0), +"times": PackedFloat32Array(0) +} +tracks/1/type = "bezier" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath(".:scale:y") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"handle_modes": PackedInt32Array(0), +"points": PackedFloat32Array(1, -0.25, 0, 0.25, 0), +"times": PackedFloat32Array(0) +} +tracks/2/type = "bezier" +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/path = NodePath(".:modulate:a") +tracks/2/interp = 1 +tracks/2/loop_wrap = true +tracks/2/keys = { +"handle_modes": PackedInt32Array(0), +"points": PackedFloat32Array(1, -0.25, 0, 0.25, 0), +"times": PackedFloat32Array(0) +} + +[sub_resource type="Animation" id="Animation_lg0kn"] +resource_name = "exit" +step = 0.1 +tracks/0/type = "bezier" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath(".:scale:x") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"handle_modes": PackedInt32Array(0, 0), +"points": PackedFloat32Array(2, -0.25, 0, 0.25, 0, 1, -0.25, 0, 0.25, 0), +"times": PackedFloat32Array(0, 1) +} +tracks/1/type = "bezier" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath(".:scale:y") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"handle_modes": PackedInt32Array(0, 0), +"points": PackedFloat32Array(0, -0.25, 0, 0.25, 0, 1, -0.25, 0, 0.25, 0), +"times": PackedFloat32Array(0, 1) +} +tracks/2/type = "bezier" +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/path = NodePath(".:modulate:a") +tracks/2/interp = 1 +tracks/2/loop_wrap = true +tracks/2/keys = { +"handle_modes": PackedInt32Array(0, 0), +"points": PackedFloat32Array(0, -0.25, 0, 0.25, 0, 1, -0.25, 0, 0.25, 0), +"times": PackedFloat32Array(0, 1) +} + +[sub_resource type="Animation" id="Animation_nfj4q"] +resource_name = "exit" +step = 0.1 +tracks/0/type = "bezier" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath(".:scale:x") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"handle_modes": PackedInt32Array(0, 0), +"points": PackedFloat32Array(1, -0.25, 0, 0.25, 0, 2, -0.25, 0, 0.25, 0), +"times": PackedFloat32Array(0, 1) +} +tracks/1/type = "bezier" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath(".:scale:y") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"handle_modes": PackedInt32Array(0, 0), +"points": PackedFloat32Array(1, -0.25, 0, 0.25, 0, 0, -0.25, 0, 0.25, 0), +"times": PackedFloat32Array(0, 1) +} +tracks/2/type = "bezier" +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/path = NodePath(".:modulate:a") +tracks/2/interp = 1 +tracks/2/loop_wrap = true +tracks/2/keys = { +"handle_modes": PackedInt32Array(0, 0), +"points": PackedFloat32Array(1, -0.25, 0, 0.25, 0, 0, -0.25, 0, 0.25, 0), +"times": PackedFloat32Array(0, 1) +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_vvkcp"] +_data = { +"RESET": SubResource("Animation_n7kxn"), +"enter": SubResource("Animation_lg0kn"), +"exit": SubResource("Animation_nfj4q") +} + [sub_resource type="Curve" id="Curve_cs3iy"] _data = [Vector2(0, 1), 0.0, 0.0, 0, 0, Vector2(1, 0), 0.0, 0.0, 0, 0] point_count = 2 @@ -280,7 +397,6 @@ stream = ExtResource("2_qt0aq") [node name="texture" type="AnimatedSprite2D" parent="."] unique_name_in_owner = true position = Vector2(0, -50) -scale = Vector2(-1, 1) sprite_frames = SubResource("SpriteFrames_wcqpm") animation = &"idle" @@ -309,6 +425,12 @@ libraries = { "": SubResource("AnimationLibrary_kbmff") } +[node name="stageAnimator" type="AnimationPlayer" parent="texture"] +unique_name_in_owner = true +libraries = { +"": SubResource("AnimationLibrary_vvkcp") +} + [node name="weapons" type="Node2D" parent="texture"] unique_name_in_owner = true diff --git a/components/Characters/Bear.tscn b/components/Characters/Bear.tscn index 663975f..a97030d 100644 --- a/components/Characters/Bear.tscn +++ b/components/Characters/Bear.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=26 format=3 uid="uid://m60bwhdpbem8"] +[gd_scene load_steps=30 format=3 uid="uid://m60bwhdpbem8"] [ext_resource type="PackedScene" uid="uid://cvogxi7mktumf" path="res://components/Abstracts/EntityBase.tscn" id="1_3ves7"] [ext_resource type="Script" path="res://scripts/Contents/Characters/Bear.gd" id="2_kh2af"] @@ -34,6 +34,58 @@ animations = [{ [sub_resource type="RectangleShape2D" id="RectangleShape2D_akdh6"] size = Vector2(335, 344) +[sub_resource type="Animation" id="Animation_sxh2u"] +length = 0.001 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath(".:scale") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Vector2(-1, 1)] +} + +[sub_resource type="Animation" id="Animation_vxanw"] +resource_name = "left" +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath(".:scale") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Vector2(-1, 1)] +} + +[sub_resource type="Animation" id="Animation_nuh11"] +resource_name = "left" +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath(".:scale") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Vector2(1, 1)] +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_dwflo"] +_data = { +"RESET": SubResource("Animation_sxh2u"), +"left": SubResource("Animation_vxanw"), +"right": SubResource("Animation_nuh11") +} + [sub_resource type="Curve" id="Curve_u430e"] _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 @@ -125,6 +177,11 @@ visible = false position = Vector2(-2.5, -1) shape = SubResource("RectangleShape2D_akdh6") +[node name="animator" parent="texture" index="1"] +libraries = { +"": SubResource("AnimationLibrary_dwflo") +} + [node name="normal" type="Node2D" parent="texture/weapons" index="0"] [node name="sprintParticle" type="GPUParticles2D" parent="texture" index="6"] @@ -136,6 +193,8 @@ process_material = SubResource("ParticleProcessMaterial_5v3nj") texture = ExtResource("13_v2sdb") [node name="mask" type="Sprite2D" parent="texture" index="7"] +unique_name_in_owner = true +visible = false material = SubResource("ShaderMaterial_6h05p") texture = ExtResource("13_v2sdb") diff --git a/scripts/Contents/Characters/Bear.gd b/scripts/Contents/Characters/Bear.gd index cc637fa..318f801 100644 --- a/scripts/Contents/Characters/Bear.gd +++ b/scripts/Contents/Characters/Bear.gd @@ -2,6 +2,7 @@ extends EntityBase class_name Bear # 攻击方式模仿泰拉瑞亚光之女皇 @onready var sprintParticle: GPUParticles2D = $"%sprintParticle" +@onready var mask: Sprite2D = $"%mask" func register(): fields[FieldStore.Entity.MAX_HEALTH] = 2000 @@ -15,12 +16,19 @@ func register(): attackCooldownMap[6] = 10000 attackCooldownMap[7] = 9000 sprintMultiplier = 80 + healthChanged.connect( + func(newHealth): + setStage(1 if newHealth < fields[FieldStore.Entity.MAX_HEALTH] * 0.5 else 0) + ) func spawn(): texture.play("walk") func ai(): PresetEntityAI.follow(self, currentFocusedBoss, 400) for i in len(attackCooldownMap.keys()): tryAttack(i) +func enterStage(stage): + mask.visible = !!stage + await TickTool.millseconds(2000) func attack(type): var weaponPos = findWeaponAnchor("normal") if type == 0: @@ -82,11 +90,11 @@ func attack(type): await TickTool.millseconds(100) return false elif type == 7: - playSound("attack7") var angle = deg_to_rad(70) for j in 4: var initAngle = randf_range(0, 360) if !is_instance_valid(currentFocusedBoss): return false + playSound("attack7") for i in 16: for bullet in BulletBase.generate(preload("res://components/Bullets/BossAttack/Bear/LightGun.tscn"), self, currentFocusedBoss.position, 0): bullet.rotation_degrees += initAngle diff --git a/scripts/Statemachine/EntityBase.gd b/scripts/Statemachine/EntityBase.gd index 5f18b03..817f0be 100644 --- a/scripts/Statemachine/EntityBase.gd +++ b/scripts/Statemachine/EntityBase.gd @@ -78,6 +78,7 @@ var inventoryMax = { @onready var hurtbox: Area2D = $"%hurtbox" @onready var sounds: Node2D = $"%sounds" @onready var hurtAnimator: AnimationPlayer = $"%hurtAnimator" +@onready var stageAnimator: AnimationPlayer = $"%stageAnimator" @onready var damageAnchor: Node2D = $"%damageAnchor" @onready var trailParticle: GPUParticles2D = $"%trailParticle" @onready var weaponStore = $"%weaponStore" @@ -94,6 +95,7 @@ var currentFocusedBoss: EntityBase = null var charginup: bool = false var weapons: Array[Weapon] = [] var canRunAi: bool = true +var currentStage: int = 0 func _ready(): register() @@ -164,6 +166,19 @@ func _physics_process(_delta: float) -> void: trailParticle.emitting = trailing # 通用方法 +func setStage(stage: int): + if currentStage == stage: + return + canRunAi = false + var oldStage = currentStage + currentStage = stage + stageAnimator.play("exit") + await stageAnimator.animation_finished + await exitStage(oldStage) + await enterStage(stage) + stageAnimator.play("enter") + await stageAnimator.animation_finished + canRunAi = true func applyLevel(): fields[FieldStore.Entity.MAX_HEALTH] *= (1 + GameRule.entityHealthIncreasePerWave * (GameRule.difficulty + 1)) ** level fields[FieldStore.Entity.DAMAGE_MULTIPILER] *= (1 + GameRule.entityDamageIncreasePerWave * (GameRule.difficulty + 1)) ** level @@ -342,6 +357,10 @@ func register(): pass func spawn(): pass +func exitStage(_stage: int): + pass +func enterStage(_stage: int): + pass static func generate( entity: PackedScene,