diff --git a/Assets/Resources/Prefabs/Games/AnimalAcrobat/Elephant.prefab b/Assets/Resources/Prefabs/Games/AnimalAcrobat/Elephant.prefab index 85f33e3e6..059c1ce70 100644 --- a/Assets/Resources/Prefabs/Games/AnimalAcrobat/Elephant.prefab +++ b/Assets/Resources/Prefabs/Games/AnimalAcrobat/Elephant.prefab @@ -505,7 +505,7 @@ GameObject: m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 1 + m_IsActive: 0 --- !u!4 &6285390310926959546 Transform: m_ObjectHideFlags: 0 @@ -560,6 +560,7 @@ MonoBehaviour: m_EditorClassIdentifier: _fullRotRange: 120 _spawnDistance: 2.602 + _spawnOffset: 0 _holdLength: 2 _ease: 4 _rotateRoot: {fileID: 2616646720197201304} diff --git a/Assets/Resources/Prefabs/Games/AnimalAcrobat/Giraffe.prefab b/Assets/Resources/Prefabs/Games/AnimalAcrobat/Giraffe.prefab index 3e46f4db8..be1bfee70 100644 --- a/Assets/Resources/Prefabs/Games/AnimalAcrobat/Giraffe.prefab +++ b/Assets/Resources/Prefabs/Games/AnimalAcrobat/Giraffe.prefab @@ -269,7 +269,7 @@ GameObject: m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 1 + m_IsActive: 0 --- !u!4 &1701002327333926128 Transform: m_ObjectHideFlags: 0 @@ -300,11 +300,13 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 2f9ee457016acdc4eb5dbfdc03be0d6f, type: 3} m_Name: m_EditorClassIdentifier: - holdLength: 4 - fullRotateAngle: 160 - anim: {fileID: 7772794942310833959} - type: 1 - rotatePivot: {fileID: 4208995891253938729} + _fullRotRange: 0 + _spawnDistance: 0 + _spawnOffset: 0 + _holdLength: 0 + _ease: 4 + _rotateRoot: {fileID: 0} + _gripPoint: {fileID: 0} --- !u!1 &3911272779464478738 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/Resources/Prefabs/Games/AnimalAcrobat/WhiteMonkey.prefab b/Assets/Resources/Prefabs/Games/AnimalAcrobat/WhiteMonkey.prefab index 50d938535..ce62712c9 100644 --- a/Assets/Resources/Prefabs/Games/AnimalAcrobat/WhiteMonkey.prefab +++ b/Assets/Resources/Prefabs/Games/AnimalAcrobat/WhiteMonkey.prefab @@ -100,7 +100,7 @@ GameObject: m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 1 + m_IsActive: 0 --- !u!4 &532140475066366254 Transform: m_ObjectHideFlags: 0 @@ -129,11 +129,13 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 2f9ee457016acdc4eb5dbfdc03be0d6f, type: 3} m_Name: m_EditorClassIdentifier: - holdLength: 1 - fullRotateAngle: 160 - anim: {fileID: 0} - type: 3 - rotatePivot: {fileID: 2068126119450832752} + _fullRotRange: 0 + _spawnDistance: 0 + _spawnOffset: 0 + _holdLength: 0 + _ease: 4 + _rotateRoot: {fileID: 0} + _gripPoint: {fileID: 0} --- !u!1 &3823740494665398411 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/Resources/Prefabs/Games/AnimalAcrobat/WhiteMonkeys.prefab b/Assets/Resources/Prefabs/Games/AnimalAcrobat/WhiteMonkeys.prefab index 5e24fb4cc..2a5088a54 100644 --- a/Assets/Resources/Prefabs/Games/AnimalAcrobat/WhiteMonkeys.prefab +++ b/Assets/Resources/Prefabs/Games/AnimalAcrobat/WhiteMonkeys.prefab @@ -1897,7 +1897,7 @@ GameObject: m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 1 + m_IsActive: 0 --- !u!4 &3439047595127619699 Transform: m_ObjectHideFlags: 0 @@ -1928,11 +1928,13 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 2f9ee457016acdc4eb5dbfdc03be0d6f, type: 3} m_Name: m_EditorClassIdentifier: - holdLength: 3 - fullRotateAngle: 160 - anim: {fileID: 8483464683545527156} - type: 2 - rotatePivot: {fileID: 3903953954711634507} + _fullRotRange: 0 + _spawnDistance: 0 + _spawnOffset: 0 + _holdLength: 0 + _ease: 4 + _rotateRoot: {fileID: 0} + _gripPoint: {fileID: 0} --- !u!1 &8302616130811808557 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/Games/AnimalAcrobat/AcrobatObstacle.cs b/Assets/Scripts/Games/AnimalAcrobat/AcrobatObstacle.cs index 4cbe2af66..bd05d8b69 100644 --- a/Assets/Scripts/Games/AnimalAcrobat/AcrobatObstacle.cs +++ b/Assets/Scripts/Games/AnimalAcrobat/AcrobatObstacle.cs @@ -10,14 +10,17 @@ namespace HeavenStudio.Games.Scripts_AnimalAcrobat [Header("Values")] [SerializeField] private float _fullRotRange; [SerializeField] private float _spawnDistance; + [SerializeField] private float _spawnOffset; [SerializeField] private double _holdLength; [SerializeField] private EasingFunction.Ease _ease = EasingFunction.Ease.EaseInOutQuad; private double _startBeat; + private double _expirationBeat = -1; private float _halfRotRange; private EasingFunction.Function _func; public float SpawnDistance => _spawnDistance; + public float SpawnOffset => _spawnOffset; [Header("Components")] [SerializeField] private Transform _rotateRoot; @@ -29,9 +32,10 @@ namespace HeavenStudio.Games.Scripts_AnimalAcrobat _func = EasingFunction.GetEasingFunction(_ease); } - public void SetStartBeat(double beat) + public void Init(double beat, double expirationBeat) { _startBeat = beat; + _expirationBeat = expirationBeat; Update(); } @@ -46,9 +50,10 @@ namespace HeavenStudio.Games.Scripts_AnimalAcrobat var cond = Conductor.instance; if (!cond.isPlaying) return; - float normalNoMod = cond.GetPositionFromBeat(_startBeat, _holdLength); + float normalNoMod = Mathf.Abs(cond.GetPositionFromBeat(_startBeat, _holdLength)); float normalizedBeat = normalNoMod % 1; + if (Mathf.Floor(normalNoMod) % 2 != 0) { normalizedBeat = 1 - normalizedBeat; @@ -56,6 +61,16 @@ namespace HeavenStudio.Games.Scripts_AnimalAcrobat float newAngleZ = _func(-_halfRotRange, _halfRotRange, normalizedBeat); _rotateRoot.localEulerAngles = new Vector3(0, 0, newAngleZ); + + if (cond.songPositionInBeatsAsDouble >= _expirationBeat) + { + gameObject.SetActive(false); + } + } + + public bool IsAvailableAtBeat(double beat) + { + return beat >= _expirationBeat; } } } diff --git a/Assets/Scripts/Games/AnimalAcrobat/AnimalAcrobat.cs b/Assets/Scripts/Games/AnimalAcrobat/AnimalAcrobat.cs index 0a56c807d..1f47f924e 100644 --- a/Assets/Scripts/Games/AnimalAcrobat/AnimalAcrobat.cs +++ b/Assets/Scripts/Games/AnimalAcrobat/AnimalAcrobat.cs @@ -44,13 +44,173 @@ namespace HeavenStudio.Games public class AnimalAcrobat : Minigame { + private static readonly int POOL_NUMBER = 4; + private static readonly int EXPIRATION_TIMES = 2; + [Header("Animal Prefabs")] [SerializeField] private AcrobatObstacle _elephant; [SerializeField] private AcrobatObstacle _giraffe, _monkeysLong, _monkeysShort; - private void Awake() + private List _pooledElephants = new(), _pooledGiraffes = new(), _pooledMonkeysLong = new(), _pooledMonkeysShort = new(); + + private enum AnimalType { - Instantiate(_elephant, transform); + Elephant, + Giraffe, + MonkeysLong, + MonkeysShort + } + + private struct QueuedAnimal + { + public AnimalType type; + public double startBeat; + public double length; + } + + private List _queuedAnimals = new(); + private int _animalPoolIndex = 0; + private float _animalSummatedDistance = 0; + + private void Update() + { + var cond = Conductor.instance; + if (!cond.isPlaying) return; + AnimalPoolUpdate(cond); + } + + private void AnimalPoolUpdate(Conductor cond) + { + if (_animalPoolIndex >= _queuedAnimals.Count) return; + + double bakeBeat = _queuedAnimals[_animalPoolIndex - EXPIRATION_TIMES].startBeat; + if (cond.songPositionInBeatsAsDouble >= bakeBeat) + { + BakeNextAvailableAnimal(); + } + } + + private void BakeNextAvailableAnimal() + { + if (_animalPoolIndex >= _queuedAnimals.Count) return; + var currentAnimal = _queuedAnimals[_animalPoolIndex]; + List pooledObstacles = currentAnimal.type switch + { + AnimalType.Elephant => _pooledElephants, + AnimalType.Giraffe => _pooledGiraffes, + AnimalType.MonkeysLong => _pooledMonkeysLong, + AnimalType.MonkeysShort => _pooledMonkeysShort, + _ => throw new System.NotImplementedException(), + }; + + var animal = pooledObstacles.Find(x => x.IsAvailableAtBeat(currentAnimal.startBeat)); + _animalSummatedDistance += (_animalPoolIndex == 0) ? animal.SpawnOffset : animal.SpawnDistance; + animal.gameObject.SetActive(true); + + double expBeat = currentAnimal.startBeat + currentAnimal.length; + + for (int i = 0; i < EXPIRATION_TIMES; i++) + { + if (_animalPoolIndex + i + 1 >= _queuedAnimals.Count) + { + expBeat = double.MaxValue; + break; + } + + var seekedAnimal = _queuedAnimals[_animalPoolIndex + i + 1]; + expBeat += seekedAnimal.length; + } + + animal.Init(currentAnimal.startBeat, expBeat); + + animal.transform.localPosition = new Vector3(_animalSummatedDistance, 0, 0); + + _animalPoolIndex++; + } + + public override void OnGameSwitch(double beat) + { + GetAnimals(beat); + } + + public override void OnPlay(double beat) + { + GetAnimals(beat); + } + + private void GetAnimals(double beat) + { + for (int i = 0; i < POOL_NUMBER; i++) + { + _pooledElephants.Add(Instantiate(_elephant, transform)); + _pooledGiraffes.Add(Instantiate(_giraffe, transform)); + _pooledMonkeysLong.Add(Instantiate(_monkeysLong, transform)); + _pooledMonkeysShort.Add(Instantiate(_monkeysShort, transform)); + } + + var allGameSwitches = EventCaller.GetAllInGameManagerList("gameManager", new string[] { "switchGame" }).FindAll(x => x.beat > beat); + double nextGameSwitchBeat = double.MaxValue; + if (allGameSwitches.Count > 0) nextGameSwitchBeat = allGameSwitches[0].beat; + + var allAnimals = EventCaller.GetAllInGameManagerList("animalAcrobat", new string[] + { + "elephant", "giraffe", "monkeys", "monkeyLong", "monkeyShort" + }).FindAll(x => x.beat >= beat && x.beat < nextGameSwitchBeat); + if (allAnimals.Count == 0) return; + + double goodBeat = allAnimals[0].beat; + for (int i = 0; i < allAnimals.Count; i++) + { + var animal = allAnimals[i]; + if (animal.beat != goodBeat) continue; + goodBeat += animal.length; + + if (animal.datamodel == "animalAcrobat/monkeys") + { + _queuedAnimals.Add(new QueuedAnimal() + { + startBeat = animal.beat, + length = 5, + type = AnimalType.MonkeysLong, + }); + _queuedAnimals.Add(new QueuedAnimal() + { + startBeat = animal.beat + 5, + length = 3, + type = AnimalType.MonkeysShort, + }); + continue; + } + _queuedAnimals.Add(new QueuedAnimal() + { + startBeat = animal.beat, + length = animal.datamodel switch + { + "animalAcrobat/elephant" => 4, + "animalAcrobat/giraffe" => 8, + "animalAcrobat/monkeyLong" => 5, + "animalAcrobat/monkeyShort" => 3, + _ => throw new System.NotImplementedException() + }, + type = animal.datamodel switch + { + "animalAcrobat/elephant" => AnimalType.Elephant, + "animalAcrobat/giraffe" => AnimalType.Giraffe, + "animalAcrobat/monkeyLong" => AnimalType.MonkeysLong, + "animalAcrobat/monkeyShort" => AnimalType.MonkeysShort, + _ => throw new System.NotImplementedException() + }, + }); + } + + if (_queuedAnimals.Count > 0) + { + _queuedAnimals.Sort((x, y) => x.startBeat.CompareTo(y.startBeat)); + for (int i = 0; i < POOL_NUMBER; i++) + { + BakeNextAvailableAnimal(); + } + } } } }