mirror of
https://github.com/RHeavenStudio/HeavenStudio.git
synced 2025-06-12 13:47:38 +02:00
Mr. Upbeat Rework (#418)
* everything but the text * new spritesheet (thank u sean) * better/more accurate background color * bg color changing with fade (code courtesy of ras) * mr. upbeat blip color changing * full blip implementation, with size changing and text display * text is still weird (gray box around all the letters) but i hope that's an easy fix. * almost done just need to fix the text and get rid of the reliance on the ding! block * finishing touches + a buncha testing everything works!!! and i don't think i left anything out * forgot an n lol * oh my god i hate mr. downbeat this "force" option is not very intuitive to use. nor is it coded amazingly. but i do not care. if you really wanna use it then mess around and see what works
This commit is contained in:
@ -3,7 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using Starpelly;
|
||||
using DG.Tweening;
|
||||
|
||||
using HeavenStudio.Util;
|
||||
|
||||
@ -15,26 +15,69 @@ namespace HeavenStudio.Games.Loaders
|
||||
public static Minigame AddGame(EventCaller eventCaller) {
|
||||
return new Minigame("mrUpbeat", "Mr. Upbeat", "ffffff", false, false, new List<GameAction>()
|
||||
{
|
||||
new GameAction("stepping", "Start Stepping")
|
||||
new GameAction("start stepping", "Start Stepping")
|
||||
{
|
||||
preFunction = delegate {var e = eventCaller.currentEntity; MrUpbeat.Stepping(e.beat, e.length); },
|
||||
preFunction = delegate {var e = eventCaller.currentEntity; MrUpbeat.StartStepping(e.beat, e.length, e["force"]); },
|
||||
defaultLength = 4f,
|
||||
resizable = true,
|
||||
parameters = new List<Param>()
|
||||
{
|
||||
new Param("force", false, "Force Mr. Downbeat", "Forces inputs to not be only on the offbeats"),
|
||||
}
|
||||
},
|
||||
new GameAction("blipping", "Beeping")
|
||||
new GameAction("ding", "Ding!")
|
||||
{
|
||||
function = delegate {var e = eventCaller.currentEntity; MrUpbeat.Blipping(e.beat, e.length); },
|
||||
defaultLength = 4f,
|
||||
resizable = true,
|
||||
inactiveFunction = delegate {var e = eventCaller.currentEntity; MrUpbeat.Blipping(e.beat, e.length); },
|
||||
},
|
||||
new GameAction("ding!", "Ding!")
|
||||
{
|
||||
function = delegate { MrUpbeat.instance.Ding(eventCaller.currentEntity["toggle"]); },
|
||||
function = delegate {
|
||||
var e = eventCaller.currentEntity;
|
||||
MrUpbeat.instance.Ding(eventCaller.currentEntity["toggle"], e["stopBlipping"]); },
|
||||
defaultLength = 0.5f,
|
||||
parameters = new List<Param>()
|
||||
{
|
||||
new Param("toggle", false, "Applause")
|
||||
new Param("toggle", false, "Applause", "Plays an applause sound effect."),
|
||||
new Param("stopBlipping", true, "Stop Blipping?", "When the stepping stops, should the blipping stop too?"),
|
||||
}
|
||||
},
|
||||
new GameAction("changeBG", "Change Background Color")
|
||||
{
|
||||
function = delegate {
|
||||
var e = eventCaller.currentEntity;
|
||||
MrUpbeat.instance.FadeBackgroundColor(e["start"], e["end"], e.length, e["toggle"]); },
|
||||
defaultLength = 1f,
|
||||
resizable = true,
|
||||
parameters = new List<Param>()
|
||||
{
|
||||
new Param("start", new Color(0.878f, 0.878f, 0.878f), "Start Color", "The start color for the fade or the color that will be switched to if -instant- is ticked on."),
|
||||
new Param("end", new Color(0.878f, 0.878f, 0.878f), "End Color", "The end color for the fade."),
|
||||
new Param("toggle", false, "Instant", "Should the background instantly change color?")
|
||||
}
|
||||
},
|
||||
new GameAction("upbeatColors", "Upbeat Colors")
|
||||
{
|
||||
function = delegate {
|
||||
var e = eventCaller.currentEntity;
|
||||
MrUpbeat.instance.UpbeatColors(e["blipColor"], e["setShadow"], e["shadowColor"]);
|
||||
},
|
||||
defaultLength = 0.5f,
|
||||
parameters = new List<Param>()
|
||||
{
|
||||
new Param("blipColor", new Color(0, 1f, 0), "Blip Color", "Change blip color"),
|
||||
new Param("setShadow", false, "Set Shadow Color?", "Should Mr. Upbeat's shadow be custom?"),
|
||||
new Param("shadowColor", new Color(1f, 1f, 1f, 0), "Shadow Color", "If \"Set Shadow Color\" is checked, this will set the shadow's color."),
|
||||
}
|
||||
},
|
||||
new GameAction("blipEvents", "Blip Events")
|
||||
{
|
||||
function = delegate {
|
||||
var e = eventCaller.currentEntity;
|
||||
MrUpbeat.instance.BlipEvents(e["letter"], e["shouldGrow"], e["resetBlip"], e["blip"]);
|
||||
},
|
||||
defaultLength = 0.5f,
|
||||
parameters = new List<Param>()
|
||||
{
|
||||
new Param("letter", "", "Letter To Appear", "Which letter to appear on the blip"),
|
||||
new Param("shouldGrow", true, "Grow Antenna?", "Should Mr. Upbeat's antenna grow?"),
|
||||
new Param("resetBlip", false, "Reset Antenna?", "Should Mr. Upbeat's antenna reset?"),
|
||||
new Param("blip", true, "Should Blip?", "Should Mr. Upbeat blip every offbeat?"),
|
||||
}
|
||||
},
|
||||
});
|
||||
@ -48,160 +91,135 @@ namespace HeavenStudio.Games
|
||||
|
||||
public class MrUpbeat : Minigame
|
||||
{
|
||||
static List<float> queuedBeeps = new List<float>();
|
||||
static List<queuedUpbeatInputs> queuedInputs = new List<queuedUpbeatInputs>();
|
||||
public struct queuedUpbeatInputs
|
||||
{
|
||||
public float beat;
|
||||
public bool goRight;
|
||||
}
|
||||
static List<float> queuedInputs = new List<float>();
|
||||
|
||||
[Header("References")]
|
||||
public Animator metronomeAnim;
|
||||
public UpbeatMan man;
|
||||
[SerializeField] Animator metronomeAnim;
|
||||
[SerializeField] UpbeatMan man;
|
||||
[SerializeField] Material blipMaterial;
|
||||
[SerializeField] SpriteRenderer bg;
|
||||
[SerializeField] SpriteRenderer[] shadowSr;
|
||||
|
||||
[Header("Properties")]
|
||||
bool startLeft;
|
||||
private Tween bgColorTween;
|
||||
public int stepIterate = 0;
|
||||
public static float downbeatMod = 0.5f;
|
||||
public static bool shouldBlip;
|
||||
static bool noDing;
|
||||
|
||||
public static MrUpbeat instance;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
instance = this;
|
||||
|
||||
blipMaterial.SetColor("_ColorBravo", new Color(0, 1f, 0));
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
man.Blip();
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
if (!Conductor.instance.isPlaying || Conductor.instance.isPaused)
|
||||
{
|
||||
if (!Conductor.instance.isPlaying || Conductor.instance.isPaused) {
|
||||
if (queuedInputs.Count > 0) queuedInputs.Clear();
|
||||
if (queuedBeeps.Count > 0) queuedBeeps.Clear();
|
||||
}
|
||||
|
||||
// these variables wouldn't get reset, even when you go in and out of unity play mode???
|
||||
shouldBlip = false;
|
||||
stepIterate = 0;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
var cond = Conductor.instance;
|
||||
if (cond.isPlaying && !cond.isPaused)
|
||||
{
|
||||
if (queuedInputs.Count > 0)
|
||||
{
|
||||
foreach (var input in queuedInputs)
|
||||
{
|
||||
ScheduleInput(cond.songPositionInBeats, input.beat - cond.songPositionInBeats, InputType.STANDARD_DOWN, Success, Miss, Nothing);
|
||||
if (input.goRight)
|
||||
{
|
||||
BeatAction.New(instance.gameObject, new List<BeatAction.Action>()
|
||||
{
|
||||
new BeatAction.Action(input.beat - 0.5f, delegate { MrUpbeat.instance.metronomeAnim.DoScaledAnimationAsync("MetronomeGoLeft", 0.5f); }),
|
||||
new BeatAction.Action(input.beat - 0.5f, delegate { Jukebox.PlayOneShotGame("mrUpbeat/metronomeRight"); }),
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
BeatAction.New(instance.gameObject, new List<BeatAction.Action>()
|
||||
{
|
||||
new BeatAction.Action(input.beat - 0.5f, delegate { MrUpbeat.instance.metronomeAnim.DoScaledAnimationAsync("MetronomeGoRight", 0.5f); }),
|
||||
new BeatAction.Action(input.beat - 0.5f, delegate { Jukebox.PlayOneShotGame("mrUpbeat/metronomeLeft"); }),
|
||||
});
|
||||
}
|
||||
}
|
||||
if (queuedInputs.Count % 2 != 0)
|
||||
{
|
||||
startLeft = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
startLeft = false;
|
||||
if (cond.isPlaying && !cond.isPaused) {
|
||||
if (queuedInputs.Count > 0) {
|
||||
foreach (var input in queuedInputs) {
|
||||
string dir = stepIterate % 2 == 1 ? "Right" : "Left";
|
||||
BeatAction.New(instance.gameObject, new List<BeatAction.Action>() {
|
||||
new BeatAction.Action(input, delegate {
|
||||
instance.metronomeAnim.DoScaledAnimationAsync("MetronomeGo" + dir, 0.5f);
|
||||
Jukebox.PlayOneShotGame("mrUpbeat/metronome" + dir);
|
||||
ScheduleInput(input, 0.5f, InputType.STANDARD_DOWN, Success, Miss, Nothing);
|
||||
if (MrUpbeat.noDing) queuedInputs.Add(input + 1);
|
||||
}),
|
||||
});
|
||||
stepIterate++;
|
||||
}
|
||||
queuedInputs.Clear();
|
||||
}
|
||||
if (PlayerInput.Pressed() && !IsExpectingInputNow(InputType.STANDARD_DOWN))
|
||||
{
|
||||
|
||||
if (PlayerInput.Pressed() && !IsExpectingInputNow(InputType.STANDARD_DOWN)) {
|
||||
man.Step();
|
||||
}
|
||||
}
|
||||
|
||||
if (queuedBeeps.Count > 0) {
|
||||
var beepAnims = new List<BeatAction.Action>();
|
||||
foreach (var item in queuedBeeps)
|
||||
{
|
||||
beepAnims.Add(new BeatAction.Action(item, delegate { man.blipAnimator.Play("Blip", 0, 0); }));
|
||||
}
|
||||
BeatAction.New(instance.gameObject, beepAnims);
|
||||
queuedBeeps.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void Ding(bool applause)
|
||||
public void Ding(bool applause, bool stopBlipping)
|
||||
{
|
||||
Jukebox.PlayOneShotGame("mrUpbeat/ding");
|
||||
if (applause) Jukebox.PlayOneShot("applause");
|
||||
if (stopBlipping) shouldBlip = false;
|
||||
}
|
||||
|
||||
public static void StartStepping(float beat, float length, bool force)
|
||||
{
|
||||
// mr. downbeat stuff. god i hate mr. downbeat
|
||||
// force != true means that mr. upbeat will always blip/step on the offbeats
|
||||
beat = force ? beat - 0.5f : MathF.Floor(beat);
|
||||
downbeatMod = force ? (beat % 1) : 0.5f;
|
||||
|
||||
if (GameManager.instance.currentGame != "mrUpbeat") {
|
||||
Blipping(beat, length);
|
||||
MrUpbeat.shouldBlip = true;
|
||||
} else {
|
||||
BeatAction.New(instance.gameObject, new List<BeatAction.Action>() {
|
||||
new BeatAction.Action(beat, delegate {
|
||||
MrUpbeat.shouldBlip = true;
|
||||
}),
|
||||
});
|
||||
}
|
||||
var dings = EventCaller.GetAllInGameManagerList("mrUpbeat", new string[] { "ding" });
|
||||
if (dings.Count == 0) {
|
||||
MrUpbeat.noDing = true;
|
||||
queuedInputs.Add(beat + (force ? length : MathF.Floor(length)));
|
||||
return;
|
||||
}
|
||||
MrUpbeat.noDing = false;
|
||||
int whichDing = 0;
|
||||
for (int i = 0; i < dings.Count; i++) {
|
||||
if (dings[i].beat > beat) {
|
||||
whichDing = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (int i = (int)length; i < dings[whichDing].beat - beat; i++) {
|
||||
queuedInputs.Add(beat + i - (force ? downbeatMod : 0));
|
||||
}
|
||||
}
|
||||
|
||||
public static void Blipping(float beat, float length)
|
||||
{
|
||||
List<MultiSound.Sound> beeps = new List<MultiSound.Sound>();
|
||||
|
||||
for (int i = 0; i < length + 1; i++)
|
||||
{
|
||||
beeps.Add(new MultiSound.Sound("mrUpbeat/blip", beat + i));
|
||||
queuedBeeps.Add(beat + i);
|
||||
}
|
||||
|
||||
MultiSound.Play(beeps.ToArray(), forcePlay: true);
|
||||
}
|
||||
|
||||
public static void Stepping(float beat, float length)
|
||||
{
|
||||
if (GameManager.instance.currentGame == "mrUpbeat")
|
||||
{
|
||||
float offSet = 0;
|
||||
if (MrUpbeat.instance.startLeft)
|
||||
{
|
||||
offSet = 1;
|
||||
}
|
||||
for (int i = 0; i < length + 1; i++)
|
||||
{
|
||||
MrUpbeat.instance.ScheduleInput(beat - 1, 1 + i, InputType.STANDARD_DOWN, MrUpbeat.instance.Success, MrUpbeat.instance.Miss, MrUpbeat.instance.Nothing);
|
||||
if ((i + offSet) % 2 == 0)
|
||||
{
|
||||
BeatAction.New(instance.gameObject, new List<BeatAction.Action>()
|
||||
{
|
||||
new BeatAction.Action(beat + i - 0.5f, delegate { MrUpbeat.instance.metronomeAnim.DoScaledAnimationAsync("MetronomeGoLeft", 0.5f); }),
|
||||
new BeatAction.Action(beat + i - 0.5f, delegate { Jukebox.PlayOneShotGame("mrUpbeat/metronomeRight"); }),
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
BeatAction.New(instance.gameObject, new List<BeatAction.Action>()
|
||||
{
|
||||
new BeatAction.Action(beat + i - 0.5f, delegate { MrUpbeat.instance.metronomeAnim.DoScaledAnimationAsync("MetronomeGoRight", 0.5f); }),
|
||||
new BeatAction.Action(beat + i - 0.5f, delegate { Jukebox.PlayOneShotGame("mrUpbeat/metronomeLeft"); }),
|
||||
});
|
||||
List<MultiSound.Sound> blips = new List<MultiSound.Sound>();
|
||||
var switchGames = EventCaller.GetAllInGameManagerList("gameManager", new string[] { "switchGame" });
|
||||
int whichSwitch = 0;
|
||||
if (switchGames.Count != 0) {
|
||||
for (int i = 0; i < switchGames.Count; i++) {
|
||||
if (switchGames[i].beat > beat) {
|
||||
whichSwitch = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if ((length + 1) % 2 != 0)
|
||||
{
|
||||
MrUpbeat.instance.startLeft = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
MrUpbeat.instance.startLeft = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < length + 1; i++)
|
||||
{
|
||||
queuedInputs.Add(new queuedUpbeatInputs
|
||||
{
|
||||
beat = beat + i,
|
||||
goRight = i % 2 == 0
|
||||
});
|
||||
}
|
||||
for (int i = 0; i < switchGames[whichSwitch].beat - beat - 0.5f; i++) {
|
||||
blips.Add(new MultiSound.Sound("mrUpbeat/blip", beat + 0.5f + i));
|
||||
}
|
||||
|
||||
MultiSound.Play(blips.ToArray(), forcePlay: true);
|
||||
}
|
||||
|
||||
public void Success(PlayerActionEvent caller, float state)
|
||||
@ -214,13 +232,41 @@ namespace HeavenStudio.Games
|
||||
man.Fall();
|
||||
}
|
||||
|
||||
bool isPlaying(Animator anim, string stateName)
|
||||
public void ChangeBackgroundColor(Color color, float beats)
|
||||
{
|
||||
if (anim.GetCurrentAnimatorStateInfo(0).IsName(stateName) &&
|
||||
anim.GetCurrentAnimatorStateInfo(0).normalizedTime < 1.0f)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
var seconds = Conductor.instance.secPerBeat * beats;
|
||||
|
||||
if (bgColorTween != null)
|
||||
bgColorTween.Kill(true);
|
||||
|
||||
if (seconds == 0) {
|
||||
bg.color = color;
|
||||
} else {
|
||||
bgColorTween = bg.DOColor(color, seconds);
|
||||
}
|
||||
}
|
||||
|
||||
public void FadeBackgroundColor(Color start, Color end, float beats, bool instant)
|
||||
{
|
||||
ChangeBackgroundColor(start, 0f);
|
||||
if (!instant) ChangeBackgroundColor(end, beats);
|
||||
}
|
||||
|
||||
public void UpbeatColors(Color blipColor, bool setShadow, Color shadowColor)
|
||||
{
|
||||
blipMaterial.SetColor("_ColorBravo", blipColor);
|
||||
|
||||
if (setShadow) foreach (var shadow in shadowSr) {
|
||||
shadow.color = new Color(shadowColor.r, shadowColor.g, shadowColor.b, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public void BlipEvents(string inputLetter, bool shouldGrow, bool resetBlip, bool blip)
|
||||
{
|
||||
if (shouldGrow && man.blipSize < 4) man.blipSize++;
|
||||
if (resetBlip) man.blipSize = 0;
|
||||
man.blipString = inputLetter;
|
||||
shouldBlip = blip;
|
||||
}
|
||||
|
||||
public void Nothing(PlayerActionEvent caller) {}
|
||||
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using Starpelly;
|
||||
using TMPro;
|
||||
|
||||
using HeavenStudio.Util;
|
||||
|
||||
@ -11,60 +12,61 @@ namespace HeavenStudio.Games.Scripts_MrUpbeat
|
||||
public class UpbeatMan : MonoBehaviour
|
||||
{
|
||||
[Header("References")]
|
||||
public MrUpbeat game;
|
||||
public Animator animator;
|
||||
public Animator blipAnimator;
|
||||
public GameObject[] shadows;
|
||||
[SerializeField] Animator anim;
|
||||
[SerializeField] Animator blipAnim;
|
||||
[SerializeField] Animator letterAnim;
|
||||
[SerializeField] GameObject[] shadows;
|
||||
[SerializeField] TMP_Text blipText;
|
||||
|
||||
public float targetBeat = 0.25f;
|
||||
public int stepTimes = 0;
|
||||
private bool stepped = false;
|
||||
private bool onGround = false;
|
||||
public int blipSize = 0;
|
||||
public string blipString = "M";
|
||||
|
||||
public GameEvent blip = new GameEvent();
|
||||
|
||||
public void Idle()
|
||||
public void Blip()
|
||||
{
|
||||
stepTimes = 0;
|
||||
transform.localScale = new Vector3(1, 1);
|
||||
animator.Play("Idle", 0, 0);
|
||||
float c = Conductor.instance.songPositionInBeats;
|
||||
// checks if the position is on an offbeat; accurate until you get down to 20 fps or so (i.e unplayable)
|
||||
float pos = ((MathF.Floor(c * 10)/10 % 1) == 0.5f) ? MathF.Floor(c) : MathF.Round(c);
|
||||
|
||||
// recursive, should happen on the offbeat (unless downbeatMod is different)
|
||||
BeatAction.New(gameObject, new List<BeatAction.Action>() {
|
||||
new BeatAction.Action(pos + MrUpbeat.downbeatMod, delegate {
|
||||
if (MrUpbeat.shouldBlip) {
|
||||
Jukebox.PlayOneShotGame("mrUpbeat/blip");
|
||||
blipAnim.Play("Blip"+(blipSize+1), 0, 0);
|
||||
blipText.text = (blipSize == 4 && blipString != "") ? blipString : "";
|
||||
}
|
||||
}),
|
||||
new BeatAction.Action(pos + MrUpbeat.downbeatMod + 0.999f, delegate {
|
||||
Blip();
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
public void Step()
|
||||
{
|
||||
stepTimes++;
|
||||
|
||||
bool x = (stepTimes % 2 == 1);
|
||||
shadows[0].SetActive(!x);
|
||||
shadows[1].SetActive(x);
|
||||
transform.localScale = new Vector3(x ? -1 : 1, 1);
|
||||
|
||||
animator.Play("Step", 0, 0);
|
||||
anim.DoScaledAnimationAsync("Step", 0.5f);
|
||||
letterAnim.DoScaledAnimationAsync(x ? "StepRight" : "StepLeft", 0.5f);
|
||||
Jukebox.PlayOneShotGame("mrUpbeat/step");
|
||||
|
||||
onGround = false;
|
||||
CheckShadows();
|
||||
}
|
||||
|
||||
public void Fall()
|
||||
{
|
||||
animator.Play("Fall", 0, 0);
|
||||
blipSize = 0;
|
||||
blipAnim.Play("Idle", 0, 0);
|
||||
blipText.text = "";
|
||||
|
||||
anim.DoScaledAnimationAsync("Fall", 0.5f);
|
||||
Jukebox.PlayOneShot("miss");
|
||||
shadows[0].SetActive(false);
|
||||
shadows[1].SetActive(false);
|
||||
onGround = true;
|
||||
}
|
||||
|
||||
private void CheckShadows()
|
||||
{
|
||||
if (onGround) return;
|
||||
|
||||
if (stepTimes % 2 == 1)
|
||||
{
|
||||
shadows[0].SetActive(false);
|
||||
shadows[1].SetActive(true);
|
||||
transform.localScale = new Vector3(-1, 1);
|
||||
} else
|
||||
{
|
||||
shadows[0].SetActive(true);
|
||||
shadows[1].SetActive(false);
|
||||
transform.localScale = new Vector3(1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user