using UnityEngine; using UnityEngine.UI; using System.Collections; using System.Collections.Generic; using TMPro; using UnityEngine.SceneManagement; public class MemoryManager : MonoBehaviour { [Header("--- PANEL NAVIGASI & POP UP ---")] public GameObject panelPilihLevel; public GameObject panelGameMemory; public GameObject panelPopUpBenar; // SINKRONISASI LOGIKA DARI GAME SEBELUMNYA public static bool mauUlangGame = false; public static bool mauKembaliKePeta = false; public static bool sudahPernahSapaMemory = false; [Header("--- KOLEKSI SUARA MEMORY ---")] public AudioSource speakerGame; public AudioClip kasetNarator; public AudioClip kasetBukaKartu; public AudioClip kasetCocok; public AudioClip kasetSalah; public AudioClip kasetPopUpHebat; public AudioClip kasetPanelHasil; public AudioClip kasetKlikTombol; public AudioClip kasetKalahWaktu; [Header("--- DAFTAR STAGE (EMPTY OBJECT) ---")] public GameObject[] listStage; [Tooltip("Isi manual: Stage 1 ada berapa PASANG? (Misal 4 kartu = 2 pasang)")] public int[] targetPasanganPerStage; private int stageSekarang = 0; private int benarDiStageIni = 0; private int totalBenarGlobal = 0; private int totalTargetSemuaStage = 0; private bool gameSelesai = false; [Header("--- SISTEM SKOR KIRI ---")] public Image barSkor; public TextMeshProUGUI teksSkorKiri; public Image[] bintangSkorProgress; [Header("--- PENGATURAN WAKTU & HAFALAN ---")] public float waktuNgafal = 3f; public float durasiWaktuMain = 60f; private float waktuSisa; public Image barWaktu; // --- BARU: KONTROL WAKTU --- private bool waktuBolehJalan = false; [Header("--- PANEL HASIL AKHIR & ANIMASI ---")] public GameObject panelHasil; public RectTransform kontenPanelHasil; public Image[] slotBintangPanel; public TextMeshProUGUI teksSkorAkhir; // --- BARU: FITUR ANTI-KLIK --- [Header("--- FITUR ANTI-KLIK ---")] public CanvasGroup groupKlikGame; // TARIK PANEL_GAMEMEMORY KE SINI void Start() { // Bersihkan total semua suara & coroutine masa lalu StopAllCoroutines(); if (speakerGame != null) speakerGame.Stop(); waktuSisa = durasiWaktuMain; gameSelesai = false; totalBenarGlobal = 0; stageSekarang = 0; benarDiStageIni = 0; kartuTerbuka.Clear(); // Pastikan awal game gemboknya terbuka if (groupKlikGame != null) groupKlikGame.blocksRaycasts = true; // Hitung total target totalTargetSemuaStage = 0; foreach (int t in targetPasanganPerStage) totalTargetSemuaStage += t; // Reset UI if (panelHasil != null) panelHasil.SetActive(false); if (panelPopUpBenar != null) panelPopUpBenar.SetActive(false); if (barSkor != null) barSkor.fillAmount = 0; if (teksSkorKiri != null) teksSkorKiri.text = "0"; foreach (Image b in bintangSkorProgress) if(b != null) b.color = Color.gray; foreach (Image b in slotBintangPanel) if(b != null) b.color = Color.gray; if (barWaktu != null) { barWaktu.fillAmount = 1; barWaktu.color = Color.white; } UpdateTampilanStage(); // CEK MODE ULANGI (SINKRON SEMUA GAME) if (mauUlangGame) { if (panelPilihLevel != null) panelPilihLevel.SetActive(false); if (panelGameMemory != null) panelGameMemory.SetActive(true); mauUlangGame = false; MulaiSuaraNaratorSatuPintu(); } else if (mauKembaliKePeta) { if (panelPilihLevel != null) panelPilihLevel.SetActive(true); if (panelGameMemory != null) panelGameMemory.SetActive(false); mauKembaliKePeta = false; } } // FUNGSI SATU PINTU (Mencegah suara nabrak & Anti Klik) public void MulaiSuaraNaratorSatuPintu() { StopAllCoroutines(); if (speakerGame != null) { speakerGame.Stop(); StartCoroutine(LogikaTungguNarator()); } } IEnumerator LogikaTungguNarator() { // Kunci tombol pas narator ngomong if (groupKlikGame != null) groupKlikGame.blocksRaycasts = false; waktuBolehJalan = false; yield return new WaitForSeconds(0.2f); if (!sudahPernahSapaMemory) { if (kasetNarator != null) { speakerGame.PlayOneShot(kasetNarator); yield return new WaitForSeconds(kasetNarator.length); sudahPernahSapaMemory = true; } } // Buka gembok setelah narator beres if (groupKlikGame != null) groupKlikGame.blocksRaycasts = true; waktuBolehJalan = true; StartCoroutine(FaseMenghafalStage()); } public void MasukGameDanNgomongMemory() { // ========================================================= // JURUS MUTLAK ANTI-NABRAK: TEMBAK LANGSUNG DARI KODE! // ========================================================= ManagerSuaraBermain satpamMenu = FindObjectOfType(); if (satpamMenu != null) { satpamMenu.HentikanPaksaSuara(); // Paksa diam detik ini juga! } if (panelPilihLevel != null) panelPilihLevel.SetActive(false); if (panelGameMemory != null) panelGameMemory.SetActive(true); MulaiSuaraNaratorSatuPintu(); } // --- LOGIKA MEMORY (SISA KODE ASLI) --- private List kartuTerbuka = new List(); public bool lagiNgecek = false; void Update() { if (gameSelesai) return; // --- BARU: JIKA NARATOR BICARA / DIKUNCI, JANGAN JALAN WAKTUNYA --- if (!waktuBolehJalan) return; if (waktuSisa > 0) { waktuSisa -= Time.deltaTime; if (barWaktu != null) { barWaktu.fillAmount = waktuSisa / durasiWaktuMain; if (waktuSisa <= 10f) barWaktu.color = Color.red; } } else if (waktuBolehJalan && waktuSisa <= 0) { waktuSisa = 0; if (barWaktu != null) barWaktu.fillAmount = 0; GagalMain(); } } IEnumerator FaseMenghafalStage() { lagiNgecek = true; waktuBolehJalan = false; // Kunci layar saat anak lagi menghafal biar kartu gak bisa diklik dulu if (groupKlikGame != null) groupKlikGame.blocksRaycasts = false; yield return new WaitForSeconds(1f); Card[] kartuDiStageIni = listStage[stageSekarang].GetComponentsInChildren(); // ACAK POSISI FISIK for (int i = 0; i < kartuDiStageIni.Length; i++) { int r = Random.Range(i, kartuDiStageIni.Length); int tempIndex = kartuDiStageIni[i].transform.GetSiblingIndex(); kartuDiStageIni[i].transform.SetSiblingIndex(kartuDiStageIni[r].transform.GetSiblingIndex()); kartuDiStageIni[r].transform.SetSiblingIndex(tempIndex); Vector3 tempPos = kartuDiStageIni[i].transform.position; kartuDiStageIni[i].transform.position = kartuDiStageIni[r].transform.position; kartuDiStageIni[r].transform.position = tempPos; } foreach (Card k in kartuDiStageIni) { if (k != null) StartCoroutine(AnimasiFlip(k.GetComponent(), true, k)); } yield return new WaitForSeconds(waktuNgafal); foreach (Card k in kartuDiStageIni) { if (k != null) StartCoroutine(AnimasiFlip(k.GetComponent(), false, k)); } lagiNgecek = false; waktuBolehJalan = true; // Buka gembok layar biar bisa mulai main if (groupKlikGame != null) groupKlikGame.blocksRaycasts = true; } public void KartuDipilih(Card kartu) { if (lagiNgecek || !waktuBolehJalan) return; if (speakerGame != null && kasetBukaKartu != null) speakerGame.PlayOneShot(kasetBukaKartu); StartCoroutine(AnimasiFlip(kartu.GetComponent(), true, kartu)); kartuTerbuka.Add(kartu); if (kartuTerbuka.Count == 2) { StartCoroutine(CekKembar()); } } IEnumerator CekKembar() { lagiNgecek = true; yield return new WaitForSeconds(0.8f); if (kartuTerbuka[0].idPasangan == kartuTerbuka[1].idPasangan) { if (speakerGame != null && kasetCocok != null) speakerGame.PlayOneShot(kasetCocok); benarDiStageIni++; totalBenarGlobal++; UpdateUISkorKiri(); if (benarDiStageIni >= targetPasanganPerStage[stageSekarang]) { StartCoroutine(PindahStageNext()); } } else { if (speakerGame != null && kasetSalah != null) speakerGame.PlayOneShot(kasetSalah); StartCoroutine(AnimasiFlip(kartuTerbuka[0].GetComponent(), false, kartuTerbuka[0])); StartCoroutine(AnimasiFlip(kartuTerbuka[1].GetComponent(), false, kartuTerbuka[1])); } kartuTerbuka.Clear(); lagiNgecek = false; } IEnumerator AnimasiFlip(RectTransform kartu, bool buka, Card scriptKartu) { float t = 0; while (t < 1f) { t += Time.deltaTime * 10f; kartu.localScale = new Vector3(Mathf.Lerp(1, 0, t), 1, 1); yield return null; } if (buka) scriptKartu.BukaKartu(); else scriptKartu.TutupKartu(); t = 0; while (t < 1f) { t += Time.deltaTime * 10f; kartu.localScale = new Vector3(Mathf.Lerp(0, 1, t), 1, 1); yield return null; } kartu.localScale = Vector3.one; } IEnumerator PindahStageNext() { waktuBolehJalan = false; // Kunci layar saat pindah stage biar ga dispam if (groupKlikGame != null) groupKlikGame.blocksRaycasts = false; yield return new WaitForSeconds(0.5f); if (panelPopUpBenar != null) { panelPopUpBenar.SetActive(true); if (speakerGame != null && kasetPopUpHebat != null) speakerGame.PlayOneShot(kasetPopUpHebat); } yield return new WaitForSeconds(1.5f); if (panelPopUpBenar != null) panelPopUpBenar.SetActive(false); TutupSemuaKartuDiLayar(); yield return new WaitForSeconds(0.5f); if (stageSekarang < listStage.Length - 1) { if (listStage[stageSekarang] != null) listStage[stageSekarang].SetActive(false); stageSekarang++; benarDiStageIni = 0; UpdateTampilanStage(); StartCoroutine(FaseMenghafalStage()); // FaseMenghafalStage akan mengunci dan membuka layar otomatis } else { MenangMain(); } } void UpdateTampilanStage() { for (int i = 0; i < listStage.Length; i++) { if (listStage[i] != null) listStage[i].SetActive(i == stageSekarang); } } void UpdateUISkorKiri() { if (totalTargetSemuaStage == 0) return; float persentase = (float)totalBenarGlobal / totalTargetSemuaStage; if (barSkor != null) barSkor.fillAmount = persentase; if (teksSkorKiri != null) teksSkorKiri.text = Mathf.RoundToInt(persentase * 100f).ToString(); if (bintangSkorProgress.Length >= 3) { if (persentase >= 0.33f && bintangSkorProgress[0] != null) bintangSkorProgress[0].color = Color.white; if (persentase >= 0.66f && bintangSkorProgress[1] != null) bintangSkorProgress[1].color = Color.white; if (persentase >= 1.00f && bintangSkorProgress[2] != null) bintangSkorProgress[2].color = Color.white; } } void MenangMain() { if (gameSelesai) return; gameSelesai = true; waktuBolehJalan = false; TutupSemuaKartuDiLayar(); StartCoroutine(AnimasiPanelDanBintang(3, false)); } void GagalMain() { if (gameSelesai) return; gameSelesai = true; waktuBolehJalan = false; TutupSemuaKartuDiLayar(); float persentase = (float)totalBenarGlobal / totalTargetSemuaStage; int bintangDapat = (persentase >= 1.00f) ? 3 : (persentase >= 0.66f) ? 2 : (persentase >= 0.33f) ? 1 : 0; StartCoroutine(AnimasiPanelDanBintang(bintangDapat, true)); } IEnumerator AnimasiPanelDanBintang(int jumlahBintang, bool waktuHabis) { // --- BUKA KUNCI KLIK DISINI BIAR AMAN SAAT MUNCUL HASIL --- if (groupKlikGame != null) groupKlikGame.blocksRaycasts = true; if (kontenPanelHasil != null) { kontenPanelHasil.localScale = Vector3.zero; panelHasil.SetActive(true); panelHasil.transform.SetAsLastSibling(); float t = 0; while (t < 1f) { t += Time.deltaTime * 4f; float curve = Mathf.Sin(t * Mathf.PI * 0.7f) * 1.15f; kontenPanelHasil.localScale = new Vector3(curve, curve, curve); yield return null; } kontenPanelHasil.localScale = Vector3.one; } else { panelHasil.SetActive(true); } if (teksSkorAkhir != null) teksSkorAkhir.text = teksSkorKiri.text; if (waktuHabis) { if (speakerGame != null && kasetKalahWaktu != null) speakerGame.PlayOneShot(kasetKalahWaktu); } else { if (speakerGame != null && kasetPanelHasil != null) speakerGame.PlayOneShot(kasetPanelHasil); } yield return new WaitForSeconds(0.3f); for (int i = 0; i < jumlahBintang; i++) { if (i < slotBintangPanel.Length && slotBintangPanel[i] != null) { if (speakerGame != null && kasetCocok != null) speakerGame.PlayOneShot(kasetCocok); slotBintangPanel[i].color = Color.white; float bT = 0; Vector3 startScale = Vector3.one * 2f; while(bT < 1f){ bT += Time.deltaTime * 5f; slotBintangPanel[i].rectTransform.localScale = Vector3.Lerp(startScale, Vector3.one, bT); yield return null; } yield return new WaitForSeconds(0.4f); } } } public void TombolUlangi() { if (speakerGame != null && kasetKlikTombol != null) speakerGame.PlayOneShot(kasetKlikTombol); sudahPernahSapaMemory = false; mauUlangGame = true; SceneManager.LoadScene(SceneManager.GetActiveScene().name); } public void TombolKeluar() { if (speakerGame != null && kasetKlikTombol != null) speakerGame.PlayOneShot(kasetKlikTombol); sudahPernahSapaMemory = false; mauKembaliKePeta = true; SceneManager.LoadScene(SceneManager.GetActiveScene().name); } void TutupSemuaKartuDiLayar() { if (stageSekarang < listStage.Length && listStage[stageSekarang] != null) { Card[] kartuDiStageIni = listStage[stageSekarang].GetComponentsInChildren(); foreach (Card k in kartuDiStageIni) { if (k != null) StartCoroutine(AnimasiFlip(k.GetComponent(), false, k)); } } } }