diff --git a/Assets/Resources/Games/rhythmTweezers.prefab b/Assets/Resources/Games/rhythmTweezers.prefab index 3987d476..4b8cbe1f 100644 --- a/Assets/Resources/Games/rhythmTweezers.prefab +++ b/Assets/Resources/Games/rhythmTweezers.prefab @@ -820,6 +820,7 @@ MonoBehaviour: hairSprite: {fileID: 2595271014815681993} stubbleSprite: {fileID: 1989337582260767153} holder: {fileID: 2160021042345747175} + loop: {fileID: 1603625733790180753} --- !u!1 &3082739543595333088 GameObject: m_ObjectHideFlags: 0 @@ -1261,6 +1262,7 @@ MonoBehaviour: m_EditorClassIdentifier: hitOnFrame: 0 heldHairSprite: {fileID: 267307033549538062} + tweezerSpriteTrans: {fileID: 2763505388420312793} --- !u!95 &574744067652312223 Animator: serializedVersion: 3 diff --git a/Assets/Resources/Sprites/Games/RhythmTweezers/Animations/Hairs/LoopPull.anim b/Assets/Resources/Sprites/Games/RhythmTweezers/Animations/Hairs/LoopPull.anim index fda62ace..d17b8988 100644 --- a/Assets/Resources/Sprites/Games/RhythmTweezers/Animations/Hairs/LoopPull.anim +++ b/Assets/Resources/Sprites/Games/RhythmTweezers/Animations/Hairs/LoopPull.anim @@ -84,15 +84,15 @@ AnimationClip: time: 0 value: {x: 1, y: 0.8, z: 1} inSlope: {x: 0, y: 0, z: 0} - outSlope: {x: 0, y: 3.3500001, z: 0} + outSlope: {x: 0, y: 6, z: 0} tangentMode: 0 weightedMode: 0 inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} - serializedVersion: 3 time: 0.2 - value: {x: 1, y: 1.47, z: 1} - inSlope: {x: -0, y: 3.3500001, z: -0} + value: {x: 1, y: 2, z: 1} + inSlope: {x: -0, y: 6, z: -0} outSlope: {x: 0, y: 0, z: 0} tangentMode: 0 weightedMode: 0 @@ -425,15 +425,15 @@ AnimationClip: time: 0 value: 0.8 inSlope: 0 - outSlope: 3.3500001 + outSlope: 6 tangentMode: 69 weightedMode: 0 inWeight: 0.33333334 outWeight: 0.33333334 - serializedVersion: 3 time: 0.2 - value: 1.47 - inSlope: 3.3500001 + value: 2 + inSlope: 6 outSlope: 0 tangentMode: 69 weightedMode: 0 diff --git a/Assets/Scripts/Games/RhythmTweezers/LongHair.cs b/Assets/Scripts/Games/RhythmTweezers/LongHair.cs index 0f09203b..f8679f92 100644 --- a/Assets/Scripts/Games/RhythmTweezers/LongHair.cs +++ b/Assets/Scripts/Games/RhythmTweezers/LongHair.cs @@ -13,52 +13,100 @@ namespace RhythmHeavenMania.Games.RhythmTweezers public GameObject stubbleSprite; private RhythmTweezers game; private Tweezers tweezers; - - private bool isHolding = false; - private float holdBeat = 0f; + private Animator anim; + private int pluckState = 0; public GameObject holder; + public GameObject loop; + + private AudioSource pullSound; private void Awake() { game = RhythmTweezers.instance; + anim = GetComponent(); tweezers = game.Tweezers; } private void Update() { - float stateBeat = Conductor.instance.GetPositionFromBeat(createBeat + game.tweezerBeatOffset, game.beatInterval); - StateCheck(stateBeat); + float stateBeat; - if (PlayerInput.Pressed() && tweezers.hitOnFrame == 0) + switch (pluckState) { - if (state.perfect) - { - Jukebox.PlayOneShotGame($"rhythmTweezers/longPull{UnityEngine.Random.Range(1, 5)}"); - isHolding = true; - holdBeat = Conductor.instance.songPositionInBeats; - } + // Able to be held. + case 0: + stateBeat = Conductor.instance.GetPositionFromMargin(createBeat + game.tweezerBeatOffset + game.beatInterval, 1f); + StateCheck(stateBeat); + + if (PlayerInput.Pressed()) + { + if (state.perfect) + { + pullSound = Jukebox.PlayOneShotGame($"rhythmTweezers/longPull{UnityEngine.Random.Range(1, 5)}"); + pluckState = 1; + ResetState(); + } + else if (state.notPerfect()) + { + // I don't know what happens if you mess up here. + pluckState = -1; + } + } + break; + + // In held state. Able to be released. + case 1: + stateBeat = Conductor.instance.GetPositionFromMargin(createBeat + game.tweezerBeatOffset + game.beatInterval + 0.5f, 1f); + StateCheck(stateBeat); + + if (PlayerInput.PressedUp()) + { + // It's possible to release earlier than earlyTime, + // and the hair will automatically be released before lateTime, + // so standard state checking isn't applied here + // (though StateCheck is still used for autoplay). + if (stateBeat >= Minigame.perfectTime) + { + Ace(); + } + else + { + var normalized = Conductor.instance.GetPositionFromBeat(createBeat + game.tweezerBeatOffset + game.beatInterval, 0.5f); + // Hair gets released early and returns whoops. + anim.Play("LoopPullReverse", 0, normalized); + tweezers.anim.Play("Idle", 0, 0); + + if (pullSound != null) + pullSound.Stop(); + + pluckState = -1; + } + } + break; + + // Released or missed. Can't be held or released. + default: + break; } - if (isHolding && Conductor.instance.songPositionInBeats >= holdBeat + 0.5f) + if (pluckState == 1) { - Destroy(holder.transform.GetChild(0).gameObject); - isHolding = false; - Ace(); - } + var hairDirection = tweezers.tweezerSpriteTrans.position - holder.transform.position; + holder.transform.rotation = Quaternion.FromToRotation(Vector3.down, hairDirection); - - if (isHolding) - { - holder.transform.eulerAngles = new Vector3(0, 0, tweezers.transform.eulerAngles.z * 1.056f); - holder.transform.GetChild(0).transform.localScale = Vector2.one / holder.transform.localScale; - - float normalizedBeat = Conductor.instance.GetPositionFromBeat(holdBeat, 0.5f); - GetComponent().Play("LoopPull", 0, normalizedBeat); + float normalizedBeat = Conductor.instance.GetPositionFromBeat(createBeat + game.tweezerBeatOffset + game.beatInterval, 0.5f); + anim.Play("LoopPull", 0, normalizedBeat); tweezers.anim.Play("Tweezers_LongPluck", 0, normalizedBeat); // float angleBetweenTweezersAndHair = angleBtw2Points(tweezers.transform.position, holder.transform.position); // holder.transform.rotation = Quaternion.Euler(new Vector3(0, 0, angleBetweenTweezersAndHair)); + + // Auto-release if holding at release time. + if (normalizedBeat >= 1f) + Ace(); } + + loop.transform.localScale = Vector2.one / holder.transform.localScale; } @@ -69,10 +117,27 @@ namespace RhythmHeavenMania.Games.RhythmTweezers public void Ace() { - Jukebox.PlayOneShotGame("rhythmTweezers/longPullEnd"); tweezers.LongPluck(true, this); - tweezers.hitOnFrame++; + + if (pullSound != null) + pullSound.Stop(); + + pluckState = -1; + } + + public override void OnAce() + { + if (pluckState == 0) + { + pullSound = Jukebox.PlayOneShotGame($"rhythmTweezers/longPull{UnityEngine.Random.Range(1, 5)}"); + pluckState = 1; + ResetState(); + } + else if (pluckState == 1) + { + Ace(); + } } } } \ No newline at end of file diff --git a/Assets/Scripts/Games/RhythmTweezers/Tweezers.cs b/Assets/Scripts/Games/RhythmTweezers/Tweezers.cs index 9980afab..9e4b5a64 100644 --- a/Assets/Scripts/Games/RhythmTweezers/Tweezers.cs +++ b/Assets/Scripts/Games/RhythmTweezers/Tweezers.cs @@ -16,6 +16,7 @@ namespace RhythmHeavenMania.Games.RhythmTweezers private bool pluckingThisFrame; private bool holdingHair; public SpriteRenderer heldHairSprite; + public Transform tweezerSpriteTrans; private void Start() { @@ -83,8 +84,12 @@ namespace RhythmHeavenMania.Games.RhythmTweezers if (ace) { + Jukebox.PlayOneShotGame("rhythmTweezers/longPullEnd"); + hair.hairSprite.SetActive(false); hair.stubbleSprite.SetActive(true); + // Making transparent instead of disabling because animators are silly. + hair.loop.GetComponent().color = Color.clear; game.hairsLeft--; game.eyeSize = Mathf.Clamp(game.eyeSize + 1, 0, 10); diff --git a/Assets/Scripts/Util/Jukebox.cs b/Assets/Scripts/Util/Jukebox.cs index 50fa63b7..079039fd 100644 --- a/Assets/Scripts/Util/Jukebox.cs +++ b/Assets/Scripts/Util/Jukebox.cs @@ -40,7 +40,7 @@ namespace RhythmHeavenMania.Util FindJukebox().GetComponent().volume = volume; } - public static void PlayOneShot(string name, float beat = -1) + public static AudioSource PlayOneShot(string name, float beat = -1) { GameObject oneShot = new GameObject("oneShot"); @@ -55,9 +55,11 @@ namespace RhythmHeavenMania.Util // snd.pitch = (clip.length / Conductor.instance.secPerBeat); GameManager.instance.SoundObjects.Add(oneShot); + + return audioSource; } - public static void PlayOneShotScheduled(string name, double targetTime) + public static AudioSource PlayOneShotScheduled(string name, double targetTime) { GameObject oneShot = new GameObject("oneShotScheduled"); @@ -75,22 +77,28 @@ namespace RhythmHeavenMania.Util audioSource.PlayScheduled(targetTime); GameManager.instance.SoundObjects.Add(oneShot); + + return audioSource; } - public static void PlayOneShotGame(string name, float beat = -1) + public static AudioSource PlayOneShotGame(string name, float beat = -1) { if (GameManager.instance.currentGame == name.Split('/')[0]) { - PlayOneShot($"games/{name}", beat); + return PlayOneShot($"games/{name}", beat); } + + return null; } - public static void PlayOneShotScheduledGame(string name, double targetTime) + public static AudioSource PlayOneShotScheduledGame(string name, double targetTime) { if (GameManager.instance.currentGame == name.Split('/')[0]) { - PlayOneShotScheduled($"games/{name}", targetTime); + return PlayOneShotScheduled($"games/{name}", targetTime); } + + return null; } }