using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using TMPro; using UnityEngine.SceneManagement; public class Mod12_TrueFalseGame : MonoBehaviour { [Header("TXT FILE (TR,EN,ES,DE,FR,PT)")] public TextAsset analogyFile; // TXT dosyasını sürükle-bırak [System.Serializable] public class WordPair { public string tr, en, es, de, fr, pt; public WordPair(string tr, string en, string es, string de, string fr, string pt) { this.tr = tr; this.en = en; this.es = es; this.de = de; this.fr = fr; this.pt = pt; } public string Get(string lang) { return lang switch { "tr" => tr, "en" => en, "es" => es, "de" => de, "fr" => fr, "pt" => pt, _ => en }; } } // ================= UI ================= public TMP_Text wordText; public TMP_Text feedbackText; public TMP_Text scoreText; public TMP_Text comboText; public TMP_Text timerText; public Button trueButton; public Button falseButton; public Button passButton; [Header("━━━ BACK BUTTON ━━━━━━━━━━━━━━━━━━━━━━━━")] public Button backButton; public string backSceneName = "ModSec 12"; [Header("COLORS")] public Color normalColor = new Color32(255, 255, 255, 40); public Color selectedColor = new Color32(60, 120, 220, 255); public Color correctColor = new Color32(0, 200, 0, 255); public Color wrongColor = new Color32(200, 0, 0, 255); [Header("━━━ FEEDBACK TEXT SETTINGS ━━━━━━━━━━━━━")] public bool feedbackOnTop = true; public float feedbackTopY = 400f; public float feedbackFontSize = 72f; [Header("━━━ ANIMATION SETTINGS ━━━━━━━━━━━━━━━━━")] [Range(0.80f, 1f)] public float selectedScale = 0.94f; public float selectAnimTime = 0.10f; // ================= Logic ================= private List words = new List(); private bool correctPair; private bool locked = false; private float timeLeft = 60f; private int score = 0; private int combo = 0; private int correctCount = 0; private int wrongCount = 0; string qLang; string aLang; string modKey = "Mod12"; readonly Color timerNormalColor = Color.white; readonly Color timerWarnColor = new Color32(255, 80, 80, 255); Vector3 trueOriginalScale = Vector3.one; Vector3 falseOriginalScale = Vector3.one; Vector3 trueOriginalPos; Vector3 falseOriginalPos; Coroutine trueScaleCo; Coroutine falseScaleCo; Coroutine feedbackCo; Coroutine wordFadeCo; // ============================================================ void Start() { qLang = PlayerPrefs.GetString("QuestionLangCode", "en"); aLang = PlayerPrefs.GetString("AnswerLangCode", "tr"); CacheButtonData(); PrepareFeedbackText(); LoadTXT(); trueButton.onClick.AddListener(() => Answer(true)); falseButton.onClick.AddListener(() => Answer(false)); passButton.onClick.AddListener(Pass); if (backButton != null) { backButton.onClick.RemoveAllListeners(); backButton.onClick.AddListener(() => SceneManager.LoadScene(backSceneName)); } UpdateScore(); UpdateCombo(); NextQuestion(); } // ============================================================ void Update() { if (!locked) { timeLeft -= Time.deltaTime; if (timeLeft <= 0) GameOver(); } UpdateTimerUI(); } // ============================================================ void CacheButtonData() { if (trueButton != null) { trueOriginalScale = trueButton.transform.localScale; trueOriginalPos = trueButton.transform.localPosition; trueButton.transition = Selectable.Transition.None; } if (falseButton != null) { falseOriginalScale = falseButton.transform.localScale; falseOriginalPos = falseButton.transform.localPosition; falseButton.transition = Selectable.Transition.None; } } void PrepareFeedbackText() { if (feedbackText == null) return; if (feedbackOnTop) { Vector3 pos = feedbackText.transform.localPosition; pos.y = feedbackTopY; feedbackText.transform.localPosition = pos; } feedbackText.alignment = TextAlignmentOptions.Center; feedbackText.fontSize = Mathf.Max(feedbackText.fontSize, feedbackFontSize); feedbackText.text = ""; Color c = feedbackText.color; c.a = 1f; feedbackText.color = c; } void UpdateTimerUI() { if (timerText == null) return; timerText.text = Mathf.Ceil(timeLeft).ToString(); if (timeLeft <= 10f) { timerText.color = FullAlpha(Color.Lerp(timerWarnColor, Color.white, Mathf.PingPong(Time.time * 3f, 1f))); timerText.transform.localScale = Vector3.one * (1f + Mathf.Sin(Time.time * 10f) * 0.05f); } else { timerText.color = FullAlpha(timerNormalColor); timerText.transform.localScale = Vector3.one; } } // ============================================================ void LoadTXT() { words.Clear(); if (analogyFile == null) { wordText.text = "TXT NOT FOUND!"; return; } string raw = analogyFile.text.Replace("\r", ""); string[] lines = raw.Split('\n'); foreach (string line in lines) { if (string.IsNullOrWhiteSpace(line)) continue; string[] p = line.Split(','); if (p.Length != 6) { Debug.LogError("HATALI SATIR → Format TR,EN,ES,DE,FR,PT olmalı: " + line); continue; } words.Add(new WordPair( p[0].Trim(), p[1].Trim(), p[2].Trim(), p[3].Trim(), p[4].Trim(), p[5].Trim() )); } if (words.Count < 2) { wordText.text = "YETERSİZ KELİME!"; } } // ============================================================ void NextQuestion() { if (words.Count < 2) return; locked = false; if (feedbackText != null) feedbackText.text = ""; ResetColors(); WordPair w1 = words[Random.Range(0, words.Count)]; WordPair w2 = w1; // %50 doğru / %50 yanlış correctPair = (Random.value > 0.5f); if (!correctPair) { WordPair temp; do temp = words[Random.Range(0, words.Count)]; while (temp == w1); w2 = temp; } // TEK TEXT EKLEME wordText.text = $"{w1.Get(qLang)} = {w2.Get(aLang)}"; if (wordFadeCo != null) StopCoroutine(wordFadeCo); wordFadeCo = StartCoroutine(FadeInText(wordText)); } // ============================================================ void Answer(bool pickedTrue) { if (locked) return; locked = true; bool ok = (pickedTrue && correctPair) || (!pickedTrue && !correctPair); if (pickedTrue) { trueButton.image.color = FullAlpha(selectedColor); StartScaleAnim(trueButton, ref trueScaleCo, trueOriginalScale * selectedScale); } else { falseButton.image.color = FullAlpha(selectedColor); StartScaleAnim(falseButton, ref falseScaleCo, falseOriginalScale * selectedScale); } if (ok) Correct(pickedTrue); else Wrong(pickedTrue); Invoke(nameof(NextQuestion), 1f); } // ============================================================ void Correct(bool pickedTrue) { correctCount++; combo++; score += 50 + combo * 10; timeLeft += 2f; SetFeedback(combo >= 3 ? $"{Local("correct")} {combo}x COMBO!" : Local("correct"), correctColor); Button btn = pickedTrue ? trueButton : falseButton; Vector3 normalScale = pickedTrue ? trueOriginalScale : falseOriginalScale; btn.image.color = FullAlpha(correctColor); StartCoroutine(CorrectPulse(btn, normalScale)); if (comboText != null) StartCoroutine(ComboAnim(comboText)); if (scoreText != null) StartCoroutine(ScorePopAnim(scoreText)); UpdateScore(); UpdateCombo(); } void Wrong(bool pickedTrue) { wrongCount++; combo = 0; score -= 20; if (score < 0) score = 0; SetFeedback(Local("wrong"), wrongColor); Button btn = pickedTrue ? trueButton : falseButton; Vector3 originalPos = pickedTrue ? trueOriginalPos : falseOriginalPos; btn.image.color = FullAlpha(wrongColor); StartCoroutine(ShakeButton(btn, originalPos)); UpdateScore(); UpdateCombo(); } // ============================================================ void Pass() { if (locked) return; combo = 0; UpdateCombo(); NextQuestion(); } void ResetColors() { if (trueScaleCo != null) { StopCoroutine(trueScaleCo); trueScaleCo = null; } if (falseScaleCo != null) { StopCoroutine(falseScaleCo); falseScaleCo = null; } trueButton.image.color = FullAlpha(normalColor); falseButton.image.color = FullAlpha(normalColor); trueButton.transform.localScale = trueOriginalScale; falseButton.transform.localScale = falseOriginalScale; trueButton.transform.localPosition = trueOriginalPos; falseButton.transform.localPosition = falseOriginalPos; } void UpdateScore() => scoreText.text = score.ToString(); void UpdateCombo() => comboText.text = combo + "x"; // ============================================================ void GameOver() { // Son elde edilen skor int lastScore = score; // 🔥 Mod Select / Leaderboard ekranına direkt bağlanacak basit key PlayerPrefs.SetInt("Mod12Skor", lastScore); // Mevcut max skoru oku (yoksa 0) int maxScore = PlayerPrefs.GetInt(modKey + "_MaxScore", 0); // Eğer yeni skor daha yüksekse güncelle if (lastScore > maxScore) { PlayerPrefs.SetInt(modKey + "_MaxScore", lastScore); } // Temel kayıtlar PlayerPrefs.SetInt(modKey + "_Score", lastScore); PlayerPrefs.SetInt(modKey + "_Correct", correctCount); PlayerPrefs.SetInt(modKey + "_Wrong", wrongCount); PlayerPrefs.Save(); // Resume sahnesine git SceneManager.LoadScene("Mod12Resume"); } // ============================================================ string Local(string key) { int L = PlayerPrefs.GetInt("AppLanguage", 1); if (key == "correct") return new[] { "Doğru!", "Correct!", "¡Correcto!", "Richtig!", "Correct!", "Correto!" }[L]; if (key == "wrong") return new[] { "Yanlış!", "Wrong!", "¡Incorrecto!", "Falsch!", "Faux!", "Errado!" }[L]; return key; } // ================== ANIMATION HELPERS ================== void SetFeedback(string msg, Color c) { if (feedbackText == null) return; feedbackText.text = msg; feedbackText.color = FullAlpha(c); if (feedbackOnTop) { Vector3 pos = feedbackText.transform.localPosition; pos.y = feedbackTopY; feedbackText.transform.localPosition = pos; } if (feedbackCo != null) StopCoroutine(feedbackCo); feedbackCo = StartCoroutine(FeedbackAnim(feedbackText)); } void StartScaleAnim(Button btn, ref Coroutine co, Vector3 targetScale) { if (btn == null) return; if (co != null) StopCoroutine(co); co = StartCoroutine(ScaleButton(btn, targetScale)); } IEnumerator ScaleButton(Button btn, Vector3 targetScale) { if (btn == null) yield break; Vector3 startScale = btn.transform.localScale; float t = 0f; while (t < 1f) { t += Time.deltaTime / Mathf.Max(0.01f, selectAnimTime); btn.transform.localScale = Vector3.Lerp(startScale, targetScale, EaseOutQuad(t)); yield return null; } btn.transform.localScale = targetScale; } IEnumerator CorrectPulse(Button btn, Vector3 normal) { if (btn == null) yield break; Vector3 big = normal * 1.12f; float t = 0f; while (t < 1f) { t += Time.deltaTime / 0.12f; btn.transform.localScale = Vector3.Lerp(normal, big, EaseOutQuad(t)); yield return null; } t = 0f; while (t < 1f) { t += Time.deltaTime / 0.12f; btn.transform.localScale = Vector3.Lerp(big, normal, EaseOutQuad(t)); yield return null; } btn.transform.localScale = normal; } IEnumerator ShakeButton(Button btn, Vector3 origin) { if (btn == null) yield break; float duration = 0.35f; float magnitude = 12f; float elapsed = 0f; while (elapsed < duration) { float power = 1f - elapsed / duration; float x = Random.Range(-1f, 1f) * magnitude * power; btn.transform.localPosition = origin + new Vector3(x, 0f, 0f); elapsed += Time.deltaTime; yield return null; } btn.transform.localPosition = origin; } IEnumerator FeedbackAnim(TMP_Text txt) { if (txt == null) yield break; Vector3 originalScale = Vector3.one; Vector3 bigScale = originalScale * 1.18f; Color c = FullAlpha(txt.color); c.a = 0f; txt.color = c; Vector3 originalPos = txt.transform.localPosition; Vector3 startPos = originalPos + Vector3.down * 18f; txt.transform.localPosition = startPos; float t = 0f; while (t < 1f) { t += Time.deltaTime / 0.16f; float ease = EaseOutBack(t); txt.transform.localScale = Vector3.Lerp(originalScale, bigScale, ease); txt.transform.localPosition = Vector3.Lerp(startPos, originalPos, ease); c.a = Mathf.Clamp01(t); txt.color = c; yield return null; } c.a = 1f; txt.color = c; txt.transform.localPosition = originalPos; t = 0f; while (t < 1f) { t += Time.deltaTime / 0.12f; txt.transform.localScale = Vector3.Lerp(bigScale, originalScale, EaseOutQuad(t)); yield return null; } txt.transform.localScale = originalScale; feedbackCo = null; } IEnumerator ComboAnim(TMP_Text txt) { if (txt == null) yield break; Vector3 original = Vector3.one; Vector3 big = original * 1.22f; Color baseColor = FullAlpha(txt.color); Color highlight = new Color32(255, 220, 50, 255); float t = 0f; while (t < 1f) { t += Time.deltaTime / 0.12f; txt.transform.localScale = Vector3.Lerp(original, big, EaseOutBack(t)); txt.color = FullAlpha(Color.Lerp(baseColor, highlight, t)); yield return null; } t = 0f; while (t < 1f) { t += Time.deltaTime / 0.14f; txt.transform.localScale = Vector3.Lerp(big, original, EaseOutQuad(t)); txt.color = FullAlpha(Color.Lerp(highlight, baseColor, t)); yield return null; } txt.transform.localScale = original; txt.color = baseColor; } IEnumerator ScorePopAnim(TMP_Text txt) { if (txt == null) yield break; Vector3 original = Vector3.one; Vector3 big = original * 1.18f; float t = 0f; while (t < 1f) { t += Time.deltaTime / 0.10f; txt.transform.localScale = Vector3.Lerp(original, big, EaseOutQuad(t)); yield return null; } t = 0f; while (t < 1f) { t += Time.deltaTime / 0.12f; txt.transform.localScale = Vector3.Lerp(big, original, EaseOutQuad(t)); yield return null; } txt.transform.localScale = original; } IEnumerator FadeInText(TMP_Text txt) { if (txt == null) yield break; Color c = FullAlpha(txt.color); c.a = 0f; txt.color = c; float t = 0f; while (t < 1f) { t += Time.deltaTime / 0.18f; c.a = EaseOutQuad(t); txt.color = c; yield return null; } c.a = 1f; txt.color = c; wordFadeCo = null; } Color FullAlpha(Color c) { c.a = 1f; return c; } float EaseOutBack(float t) { t = Mathf.Clamp01(t); float c1 = 1.70158f; float c3 = c1 + 1f; return 1f + c3 * Mathf.Pow(t - 1f, 3f) + c1 * Mathf.Pow(t - 1f, 2f); } float EaseOutQuad(float t) { t = Mathf.Clamp01(t); return 1f - (1f - t) * (1f - t); } }