diff --git a/Assets/skins/phoebe_skin.tres b/Assets/skins/phoebe_skin.tres new file mode 100644 index 00000000..f53dd169 --- /dev/null +++ b/Assets/skins/phoebe_skin.tres @@ -0,0 +1,13 @@ +[gd_resource type="Resource" script_class="SkinData" format=3 uid="uid://s5c2qgydsf8d"] + +[ext_resource type="Script" uid="uid://c6vuqckcyjdey" path="res://Scripts/menu/skin_data.gd" id="1_33o6v"] +[ext_resource type="PackedScene" uid="uid://c00u6gwrp401x" path="res://Scenes/skins/phoebe_skin.tscn" id="2_n5nul"] + +[resource] +script = ExtResource("1_33o6v") +skin_id = "phoebe_skin" +true_name = "菲比啾比" +description = "海風溫和!菲比啾比!" +price_text_override = "明年成為 Challenge 組員" +skin_prefab = ExtResource("2_n5nul") +metadata/_custom_type_script = "uid://c6vuqckcyjdey" diff --git a/Scenes/menu/skin_shop.tscn b/Scenes/menu/skin_shop.tscn index 6262e29e..d79929a0 100644 --- a/Scenes/menu/skin_shop.tscn +++ b/Scenes/menu/skin_shop.tscn @@ -37,6 +37,7 @@ [ext_resource type="Resource" uid="uid://bkdpwtdnacuk7" path="res://Assets/skins/close_button_skin.tres" id="31_te67l2"] [ext_resource type="Resource" uid="uid://8fjvexvxryqw" path="res://Assets/skins/sans_skin.tres" id="32_so6hm"] [ext_resource type="Resource" uid="uid://c1lvf816dp64b" path="res://Assets/skins/worship_skin.tres" id="36_qb5jc"] +[ext_resource type="Resource" uid="uid://s5c2qgydsf8d" path="res://Assets/skins/phoebe_skin.tres" id="37_qb5jd"] [node name="SkinShop" type="Control" unique_id=1696416848] layout_mode = 3 @@ -48,7 +49,7 @@ grow_vertical = 2 theme = ExtResource("7_theme") script = ExtResource("1_0p25h") skin_item_scene = ExtResource("2_5rtp3") -all_skins = Array[ExtResource("2_h3ndm")]([ExtResource("4_bliee"), ExtResource("10_advanced"), ExtResource("11_phantom"), ExtResource("12_magma"), ExtResource("13_slime"), ExtResource("14_meteor"), ExtResource("15_cyber"), ExtResource("16_thunder"), ExtResource("5_ta6b8"), ExtResource("6_dap7d"), ExtResource("9_ta6b8"), ExtResource("3_5rtp3"), ExtResource("17_sing"), ExtResource("18_abs"), ExtResource("19_retro"), ExtResource("20_vfdo8"), ExtResource("21_amongus"), ExtResource("22_matrix"), ExtResource("23_ut"), ExtResource("24_coconut_king"), ExtResource("25_rbt"), ExtResource("26_perry"), ExtResource("27_claude"), ExtResource("28_steel_brain"), ExtResource("29_tbc"), ExtResource("28_v4wv5"), ExtResource("31_te67l"), ExtResource("30_drive_skin"), ExtResource("31_te67l2"), ExtResource("30_invpalm"), ExtResource("32_so6hm"), ExtResource("36_qb5jc")]) +all_skins = Array[ExtResource("2_h3ndm")]([ExtResource("4_bliee"), ExtResource("10_advanced"), ExtResource("11_phantom"), ExtResource("12_magma"), ExtResource("13_slime"), ExtResource("14_meteor"), ExtResource("15_cyber"), ExtResource("16_thunder"), ExtResource("5_ta6b8"), ExtResource("6_dap7d"), ExtResource("9_ta6b8"), ExtResource("3_5rtp3"), ExtResource("17_sing"), ExtResource("18_abs"), ExtResource("19_retro"), ExtResource("20_vfdo8"), ExtResource("21_amongus"), ExtResource("22_matrix"), ExtResource("23_ut"), ExtResource("24_coconut_king"), ExtResource("25_rbt"), ExtResource("26_perry"), ExtResource("27_claude"), ExtResource("28_steel_brain"), ExtResource("29_tbc"), ExtResource("28_v4wv5"), ExtResource("31_te67l"), ExtResource("30_drive_skin"), ExtResource("31_te67l2"), ExtResource("30_invpalm"), ExtResource("32_so6hm"), ExtResource("36_qb5jc"), ExtResource("37_qb5jd")]) [node name="Background" type="TextureRect" parent="." unique_id=1385573461] modulate = Color(1, 1, 1, 0.7490196) diff --git a/Scenes/skins/phoebe_skin.tscn b/Scenes/skins/phoebe_skin.tscn new file mode 100644 index 00000000..0c81e3a8 --- /dev/null +++ b/Scenes/skins/phoebe_skin.tscn @@ -0,0 +1,379 @@ +[gd_scene format=3 uid="uid://c00u6gwrp401x"] + +[ext_resource type="Script" uid="uid://n4ys3ocjtbrn" path="res://Scripts/skins/phoebe_skin.gd" id="1_3v2an"] +[ext_resource type="Texture2D" uid="uid://dtpcqwa4dak86" path="res://Shapes/phoebo.webp" id="2_eqia5"] + +[sub_resource type="AtlasTexture" id="AtlasTexture_dv5va"] +atlas = ExtResource("2_eqia5") +region = Rect2(0, 1040, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_roin1"] +atlas = ExtResource("2_eqia5") +region = Rect2(192, 1040, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_evkf2"] +atlas = ExtResource("2_eqia5") +region = Rect2(384, 1040, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_hgx6x"] +atlas = ExtResource("2_eqia5") +region = Rect2(576, 1040, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_og881"] +atlas = ExtResource("2_eqia5") +region = Rect2(768, 1040, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_27onu"] +atlas = ExtResource("2_eqia5") +region = Rect2(960, 1040, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_t6var"] +atlas = ExtResource("2_eqia5") +region = Rect2(1152, 1040, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_ffdf7"] +atlas = ExtResource("2_eqia5") +region = Rect2(1344, 1040, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_e05er"] +atlas = ExtResource("2_eqia5") +region = Rect2(0, 0, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_7tlwi"] +atlas = ExtResource("2_eqia5") +region = Rect2(192, 0, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_o2abm"] +atlas = ExtResource("2_eqia5") +region = Rect2(384, 0, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_shln6"] +atlas = ExtResource("2_eqia5") +region = Rect2(576, 0, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_1ewyf"] +atlas = ExtResource("2_eqia5") +region = Rect2(768, 0, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_2dv85"] +atlas = ExtResource("2_eqia5") +region = Rect2(960, 0, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_yura4"] +atlas = ExtResource("2_eqia5") +region = Rect2(0, 832, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_ua6p7"] +atlas = ExtResource("2_eqia5") +region = Rect2(192, 832, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_rwj2o"] +atlas = ExtResource("2_eqia5") +region = Rect2(384, 832, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_2s0kl"] +atlas = ExtResource("2_eqia5") +region = Rect2(576, 832, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_v0coo"] +atlas = ExtResource("2_eqia5") +region = Rect2(768, 832, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_444o4"] +atlas = ExtResource("2_eqia5") +region = Rect2(0, 1456, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_hid32"] +atlas = ExtResource("2_eqia5") +region = Rect2(192, 1456, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_qpuqb"] +atlas = ExtResource("2_eqia5") +region = Rect2(384, 1456, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_k651v"] +atlas = ExtResource("2_eqia5") +region = Rect2(576, 1456, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_odsmv"] +atlas = ExtResource("2_eqia5") +region = Rect2(768, 1456, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_tedc4"] +atlas = ExtResource("2_eqia5") +region = Rect2(960, 1456, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_eqia5"] +atlas = ExtResource("2_eqia5") +region = Rect2(0, 416, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_g6g7f"] +atlas = ExtResource("2_eqia5") +region = Rect2(192, 416, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_hwtwk"] +atlas = ExtResource("2_eqia5") +region = Rect2(384, 416, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_lnouf"] +atlas = ExtResource("2_eqia5") +region = Rect2(576, 416, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_f2tjp"] +atlas = ExtResource("2_eqia5") +region = Rect2(768, 416, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_qf23n"] +atlas = ExtResource("2_eqia5") +region = Rect2(960, 416, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_m432d"] +atlas = ExtResource("2_eqia5") +region = Rect2(1152, 416, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_6116h"] +atlas = ExtResource("2_eqia5") +region = Rect2(1344, 416, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_wjk7i"] +atlas = ExtResource("2_eqia5") +region = Rect2(0, 208, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_a0qk2"] +atlas = ExtResource("2_eqia5") +region = Rect2(192, 208, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_q7rsq"] +atlas = ExtResource("2_eqia5") +region = Rect2(384, 208, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_pxbpm"] +atlas = ExtResource("2_eqia5") +region = Rect2(576, 208, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_2m8cw"] +atlas = ExtResource("2_eqia5") +region = Rect2(768, 208, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_417xj"] +atlas = ExtResource("2_eqia5") +region = Rect2(960, 208, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_8m25i"] +atlas = ExtResource("2_eqia5") +region = Rect2(1152, 208, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_voxcc"] +atlas = ExtResource("2_eqia5") +region = Rect2(1344, 208, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_udf8x"] +atlas = ExtResource("2_eqia5") +region = Rect2(0, 1248, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_h08kb"] +atlas = ExtResource("2_eqia5") +region = Rect2(192, 1248, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_x7vpc"] +atlas = ExtResource("2_eqia5") +region = Rect2(384, 1248, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_c617d"] +atlas = ExtResource("2_eqia5") +region = Rect2(576, 1248, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_a0qdd"] +atlas = ExtResource("2_eqia5") +region = Rect2(768, 1248, 192, 208) + +[sub_resource type="AtlasTexture" id="AtlasTexture_cgcch"] +atlas = ExtResource("2_eqia5") +region = Rect2(960, 1248, 192, 208) + +[sub_resource type="SpriteFrames" id="SpriteFrames_3v2an"] +animations = [{ +"frames": [{ +"duration": 1.0, +"texture": SubResource("AtlasTexture_dv5va") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_roin1") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_evkf2") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_hgx6x") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_og881") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_27onu") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_t6var") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_ffdf7") +}], +"loop": true, +"name": &"failed", +"speed": 5.0 +}, { +"frames": [{ +"duration": 1.0, +"texture": SubResource("AtlasTexture_e05er") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_7tlwi") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_o2abm") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_shln6") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_1ewyf") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_2dv85") +}], +"loop": true, +"name": &"idle", +"speed": 5.0 +}, { +"frames": [{ +"duration": 1.0, +"texture": SubResource("AtlasTexture_yura4") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_ua6p7") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_rwj2o") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_2s0kl") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_v0coo") +}], +"loop": true, +"name": &"jumping", +"speed": 5.0 +}, { +"frames": [{ +"duration": 1.0, +"texture": SubResource("AtlasTexture_444o4") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_hid32") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_qpuqb") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_k651v") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_odsmv") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_tedc4") +}], +"loop": true, +"name": &"running", +"speed": 5.0 +}, { +"frames": [{ +"duration": 1.0, +"texture": SubResource("AtlasTexture_eqia5") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_g6g7f") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_hwtwk") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_lnouf") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_f2tjp") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_qf23n") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_m432d") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_6116h") +}], +"loop": true, +"name": &"running_left", +"speed": 5.0 +}, { +"frames": [{ +"duration": 1.0, +"texture": SubResource("AtlasTexture_wjk7i") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_a0qk2") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_q7rsq") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_pxbpm") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_2m8cw") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_417xj") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_8m25i") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_voxcc") +}], +"loop": true, +"name": &"running_right", +"speed": 5.0 +}, { +"frames": [{ +"duration": 1.0, +"texture": SubResource("AtlasTexture_udf8x") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_h08kb") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_x7vpc") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_c617d") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_a0qdd") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_cgcch") +}], +"loop": true, +"name": &"waving", +"speed": 5.0 +}] + +[node name="PhoebeSkin" type="Node2D" unique_id=1762164643] +scale = Vector2(0.25, 0.25) +script = ExtResource("1_3v2an") + +[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="." unique_id=333138197] +sprite_frames = SubResource("SpriteFrames_3v2an") +animation = &"failed" diff --git a/Scripts/menu/player_data.gd b/Scripts/menu/player_data.gd index 878f540d..c3029d04 100644 --- a/Scripts/menu/player_data.gd +++ b/Scripts/menu/player_data.gd @@ -37,7 +37,8 @@ const REDEEM_CODES = { "b355c1e254a16eec13b5b41a6460c6ada838ae6e9ce8b53c29c89861f98ef2f4": "inverted_palm_skin", "880467377209f84a74e1379d52067614d62162b88f1a63a9ea13d6f13f167ee1": "close_button_skin", "6b3fa673194d764cc52a0526717c3619efa8d2be0cc85e0f45c16ae05a14cb3c": "sans_skin", - "123d4ee8f612e11cb2776ae19aec390e5c139a64fdebbda2713706b0178648b5": "worship_skin" + "123d4ee8f612e11cb2776ae19aec390e5c139a64fdebbda2713706b0178648b5": "worship_skin", + "6c1b16a5a34b8b273636569e7952512a6bb4503e5badc12cdc62dad1e90f53d0": "phoebe_skin" } var entered_codes: Array = [] diff --git a/Scripts/skins/phoebe_skin.gd b/Scripts/skins/phoebe_skin.gd new file mode 100644 index 00000000..997e7e76 --- /dev/null +++ b/Scripts/skins/phoebe_skin.gd @@ -0,0 +1,216 @@ +extends BaseSkin + +# --- Visual Settings --- +const IDLE_WAVE_THRESHOLD: float = 3.0 +const MAX_LEAN_ANGLE: float = 8.0 # How many degrees to tilt when running + +# State flags +var is_dead: bool = false +var is_spawning: bool = false +var is_celebrating: bool = false +var is_jumping: bool = false +var is_idle_waving: bool = false + +var idle_time: float = 0.0 +var player: CharacterBody2D = null + +# Active tweens for juice effects +var scale_tween: Tween +var rotation_tween: Tween +var current_visual_state: String = "none" + +# Onready variables must be declared LAST, right before your methods! +@onready var sprite = $AnimatedSprite2D + + +func _ready() -> void: + if has_meta("player"): + player = get_meta("player") + + +func _process(delta: float) -> void: + if is_dead: + _set_visual_state("failed") + return + + # 1. Grab inputs + var horizontal_input = Input.get_axis("move_left", "move_right") + var vertical_input = Input.is_action_pressed("move_up") or Input.is_action_pressed("move_down") + var is_moving = (horizontal_input != 0) or vertical_input + + # 2. Inactivity tracking + if is_moving or is_jumping: + idle_time = 0.0 + is_idle_waving = false + is_spawning = false + is_celebrating = false + else: + if not is_spawning and not is_celebrating and not is_idle_waving: + idle_time += delta + if idle_time >= IDLE_WAVE_THRESHOLD: + is_idle_waving = true + + # 3. Determine and assign current animation state + if is_spawning or is_celebrating or is_idle_waving: + _set_visual_state("waving") + elif is_jumping: + _set_visual_state("jumping") + elif horizontal_input < 0: + _set_visual_state("running_left") + elif horizontal_input > 0: + _set_visual_state("running_right") + elif vertical_input: + _set_visual_state("running_up_down") + else: + _set_visual_state("idle") + + +# --- Dynamic State Machine --- + + +func _set_visual_state(new_state: String) -> void: + if current_visual_state == new_state: + return + + current_visual_state = new_state + + match new_state: + "idle", "waving": + sprite.play(new_state) + _start_breathing_loop() + _apply_lean(0.0) + + "running_left": + _stop_breathing_loop() + sprite.play("running_left") + _apply_lean(-MAX_LEAN_ANGLE) + + "running_right": + _stop_breathing_loop() + sprite.play("running_right") + _apply_lean(MAX_LEAN_ANGLE) + + "running_up_down": + _stop_breathing_loop() + sprite.play("running") + _apply_lean(0.0) + + "jumping": + _stop_breathing_loop() + sprite.play("jumping") + _apply_lean(0.0) + + "failed": + _stop_breathing_loop() + if rotation_tween and rotation_tween.is_valid(): + rotation_tween.kill() + + # Reset visual changes so the failed loop looks completely natural + sprite.scale = Vector2.ONE + sprite.rotation_degrees = 0.0 + sprite.play("failed") + + +# --- Event-Driven Juice Effects --- + + +func play_spawn() -> void: + is_spawning = true + is_dead = false + is_celebrating = false + is_jumping = false + is_idle_waving = false + idle_time = 0.0 + + if scale_tween and scale_tween.is_valid(): + scale_tween.kill() + sprite.scale = Vector2.ZERO + scale_tween = create_tween().set_trans(Tween.TRANS_ELASTIC).set_ease(Tween.EASE_OUT) + scale_tween.tween_property(sprite, "scale", Vector2.ONE, 1.2) + + if is_inside_tree(): + get_tree().create_timer(1.5).timeout.connect(func(): is_spawning = false) + + +func play_die() -> void: + is_dead = true + _set_visual_state("failed") + + # Keep the game tree pause-timer happy + if is_inside_tree(): + await get_tree().create_timer(1.0, true).timeout + + +func play_eat_ball() -> void: + if not is_dead: + is_celebrating = true + idle_time = 0.0 + + if scale_tween and scale_tween.is_valid(): + scale_tween.kill() + sprite.scale = Vector2(1.3, 1.3) + scale_tween = create_tween().set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT) + scale_tween.tween_property(sprite, "scale", Vector2.ONE, 0.4) + + if is_inside_tree(): + get_tree().create_timer(1.0).timeout.connect(func(): is_celebrating = false) + + +func play_jump() -> void: + if not is_dead: + is_jumping = true + idle_time = 0.0 + + if scale_tween and scale_tween.is_valid(): + scale_tween.kill() + sprite.scale = Vector2(0.75, 1.35) + scale_tween = create_tween().set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT) + scale_tween.tween_property(sprite, "scale", Vector2.ONE, 0.35) + + +func play_land() -> void: + if not is_dead: + is_jumping = false + idle_time = 0.0 + + if scale_tween and scale_tween.is_valid(): + scale_tween.kill() + sprite.scale = Vector2(1.4, 0.65) + scale_tween = create_tween().set_trans(Tween.TRANS_ELASTIC).set_ease(Tween.EASE_OUT) + scale_tween.tween_property(sprite, "scale", Vector2.ONE, 0.6) + + +# --- Tween Helper Engines --- + + +func _apply_lean(angle_degrees: float) -> void: + if rotation_tween and rotation_tween.is_valid(): + rotation_tween.kill() + rotation_tween = create_tween().set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_OUT) + rotation_tween.tween_property(sprite, "rotation_degrees", angle_degrees, 0.15) + + +func _start_breathing_loop() -> void: + if scale_tween and scale_tween.is_valid(): + scale_tween.kill() + sprite.scale = Vector2.ONE + + scale_tween = create_tween().set_loops() + ( + scale_tween + . tween_property(sprite, "scale", Vector2(0.97, 1.03), 0.7) + . set_trans(Tween.TRANS_SINE) + . set_ease(Tween.EASE_IN_OUT) + ) + ( + scale_tween + . tween_property(sprite, "scale", Vector2(1.03, 0.97), 0.7) + . set_trans(Tween.TRANS_SINE) + . set_ease(Tween.EASE_IN_OUT) + ) + + +func _stop_breathing_loop() -> void: + if scale_tween and scale_tween.is_valid(): + scale_tween.kill() + sprite.scale = Vector2.ONE diff --git a/Scripts/skins/phoebe_skin.gd.uid b/Scripts/skins/phoebe_skin.gd.uid new file mode 100644 index 00000000..df5ce7a7 --- /dev/null +++ b/Scripts/skins/phoebe_skin.gd.uid @@ -0,0 +1 @@ +uid://n4ys3ocjtbrn diff --git a/Shapes/phoebo.webp b/Shapes/phoebo.webp new file mode 100644 index 00000000..c9bdb590 Binary files /dev/null and b/Shapes/phoebo.webp differ diff --git a/Shapes/phoebo.webp.import b/Shapes/phoebo.webp.import new file mode 100644 index 00000000..bea04357 --- /dev/null +++ b/Shapes/phoebo.webp.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dtpcqwa4dak86" +path="res://.godot/imported/phoebo.webp-5c640e7a4db81e452f5359abc62cecf4.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Shapes/phoebo.webp" +dest_files=["res://.godot/imported/phoebo.webp-5c640e7a4db81e452f5359abc62cecf4.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1