Ekosistem_Game/Assets/Script/MemoryManager.cs

446 lines
15 KiB
C#

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<ManagerSuaraBermain>();
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<Card> kartuTerbuka = new List<Card>();
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<Card>();
// 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<RectTransform>(), true, k));
}
yield return new WaitForSeconds(waktuNgafal);
foreach (Card k in kartuDiStageIni) {
if (k != null) StartCoroutine(AnimasiFlip(k.GetComponent<RectTransform>(), 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<RectTransform>(), 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<RectTransform>(), false, kartuTerbuka[0]));
StartCoroutine(AnimasiFlip(kartuTerbuka[1].GetComponent<RectTransform>(), 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<Card>();
foreach (Card k in kartuDiStageIni)
{
if (k != null) StartCoroutine(AnimasiFlip(k.GetComponent<RectTransform>(), false, k));
}
}
}
}