Files
match3-unity/Assets/Scripts/Views/GemView.cs

107 lines
3.3 KiB
C#

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 * Time.deltaTime);
}
}
}
}