mirror of
https://github.com/RHeavenStudioPlus/HeavenStudioPlus.git
synced 2024-11-14 13:45:10 +00:00
2123c75c97
* Bouncy Road Stuff yeah -weirdly set up prefab so i can see animations side by side - animations for the 3 podium things we ball * modified: Assets/Resources/Games/bouncyRoad.prefab * Preliminary stage of sorting according to the equation * reached a point where it's functional * miss curve * proper spawn * oops * bounce sound avoid duplication --------- Co-authored-by: GhostiGuy <srskok1@gmail.com> Co-authored-by: GhostiGuy <156829475+GhostiGuy@users.noreply.github.com>
314 lines
11 KiB
C#
314 lines
11 KiB
C#
using System.Linq;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using NaughtyBezierCurves;
|
|
|
|
using HeavenStudio.Util;
|
|
using HeavenStudio.InputSystem;
|
|
|
|
namespace HeavenStudio.Games.Loaders
|
|
{
|
|
using static Minigames;
|
|
|
|
public static class AgbBouncyRoadLoader
|
|
{
|
|
public static Minigame AddGame(EventCaller eventCaller)
|
|
{
|
|
return new Minigame("bouncyRoad", "Bouncy Road", "0296FF", false, false, new List<GameAction>()
|
|
{
|
|
new GameAction("ball", "Ball")
|
|
{
|
|
defaultLength = 1f,
|
|
resizable = true,
|
|
parameters = new List<Param>()
|
|
{
|
|
new Param("goal", true, "Play Goal Sound"),
|
|
new Param("color", Color.white, "Color", "Choose the color of the ball."),
|
|
}
|
|
},
|
|
},
|
|
new List<string>() { "agb", "normal" },
|
|
"agbbouncy", "en",
|
|
new List<string>() { },
|
|
chronologicalSortKey: 24
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
namespace HeavenStudio.Games
|
|
{
|
|
using Scripts_BouncyRoad;
|
|
public class BouncyRoad : Minigame
|
|
{
|
|
[SerializeField] GameObject baseBall;
|
|
[SerializeField] GameObject baseBounceCurve;
|
|
[SerializeField] Transform CurveHolder;
|
|
|
|
[SerializeField] Transform ThingsTrans;
|
|
[System.NonSerialized] public Animator[] ThingsAnim;
|
|
[System.NonSerialized] public Dictionary<float, BezierCurve3D[]> CurveCache;
|
|
[SerializeField] BezierCurve3D PosCurve;
|
|
|
|
[SerializeField] float fallY;
|
|
|
|
const double BALL_SEEK_TIME = 1.0;
|
|
private struct ScheduledBall
|
|
{
|
|
public double beat;
|
|
public double length;
|
|
public bool goal;
|
|
public Color color;
|
|
}
|
|
List<ScheduledBall> scheduledBalls = new();
|
|
int ballIndex;
|
|
|
|
public static BouncyRoad instance;
|
|
|
|
const int IALeft = 0;
|
|
const int IARight = 1;
|
|
|
|
protected static bool IA_PadLeft(out double dt)
|
|
{
|
|
return PlayerInput.GetPadDown(InputController.ActionsPad.Up, out dt)
|
|
|| PlayerInput.GetPadDown(InputController.ActionsPad.Down, out dt)
|
|
|| PlayerInput.GetPadDown(InputController.ActionsPad.Left, out dt)
|
|
|| PlayerInput.GetPadDown(InputController.ActionsPad.Right, out dt);
|
|
}
|
|
protected static bool IA_TouchLeft(out double dt)
|
|
{
|
|
return PlayerInput.GetTouchDown(InputController.ActionsTouch.Left, out dt);
|
|
}
|
|
|
|
protected static bool IA_PadRight(out double dt)
|
|
{
|
|
return PlayerInput.GetPadDown(InputController.ActionsPad.East, out dt);
|
|
}
|
|
protected static bool IA_TouchRight(out double dt)
|
|
{
|
|
return PlayerInput.GetTouchDown(InputController.ActionsTouch.Right, out dt);
|
|
}
|
|
|
|
public static PlayerInput.InputAction InputAction_Left =
|
|
new("AgbBouncyLeft", new int[] { IALeft, IALeft, IALeft },
|
|
IA_PadLeft, IA_TouchLeft, IA_BatonBasicPress);
|
|
|
|
public static PlayerInput.InputAction InputAction_Right =
|
|
new("AgbBouncyRight", new int[] { IARight, IARight, IAEmptyCat },
|
|
IA_PadRight, IA_TouchRight, IA_Empty);
|
|
|
|
void Awake()
|
|
{
|
|
instance = this;
|
|
|
|
ThingsAnim = new Animator[ThingsTrans.childCount];
|
|
int childIndex = 0;
|
|
foreach (Transform child in ThingsTrans)
|
|
{
|
|
// var prog = (float)childIndex/(ThingsTrans.childCount-1);
|
|
// child.transform.localPosition = PosCurve.GetPoint(prog);
|
|
ThingsAnim[childIndex++] = child.GetComponent<Animator>();
|
|
}
|
|
|
|
var newCurves = new BezierCurve3D[ThingsTrans.childCount + 3];
|
|
// for (var i = 0; i < ThingsAnim.Length + 1; ++i)
|
|
// {
|
|
// var prog1 = (float)(i-1)/(ThingsTrans.childCount-1);
|
|
// var prog2 = (float)(i)/(ThingsTrans.childCount-1);
|
|
// var pos1 = PosCurve.GetPoint(prog1);
|
|
// var pos2 = PosCurve.GetPoint(prog2);
|
|
|
|
// var newCurve = GenerateInitCurve(pos1, pos2);
|
|
|
|
// newCurves[i] = newCurve.GetComponent<BezierCurve3D>();
|
|
// }
|
|
{
|
|
Vector3 pos1, pos2;
|
|
pos1 = PosCurve.GetPoint((float)(-1)/(ThingsAnim.Length-1));
|
|
pos2 = PosCurve.GetPoint(0);
|
|
newCurves[0] = GenerateInitCurve(pos1, pos2).GetComponent<BezierCurve3D>();
|
|
|
|
for (var i = 0; i < ThingsAnim.Length-1; ++i)
|
|
{
|
|
pos1 = ThingsTrans.GetChild(i).transform.localPosition;
|
|
pos2 = ThingsTrans.GetChild(i+1).transform.localPosition;
|
|
|
|
var newCurve = GenerateInitCurve(pos1, pos2);
|
|
|
|
newCurves[1+i] = newCurve.GetComponent<BezierCurve3D>();
|
|
}
|
|
|
|
pos1 = PosCurve.GetPoint(1);
|
|
pos2 = PosCurve.GetPoint((float)(ThingsAnim.Length)/(ThingsAnim.Length-1));
|
|
newCurves[ThingsAnim.Length] = GenerateInitCurve(pos1, pos2).GetComponent<BezierCurve3D>();
|
|
}
|
|
newCurves[^2] = GenerateMissCurve(13).GetComponent<BezierCurve3D>();
|
|
newCurves[^1] = GenerateMissCurve(14).GetComponent<BezierCurve3D>();
|
|
|
|
CurveCache = new Dictionary<float, BezierCurve3D[]>();
|
|
CurveCache.Add(1, newCurves);
|
|
}
|
|
|
|
public override void OnGameSwitch(double beat)
|
|
{
|
|
double gameStartBeat = beat, gameEndBeat = double.MaxValue;
|
|
var firstEnd = EventCaller.GetAllInGameManagerList("gameManager", new string[] { "switchGame", "end" }).Find(x => x.beat > gameStartBeat);
|
|
gameEndBeat = firstEnd?.beat ?? gameEndBeat;
|
|
|
|
|
|
scheduledBalls.Clear();
|
|
ballIndex = 0;
|
|
var events = EventCaller.GetAllInGameManagerList("bouncyRoad", new string[] { "ball" }).FindAll(x => x.beat >= gameStartBeat && x.beat < gameEndBeat);
|
|
foreach (var e in events)
|
|
{
|
|
if (e.length == 0) continue;
|
|
var ball = new ScheduledBall
|
|
{
|
|
beat = e.beat,
|
|
length = e.length,
|
|
goal = e["goal"],
|
|
color = e["color"],
|
|
};
|
|
scheduledBalls.Add(ball);
|
|
}
|
|
scheduledBalls.Sort((x, y) => (x.beat - x.length).CompareTo(y.beat - y.length));
|
|
}
|
|
public override void OnPlay(double beat)
|
|
{
|
|
OnGameSwitch(beat);
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
var cond = Conductor.instance;
|
|
if (!cond.isPlaying || cond.isPaused) return;
|
|
|
|
if (PlayerInput.GetIsAction(InputAction_Right) && !IsExpectingInputNow(InputAction_Right))
|
|
{
|
|
ThingsAnim[12].Play("podium", 0, 0);
|
|
}
|
|
if (PlayerInput.GetIsAction(InputAction_Left) && !IsExpectingInputNow(InputAction_Left))
|
|
{
|
|
ThingsAnim[13].Play("podium", 0, 0);
|
|
}
|
|
|
|
UpdateBalls();
|
|
}
|
|
|
|
void UpdateBalls()
|
|
{
|
|
double beat = conductor.songPositionInBeatsAsDouble;
|
|
while(ballIndex < scheduledBalls.Count)
|
|
{
|
|
var ball = scheduledBalls[ballIndex];
|
|
if (ball.beat - ball.length < beat + BALL_SEEK_TIME)
|
|
{
|
|
SpawnBall(ball.beat, ball.length, ball.goal, ball.color);
|
|
ballIndex++;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void SpawnBall(double beat, double length, bool goal, Color color)
|
|
{
|
|
var newBall = Instantiate(baseBall, transform).GetComponent<Ball>();
|
|
|
|
newBall.startBeat = beat;
|
|
newBall.lengthBeat = length;
|
|
newBall.goal = goal;
|
|
newBall.color = color;
|
|
|
|
newBall.curve = GetHeightCurve((float)length);
|
|
|
|
BeatAction.New(instance, new List<BeatAction.Action>()
|
|
{
|
|
new BeatAction.Action(beat - length, delegate
|
|
{
|
|
newBall.Init();
|
|
newBall.gameObject.SetActive(true);
|
|
})
|
|
});
|
|
}
|
|
|
|
List<double> bounceBeats = new();
|
|
public void PlayBounceSound(double beat, double length)
|
|
{
|
|
var sounds = new List<MultiSound.Sound>();
|
|
for (int i = 0; i < 12 ; i++)
|
|
{
|
|
var bounceBeat = beat + i * length;
|
|
if (!bounceBeats.Contains(bounceBeat)) sounds.Add(new MultiSound.Sound("bouncyRoad/ballBounce", bounceBeat));
|
|
bounceBeats.Add(bounceBeat);
|
|
}
|
|
MultiSound.Play(sounds.ToArray());
|
|
}
|
|
|
|
private Transform GenerateInitCurve(Vector3 pos1, Vector3 pos2)
|
|
{
|
|
float dist = Vector3.Distance(pos1, pos2);
|
|
float angle = Mathf.Atan2(pos1.z - pos2.z, pos1.x - pos2.x) * Mathf.Rad2Deg;
|
|
|
|
var newCurve = Instantiate(baseBounceCurve, CurveHolder).transform;
|
|
|
|
var point0 = newCurve.GetChild(0);
|
|
var point1 = newCurve.GetChild(1);
|
|
|
|
point0.transform.localPosition = pos1;
|
|
point0.transform.localEulerAngles = new Vector3(0, -angle, 0);
|
|
point0.transform.localScale = new Vector3(dist, 1, 1);
|
|
point1.transform.localPosition = pos2;
|
|
point1.transform.localEulerAngles = new Vector3(0, -angle, 0);
|
|
point1.transform.localScale = new Vector3(dist, 1, 1);
|
|
|
|
return newCurve;
|
|
}
|
|
|
|
private Transform GenerateMissCurve(int number)
|
|
{
|
|
var curve = CurveHolder.GetChild(number);
|
|
|
|
var newCurve = Instantiate(curve, CurveHolder).transform;
|
|
|
|
var point0 = newCurve.GetChild(0);
|
|
var point1 = newCurve.GetChild(1);
|
|
|
|
Vector3 pos1 = point1.transform.localPosition;
|
|
point1.transform.localPosition = pos1 + new Vector3(0, fallY, 0);
|
|
|
|
return newCurve;
|
|
}
|
|
|
|
private BezierCurve3D[] GetHeightCurve(float length)
|
|
{
|
|
BezierCurve3D[] newCurves;
|
|
CurveCache.TryGetValue(length, out newCurves);
|
|
|
|
if (newCurves is null)
|
|
{
|
|
var newCurveHolder = Instantiate(CurveHolder, transform);
|
|
newCurveHolder.name = $"CurveHolder_{length}";
|
|
var newCurvesTrans = newCurveHolder.transform;
|
|
|
|
newCurves = new BezierCurve3D[newCurvesTrans.childCount];
|
|
int childIndex = 0;
|
|
foreach (Transform child in newCurvesTrans)
|
|
{
|
|
var point0 = child.GetChild(0);
|
|
var point1 = child.GetChild(1);
|
|
|
|
Vector3 scale = point0.transform.localScale;
|
|
point0.transform.localScale = new Vector3(scale.x, length * scale.y, scale.z);
|
|
point1.transform.localScale = new Vector3(scale.x, length * scale.y, scale.z);
|
|
newCurves[childIndex++] = child.GetComponent<BezierCurve3D>();
|
|
}
|
|
CurveCache.Add(length, newCurves);
|
|
}
|
|
|
|
return newCurves;
|
|
}
|
|
}
|
|
}
|