Tweezers: Long hair implementation

This commit is contained in:
Jenny Crowe 2022-02-11 00:21:43 -07:00
parent a65a6c012c
commit b5a49c7ce9
5 changed files with 119 additions and 39 deletions

View file

@ -820,6 +820,7 @@ MonoBehaviour:
hairSprite: {fileID: 2595271014815681993} hairSprite: {fileID: 2595271014815681993}
stubbleSprite: {fileID: 1989337582260767153} stubbleSprite: {fileID: 1989337582260767153}
holder: {fileID: 2160021042345747175} holder: {fileID: 2160021042345747175}
loop: {fileID: 1603625733790180753}
--- !u!1 &3082739543595333088 --- !u!1 &3082739543595333088
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -1261,6 +1262,7 @@ MonoBehaviour:
m_EditorClassIdentifier: m_EditorClassIdentifier:
hitOnFrame: 0 hitOnFrame: 0
heldHairSprite: {fileID: 267307033549538062} heldHairSprite: {fileID: 267307033549538062}
tweezerSpriteTrans: {fileID: 2763505388420312793}
--- !u!95 &574744067652312223 --- !u!95 &574744067652312223
Animator: Animator:
serializedVersion: 3 serializedVersion: 3

View file

@ -84,15 +84,15 @@ AnimationClip:
time: 0 time: 0
value: {x: 1, y: 0.8, z: 1} value: {x: 1, y: 0.8, z: 1}
inSlope: {x: 0, y: 0, z: 0} inSlope: {x: 0, y: 0, z: 0}
outSlope: {x: 0, y: 3.3500001, z: 0} outSlope: {x: 0, y: 6, z: 0}
tangentMode: 0 tangentMode: 0
weightedMode: 0 weightedMode: 0
inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
- serializedVersion: 3 - serializedVersion: 3
time: 0.2 time: 0.2
value: {x: 1, y: 1.47, z: 1} value: {x: 1, y: 2, z: 1}
inSlope: {x: -0, y: 3.3500001, z: -0} inSlope: {x: -0, y: 6, z: -0}
outSlope: {x: 0, y: 0, z: 0} outSlope: {x: 0, y: 0, z: 0}
tangentMode: 0 tangentMode: 0
weightedMode: 0 weightedMode: 0
@ -425,15 +425,15 @@ AnimationClip:
time: 0 time: 0
value: 0.8 value: 0.8
inSlope: 0 inSlope: 0
outSlope: 3.3500001 outSlope: 6
tangentMode: 69 tangentMode: 69
weightedMode: 0 weightedMode: 0
inWeight: 0.33333334 inWeight: 0.33333334
outWeight: 0.33333334 outWeight: 0.33333334
- serializedVersion: 3 - serializedVersion: 3
time: 0.2 time: 0.2
value: 1.47 value: 2
inSlope: 3.3500001 inSlope: 6
outSlope: 0 outSlope: 0
tangentMode: 69 tangentMode: 69
weightedMode: 0 weightedMode: 0

View file

@ -13,52 +13,100 @@ namespace RhythmHeavenMania.Games.RhythmTweezers
public GameObject stubbleSprite; public GameObject stubbleSprite;
private RhythmTweezers game; private RhythmTweezers game;
private Tweezers tweezers; private Tweezers tweezers;
private Animator anim;
private bool isHolding = false; private int pluckState = 0;
private float holdBeat = 0f;
public GameObject holder; public GameObject holder;
public GameObject loop;
private AudioSource pullSound;
private void Awake() private void Awake()
{ {
game = RhythmTweezers.instance; game = RhythmTweezers.instance;
anim = GetComponent<Animator>();
tweezers = game.Tweezers; tweezers = game.Tweezers;
} }
private void Update() private void Update()
{ {
float stateBeat = Conductor.instance.GetPositionFromBeat(createBeat + game.tweezerBeatOffset, game.beatInterval); float stateBeat;
StateCheck(stateBeat);
if (PlayerInput.Pressed() && tweezers.hitOnFrame == 0) switch (pluckState)
{ {
if (state.perfect) // Able to be held.
{ case 0:
Jukebox.PlayOneShotGame($"rhythmTweezers/longPull{UnityEngine.Random.Range(1, 5)}"); stateBeat = Conductor.instance.GetPositionFromMargin(createBeat + game.tweezerBeatOffset + game.beatInterval, 1f);
isHolding = true; StateCheck(stateBeat);
holdBeat = Conductor.instance.songPositionInBeats;
} 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); var hairDirection = tweezers.tweezerSpriteTrans.position - holder.transform.position;
isHolding = false; holder.transform.rotation = Quaternion.FromToRotation(Vector3.down, hairDirection);
Ace();
}
float normalizedBeat = Conductor.instance.GetPositionFromBeat(createBeat + game.tweezerBeatOffset + game.beatInterval, 0.5f);
if (isHolding) anim.Play("LoopPull", 0, normalizedBeat);
{
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<Animator>().Play("LoopPull", 0, normalizedBeat);
tweezers.anim.Play("Tweezers_LongPluck", 0, normalizedBeat); tweezers.anim.Play("Tweezers_LongPluck", 0, normalizedBeat);
// float angleBetweenTweezersAndHair = angleBtw2Points(tweezers.transform.position, holder.transform.position); // float angleBetweenTweezersAndHair = angleBtw2Points(tweezers.transform.position, holder.transform.position);
// holder.transform.rotation = Quaternion.Euler(new Vector3(0, 0, angleBetweenTweezersAndHair)); // 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() public void Ace()
{ {
Jukebox.PlayOneShotGame("rhythmTweezers/longPullEnd");
tweezers.LongPluck(true, this); tweezers.LongPluck(true, this);
tweezers.hitOnFrame++; 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();
}
} }
} }
} }

View file

@ -16,6 +16,7 @@ namespace RhythmHeavenMania.Games.RhythmTweezers
private bool pluckingThisFrame; private bool pluckingThisFrame;
private bool holdingHair; private bool holdingHair;
public SpriteRenderer heldHairSprite; public SpriteRenderer heldHairSprite;
public Transform tweezerSpriteTrans;
private void Start() private void Start()
{ {
@ -83,8 +84,12 @@ namespace RhythmHeavenMania.Games.RhythmTweezers
if (ace) if (ace)
{ {
Jukebox.PlayOneShotGame("rhythmTweezers/longPullEnd");
hair.hairSprite.SetActive(false); hair.hairSprite.SetActive(false);
hair.stubbleSprite.SetActive(true); hair.stubbleSprite.SetActive(true);
// Making transparent instead of disabling because animators are silly.
hair.loop.GetComponent<SpriteRenderer>().color = Color.clear;
game.hairsLeft--; game.hairsLeft--;
game.eyeSize = Mathf.Clamp(game.eyeSize + 1, 0, 10); game.eyeSize = Mathf.Clamp(game.eyeSize + 1, 0, 10);

View file

@ -40,7 +40,7 @@ namespace RhythmHeavenMania.Util
FindJukebox().GetComponent<AudioSource>().volume = volume; FindJukebox().GetComponent<AudioSource>().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"); GameObject oneShot = new GameObject("oneShot");
@ -55,9 +55,11 @@ namespace RhythmHeavenMania.Util
// snd.pitch = (clip.length / Conductor.instance.secPerBeat); // snd.pitch = (clip.length / Conductor.instance.secPerBeat);
GameManager.instance.SoundObjects.Add(oneShot); 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"); GameObject oneShot = new GameObject("oneShotScheduled");
@ -75,22 +77,28 @@ namespace RhythmHeavenMania.Util
audioSource.PlayScheduled(targetTime); audioSource.PlayScheduled(targetTime);
GameManager.instance.SoundObjects.Add(oneShot); 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]) 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]) if (GameManager.instance.currentGame == name.Split('/')[0])
{ {
PlayOneShotScheduled($"games/{name}", targetTime); return PlayOneShotScheduled($"games/{name}", targetTime);
} }
return null;
} }
} }