using System.Threading; using Cysharp.Threading.Tasks; using Services; using Structs; using UnityEngine; using Utils; namespace Views { public class GemView : MonoBehaviour { [SerializeField] private SpriteRenderer childSpriteRenderer; private Gem gem; public Gem Gem => this.gem; private bool isFalling; private const float SPAWN_SCALE_FROM = 0f; private const float SPAWN_SCALE_DURATION = 0.12f; private CancellationTokenSource spawnScaleCts; public void Bind(Gem gem, GemTypeValues gemvalue, bool isBomb = false) { this.gem = gem; this.gameObject.SetActive(true); SetupGem(isBomb, gemvalue.gemSprite); PlaySpawnScale(); } private void SetupGem(bool isBomb, Sprite gemSprite = null) { if (!isBomb) return; if (this.childSpriteRenderer is null) return; if (gemSprite != null) { this.childSpriteRenderer.enabled = true; this.childSpriteRenderer.sprite = gemSprite; } else { this.childSpriteRenderer.enabled = false; this.childSpriteRenderer.color = Color.white; } } public void Unbind() { this.spawnScaleCts?.Cancel(); this.spawnScaleCts?.Dispose(); this.spawnScaleCts = null; this.gem = null; this.gameObject.SetActive(false); this.isFalling = false; } private void PlaySpawnScale() { this.spawnScaleCts?.Cancel(); this.spawnScaleCts?.Dispose(); this.spawnScaleCts = new CancellationTokenSource(); this.transform.localScale = Vector3.one * SPAWN_SCALE_FROM; AnimateSpawnScaleAsync(this.spawnScaleCts.Token).Forget(); } private async UniTask AnimateSpawnScaleAsync(CancellationToken ct) { float timer = 0f; while (timer < SPAWN_SCALE_DURATION) { ct.ThrowIfCancellationRequested(); timer += Time.deltaTime; float scale = Mathf.Clamp01(timer / SPAWN_SCALE_DURATION); scale = Mathf.SmoothStep(0f, 1f, scale); this.transform.localScale = Vector3.LerpUnclamped( Vector3.one * SPAWN_SCALE_FROM, Vector3.one, scale ); await UniTask.Yield(PlayerLoopTiming.Update, ct); } this.transform.localScale = Vector3.one; } private async UniTask FallDelay() { float fallDelay = 1 * (this.gem.Position.y / 10f); await UniTask.WaitForSeconds(fallDelay); this.isFalling = true; } public async UniTaskVoid UpdatePosition(Vector2Int positionBasedOnIndex, float gemSpeed) { if (!this.isFalling) { await FallDelay(); } if (!this.isFalling) return; if (Vector2.Distance(this.transform.position, positionBasedOnIndex.ToVector2()) > 0.01f) { this.transform.position = Vector2.Lerp(this.transform.position, positionBasedOnIndex.ToVector2(), gemSpeed); } } } }