diff --git a/Assets/Scenes/Main.unity b/Assets/Scenes/Main.unity index 64e43c2..3080e1e 100644 --- a/Assets/Scenes/Main.unity +++ b/Assets/Scenes/Main.unity @@ -158,6 +158,7 @@ MonoBehaviour: y: -5 width: 12 height: 10 + initialSpawnerAvoidedRegion: 4 rose: {fileID: 2147392553565862127, guid: 72ac2e17b1585614eb5c2eb65a0d37c0, type: 3} --- !u!4 &4783506 Transform: diff --git a/Assets/Scripts/Domain/Score.cs b/Assets/Scripts/Domain/Score.cs index fa02cef..9ad85f9 100644 --- a/Assets/Scripts/Domain/Score.cs +++ b/Assets/Scripts/Domain/Score.cs @@ -2,10 +2,13 @@ public class Score { public int Value { private set; get; } + public const int InitialRosesThreshold = 5; + public readonly int SpawnRate; public readonly int GrowIterations; public float GrowPercentage { private set; get; } + public int Roses => Value / (SpawnRate * GrowIterations); public Score(int spawnRate, int growIterations) : this(0, spawnRate, growIterations) { } diff --git a/Assets/Scripts/Presenter/ExpressionClick.cs b/Assets/Scripts/Presenter/ExpressionClick.cs index e04c9b7..73d8c14 100644 --- a/Assets/Scripts/Presenter/ExpressionClick.cs +++ b/Assets/Scripts/Presenter/ExpressionClick.cs @@ -23,8 +23,12 @@ namespace Presenter { _view.UpdateView(_score.Value); _onInputReceived.OnInputReceived(); - if (CanSpawn) - _spawner.SpawnRose(); + if (CanSpawn) { + if(_score.Value > Score.InitialRosesThreshold) + _spawner.SpawnRose(); + else + _spawner.SpawnInitialRose(); + } if (_score.Value % _score.GrowIterations == 0) _grow.GrowStep(); } diff --git a/Assets/Scripts/Presenter/IRoseSpawner.cs b/Assets/Scripts/Presenter/IRoseSpawner.cs index 83aba98..283706e 100644 --- a/Assets/Scripts/Presenter/IRoseSpawner.cs +++ b/Assets/Scripts/Presenter/IRoseSpawner.cs @@ -1,5 +1,6 @@ namespace Presenter { public interface IRoseSpawner { void SpawnRose(); + void SpawnInitialRose(); } } \ No newline at end of file diff --git a/Assets/Scripts/Presenter/SaveSystem/LoadGame.cs b/Assets/Scripts/Presenter/SaveSystem/LoadGame.cs index 962c4b2..07a6e3a 100644 --- a/Assets/Scripts/Presenter/SaveSystem/LoadGame.cs +++ b/Assets/Scripts/Presenter/SaveSystem/LoadGame.cs @@ -22,9 +22,12 @@ namespace Presenter.SaveSystem { _scoreView.UpdateView(_score.Value); _growAnimation.GrowStep(); - int roses = _score.Value / (_score.SpawnRate * _score.GrowIterations); - for (int i = 0; i < roses; i++) - _spawner.SpawnRose(); + for (int i = 0; i < _score.Roses; i++) { + if (_score.Roses > Score.InitialRosesThreshold) + _spawner.SpawnRose(); + else + _spawner.SpawnInitialRose(); + } } } } \ No newline at end of file diff --git a/Assets/Scripts/View/Collections/InputCallbackCollection.cs b/Assets/Scripts/View/Collections/InputCallbackCollection.cs new file mode 100644 index 0000000..5a8a143 --- /dev/null +++ b/Assets/Scripts/View/Collections/InputCallbackCollection.cs @@ -0,0 +1,16 @@ +using Presenter; + +namespace View.Collections { + public class InputCallbackCollection : IInputCallback { + private readonly IInputCallback[] _inputs; + + public InputCallbackCollection(IInputCallback[] inputs) { + _inputs = inputs; + } + + public void OnInputReceived() { + foreach (IInputCallback input in _inputs) + input.OnInputReceived(); + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/View/Collections/ScoreViewCollection.cs.meta b/Assets/Scripts/View/Collections/InputCallbackCollection.cs.meta similarity index 100% rename from Assets/Scripts/View/Collections/ScoreViewCollection.cs.meta rename to Assets/Scripts/View/Collections/InputCallbackCollection.cs.meta diff --git a/Assets/Scripts/View/Collections/ScoreViewCollection.cs b/Assets/Scripts/View/Collections/ScoreViewCollection.cs deleted file mode 100644 index 0bc6176..0000000 --- a/Assets/Scripts/View/Collections/ScoreViewCollection.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Presenter; - -namespace View.Collections { - public class ScoreViewCollection : IScoreView { - private readonly IScoreView[] _inputs; - - public ScoreViewCollection(IScoreView[] inputs) { - _inputs = inputs; - } - - public void UpdateView(int score) { - foreach (IScoreView input in _inputs) - input.UpdateView(score); - } - } -} \ No newline at end of file diff --git a/Assets/Scripts/View/Dependencies.cs b/Assets/Scripts/View/Dependencies.cs index e27a17d..4dbad6d 100644 --- a/Assets/Scripts/View/Dependencies.cs +++ b/Assets/Scripts/View/Dependencies.cs @@ -20,21 +20,21 @@ namespace View { Score = new Score(10, 10); IScoreView input = FindObjectOfType(); - IScoreView visibility = FindObjectOfType(); - IScoreView inputCollections = new ScoreViewCollection(new[] { input, visibility }); IRoseSpawner spawner = FindObjectOfType(); + IInputCallback visibility = FindObjectOfType(); IInputCallback growParticles = FindObjectOfType(); + IInputCallback inputCallback = new InputCallbackCollection(new[] { visibility, growParticles }); IRoseGrow growAnimation = FindObjectOfType(); - ExpressionClick = new ExpressionClick(Score, inputCollections, spawner, growAnimation, growParticles); + ExpressionClick = new ExpressionClick(Score, input, spawner, growAnimation, inputCallback); CustomInput = new CustomInput(); PlayerPrefsRepository repository = new(); Saver = new SaveGame(repository, Score); - Loader = new LoadGame(repository, Score, inputCollections, spawner, growAnimation); + Loader = new LoadGame(repository, Score, input, spawner, growAnimation); } } } \ No newline at end of file diff --git a/Assets/Scripts/View/RoseSpawner.cs b/Assets/Scripts/View/RoseSpawner.cs index 94b258f..faf4df9 100644 --- a/Assets/Scripts/View/RoseSpawner.cs +++ b/Assets/Scripts/View/RoseSpawner.cs @@ -6,6 +6,7 @@ using Random = UnityEngine.Random; namespace View { public class RoseSpawner : MonoBehaviour, IRoseSpawner { [SerializeField] private Rect spawnerRegion; + [SerializeField] private float initialSpawnerAvoidedRegion; [SerializeField] private GameObject rose; public void SpawnRose() { @@ -14,11 +15,35 @@ namespace View { spawnerRegion.position.y + Random.Range(-spawnerRegion.size.y / 2f, spawnerRegion.size.y / 2f) ); - Instantiate(rose, spawnPos, Quaternion.identity); + Spawn(spawnPos); + } + + public void SpawnInitialRose() { + bool spawnOnRight = Random.Range(0, 2) == 0; + Vector2 spawnPos; + if (spawnOnRight) { + spawnPos = new Vector2( + spawnerRegion.position.x + Random.Range(initialSpawnerAvoidedRegion / 2f, spawnerRegion.size.x / 2f), + spawnerRegion.position.y + Random.Range(-spawnerRegion.size.y / 2f, spawnerRegion.size.y / 2f) + ); + } else { + spawnPos = new Vector2( + spawnerRegion.position.x + Random.Range(-spawnerRegion.size.x / 2f, -initialSpawnerAvoidedRegion / 2f), + spawnerRegion.position.y + Random.Range(-spawnerRegion.size.y / 2f, spawnerRegion.size.y / 2f) + ); + } + + Spawn(spawnPos); + } + + private void Spawn(Vector2 pos) { + Instantiate(rose, pos, Quaternion.identity); } private void OnDrawGizmos() { Gizmos.DrawWireCube(spawnerRegion.position, spawnerRegion.size); + Gizmos.color = Color.red; + Gizmos.DrawWireCube(spawnerRegion.position, new Vector2(initialSpawnerAvoidedRegion, spawnerRegion.size.y)); } } } \ No newline at end of file diff --git a/Assets/Scripts/View/Scene/GrowAnimation.cs b/Assets/Scripts/View/Scene/GrowAnimation.cs index dc452db..cbea10e 100644 --- a/Assets/Scripts/View/Scene/GrowAnimation.cs +++ b/Assets/Scripts/View/Scene/GrowAnimation.cs @@ -16,7 +16,7 @@ namespace View.Scene { [SerializeField] private EventReference gloomEvent; private Score _score; - private bool _firstUpdate; + private bool _firstUpdate = true; private void Start() { _score = FindObjectOfType().Score; @@ -41,7 +41,7 @@ namespace View.Scene { public void GrowStep() { if (animator.CurrentAnimation == "Rosa_Grow") { animator.PlayUntil(IsLastGrowState(_score.Value, _score.GrowPercentage) ? 1f : _score.GrowPercentage); - if (_score.GrowPercentage < 1f) + if (_score.GrowPercentage < 1f && !_firstUpdate) RuntimeManager.PlayOneShot(growEvent); } _firstUpdate = false; diff --git a/Assets/Scripts/View/UI/UIVisibility.cs b/Assets/Scripts/View/UI/UIVisibility.cs index 5cdd32d..b32ab23 100644 --- a/Assets/Scripts/View/UI/UIVisibility.cs +++ b/Assets/Scripts/View/UI/UIVisibility.cs @@ -5,7 +5,7 @@ using UnityEngine.EventSystems; using UnityEngine.UI; namespace View.UI { - public class UIVisibility : MonoBehaviour, IScoreView { + public class UIVisibility : MonoBehaviour, IInputCallback { [SerializeField] private CanvasGroup ui; [SerializeField] private float fadeDuration = .5f; @@ -31,7 +31,7 @@ namespace View.UI { } } - public void UpdateView(int score) { + public void OnInputReceived() { if (!_titleVisible) return; _titleVisible = false; diff --git a/fmod_editor.log b/fmod_editor.log index e69de29..7d6b5e7 100644 --- a/fmod_editor.log +++ b/fmod_editor.log @@ -0,0 +1,32 @@ +[LOG] System::create : Header version = 2.02.06. Current version = 2.02.06. +[LOG] Manager::init : maxchannels = 256 studioflags = 00000006 flags 00000000 extradriverdata 0000000000000000. +[LOG] SystemI::init : Initialize version=20206 (124257), maxchannels=256, flags=0x00020000 +[LOG] SystemI::setOutputInternal : Setting output to 'FMOD WASAPI Output' +[LOG] OutputWASAPI::init : Mix Format (WAVEFORMATEX): wFormatTag=0xFFFE, nChannels=2, nSamplesPerSec=48000, nAvgBytesPerSec=384000, nBlockAlign=8, wBitsPerSample=32, cbSize=22. +[LOG] OutputWASAPI::init : Mix Format (WAVEFORMATEXTENSIBLE): wValidBitsPerSample=32, dwChannelMask=0x00000003, SubFormat=00000003-0000-0010-8000-00AA00389B71. +[LOG] OutputWASAPI::init : Output buffer size: 4096 samples, latency: 0.00ms, period: 10.00ms, DSP buffer: 1024 * 4 +[LOG] Thread::initThread : Init FMOD stream thread. Affinity: 0x4000000000000003, Priority: 0xFFFF7FFB, Stack Size: 98304, Semaphore: No, Sleep Time: 10, Looping: Yes. +[LOG] Thread::initThread : Init FMOD mixer thread. Affinity: 0x4000000000000001, Priority: 0xFFFF7FFA, Stack Size: 81920, Semaphore: No, Sleep Time: 0, Looping: Yes. +[LOG] AsyncManager::init : manager 000001B757DCD1A8 isAsync 0 updatePeriod 0.02 +[LOG] AsyncManager::init : done +[LOG] PlaybackSystem::init : +[LOG] Thread::initThread : Init FMOD Studio sample load thread. Affinity: 0x4000000000000003, Priority: 0xFFFF7FFD, Stack Size: 98304, Semaphore: No, Sleep Time: 1, Looping: No. +[LOG] PlaybackSystem::init : done +[LOG] Thread::initThread : Init FMOD Studio bank load thread. Affinity: 0x4000000000000003, Priority: 0xFFFF7FFD, Stack Size: 98304, Semaphore: No, Sleep Time: 1, Looping: No. +[LOG] Manager::init : done. +[LOG] SystemI::createSoundInternal : Create name='', mode=0x02000202 +[LOG] SystemI::createSoundInternal : exinfo->cbsize = 224 +[LOG] SystemI::createSoundInternal : exinfo->length = 28161664 +[LOG] SystemI::createSoundInternal : exinfo->fileoffset = 10400 +[LOG] SystemI::createSoundInternal : exinfo->numsubsounds = 1 +[LOG] SystemI::createSoundInternal : exinfo->inclusionlist = 0000009D2BA6F328 +[LOG] SystemI::createSoundInternal : exinfo->inclusionlistnum = 1 +[LOG] SystemI::createSoundInternal : exinfo->suggestedsoundtype = 5 +[LOG] SystemI::createSoundInternal : exinfo->useropen = 00007FF880C04660 +[LOG] SystemI::createSoundInternal : exinfo->userclose = 00007FF880C04630 +[LOG] SystemI::createSoundInternal : exinfo->userread = 00007FF880C04730 +[LOG] SystemI::createSoundInternal : exinfo->userseek = 00007FF880C047F0 +[LOG] SystemI::createSoundInternal : exinfo->fileuserdata = 000001B764B2DF88 +[LOG] SystemI::createSoundInternal : exinfo->initialseekpostype = 1 +[LOG] SystemI::DSPCodecPoolRegister : register codec pool for pool type 5 +[LOG] SystemI::createSoundInternal : Sample 0/1: name='Rosa_grow_01', format=5, channels=2, frequency=48000, lengthbytes=53664, lengthpcm=264000, pcmblocksize=0, loopstart=0, loopend=0, mode=0x00000000, channelmask=0x00000000, channelorder=0, peakvolume=0.124284.