MIF_E31230101/Assets/Script Manager/DragDropManager.cs

329 lines
11 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class DragDropManager : MonoBehaviour
{
[System.Serializable]
public struct LevelConfig
{
public string namaLevel;
public int itemCount;
public float maxTime;
}
[Header("Game Settings")]
public List<LevelConfig> levelConfigs;
public List<Sprite> spritePool;
[Header("Prefabs")]
public GameObject prefabSlotBayangan;
public GameObject prefabSlotWarna;
[Header("Containers")]
public Transform shadowContainer;
public Transform cardContainer;
[Header("Timer UI")]
public Image timerFill;
public float penguranganWaktu = 3f; // Jumlah detik yang dikurangi kalau salah
public float tambahanWaktu = 2f; // Jumlah detik yang ditambah kalau benar (BARU)
private float currentTime, totalMaxTime;
private Color warnaAsliTimer; // Untuk menyimpan warna hijau aslinya
[Header("Win UI & Stars")]
public GameObject winPopup;
public GameObject[] activeStars;
[Header("Audio SFX")]
public AudioSource sfxSource;
public AudioClip klipBenar;
public AudioClip klipSalah;
private int matchedCount = 0;
private int goal;
private bool isGameActive = false;
void Start()
{
if (timerFill) warnaAsliTimer = timerFill.color; // Simpan warna aslinya
SetupLevel();
}
void Update()
{
if (isGameActive)
{
currentTime -= Time.deltaTime;
// Jaga biar waktu nggak minus
if (currentTime < 0) currentTime = 0;
if (timerFill) timerFill.fillAmount = currentTime / totalMaxTime;
if (currentTime <= 0)
{
isGameActive = false;
StartCoroutine(ShowWinPopup(true));
}
}
}
public void MainkanSuaraBenar()
{
if (sfxSource != null && klipBenar != null)
{
sfxSource.PlayOneShot(klipBenar);
}
}
public void MainkanSuaraSalah()
{
if (sfxSource != null && klipSalah != null)
{
sfxSource.PlayOneShot(klipSalah);
}
}
// --- FITUR BARU: REWARD FEEDBACK POSITIF ---
public void BerikanBonusWaktu()
{
currentTime += tambahanWaktu;
// Jaga agar penambahan waktu tidak meluber melebihi kapasitas maksimal Bar Timer
if (currentTime > totalMaxTime) currentTime = totalMaxTime;
StartCoroutine(TimerBerkedipHijau());
MainkanSuaraBenar(); // Otomatis bunyikan sfx benar
}
IEnumerator TimerBerkedipHijau()
{
if (timerFill != null)
{
timerFill.color = Color.green; // Flash warna hijau cerah sebagai reward
yield return new WaitForSeconds(0.2f);
timerFill.color = warnaAsliTimer; // Balik ke warna UI semula
}
}
public void BerikanHukumanWaktu()
{
currentTime -= penguranganWaktu;
StartCoroutine(TimerBerkedipMerah());
MainkanSuaraSalah(); // Otomatis bunyikan sfx salah
}
IEnumerator TimerBerkedipMerah()
{
if (timerFill != null)
{
timerFill.color = Color.red; // Berubah merah
yield return new WaitForSeconds(0.2f);
timerFill.color = warnaAsliTimer; // Balik ke warna semula
}
}
void SetupLevel()
{
int lv = LevelData.SelectedLevel;
if (lv >= levelConfigs.Count) lv = 0;
LevelConfig config = levelConfigs[lv];
goal = config.itemCount;
totalMaxTime = config.maxTime;
currentTime = totalMaxTime;
// =========================================================================
// FORMULA UTAMA: KALKULASI UKURAN KARTU DINAMIS (RESPONSIVE UI)
// =========================================================================
GridLayoutGroup shadowGrid = shadowContainer.GetComponent<GridLayoutGroup>();
RectTransform shadowRect = shadowContainer.GetComponent<RectTransform>();
GridLayoutGroup cardGrid = cardContainer.GetComponent<GridLayoutGroup>();
RectTransform cardRect = cardContainer.GetComponent<RectTransform>();
float spacingX = 30f;
Vector2 paddingDanSpacing = new Vector2(spacingX, 0);
if (shadowGrid != null && shadowRect != null)
{
float lebarContainer = shadowRect.rect.width;
float paddingKananKiri = 160f;
float lebarTersedia = lebarContainer - paddingKananKiri - (spacingX * (goal - 1));
float dynamicWidth = lebarTersedia / goal;
if (dynamicWidth > 240f) dynamicWidth = 240f;
float dynamicHeight = dynamicWidth * 1.35f;
Vector2 dynamicCellSize = new Vector2(dynamicWidth, dynamicHeight);
shadowGrid.padding.left = 0; shadowGrid.padding.right = 0;
shadowGrid.cellSize = dynamicCellSize;
shadowGrid.spacing = paddingDanSpacing;
shadowGrid.childAlignment = TextAnchor.MiddleCenter;
shadowGrid.constraint = GridLayoutGroup.Constraint.FixedColumnCount;
shadowGrid.constraintCount = goal;
}
if (cardGrid != null && cardRect != null)
{
cardGrid.padding.left = 0; cardGrid.padding.right = 0;
cardGrid.cellSize = shadowGrid.cellSize;
cardGrid.spacing = paddingDanSpacing;
cardGrid.childAlignment = TextAnchor.MiddleCenter;
cardGrid.constraint = GridLayoutGroup.Constraint.FixedColumnCount;
cardGrid.constraintCount = goal;
}
// =========================================================================
List<Sprite> selected = new List<Sprite>();
List<Sprite> tempPool = new List<Sprite>(spritePool);
for (int i = 0; i < goal; i++)
{
if (tempPool.Count == 0) break;
int r = Random.Range(0, tempPool.Count);
selected.Add(tempPool[r]);
tempPool.RemoveAt(r);
}
StartCoroutine(SpawnSequence(selected));
}
IEnumerator SpawnSequence(List<Sprite> selected)
{
for (int i = 0; i < selected.Count; i++)
{
GameObject s = Instantiate(prefabSlotBayangan, shadowContainer);
ShadowSlot slot = s.GetComponentInChildren<ShadowSlot>();
if (slot != null) slot.Setup(selected[i], i);
s.transform.localScale = Vector3.zero;
StartCoroutine(AnimasiSpawnKeren(s.transform));
yield return new WaitForSeconds(0.1f);
}
List<int> shuffledIndices = new List<int>();
for (int i = 0; i < selected.Count; i++) shuffledIndices.Add(i);
for (int i = 0; i < shuffledIndices.Count; i++)
{
int temp = shuffledIndices[i];
int r = Random.Range(i, shuffledIndices.Count);
shuffledIndices[i] = shuffledIndices[r];
shuffledIndices[r] = temp;
}
foreach (int idx in shuffledIndices)
{
GameObject c = Instantiate(prefabSlotWarna, cardContainer);
DragDropItem ddi = c.GetComponentInChildren<DragDropItem>();
if (ddi != null) ddi.Setup(selected[idx], idx, this);
c.transform.localScale = Vector3.zero;
StartCoroutine(AnimasiSpawnKeren(c.transform));
yield return new WaitForSeconds(0.1f);
}
yield return new WaitForSeconds(0.2f);
isGameActive = true;
}
IEnumerator AnimasiSpawnKeren(Transform t)
{
float time = 0;
t.localRotation = Quaternion.Euler(0, 0, 180f);
while (time < 1)
{
time += Time.deltaTime * 4;
float scaleCrv = 1f + Mathf.Sin(time * Mathf.PI) * 0.2f;
t.localScale = Vector3.one * (time < 1 ? time * scaleCrv : 1f);
t.localRotation = Quaternion.Euler(0, 0, Mathf.Lerp(180f, 0f, time));
yield return null;
}
t.localScale = Vector3.one;
t.localRotation = Quaternion.Euler(0, 0, 0);
}
public void CheckWin()
{
matchedCount++;
if (matchedCount >= goal)
{
MainkanSuaraBenar(); // Putar sfx menang untuk kartu terakhir
isGameActive = false;
StartCoroutine(ShowWinPopup(false));
}
else
{
BerikanBonusWaktu(); // Jika belum menang total, berikan bonus waktu + flash hijau + sfx benar
}
}
IEnumerator ShowWinPopup(bool isTimeOut)
{
yield return new WaitForSeconds(0.5f);
if (winPopup)
{
winPopup.SetActive(true);
winPopup.transform.SetAsLastSibling();
}
foreach (GameObject star in activeStars)
{
if (star != null) star.SetActive(false);
}
yield return new WaitForSeconds(0.3f);
int starsEarned = 0;
if (!isTimeOut)
{
float ratio = currentTime / totalMaxTime;
if (ratio >= 0.6f) starsEarned = 3;
else if (ratio >= 0.2f) starsEarned = 2;
else starsEarned = 1;
int levelTerbuka = PlayerPrefs.GetInt("ProgresDrag", 1);
if (LevelData.SelectedLevel + 1 >= levelTerbuka)
{
PlayerPrefs.SetInt("ProgresDrag", LevelData.SelectedLevel + 2);
}
}
else
{
float progress = (float)matchedCount / goal;
if (progress >= 0.8f) starsEarned = 2;
else if (progress >= 0.4f) starsEarned = 1;
}
for (int i = 0; i < starsEarned; i++)
{
if (i < activeStars.Length && activeStars[i] != null)
{
activeStars[i].transform.localScale = Vector3.zero;
activeStars[i].SetActive(true);
StartCoroutine(AnimasiSpawnKeren(activeStars[i].transform));
yield return new WaitForSeconds(0.3f);
}
}
PlayerPrefs.SetInt("Stars_Drag_" + LevelData.SelectedLevel, starsEarned);
}
public void TombolRetry() { SceneManager.LoadScene(SceneManager.GetActiveScene().name); }
public void TombolHome() { SceneManager.LoadScene("MenuLevel_DragDrop"); }
public void TombolNext()
{
LevelData.SelectedLevel++;
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
}