349 lines
11 KiB
C#
349 lines
11 KiB
C#
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using TMPro;
|
|
using UnityEngine.SceneManagement;
|
|
|
|
public class GameManagerSusun : MonoBehaviour
|
|
{
|
|
public static GameManagerSusun instance;
|
|
|
|
[Header("Sistem Data Soal")]
|
|
public VegetableSusun[] listSoal;
|
|
private int indexSoal = 0;
|
|
|
|
[Header("Sistem Skor & Progress")]
|
|
public Slider sliderSkor;
|
|
public TextMeshProUGUI textSkor;
|
|
public Material materialKartuAtas;
|
|
public Image bintang1, bintang2, bintang3;
|
|
public Sprite bintangNyala;
|
|
private float skorSekarangVisual = 0;
|
|
private int skorTarget = 0;
|
|
|
|
[Header("Sistem Timer")]
|
|
public TextMeshProUGUI textTimer;
|
|
public float durasiMenit = 2f;
|
|
private float waktuTersisa;
|
|
private bool gameAktif = false;
|
|
|
|
[Header("Area & Prefabs")]
|
|
public Transform letterGrid;
|
|
public Transform letterBank;
|
|
public Image displaySayur;
|
|
public GameObject slotPrefab;
|
|
public GameObject kartuStatisPrefab;
|
|
public GameObject kartuDragPrefab;
|
|
|
|
[Header("Sistem Suara")]
|
|
public AudioClip suaraBintang;
|
|
|
|
[Header("UI PopUp & Board Hasil Akhir")]
|
|
public GameObject popupWahKeren;
|
|
public GameObject popupSalah;
|
|
public GameObject panelBoardHasil;
|
|
public GameObject latarHitam;
|
|
public TextMeshProUGUI textNilaiAkhir;
|
|
public Image hasilBintang1, hasilBintang2, hasilBintang3;
|
|
|
|
[Header("Sistem Audio")]
|
|
public AudioSource audioSource;
|
|
public AudioClip sfxDropBenar;
|
|
|
|
void Awake() { if (instance == null) instance = this; }
|
|
|
|
void Start()
|
|
{
|
|
skorTarget = 0;
|
|
skorSekarangVisual = 0;
|
|
indexSoal = 0;
|
|
waktuTersisa = durasiMenit * 60f;
|
|
gameAktif = true;
|
|
|
|
if(sliderSkor != null) {
|
|
sliderSkor.maxValue = 100;
|
|
sliderSkor.value = 0;
|
|
}
|
|
|
|
ResetPopups();
|
|
UpdateVisualSkor();
|
|
MuatSoal();
|
|
}
|
|
|
|
void ResetPopups()
|
|
{
|
|
if(popupWahKeren != null) popupWahKeren.SetActive(false);
|
|
if(popupSalah != null) popupSalah.SetActive(false);
|
|
if(panelBoardHasil != null) panelBoardHasil.SetActive(false);
|
|
if(latarHitam != null) latarHitam.SetActive(false);
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
if (gameAktif && waktuTersisa > 0)
|
|
{
|
|
waktuTersisa -= Time.deltaTime;
|
|
UpdateDisplayTimer();
|
|
}
|
|
else if (gameAktif && waktuTersisa <= 0)
|
|
{
|
|
MunculkanBoardAkhir();
|
|
}
|
|
|
|
if (sliderSkor != null && skorSekarangVisual < skorTarget)
|
|
{
|
|
skorSekarangVisual = Mathf.MoveTowards(skorSekarangVisual, skorTarget, 50f * Time.deltaTime);
|
|
sliderSkor.value = skorSekarangVisual;
|
|
CheckBintangLevel(skorSekarangVisual, bintang1, bintang2, bintang3);
|
|
}
|
|
}
|
|
|
|
public void MuatSoal()
|
|
{
|
|
ResetPopups();
|
|
|
|
foreach (Transform child in letterGrid) Destroy(child.gameObject);
|
|
foreach (Transform child in letterBank) Destroy(child.gameObject);
|
|
|
|
if (indexSoal >= listSoal.Length) {
|
|
MunculkanBoardAkhir();
|
|
return;
|
|
}
|
|
|
|
VegetableSusun data = listSoal[indexSoal];
|
|
displaySayur.sprite = data.gambarSayur;
|
|
|
|
char[] hurufArray = data.namaSayur.ToUpper().ToCharArray();
|
|
List<char> listHurufBank = new List<char>();
|
|
|
|
for (int i = 0; i < hurufArray.Length; i++)
|
|
{
|
|
if (data.visibilityHuruf[i] == true) {
|
|
GameObject kartu = Instantiate(kartuStatisPrefab, letterGrid);
|
|
kartu.GetComponentInChildren<TextMeshProUGUI>().text = hurufArray[i].ToString();
|
|
} else {
|
|
GameObject slot = Instantiate(slotPrefab, letterGrid);
|
|
slot.GetComponent<SlotHuruf>().jawabanBenar = hurufArray[i];
|
|
listHurufBank.Add(hurufArray[i]);
|
|
}
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(data.hurufPengecoh))
|
|
{
|
|
foreach (char p in data.hurufPengecoh.ToUpper().ToCharArray()) {
|
|
listHurufBank.Add(p);
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < listHurufBank.Count; i++) {
|
|
char temp = listHurufBank[i];
|
|
int randomIndex = Random.Range(i, listHurufBank.Count);
|
|
listHurufBank[i] = listHurufBank[randomIndex];
|
|
listHurufBank[randomIndex] = temp;
|
|
}
|
|
|
|
foreach (char h in listHurufBank) {
|
|
GameObject kartuDrag = Instantiate(kartuDragPrefab, letterBank);
|
|
kartuDrag.GetComponent<KartuHuruf>().isiHuruf = h;
|
|
kartuDrag.GetComponentInChildren<TextMeshProUGUI>().text = h.ToString();
|
|
}
|
|
}
|
|
|
|
public void CekJawaban()
|
|
{
|
|
if (audioSource != null && sfxDropBenar != null) audioSource.PlayOneShot(sfxDropBenar);
|
|
|
|
bool semuaSlotSudahTerisi = true;
|
|
SlotHuruf[] semuaSlot = letterGrid.GetComponentsInChildren<SlotHuruf>();
|
|
|
|
foreach (SlotHuruf slot in semuaSlot)
|
|
{
|
|
if (!slot.sudahTerisi)
|
|
{
|
|
semuaSlotSudahTerisi = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (semuaSlotSudahTerisi)
|
|
{
|
|
// Ambil referensi soal SEKARANG sebelum index berubah
|
|
VegetableSusun soalSekarang = listSoal[indexSoal];
|
|
StartCoroutine(UrutanMenangSoal(soalSekarang));
|
|
}
|
|
}
|
|
|
|
// Tambahkan parameter VegetableSusun agar VO tidak salah panggil
|
|
IEnumerator UrutanMenangSoal(VegetableSusun data)
|
|
{
|
|
// 1. Efek Kartu Hijau (Blink)
|
|
StartCoroutine(EfekKartuHijau());
|
|
yield return new WaitForSeconds(0.8f);
|
|
|
|
// 2. Putar VO Nama Sayur
|
|
if (audioSource != null && data.voSayur != null)
|
|
{
|
|
audioSource.PlayOneShot(data.voSayur);
|
|
// Tunggu sampai VO benar-benar selesai
|
|
yield return new WaitForSeconds(data.voSayur.length);
|
|
}
|
|
|
|
// 3. Jeda tambahan 1 detik
|
|
yield return new WaitForSeconds(0.5f);
|
|
|
|
// 4. Munculkan Pop Up Benar
|
|
skorTarget += 10;
|
|
UpdateVisualSkor();
|
|
if(popupWahKeren != null) popupWahKeren.SetActive(true);
|
|
|
|
// 5. Jeda Pop Up muncul sebelum ganti soal
|
|
yield return new WaitForSeconds(1f);
|
|
indexSoal++;
|
|
MuatSoal();
|
|
}
|
|
|
|
// Fungsi-fungsi lainnya tetap sama...
|
|
// (MunculkanWrong, EfekKartuHijau, dll)
|
|
|
|
public void MunculkanWrong()
|
|
{
|
|
if(popupSalah != null)
|
|
{
|
|
popupSalah.SetActive(true);
|
|
StopCoroutine("SembunyikanWrongTimer");
|
|
StartCoroutine(SembunyikanWrongTimer());
|
|
}
|
|
}
|
|
|
|
IEnumerator SembunyikanWrongTimer()
|
|
{
|
|
yield return new WaitForSeconds(1f);
|
|
if(popupSalah != null) popupSalah.SetActive(false);
|
|
}
|
|
|
|
public void MunculkanBoardAkhir()
|
|
{
|
|
// 1. Cek pengaman agar tidak simpan berkali-kali
|
|
if (!gameAktif) return;
|
|
gameAktif = false;
|
|
|
|
// --- PROSES SIMPAN DATA KE DATABASE JSON ---
|
|
float durasiMain = 0;
|
|
TimeTracker tt = FindObjectOfType<TimeTracker>();
|
|
if (tt != null) durasiMain = tt.GetDurasiBermain();
|
|
|
|
if (SaveSystem.instance != null)
|
|
{
|
|
// Index 3 adalah khusus untuk Game Susun Huruf
|
|
SaveSystem.instance.SimpanHasilGame(3, skorTarget, durasiMain);
|
|
}
|
|
// --------------------------------------------
|
|
|
|
waktuTersisa = 0;
|
|
textTimer.text = "00:00";
|
|
|
|
if(panelBoardHasil != null)
|
|
{
|
|
if(latarHitam != null) latarHitam.SetActive(true);
|
|
panelBoardHasil.SetActive(true);
|
|
StartCoroutine(AnimasiHasilAkhir());
|
|
}
|
|
}
|
|
|
|
IEnumerator AnimasiHasilAkhir()
|
|
{
|
|
float durasiAcak = 0.1f;
|
|
float timerAcak = 0;
|
|
|
|
// Ambil komponen AudioSource untuk memutar suara
|
|
AudioSource audio = GetComponent<AudioSource>();
|
|
|
|
// Efek angka acak sebelum skor asli muncul
|
|
while (timerAcak < durasiAcak)
|
|
{
|
|
timerAcak += Time.deltaTime;
|
|
int angkaTampil = Random.Range(0, skorTarget + 1);
|
|
if(textNilaiAkhir != null) textNilaiAkhir.text = angkaTampil.ToString();
|
|
yield return new WaitForSeconds(0.05f);
|
|
}
|
|
|
|
if(textNilaiAkhir != null) textNilaiAkhir.text = skorTarget.ToString();
|
|
yield return new WaitForSeconds(0.3f);
|
|
|
|
// --- PROSES MUNCUL BINTANG DENGAN SUARA ---
|
|
|
|
// Bintang 1 (Skor minimal 40)
|
|
if (skorTarget >= 40 && hasilBintang1 != null) {
|
|
hasilBintang1.sprite = bintangNyala;
|
|
|
|
// Mainkan Suara
|
|
if(audio != null && suaraBintang != null) audio.PlayOneShot(suaraBintang);
|
|
|
|
if(hasilBintang1.GetComponent<EfekPopKenyal>())
|
|
hasilBintang1.GetComponent<EfekPopKenyal>().enabled = true;
|
|
|
|
yield return new WaitForSeconds(0.5f); // Jeda sebelum bintang berikutnya
|
|
}
|
|
|
|
// Bintang 2 (Skor minimal 80)
|
|
if (skorTarget >= 80 && hasilBintang2 != null) {
|
|
hasilBintang2.sprite = bintangNyala;
|
|
|
|
// Mainkan Suara (Pitch dinaikkan dikit biar suaranya lebih tinggi/ceriam)
|
|
if(audio != null && suaraBintang != null) {
|
|
audio.pitch = 1.1f;
|
|
audio.PlayOneShot(suaraBintang);
|
|
}
|
|
|
|
if(hasilBintang2.GetComponent<EfekPopKenyal>())
|
|
hasilBintang2.GetComponent<EfekPopKenyal>().enabled = true;
|
|
|
|
yield return new WaitForSeconds(0.5f);
|
|
}
|
|
|
|
// Bintang 3 (Skor sempurna 100)
|
|
if (skorTarget >= 100 && hasilBintang3 != null) {
|
|
hasilBintang3.sprite = bintangNyala;
|
|
|
|
// Mainkan Suara (Pitch dinaikkan lagi)
|
|
if(audio != null && suaraBintang != null) {
|
|
audio.pitch = 1.2f;
|
|
audio.PlayOneShot(suaraBintang);
|
|
}
|
|
|
|
if(hasilBintang3.GetComponent<EfekPopKenyal>())
|
|
hasilBintang3.GetComponent<EfekPopKenyal>().enabled = true;
|
|
|
|
// Kembalikan pitch ke normal setelah selesai
|
|
if(audio != null) audio.pitch = 1f;
|
|
}
|
|
}
|
|
|
|
void UpdateDisplayTimer() {
|
|
float menit = Mathf.FloorToInt(waktuTersisa / 60);
|
|
float detik = Mathf.FloorToInt(waktuTersisa % 60);
|
|
textTimer.text = string.Format("{0:00}:{1:00}", menit, detik);
|
|
}
|
|
|
|
void UpdateVisualSkor() {
|
|
if(textSkor != null) textSkor.text = skorTarget.ToString();
|
|
}
|
|
|
|
void CheckBintangLevel(float skor, Image b1, Image b2, Image b3) {
|
|
if (skor >= 40 && b1 != null) b1.sprite = bintangNyala;
|
|
if (skor >= 80 && b2 != null) b2.sprite = bintangNyala;
|
|
if (skor >= 100 && b3 != null) b3.sprite = bintangNyala;
|
|
}
|
|
|
|
IEnumerator EfekKartuHijau()
|
|
{
|
|
Image[] semuaGambar = letterGrid.GetComponentsInChildren<Image>();
|
|
foreach (Image img in semuaGambar) img.color = Color.green;
|
|
yield return new WaitForSeconds(0.5f);
|
|
foreach (Image img in semuaGambar) img.color = Color.white;
|
|
}
|
|
|
|
public void TombolReplay() { SceneManager.LoadScene(SceneManager.GetActiveScene().name); }
|
|
public void TombolKembaliMenu() { SceneManager.LoadScene("MenuBermain"); }
|
|
} |