Initial commit: Star of Words Unity project

Snapshot of the existing Unity 6 language-learning word game before any
refactoring. Adds Unity .gitignore and .gitattributes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
portakal 2026-07-05 15:31:20 +03:00
commit ecb1c9edea
1455 changed files with 933295 additions and 0 deletions

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 361cc2564c58fe6449c1822064d12c32
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,804 @@
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class ClozeGameScene : MonoBehaviour
{
[Header("TXT DOSYASI (6 Dil)")]
public TextAsset questionFile;
[Header("UI")]
public TMP_Text questionText;
public TMP_Text[] answerTexts;
public Button[] answerButtons;
public Button submitButton;
public TMP_Text scoreText;
public TMP_Text comboText;
public TMP_Text timerText;
public TMP_Text feedbackText;
[Header("EXTRA BUTTONS")]
public Button extraTimeButton;
public Button extraHintButton;
public Button extraSkipButton;
[Header("━━━ BACK BUTTON ━━━━━━━━━━━━━━━━━━━━━━━━")]
public Button backButton;
public string backSceneName = "ModSec 4";
[Header("RENKLER")]
public Color normalColor = new Color32(255, 255, 255, 255);
public Color selectedColor = new Color32(60, 110, 200, 255);
public Color correctColor = new Color32(0, 200, 0, 255);
public Color wrongColor = new Color32(200, 0, 0, 255);
public Color hintColor = new Color32(255, 255, 128, 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;
public float enterAnimTime = 0.22f;
// ---------------- INTERNAL STATE ----------------
private class ClozeEntry
{
public string[] q = new string[6];
public string[] c = new string[6];
public string[] w1 = new string[6];
public string[] w2 = new string[6];
public string[] w3 = new string[6];
}
private List<ClozeEntry> questions = new List<ClozeEntry>();
private int selected = -1;
private int correctIndex = -1;
private int lastQuestionID = -1;
private int score = 0;
private int combo = 0;
private int correctCount = 0;
private int wrongCount = 0;
private float timeLeft = 60f;
private float nextDelay = 1.2f;
private bool locked = false;
private string lang;
private string modKey = "Mod4"; // ✅ Bu modun özel key'i
readonly Color timerNormalColor = Color.white;
readonly Color timerWarnColor = new Color32(255, 80, 80, 255);
Vector3[] originalButtonScales;
Vector3[] originalButtonPositions;
Coroutine[] buttonScaleCoroutines;
Coroutine[] buttonEnterCoroutines;
// ------------------------------------------------
void Start()
{
lang = PlayerPrefs.GetString("QuestionLangCode", "en");
if (questionFile == null)
{
Debug.LogError("TXT Dosyası atanmadı!");
return;
}
LoadTXT(questionFile.text);
CacheButtonData();
ForceButtonTransitionNone();
PrepareFeedbackText();
submitButton.onClick.AddListener(OnSubmit);
extraTimeButton.onClick.AddListener(() => { if (!locked) timeLeft += 5; });
extraHintButton.onClick.AddListener(OnHint);
extraSkipButton.onClick.AddListener(() => NextQuestion());
if (backButton != null)
{
backButton.onClick.RemoveAllListeners();
backButton.onClick.AddListener(() => SceneManager.LoadScene(backSceneName));
}
scoreText.text = "0";
comboText.text = "0x";
feedbackText.text = "";
NextQuestion();
}
// ------------------------------------------------
void Update()
{
if (!locked)
{
timeLeft -= Time.deltaTime;
if (timeLeft <= 0)
{
timeLeft = 0;
GameOver();
}
}
UpdateTimerUI();
}
// ------------------------------------------------
void CacheButtonData()
{
if (answerButtons == null) return;
int len = answerButtons.Length;
originalButtonScales = new Vector3[len];
originalButtonPositions = new Vector3[len];
buttonScaleCoroutines = new Coroutine[len];
buttonEnterCoroutines = new Coroutine[len];
for (int i = 0; i < len; i++)
{
if (answerButtons[i] == null) continue;
originalButtonScales[i] = answerButtons[i].transform.localScale;
originalButtonPositions[i] = answerButtons[i].transform.localPosition;
}
}
void ForceButtonTransitionNone()
{
if (answerButtons == null) return;
for (int i = 0; i < answerButtons.Length; i++)
{
if (answerButtons[i] == null) continue;
answerButtons[i].transition = Selectable.Transition.None;
Image img = answerButtons[i].image;
if (img != null)
img.color = FullAlpha(normalColor);
}
}
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 LoadTXT(string raw)
{
foreach (string line in raw.Trim().Split('\n'))
{
if (string.IsNullOrWhiteSpace(line)) continue;
string[] p = line.Split('|');
if (p.Length < 30)
{
Debug.LogWarning("Eksik satır: " + line);
continue;
}
ClozeEntry e = new ClozeEntry();
for (int i = 0; i < 6; i++)
{
e.q[i] = p[i].Trim();
e.c[i] = p[6 + i].Trim();
e.w1[i] = p[12 + i].Trim();
e.w2[i] = p[18 + i].Trim();
e.w3[i] = p[24 + i].Trim();
}
questions.Add(e);
}
}
// ------------------------------------------------
void NextQuestion()
{
locked = false;
feedbackText.text = "";
selected = -1;
ResetButtons();
// Aynı soru ard arda gelmesin
int id = Random.Range(0, questions.Count);
if (id == lastQuestionID && questions.Count > 1)
id = (id + 1) % questions.Count;
lastQuestionID = id;
ClozeEntry q = questions[id];
int L = GetLangIndex();
questionText.text = q.q[L];
StartCoroutine(FadeInText(questionText));
List<string> opts = new List<string>()
{
q.c[L], q.w1[L], q.w2[L], q.w3[L]
};
Shuffle(opts);
// Şık yerleşimi
correctIndex = opts.IndexOf(q.c[L]);
for (int i = 0; i < 4; i++)
{
answerTexts[i].text = opts[i];
int index = i;
answerButtons[i].onClick.RemoveAllListeners();
answerButtons[i].onClick.AddListener(() => SelectAnswer(index));
}
for (int i = 0; i < answerButtons.Length; i++)
{
if (answerButtons[i] == null) continue;
if (buttonEnterCoroutines[i] != null)
StopCoroutine(buttonEnterCoroutines[i]);
buttonEnterCoroutines[i] = StartCoroutine(ButtonEnterAnim(answerButtons[i], i));
}
}
// ------------------------------------------------
void ResetButtons()
{
if (answerButtons == null) return;
for (int i = 0; i < answerButtons.Length; i++)
{
if (answerButtons[i] == null) continue;
StopButtonCoroutines(i);
answerButtons[i].interactable = true;
answerButtons[i].transition = Selectable.Transition.None;
Image img = answerButtons[i].image;
if (img != null)
img.color = FullAlpha(normalColor);
answerButtons[i].transform.localScale = originalButtonScales[i];
answerButtons[i].transform.localPosition = originalButtonPositions[i];
}
}
// ------------------------------------------------
void SelectAnswer(int id)
{
if (locked) return;
if (selected == id)
return;
if (selected >= 0 && selected < answerButtons.Length)
{
Button oldButton = answerButtons[selected];
if (oldButton != null)
{
Image oldImg = oldButton.image;
if (oldImg != null)
oldImg.color = FullAlpha(normalColor);
StartScaleAnim(selected, originalButtonScales[selected]);
}
}
selected = id;
Image img = answerButtons[id].image;
if (img != null)
img.color = FullAlpha(selectedColor);
StartScaleAnim(id, originalButtonScales[id] * selectedScale);
}
// ------------------------------------------------
void OnSubmit()
{
if (selected == -1 || locked) return;
locked = true;
foreach (Button b in answerButtons)
b.interactable = false;
bool ok = (selected == correctIndex);
if (ok)
{
correctCount++;
combo++;
score += 50 + combo * 10;
Image img = answerButtons[selected].image;
if (img != null)
img.color = FullAlpha(correctColor);
StartCoroutine(CorrectPulse(answerButtons[selected], selected));
feedbackText.color = FullAlpha(correctColor);
feedbackText.text = combo >= 3 ? $"TRUE {combo}x COMBO!" : "TRUE";
timeLeft += 2f;
if (comboText != null) StartCoroutine(ComboAnim(comboText));
if (scoreText != null) StartCoroutine(ScorePopAnim(scoreText));
}
else
{
wrongCount++;
combo = 0;
Image selImg = answerButtons[selected].image;
if (selImg != null)
selImg.color = FullAlpha(wrongColor);
StartCoroutine(ShakeButton(answerButtons[selected], selected));
Image corImg = answerButtons[correctIndex].image;
if (corImg != null)
corImg.color = FullAlpha(correctColor);
StartScaleAnim(correctIndex, originalButtonScales[correctIndex] * 1.04f);
feedbackText.color = FullAlpha(wrongColor);
feedbackText.text = "FALSE";
}
scoreText.text = score.ToString();
comboText.text = combo + "x";
if (feedbackOnTop)
{
Vector3 pos = feedbackText.transform.localPosition;
pos.y = feedbackTopY;
feedbackText.transform.localPosition = pos;
}
StartCoroutine(FeedbackAnim(feedbackText));
StartCoroutine(NextDelay());
}
IEnumerator NextDelay()
{
yield return new WaitForSeconds(nextDelay);
NextQuestion();
}
// ------------------------------------------------
void OnHint()
{
if (locked) return;
Image img = answerButtons[correctIndex].image;
if (img != null)
img.color = FullAlpha(hintColor);
StartCoroutine(CorrectPulse(answerButtons[correctIndex], correctIndex));
feedbackText.color = FullAlpha(selectedColor);
feedbackText.text = "Hint: Correct Answer Highlighted!";
if (feedbackOnTop)
{
Vector3 pos = feedbackText.transform.localPosition;
pos.y = feedbackTopY;
feedbackText.transform.localPosition = pos;
}
StartCoroutine(FeedbackAnim(feedbackText));
}
// ------------------------------------------------
void GameOver()
{
PlayerPrefs.SetString("LastPlayedMod", modKey);
// 🔥 Mod Select / Leaderboard ekranına direkt bağlanacak basit key
PlayerPrefs.SetInt("Mod4Skor", score);
// Bu oyundaki sonuçlar
PlayerPrefs.SetInt(modKey + "_LastScore", score);
PlayerPrefs.SetInt(modKey + "_Correct", correctCount);
PlayerPrefs.SetInt(modKey + "_Wrong", wrongCount);
PlayerPrefs.SetInt(modKey + "_LastCombo", combo);
// 🔥 En iyi skor (Mod Select / Leaderboard için)
int oldMax = PlayerPrefs.GetInt(modKey + "_MaxScore", 0);
if (score > oldMax)
PlayerPrefs.SetInt(modKey + "_MaxScore", score);
// 🔥 En iyi combo
int oldBestCombo = PlayerPrefs.GetInt(modKey + "_BestCombo", 0);
if (combo > oldBestCombo)
PlayerPrefs.SetInt(modKey + "_BestCombo", combo);
// 🔥 Doğruluk oranı (%)
int totalAnswers = correctCount + wrongCount;
int accuracy = totalAnswers > 0 ? Mathf.RoundToInt((correctCount / (float)totalAnswers) * 100f) : 0;
PlayerPrefs.SetInt(modKey + "_LastAccuracy", accuracy);
// 🔥 Toplam istatistikler
PlayerPrefs.SetInt(modKey + "_TotalCorrect", PlayerPrefs.GetInt(modKey + "_TotalCorrect", 0) + correctCount);
PlayerPrefs.SetInt(modKey + "_TotalWrong", PlayerPrefs.GetInt(modKey + "_TotalWrong", 0) + wrongCount);
PlayerPrefs.SetInt(modKey + "_PlayCount", PlayerPrefs.GetInt(modKey + "_PlayCount", 0) + 1);
// 🔥 Genel toplam skor (Mod Select ekranındaki global leaderboard için)
PlayerPrefs.SetInt("TotalScore", PlayerPrefs.GetInt("TotalScore", 0) + score);
PlayerPrefs.Save();
SceneManager.LoadScene("Mod4Resume");
}
// ------------------------------------------------
int GetLangIndex()
{
return lang switch
{
"tr" => 0,
"en" => 1,
"es" => 2,
"de" => 3,
"fr" => 4,
"pt" => 5,
_ => 1
};
}
// ------------------------------------------------
void Shuffle<T>(IList<T> arr)
{
for (int i = 0; i < arr.Count; i++)
{
int r = Random.Range(i, arr.Count);
(arr[i], arr[r]) = (arr[r], arr[i]);
}
}
// ================== ANIMATION HELPERS ==================
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 StartScaleAnim(int index, Vector3 targetScale)
{
if (index < 0 || index >= answerButtons.Length) return;
if (answerButtons[index] == null) return;
if (buttonScaleCoroutines[index] != null)
StopCoroutine(buttonScaleCoroutines[index]);
buttonScaleCoroutines[index] = StartCoroutine(ScaleButton(answerButtons[index], targetScale));
}
void StopButtonCoroutines(int index)
{
if (buttonScaleCoroutines != null && index < buttonScaleCoroutines.Length && buttonScaleCoroutines[index] != null)
{
StopCoroutine(buttonScaleCoroutines[index]);
buttonScaleCoroutines[index] = null;
}
if (buttonEnterCoroutines != null && index < buttonEnterCoroutines.Length && buttonEnterCoroutines[index] != null)
{
StopCoroutine(buttonEnterCoroutines[index]);
buttonEnterCoroutines[index] = null;
}
}
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 ButtonEnterAnim(Button btn, int delayIndex)
{
if (btn == null) yield break;
int idx = System.Array.IndexOf(answerButtons, btn);
if (idx < 0) yield break;
yield return new WaitForSeconds(delayIndex * 0.06f);
Vector3 targetPos = originalButtonPositions[idx];
Vector3 startPos = targetPos + Vector3.up * 35f;
Vector3 targetScale = originalButtonScales[idx];
Vector3 startScale = targetScale * 0.85f;
btn.transform.localPosition = startPos;
btn.transform.localScale = startScale;
float t = 0f;
while (t < 1f)
{
t += Time.deltaTime / Mathf.Max(0.01f, enterAnimTime);
float ease = EaseOutBack(t);
btn.transform.localPosition = Vector3.Lerp(startPos, targetPos, ease);
btn.transform.localScale = Vector3.Lerp(startScale, targetScale, ease);
yield return null;
}
btn.transform.localPosition = targetPos;
btn.transform.localScale = targetScale;
}
IEnumerator CorrectPulse(Button btn, int idx)
{
if (btn == null) yield break;
Vector3 normal = originalButtonScales[idx];
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, int idx)
{
if (btn == null) yield break;
Vector3 origin = originalButtonPositions[idx];
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 = txt.transform.localScale;
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;
}
IEnumerator ComboAnim(TMP_Text txt)
{
if (txt == null) yield break;
Vector3 original = txt.transform.localScale;
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 = txt.transform.localScale;
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;
}
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);
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: e2fc2555785ff244ca431198dfe8bc21

View file

@ -0,0 +1,168 @@
using System.Collections;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class Mod4Resume : MonoBehaviour
{
[Header("UI TEXTS (ONLY NUMBERS)")]
public TMP_Text scoreText;
public TMP_Text maxScoreText;
public TMP_Text correctText;
public TMP_Text wrongText;
[Header("BUTTONS")]
public Button retryButton;
public Button exitButton;
[Header("AUDIO")]
public AudioSource sfx;
public AudioClip clickSound;
[Header("━━━ ANIMATION SETTINGS ━━━━━━━━━━━━━━━━━")]
public float countUpDuration = 0.8f;
public float popInDelay = 0.08f;
public float popInTime = 0.3f;
// Bu modun kendi ana anahtarı
private string modKey = "Mod4";
private int score;
private int maxScore;
private int correct;
private int wrong;
void Start()
{
LoadResults();
PrepareTexts();
if (retryButton != null)
retryButton.onClick.AddListener(() => { PlaySFX(); Retry(); });
if (exitButton != null)
exitButton.onClick.AddListener(() => { PlaySFX(); ExitToMenu(); });
StartCoroutine(PlayRevealSequence());
}
// ---------------------------------------------------------------
void LoadResults()
{
score = PlayerPrefs.GetInt(modKey + "_LastScore", 0);
maxScore = PlayerPrefs.GetInt(modKey + "_MaxScore", 0);
correct = PlayerPrefs.GetInt(modKey + "_Correct", 0);
wrong = PlayerPrefs.GetInt(modKey + "_Wrong", 0);
Debug.Log("MOD4 RESULT → " +
$"Score:{score} | Max:{maxScore} | C:{correct} | W:{wrong}");
}
// ---------------------------------------------------------------
void PrepareTexts()
{
SetTextZero(scoreText);
SetTextZero(maxScoreText);
SetTextZero(correctText);
SetTextZero(wrongText);
}
void SetTextZero(TMP_Text txt)
{
if (txt == null) return;
txt.text = "0";
txt.transform.localScale = Vector3.zero;
}
// ---------------------------------------------------------------
IEnumerator PlayRevealSequence()
{
yield return StartCoroutine(RevealStat(scoreText, score));
yield return new WaitForSeconds(popInDelay);
yield return StartCoroutine(RevealStat(maxScoreText, maxScore));
yield return new WaitForSeconds(popInDelay);
yield return StartCoroutine(RevealStat(correctText, correct));
yield return new WaitForSeconds(popInDelay);
yield return StartCoroutine(RevealStat(wrongText, wrong));
}
IEnumerator RevealStat(TMP_Text txt, int targetValue)
{
if (txt == null) yield break;
// pop-in scale
Vector3 normal = Vector3.one;
float t = 0f;
while (t < 1f)
{
t += Time.deltaTime / Mathf.Max(0.01f, popInTime);
txt.transform.localScale = Vector3.Lerp(Vector3.zero, normal, EaseOutBack(t));
if (targetValue == 0)
txt.text = "0";
yield return null;
}
txt.transform.localScale = normal;
// count-up
if (targetValue > 0)
{
float ct = 0f;
while (ct < 1f)
{
ct += Time.deltaTime / Mathf.Max(0.01f, countUpDuration);
int shown = Mathf.RoundToInt(Mathf.Lerp(0, targetValue, EaseOutQuad(ct)));
txt.text = shown.ToString();
yield return null;
}
}
txt.text = targetValue.ToString();
}
// ---------------------------------------------------------------
void PlaySFX()
{
if (sfx && clickSound)
sfx.PlayOneShot(clickSound);
}
// ---------------------------------------------------------------
void Retry()
{
// 🔥 MOD 4 OYUN SAHNESİNE GERİ DÖNÜŞ
SceneManager.LoadScene("Mod4");
}
// ---------------------------------------------------------------
void ExitToMenu()
{
SceneManager.LoadScene("Anamen");
}
// ---------------------------------------------------------------
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);
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 323d69d6258982b41ad0ec9e34e0ba98

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2b5728892019a2347bac5fea0b29df9a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,90 @@
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class Mod5Resume : MonoBehaviour
{
[Header("UI TEXTS (ONLY NUMBERS)")]
public TMP_Text scoreText;
public TMP_Text maxScoreText;
public TMP_Text correctText;
public TMP_Text wrongText;
[Header("BUTTONS")]
public Button retryButton;
public Button exitButton;
[Header("AUDIO")]
public AudioSource sfx;
public AudioClip clickSound;
// 🔥 Bu modun özel ana keyi
private string modKey = "Mod5";
private int score;
private int maxScore;
private int correct;
private int wrong;
void Start()
{
LoadResults();
UpdateUI();
if (retryButton != null)
retryButton.onClick.AddListener(() =>
{
PlaySFX();
Retry();
});
if (exitButton != null)
exitButton.onClick.AddListener(() =>
{
PlaySFX();
ExitToMenu();
});
}
// ---------------------------------------------------------------
void LoadResults()
{
score = PlayerPrefs.GetInt(modKey + "_LastScore", 0);
maxScore = PlayerPrefs.GetInt(modKey + "_MaxScore", 0);
correct = PlayerPrefs.GetInt(modKey + "_Correct", 0);
wrong = PlayerPrefs.GetInt(modKey + "_Wrong", 0);
Debug.Log("MOD5 RESULT → " +
$"Score:{score} | Max:{maxScore} | C:{correct} | W:{wrong}");
}
// ---------------------------------------------------------------
void UpdateUI()
{
if (scoreText != null) scoreText.text = score.ToString();
if (maxScoreText != null) maxScoreText.text = maxScore.ToString();
if (correctText != null) correctText.text = correct.ToString();
if (wrongText != null) wrongText.text = wrong.ToString();
}
// ---------------------------------------------------------------
void PlaySFX()
{
if (sfx && clickSound)
sfx.PlayOneShot(clickSound);
}
// ---------------------------------------------------------------
void Retry()
{
// 🔥 Mod 5'in oyun sahnesine geri dönüş
SceneManager.LoadScene("Mod5");
}
// ---------------------------------------------------------------
void ExitToMenu()
{
SceneManager.LoadScene("Anamen");
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 5aef591567d26be469298582b4dde11b

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: a63c8afea6ac9ef49808e75ed89dc7cb

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8bddf192a36777c4f89d9bc2f7c58312
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,177 @@
using System.Collections;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class Mod6Resume : MonoBehaviour
{
[Header("UI TEXTS")]
public TMP_Text scoreText; // Toplam skor
public TMP_Text maxScoreText; // En yüksek skor
public TMP_Text correctText; // Doğru sayısı
public TMP_Text wrongText; // Yanlış sayısı
[Header("BUTTONS")]
public Button retryButton;
public Button exitButton;
[Header("AUDIO")]
public AudioSource sfx;
public AudioClip clickSound;
[Header("━━━ ANIMATION SETTINGS ━━━━━━━━━━━━━━━━━")]
public float countUpDuration = 0.8f;
public float popInDelay = 0.08f;
public float popInTime = 0.3f;
// Mod6 PlayerPrefs Key
private string modKey = "Mod6";
private int score;
private int maxScore;
private int correct;
private int wrong;
// ============================================================
void Start()
{
LoadResults();
PrepareTexts();
// Retry
if (retryButton != null)
retryButton.onClick.AddListener(() =>
{
PlaySFX();
Retry();
});
// Exit
if (exitButton != null)
exitButton.onClick.AddListener(() =>
{
PlaySFX();
ExitToMenu();
});
StartCoroutine(PlayRevealSequence());
}
// ============================================================
void LoadResults()
{
score = PlayerPrefs.GetInt(modKey + "_LastScore", 0);
maxScore = PlayerPrefs.GetInt(modKey + "_MaxScore", 0);
correct = PlayerPrefs.GetInt(modKey + "_Correct", 0);
wrong = PlayerPrefs.GetInt(modKey + "_Wrong", 0);
Debug.Log($"[MOD6 RESULT] Score={score} | Max={maxScore} | Correct={correct} | Wrong={wrong}");
}
// ============================================================
void PrepareTexts()
{
SetTextZero(scoreText);
SetTextZero(maxScoreText);
SetTextZero(correctText);
SetTextZero(wrongText);
}
void SetTextZero(TMP_Text txt)
{
if (txt == null) return;
txt.text = "0";
txt.transform.localScale = Vector3.zero;
}
// ============================================================
IEnumerator PlayRevealSequence()
{
yield return StartCoroutine(RevealStat(scoreText, score));
yield return new WaitForSeconds(popInDelay);
yield return StartCoroutine(RevealStat(maxScoreText, maxScore));
yield return new WaitForSeconds(popInDelay);
yield return StartCoroutine(RevealStat(correctText, correct));
yield return new WaitForSeconds(popInDelay);
yield return StartCoroutine(RevealStat(wrongText, wrong));
}
IEnumerator RevealStat(TMP_Text txt, int targetValue)
{
if (txt == null) yield break;
// pop-in scale
Vector3 normal = Vector3.one;
float t = 0f;
while (t < 1f)
{
t += Time.deltaTime / Mathf.Max(0.01f, popInTime);
txt.transform.localScale = Vector3.Lerp(Vector3.zero, normal, EaseOutBack(t));
if (targetValue == 0)
txt.text = "0";
yield return null;
}
txt.transform.localScale = normal;
// count-up
if (targetValue > 0)
{
float ct = 0f;
while (ct < 1f)
{
ct += Time.deltaTime / Mathf.Max(0.01f, countUpDuration);
int shown = Mathf.RoundToInt(Mathf.Lerp(0, targetValue, EaseOutQuad(ct)));
txt.text = shown.ToString();
yield return null;
}
}
txt.text = targetValue.ToString();
}
// ============================================================
void PlaySFX()
{
if (sfx && clickSound)
sfx.PlayOneShot(clickSound);
}
// ============================================================
void Retry()
{
SceneManager.LoadScene("Mod6");
}
// ============================================================
void ExitToMenu()
{
SceneManager.LoadScene("Anamen");
}
// ============================================================
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);
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 7732f4a1c046d054cadae9b2b5482c31

View file

@ -0,0 +1,897 @@
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine.SceneManagement;
public class WordMatchMod : MonoBehaviour
{
[Header("UI - QUESTIONS (LEFT)")]
[SerializeField] private Button[] questionButtons;
[SerializeField] private TMP_Text[] questionTexts;
[Header("UI - ANSWERS (RIGHT)")]
[SerializeField] private Button[] answerButtons;
[SerializeField] private TMP_Text[] answerTexts;
[Header("UI - OTHER")]
[SerializeField] private Button submitButton;
[SerializeField] private TMP_Text scoreText;
[SerializeField] private TMP_Text comboText;
[SerializeField] private TMP_Text timeText;
[SerializeField] private TMP_Text feedbackText;
[Header("━━━ BACK BUTTON ━━━━━━━━━━━━━━━━━━━━━━━━")]
public Button backButton;
public string backSceneName = "ModSec 6";
[Header("WORD DATA")]
[SerializeField] private TextAsset wordFile;
[Header("COLORS")]
public Color baseColor = new Color32(230, 230, 230, 255);
public Color[] pairColors = new Color[]
{
new Color32(120,180,255,255),
new Color32(255,200,120,255),
new Color32(160,255,160,255),
new Color32(255,150,150,255),
new Color32(210,150,255,255),
};
public Color correctColor = new Color32(0, 160, 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;
public float enterAnimTime = 0.22f;
Dictionary<string, string> activeMap = new Dictionary<string, string>();
List<KeyValuePair<string, string>> selectedPairs = new List<KeyValuePair<string, string>>();
private int[] questionToAnswer = new int[5];
private int[] questionColorIdx = new int[5];
private int[] answerColorIdx = new int[5];
private int selectedQuestion = -1;
// 🔥 90 saniyelik toplam süre, round başına sıfırlanmıyor
private float timeLeft = 90f;
private int score = 0;
private int combo = 0;
private int correctCount = 0;
private int wrongCount = 0;
// Durum kontrolü
private bool isTimeUp = false; // süre tamamen bitti mi?
private bool isRoundProcessing = false; // bu round için submit işlemi devam ediyor mu?
// PlayerPrefs Key
private string modKey = "Mod6";
private string qLang;
private string aLang;
readonly Color timerNormalColor = Color.white;
readonly Color timerWarnColor = new Color32(255, 80, 80, 255);
Vector3[] questionOriginalScales;
Vector3[] answerOriginalScales;
Vector3[] questionOriginalPositions;
Vector3[] answerOriginalPositions;
Coroutine[] questionScaleCo;
Coroutine[] answerScaleCo;
Coroutine[] questionEnterCo;
Coroutine[] answerEnterCo;
Coroutine feedbackCo;
//---------------------------------------------------------
void Start()
{
qLang = PlayerPrefs.GetString("QuestionLangCode", "en");
aLang = PlayerPrefs.GetString("AnswerLangCode", "tr");
LoadWordFile();
CacheButtonData();
PrepareFeedbackText();
if (submitButton != null)
{
submitButton.onClick.RemoveAllListeners();
submitButton.onClick.AddListener(OnSubmit);
}
if (backButton != null)
{
backButton.onClick.RemoveAllListeners();
backButton.onClick.AddListener(() => SceneManager.LoadScene(backSceneName));
}
LoadRound();
ResetColorMaps();
// Oyun başlangıcı süresi
timeLeft = 90f;
isTimeUp = false;
isRoundProcessing = false;
scoreText.text = score.ToString();
comboText.text = combo + "x";
}
//---------------------------------------------------------
void Update()
{
if (isTimeUp) // süre bittiyse artık hiçbir şey yapma
{
UpdateTimerUI();
return;
}
timeLeft -= Time.deltaTime;
if (timeLeft < 0f) timeLeft = 0f;
UpdateTimerUI();
if (!isTimeUp && timeLeft <= 0f)
{
// Süre ilk kez bitti
isTimeUp = true;
ProcessSubmit(true); // timeout'tan gelen submit
StartCoroutine(GoResume()); // sonuç sahnesine git
}
}
//---------------------------------------------------------
void UpdateTimerUI()
{
if (timeText == null) return;
timeText.text = Mathf.CeilToInt(timeLeft).ToString();
if (timeLeft <= 10f)
{
timeText.color = FullAlpha(Color.Lerp(timerWarnColor, Color.white, Mathf.PingPong(Time.time * 3f, 1f)));
timeText.transform.localScale = Vector3.one * (1f + Mathf.Sin(Time.time * 10f) * 0.05f);
}
else
{
timeText.color = FullAlpha(timerNormalColor);
timeText.transform.localScale = Vector3.one;
}
}
//---------------------------------------------------------
void LoadWordFile()
{
activeMap.Clear();
string[] lines = wordFile.text.Split('\n');
int qi = LangIndex(qLang);
int ai = LangIndex(aLang);
foreach (string raw in lines)
{
string line = raw.Trim();
if (string.IsNullOrWhiteSpace(line)) continue;
if (!line.Contains(",")) continue;
string[] p = line.Split(',');
if (p.Length < 6) continue;
string q = p[qi].Trim();
string a = p[ai].Trim();
if (!activeMap.ContainsKey(q))
activeMap.Add(q, a);
}
}
int LangIndex(string c)
{
switch (c)
{
case "tr": return 0;
case "en": return 1;
case "es": return 2;
case "de": return 3;
case "fr": return 4;
case "pt": return 5;
}
return 1;
}
//---------------------------------------------------------
void CacheButtonData()
{
int n = questionButtons.Length;
questionOriginalScales = new Vector3[n];
answerOriginalScales = new Vector3[n];
questionOriginalPositions = new Vector3[n];
answerOriginalPositions = new Vector3[n];
questionScaleCo = new Coroutine[n];
answerScaleCo = new Coroutine[n];
questionEnterCo = new Coroutine[n];
answerEnterCo = new Coroutine[n];
for (int i = 0; i < n; i++)
{
if (questionButtons[i] != null)
{
questionOriginalScales[i] = questionButtons[i].transform.localScale;
questionOriginalPositions[i] = questionButtons[i].transform.localPosition;
questionButtons[i].transition = Selectable.Transition.None;
}
if (answerButtons[i] != null)
{
answerOriginalScales[i] = answerButtons[i].transform.localScale;
answerOriginalPositions[i] = answerButtons[i].transform.localPosition;
answerButtons[i].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 LoadRound()
{
ResetVisuals();
ResetColorMaps();
isRoundProcessing = false; // yeni round için submit tekrar aktif
var all = activeMap.ToList();
Shuffle(all);
selectedPairs = all.Take(5).ToList();
// Questions
for (int i = 0; i < 5; i++)
{
questionTexts[i].text = selectedPairs[i].Key;
int id = i;
questionButtons[i].onClick.RemoveAllListeners();
questionButtons[i].onClick.AddListener(() => SelectQuestion(id));
}
// Answers
List<string> answers = selectedPairs.Select(x => x.Value).ToList();
Shuffle(answers);
for (int i = 0; i < 5; i++)
{
answerTexts[i].text = answers[i];
int id = i;
answerButtons[i].onClick.RemoveAllListeners();
answerButtons[i].onClick.AddListener(() => SelectAnswer(id));
}
// Enter animasyonları
for (int i = 0; i < 5; i++)
{
if (questionEnterCo[i] != null) StopCoroutine(questionEnterCo[i]);
questionEnterCo[i] = StartCoroutine(ButtonEnterAnim(questionButtons[i], questionOriginalScales[i], questionOriginalPositions[i], i, -1));
if (answerEnterCo[i] != null) StopCoroutine(answerEnterCo[i]);
answerEnterCo[i] = StartCoroutine(ButtonEnterAnim(answerButtons[i], answerOriginalScales[i], answerOriginalPositions[i], i, 1));
if (questionTexts[i] != null) StartCoroutine(FadeInText(questionTexts[i]));
if (answerTexts[i] != null) StartCoroutine(FadeInText(answerTexts[i]));
}
}
//---------------------------------------------------------
void ResetVisuals()
{
for (int i = 0; i < 5; i++)
{
StopButtonAnims(i);
questionButtons[i].image.color = FullAlpha(baseColor);
answerButtons[i].image.color = FullAlpha(baseColor);
questionButtons[i].transform.localScale = questionOriginalScales[i];
answerButtons[i].transform.localScale = answerOriginalScales[i];
questionButtons[i].transform.localPosition = questionOriginalPositions[i];
answerButtons[i].transform.localPosition = answerOriginalPositions[i];
}
feedbackText.text = "";
}
void StopButtonAnims(int i)
{
if (questionScaleCo[i] != null) { StopCoroutine(questionScaleCo[i]); questionScaleCo[i] = null; }
if (answerScaleCo[i] != null) { StopCoroutine(answerScaleCo[i]); answerScaleCo[i] = null; }
if (questionEnterCo[i] != null) { StopCoroutine(questionEnterCo[i]); questionEnterCo[i] = null; }
if (answerEnterCo[i] != null) { StopCoroutine(answerEnterCo[i]); answerEnterCo[i] = null; }
}
void ResetColorMaps()
{
for (int i = 0; i < 5; i++)
{
questionToAnswer[i] = -1;
questionColorIdx[i] = -1;
answerColorIdx[i] = -1;
}
}
//---------------------------------------------------------
void SelectQuestion(int q)
{
if (isRoundProcessing || isTimeUp) return;
selectedQuestion = q;
StartScaleAnim(questionButtons, questionScaleCo, questionOriginalScales, q, questionOriginalScales[q] * selectedScale);
}
//---------------------------------------------------------
void SelectAnswer(int a)
{
if (isRoundProcessing || isTimeUp) return;
if (selectedQuestion == -1)
return;
int prevQuestion = selectedQuestion;
// Aynı cevabı tekrar tıklarsa iptal et
if (questionToAnswer[selectedQuestion] == a)
{
questionToAnswer[selectedQuestion] = -1;
questionColorIdx[selectedQuestion] = -1;
answerColorIdx[a] = -1;
RefreshColors();
selectedQuestion = -1;
ResetScaleAnim(questionButtons, questionScaleCo, questionOriginalScales, prevQuestion);
ResetScaleAnim(answerButtons, answerScaleCo, answerOriginalScales, a);
return;
}
// Bu cevap başka bir soruya atanmışsa oradan kaldır
for (int i = 0; i < 5; i++)
{
if (questionToAnswer[i] == a && i != selectedQuestion)
{
questionToAnswer[i] = -1;
questionColorIdx[i] = -1;
ResetScaleAnim(questionButtons, questionScaleCo, questionOriginalScales, i);
}
}
// Önceden seçilmiş cevabı temizle
int oldAns = questionToAnswer[selectedQuestion];
if (oldAns != -1)
{
answerColorIdx[oldAns] = -1;
ResetScaleAnim(answerButtons, answerScaleCo, answerOriginalScales, oldAns);
}
// Yeni eşleşmeyi ata
questionToAnswer[selectedQuestion] = a;
int colorIdx = selectedQuestion;
questionColorIdx[selectedQuestion] = colorIdx;
answerColorIdx[a] = colorIdx;
RefreshColors();
// pair pulse animasyonu
StartCoroutine(PairPulse(prevQuestion, a));
ResetScaleAnim(questionButtons, questionScaleCo, questionOriginalScales, prevQuestion);
selectedQuestion = -1;
}
//---------------------------------------------------------
void RefreshColors()
{
for (int i = 0; i < 5; i++)
{
questionButtons[i].image.color =
questionColorIdx[i] == -1 ? FullAlpha(baseColor) : FullAlpha(pairColors[questionColorIdx[i]]);
answerButtons[i].image.color =
answerColorIdx[i] == -1 ? FullAlpha(baseColor) : FullAlpha(pairColors[answerColorIdx[i]]);
}
}
//---------------------------------------------------------
// Butondan gelen submit
void OnSubmit()
{
// Eğer bu round zaten işleniyorsa veya süre bittiyse tekrar işleme
if (isRoundProcessing || isTimeUp)
return;
ProcessSubmit(false);
}
// Asıl hesaplamayı yapan fonksiyon
void ProcessSubmit(bool fromTimeout)
{
isRoundProcessing = true;
int roundCorrect = 0;
for (int q = 0; q < 5; q++)
{
int a = questionToAnswer[q];
if (a == -1)
{
questionButtons[q].image.color = FullAlpha(wrongColor);
StartCoroutine(ShakeButton(questionButtons[q], questionOriginalPositions[q]));
wrongCount++;
continue;
}
string qWord = questionTexts[q].text;
string correctA = activeMap[qWord];
string chosen = answerTexts[a].text;
if (chosen == correctA)
{
roundCorrect++;
correctCount++;
questionButtons[q].image.color = FullAlpha(correctColor);
answerButtons[a].image.color = FullAlpha(correctColor);
StartCoroutine(CorrectPulse(questionButtons[q], questionOriginalScales[q]));
StartCoroutine(CorrectPulse(answerButtons[a], answerOriginalScales[a]));
}
else
{
wrongCount++;
questionButtons[q].image.color = FullAlpha(wrongColor);
answerButtons[a].image.color = FullAlpha(wrongColor);
StartCoroutine(ShakeButton(questionButtons[q], questionOriginalPositions[q]));
StartCoroutine(ShakeButton(answerButtons[a], answerOriginalPositions[a]));
}
}
// Her doğru 20 puan
int gainedScore = roundCorrect * 20;
score += gainedScore;
Color feedbackColor;
if (roundCorrect == 5)
{
combo++;
feedbackText.text = combo >= 2 ? $"PERFECT! {combo}x COMBO!" : "PERFECT!";
feedbackColor = correctColor;
}
else if (roundCorrect > 0)
{
combo = 0;
feedbackText.text = "+" + gainedScore + " Puan";
feedbackColor = correctColor;
}
else
{
combo = 0;
feedbackText.text = "Try again!";
feedbackColor = wrongColor;
}
feedbackText.color = FullAlpha(feedbackColor);
if (feedbackOnTop)
{
Vector3 pos = feedbackText.transform.localPosition;
pos.y = feedbackTopY;
feedbackText.transform.localPosition = pos;
}
if (feedbackCo != null) StopCoroutine(feedbackCo);
feedbackCo = StartCoroutine(FeedbackAnim(feedbackText));
scoreText.text = score.ToString();
comboText.text = combo + "x";
if (scoreText != null) StartCoroutine(ScorePopAnim(scoreText));
if (combo > 0 && comboText != null) StartCoroutine(ComboAnim(comboText));
SaveProgress();
// Eğer bu timeout değilse ve oyun tamamen bitmediyse yeni round
if (!fromTimeout && !isTimeUp)
{
StartCoroutine(NextRound());
}
}
//---------------------------------------------------------
void SaveProgress()
{
// 🔥 Mod Select / Leaderboard ekranına direkt bağlanacak basit key
PlayerPrefs.SetInt("Mod6Skor", score);
PlayerPrefs.SetInt(modKey + "_LastScore", score);
int maxScore = PlayerPrefs.GetInt(modKey + "_MaxScore", 0);
if (score > maxScore)
PlayerPrefs.SetInt(modKey + "_MaxScore", score);
PlayerPrefs.SetInt(modKey + "_Correct", correctCount);
PlayerPrefs.SetInt(modKey + "_Wrong", wrongCount);
PlayerPrefs.Save();
}
//---------------------------------------------------------
IEnumerator NextRound()
{
yield return new WaitForSeconds(0.8f);
LoadRound();
}
IEnumerator GoResume()
{
yield return new WaitForSeconds(1f);
SceneManager.LoadScene("Mod6Resume");
}
//---------------------------------------------------------
void Shuffle<T>(List<T> list)
{
for (int i = list.Count - 1; i > 0; i--)
{
int j = Random.Range(0, i + 1);
(list[i], list[j]) = (list[j], list[i]);
}
}
// ================== ANIMATION HELPERS ==================
void StartScaleAnim(Button[] buttons, Coroutine[] coArr, Vector3[] originalScales, int idx, Vector3 targetScale)
{
if (idx < 0 || idx >= buttons.Length || buttons[idx] == null) return;
if (coArr[idx] != null)
StopCoroutine(coArr[idx]);
coArr[idx] = StartCoroutine(ScaleButton(buttons[idx], targetScale, idx, coArr));
}
void ResetScaleAnim(Button[] buttons, Coroutine[] coArr, Vector3[] originalScales, int idx)
{
if (idx < 0 || idx >= buttons.Length || buttons[idx] == null) return;
StartScaleAnim(buttons, coArr, originalScales, idx, originalScales[idx]);
}
IEnumerator ScaleButton(Button btn, Vector3 targetScale, int idx, Coroutine[] coArr)
{
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;
coArr[idx] = null;
}
IEnumerator ButtonEnterAnim(Button btn, Vector3 targetScale, Vector3 targetPos, int delayIndex, int sideSign)
{
if (btn == null) yield break;
yield return new WaitForSeconds(delayIndex * 0.05f);
Vector3 startPos = targetPos + new Vector3(sideSign * 40f, 0f, 0f);
Vector3 startScale = targetScale * 0.85f;
btn.transform.localPosition = startPos;
btn.transform.localScale = startScale;
float t = 0f;
while (t < 1f)
{
t += Time.deltaTime / Mathf.Max(0.01f, enterAnimTime);
float ease = EaseOutBack(t);
btn.transform.localPosition = Vector3.Lerp(startPos, targetPos, ease);
btn.transform.localScale = Vector3.Lerp(startScale, targetScale, ease);
yield return null;
}
btn.transform.localPosition = targetPos;
btn.transform.localScale = targetScale;
}
IEnumerator PairPulse(int questionIdx, int answerIdx)
{
if (questionIdx >= 0 && questionIdx < questionButtons.Length)
yield return StartCoroutine(QuickPulse(questionButtons[questionIdx].transform, questionOriginalScales[questionIdx]));
if (answerIdx >= 0 && answerIdx < answerButtons.Length)
yield return StartCoroutine(QuickPulse(answerButtons[answerIdx].transform, answerOriginalScales[answerIdx]));
}
IEnumerator QuickPulse(Transform tr, Vector3 normal)
{
if (tr == null) yield break;
Vector3 big = normal * 1.08f;
float t = 0f;
while (t < 1f)
{
t += Time.deltaTime / 0.08f;
tr.localScale = Vector3.Lerp(normal, big, EaseOutQuad(t));
yield return null;
}
t = 0f;
while (t < 1f)
{
t += Time.deltaTime / 0.08f;
tr.localScale = Vector3.Lerp(big, normal, EaseOutQuad(t));
yield return null;
}
tr.localScale = normal;
}
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 baseC = 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(baseC, 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, baseC, t));
yield return null;
}
txt.transform.localScale = original;
txt.color = baseC;
}
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;
}
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);
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 8009dfdd6ea39fb4e8299d3815d05377

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ec4dd0c0e48b6d445aac4329391489cc
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,152 @@
using System.Collections;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class Mod8Resume : MonoBehaviour
{
[Header("UI TEXTS")]
public TMP_Text scoreText;
public TMP_Text maxScoreText;
public TMP_Text correctText;
public TMP_Text wrongText;
[Header("BUTTONS")]
public Button retryButton;
public Button exitButton;
[Header("AUDIO")]
public AudioSource sfx;
public AudioClip clickSound;
[Header("━━━ ANIMATION SETTINGS ━━━━━━━━━━━━━━━━━")]
public float countUpDuration = 0.8f;
public float popInDelay = 0.08f;
public float popInTime = 0.3f;
private string modKey = "Mod8_Antonym";
private int score;
private int maxScore;
private int correct;
private int wrong;
// ============================================================
void Start()
{
LoadResults();
PrepareTexts();
if (retryButton != null)
retryButton.onClick.AddListener(() => { PlaySFX(); Retry(); });
if (exitButton != null)
exitButton.onClick.AddListener(() => { PlaySFX(); ExitToMenu(); });
StartCoroutine(PlayRevealSequence());
}
// ============================================================
void LoadResults()
{
score = PlayerPrefs.GetInt(modKey + "_LastScore", 0);
maxScore = PlayerPrefs.GetInt(modKey + "_MaxScore", 0);
correct = PlayerPrefs.GetInt(modKey + "_Correct", 0);
wrong = PlayerPrefs.GetInt(modKey + "_Wrong", 0);
Debug.Log($"[MOD8 RESULT] Score={score} | Max={maxScore} | Correct={correct} | Wrong={wrong}");
}
// ============================================================
void PrepareTexts()
{
SetTextZero(scoreText);
SetTextZero(maxScoreText);
SetTextZero(correctText);
SetTextZero(wrongText);
}
void SetTextZero(TMP_Text txt)
{
if (txt == null) return;
txt.text = "0";
txt.transform.localScale = Vector3.zero;
}
// ============================================================
IEnumerator PlayRevealSequence()
{
yield return StartCoroutine(RevealStat(scoreText, score));
yield return new WaitForSeconds(popInDelay);
yield return StartCoroutine(RevealStat(maxScoreText, maxScore));
yield return new WaitForSeconds(popInDelay);
yield return StartCoroutine(RevealStat(correctText, correct));
yield return new WaitForSeconds(popInDelay);
yield return StartCoroutine(RevealStat(wrongText, wrong));
}
IEnumerator RevealStat(TMP_Text txt, int targetValue)
{
if (txt == null) yield break;
float t = 0f;
while (t < 1f)
{
t += Time.deltaTime / Mathf.Max(0.01f, popInTime);
txt.transform.localScale = Vector3.Lerp(Vector3.zero, Vector3.one, EaseOutBack(t));
if (targetValue == 0) txt.text = "0";
yield return null;
}
txt.transform.localScale = Vector3.one;
if (targetValue > 0)
{
float ct = 0f;
while (ct < 1f)
{
ct += Time.deltaTime / Mathf.Max(0.01f, countUpDuration);
txt.text = Mathf.RoundToInt(Mathf.Lerp(0, targetValue, EaseOutQuad(ct))).ToString();
yield return null;
}
}
txt.text = targetValue.ToString();
}
// ============================================================
void PlaySFX()
{
if (sfx != null && clickSound != null)
sfx.PlayOneShot(clickSound);
}
// ============================================================
void Retry()
{
SceneManager.LoadScene("Mod8");
}
// ============================================================
void ExitToMenu()
{
SceneManager.LoadScene("Anamen");
}
// ============================================================
float EaseOutBack(float t)
{
t = Mathf.Clamp01(t);
float c1 = 1.70158f, 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);
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 2aa39617cac61c542b3904ef06fefa38

View file

@ -0,0 +1,876 @@
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine.SceneManagement;
public class WordMatchMod8 : MonoBehaviour
{
[Header("UI - QUESTIONS (LEFT)")]
[SerializeField] private Button[] questionButtons;
[SerializeField] private TMP_Text[] questionTexts;
[Header("UI - ANSWERS (RIGHT)")]
[SerializeField] private Button[] answerButtons;
[SerializeField] private TMP_Text[] answerTexts;
[Header("UI - OTHER")]
[SerializeField] private Button submitButton;
[SerializeField] private TMP_Text scoreText;
[SerializeField] private TMP_Text comboText;
[SerializeField] private TMP_Text timeText;
[SerializeField] private TMP_Text feedbackText;
[Header("━━━ BACK BUTTON ━━━━━━━━━━━━━━━━━━━━━━━━")]
public Button backButton;
public string backSceneName = "ModSec 8";
[Header("WORD DATA")]
[SerializeField] private TextAsset wordFile;
[Header("COLORS")]
public Color baseColor = new Color32(230, 230, 230, 255);
public Color[] pairColors = new Color[]
{
new Color32(120,180,255,255),
new Color32(255,200,120,255),
new Color32(160,255,160,255),
new Color32(255,150,150,255),
new Color32(210,150,255,255),
};
public Color correctColor = new Color32(0, 160, 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;
public float enterAnimTime = 0.22f;
Dictionary<string, string> activeMap = new Dictionary<string, string>();
private int[] questionToAnswer = new int[5];
private int[] questionColorIdx = new int[5];
private int[] answerColorIdx = new int[5];
private int selectedQuestion = -1;
private float timeLeft = 90f;
private bool isTimeUp = false;
private bool isRoundProcessing = false;
private int score = 0;
private int combo = 0;
private int correctCount = 0;
private int wrongCount = 0;
private string modKey = "Mod8_Antonym";
private string qLang;
private List<KeyValuePair<string, string>> selectedPairs = new List<KeyValuePair<string, string>>();
readonly Color timerNormalColor = Color.white;
readonly Color timerWarnColor = new Color32(255, 80, 80, 255);
Vector3[] questionOriginalScales;
Vector3[] answerOriginalScales;
Vector3[] questionOriginalPositions;
Vector3[] answerOriginalPositions;
Coroutine[] questionScaleCo;
Coroutine[] answerScaleCo;
Coroutine[] questionEnterCo;
Coroutine[] answerEnterCo;
Coroutine feedbackCo;
// ---------------------------------------------------------
void Start()
{
qLang = PlayerPrefs.GetString("QuestionLangCode", "en");
LoadWordFile();
CacheButtonData();
PrepareFeedbackText();
if (submitButton != null)
{
submitButton.onClick.RemoveAllListeners();
submitButton.onClick.AddListener(OnSubmit);
}
if (backButton != null)
{
backButton.onClick.RemoveAllListeners();
backButton.onClick.AddListener(() => SceneManager.LoadScene(backSceneName));
}
ResetColorMaps();
LoadRound();
scoreText.text = score.ToString();
comboText.text = combo + "x";
timeLeft = 90f;
isTimeUp = false;
}
// ---------------------------------------------------------
void Update()
{
if (isTimeUp)
{
UpdateTimerUI();
return;
}
timeLeft -= Time.deltaTime;
if (timeLeft < 0f) timeLeft = 0f;
UpdateTimerUI();
if (timeLeft <= 0f)
{
isTimeUp = true;
ProcessSubmit(true);
StartCoroutine(GoResume());
}
}
// ---------------------------------------------------------
void UpdateTimerUI()
{
if (timeText == null) return;
timeText.text = Mathf.CeilToInt(timeLeft).ToString();
if (timeLeft <= 10f)
{
timeText.color = FullAlpha(Color.Lerp(timerWarnColor, Color.white, Mathf.PingPong(Time.time * 3f, 1f)));
timeText.transform.localScale = Vector3.one * (1f + Mathf.Sin(Time.time * 10f) * 0.05f);
}
else
{
timeText.color = FullAlpha(timerNormalColor);
timeText.transform.localScale = Vector3.one;
}
}
// ---------------------------------------------------------
void LoadWordFile()
{
activeMap.Clear();
if (wordFile == null)
{
Debug.LogError("Mod8: wordFile atanmadı!");
return;
}
string[] lines = wordFile.text.Split('\n');
int li = LangIndex(qLang);
for (int i = 0; i + 1 < lines.Length; i += 2)
{
string A = lines[i].Trim();
string B = lines[i + 1].Trim();
if (string.IsNullOrWhiteSpace(A) || string.IsNullOrWhiteSpace(B)) continue;
if (!A.Contains(",") || !B.Contains(",")) continue;
string[] wA = A.Split(',');
string[] wB = B.Split(',');
if (wA.Length < 6 || wB.Length < 6) continue;
string q = wA[li].Trim();
string a = wB[li].Trim();
if (!activeMap.ContainsKey(q))
activeMap.Add(q, a);
}
}
int LangIndex(string c)
{
switch (c)
{
case "tr": return 0;
case "en": return 1;
case "es": return 2;
case "de": return 3;
case "fr": return 4;
case "pt": return 5;
}
return 1;
}
// ---------------------------------------------------------
void CacheButtonData()
{
int n = questionButtons.Length;
questionOriginalScales = new Vector3[n];
answerOriginalScales = new Vector3[n];
questionOriginalPositions = new Vector3[n];
answerOriginalPositions = new Vector3[n];
questionScaleCo = new Coroutine[n];
answerScaleCo = new Coroutine[n];
questionEnterCo = new Coroutine[n];
answerEnterCo = new Coroutine[n];
for (int i = 0; i < n; i++)
{
if (questionButtons[i] != null)
{
questionOriginalScales[i] = questionButtons[i].transform.localScale;
questionOriginalPositions[i] = questionButtons[i].transform.localPosition;
questionButtons[i].transition = Selectable.Transition.None;
}
if (answerButtons[i] != null)
{
answerOriginalScales[i] = answerButtons[i].transform.localScale;
answerOriginalPositions[i] = answerButtons[i].transform.localPosition;
answerButtons[i].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 LoadRound()
{
ResetVisuals();
ResetColorMaps();
isRoundProcessing = false;
var all = activeMap.ToList();
Shuffle(all);
selectedPairs = all.Take(5).ToList();
for (int i = 0; i < 5; i++)
{
questionTexts[i].text = selectedPairs[i].Key;
int id = i;
questionButtons[i].onClick.RemoveAllListeners();
questionButtons[i].onClick.AddListener(() => SelectQuestion(id));
}
List<string> answers = selectedPairs.Select(p => p.Value).ToList();
Shuffle(answers);
for (int i = 0; i < 5; i++)
{
answerTexts[i].text = answers[i];
int id = i;
answerButtons[i].onClick.RemoveAllListeners();
answerButtons[i].onClick.AddListener(() => SelectAnswer(id));
}
// Enter animasyonları
for (int i = 0; i < 5; i++)
{
if (questionEnterCo[i] != null) StopCoroutine(questionEnterCo[i]);
questionEnterCo[i] = StartCoroutine(ButtonEnterAnim(questionButtons[i], questionOriginalScales[i], questionOriginalPositions[i], i, -1));
if (answerEnterCo[i] != null) StopCoroutine(answerEnterCo[i]);
answerEnterCo[i] = StartCoroutine(ButtonEnterAnim(answerButtons[i], answerOriginalScales[i], answerOriginalPositions[i], i, 1));
if (questionTexts[i] != null) StartCoroutine(FadeInText(questionTexts[i]));
if (answerTexts[i] != null) StartCoroutine(FadeInText(answerTexts[i]));
}
}
// ---------------------------------------------------------
void ResetVisuals()
{
for (int i = 0; i < 5; i++)
{
StopButtonAnims(i);
questionButtons[i].image.color = FullAlpha(baseColor);
answerButtons[i].image.color = FullAlpha(baseColor);
questionButtons[i].transform.localScale = questionOriginalScales[i];
answerButtons[i].transform.localScale = answerOriginalScales[i];
questionButtons[i].transform.localPosition = questionOriginalPositions[i];
answerButtons[i].transform.localPosition = answerOriginalPositions[i];
}
if (feedbackText != null)
feedbackText.text = "";
}
void StopButtonAnims(int i)
{
if (questionScaleCo[i] != null) { StopCoroutine(questionScaleCo[i]); questionScaleCo[i] = null; }
if (answerScaleCo[i] != null) { StopCoroutine(answerScaleCo[i]); answerScaleCo[i] = null; }
if (questionEnterCo[i] != null) { StopCoroutine(questionEnterCo[i]); questionEnterCo[i] = null; }
if (answerEnterCo[i] != null) { StopCoroutine(answerEnterCo[i]); answerEnterCo[i] = null; }
}
void ResetColorMaps()
{
for (int i = 0; i < 5; i++)
{
questionToAnswer[i] = -1;
questionColorIdx[i] = -1;
answerColorIdx[i] = -1;
}
}
// ---------------------------------------------------------
void SelectQuestion(int q)
{
if (isRoundProcessing || isTimeUp) return;
selectedQuestion = q;
StartScaleAnim(questionButtons, questionScaleCo, questionOriginalScales, q, questionOriginalScales[q] * selectedScale);
}
void SelectAnswer(int a)
{
if (isRoundProcessing || isTimeUp) return;
if (selectedQuestion == -1) return;
int prevQuestion = selectedQuestion;
if (questionToAnswer[selectedQuestion] == a)
{
questionToAnswer[selectedQuestion] = -1;
questionColorIdx[selectedQuestion] = -1;
answerColorIdx[a] = -1;
RefreshColors();
selectedQuestion = -1;
ResetScaleAnim(questionButtons, questionScaleCo, questionOriginalScales, prevQuestion);
ResetScaleAnim(answerButtons, answerScaleCo, answerOriginalScales, a);
return;
}
for (int i = 0; i < 5; i++)
{
if (questionToAnswer[i] == a && i != selectedQuestion)
{
questionToAnswer[i] = -1;
questionColorIdx[i] = -1;
ResetScaleAnim(questionButtons, questionScaleCo, questionOriginalScales, i);
}
}
int oldA = questionToAnswer[selectedQuestion];
if (oldA != -1)
{
answerColorIdx[oldA] = -1;
ResetScaleAnim(answerButtons, answerScaleCo, answerOriginalScales, oldA);
}
questionToAnswer[selectedQuestion] = a;
int c = selectedQuestion % pairColors.Length;
questionColorIdx[selectedQuestion] = c;
answerColorIdx[a] = c;
RefreshColors();
StartCoroutine(PairPulse(prevQuestion, a));
ResetScaleAnim(questionButtons, questionScaleCo, questionOriginalScales, prevQuestion);
selectedQuestion = -1;
}
void RefreshColors()
{
for (int i = 0; i < 5; i++)
{
questionButtons[i].image.color =
questionColorIdx[i] == -1 ? FullAlpha(baseColor) : FullAlpha(pairColors[questionColorIdx[i]]);
answerButtons[i].image.color =
answerColorIdx[i] == -1 ? FullAlpha(baseColor) : FullAlpha(pairColors[answerColorIdx[i]]);
}
}
// ---------------------------------------------------------
void OnSubmit()
{
if (isRoundProcessing || isTimeUp) return;
ProcessSubmit(false);
}
void ProcessSubmit(bool fromTimeout)
{
isRoundProcessing = true;
int roundCorrect = 0;
for (int q = 0; q < 5; q++)
{
int a = questionToAnswer[q];
if (a == -1)
{
questionButtons[q].image.color = FullAlpha(wrongColor);
StartCoroutine(ShakeButton(questionButtons[q], questionOriginalPositions[q]));
wrongCount++;
continue;
}
string qWord = questionTexts[q].text;
string correctA = activeMap[qWord];
string chosenA = answerTexts[a].text;
if (chosenA == correctA)
{
roundCorrect++;
correctCount++;
questionButtons[q].image.color = FullAlpha(correctColor);
answerButtons[a].image.color = FullAlpha(correctColor);
StartCoroutine(CorrectPulse(questionButtons[q], questionOriginalScales[q]));
StartCoroutine(CorrectPulse(answerButtons[a], answerOriginalScales[a]));
}
else
{
wrongCount++;
questionButtons[q].image.color = FullAlpha(wrongColor);
answerButtons[a].image.color = FullAlpha(wrongColor);
StartCoroutine(ShakeButton(questionButtons[q], questionOriginalPositions[q]));
StartCoroutine(ShakeButton(answerButtons[a], answerOriginalPositions[a]));
}
}
int gained = roundCorrect * 20;
score += gained;
Color feedbackColor;
if (roundCorrect == 5)
{
combo++;
feedbackText.text = combo >= 2 ? $"PERFECT! {combo}x COMBO!" : "PERFECT!";
feedbackColor = correctColor;
}
else if (roundCorrect > 0)
{
combo = 0;
feedbackText.text = "+" + gained + " Points";
feedbackColor = correctColor;
}
else
{
combo = 0;
feedbackText.text = "Try Again!";
feedbackColor = wrongColor;
}
feedbackText.color = FullAlpha(feedbackColor);
if (feedbackOnTop)
{
Vector3 pos = feedbackText.transform.localPosition;
pos.y = feedbackTopY;
feedbackText.transform.localPosition = pos;
}
if (feedbackCo != null) StopCoroutine(feedbackCo);
feedbackCo = StartCoroutine(FeedbackAnim(feedbackText));
scoreText.text = score.ToString();
comboText.text = combo + "x";
if (scoreText != null) StartCoroutine(ScorePopAnim(scoreText));
if (combo > 0 && comboText != null) StartCoroutine(ComboAnim(comboText));
SaveProgress();
if (!fromTimeout)
StartCoroutine(NextRound());
}
// ---------------------------------------------------------
void SaveProgress()
{
// 🔥 Mod Select / Leaderboard ekranına direkt bağlanacak basit key
PlayerPrefs.SetInt("Mod8Skor", score);
PlayerPrefs.SetInt(modKey + "_LastScore", score);
int best = PlayerPrefs.GetInt(modKey + "_MaxScore", 0);
if (score > best)
PlayerPrefs.SetInt(modKey + "_MaxScore", score);
PlayerPrefs.SetInt(modKey + "_Correct", correctCount);
PlayerPrefs.SetInt(modKey + "_Wrong", wrongCount);
PlayerPrefs.Save();
}
IEnumerator NextRound()
{
yield return new WaitForSeconds(0.8f);
LoadRound();
}
IEnumerator GoResume()
{
yield return new WaitForSeconds(1f);
SceneManager.LoadScene("Mod8Resume");
}
// ---------------------------------------------------------
void Shuffle<T>(List<T> list)
{
for (int i = list.Count - 1; i > 0; i--)
{
int j = Random.Range(0, i + 1);
(list[i], list[j]) = (list[j], list[i]);
}
}
// ================== ANIMATION HELPERS ==================
void StartScaleAnim(Button[] buttons, Coroutine[] coArr, Vector3[] originalScales, int idx, Vector3 targetScale)
{
if (idx < 0 || idx >= buttons.Length || buttons[idx] == null) return;
if (coArr[idx] != null)
StopCoroutine(coArr[idx]);
coArr[idx] = StartCoroutine(ScaleButton(buttons[idx], targetScale, idx, coArr));
}
void ResetScaleAnim(Button[] buttons, Coroutine[] coArr, Vector3[] originalScales, int idx)
{
if (idx < 0 || idx >= buttons.Length || buttons[idx] == null) return;
StartScaleAnim(buttons, coArr, originalScales, idx, originalScales[idx]);
}
IEnumerator ScaleButton(Button btn, Vector3 targetScale, int idx, Coroutine[] coArr)
{
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;
coArr[idx] = null;
}
IEnumerator ButtonEnterAnim(Button btn, Vector3 targetScale, Vector3 targetPos, int delayIndex, int sideSign)
{
if (btn == null) yield break;
yield return new WaitForSeconds(delayIndex * 0.05f);
Vector3 startPos = targetPos + new Vector3(sideSign * 40f, 0f, 0f);
Vector3 startScale = targetScale * 0.85f;
btn.transform.localPosition = startPos;
btn.transform.localScale = startScale;
float t = 0f;
while (t < 1f)
{
t += Time.deltaTime / Mathf.Max(0.01f, enterAnimTime);
float ease = EaseOutBack(t);
btn.transform.localPosition = Vector3.Lerp(startPos, targetPos, ease);
btn.transform.localScale = Vector3.Lerp(startScale, targetScale, ease);
yield return null;
}
btn.transform.localPosition = targetPos;
btn.transform.localScale = targetScale;
}
IEnumerator PairPulse(int questionIdx, int answerIdx)
{
if (questionIdx >= 0 && questionIdx < questionButtons.Length)
yield return StartCoroutine(QuickPulse(questionButtons[questionIdx].transform, questionOriginalScales[questionIdx]));
if (answerIdx >= 0 && answerIdx < answerButtons.Length)
yield return StartCoroutine(QuickPulse(answerButtons[answerIdx].transform, answerOriginalScales[answerIdx]));
}
IEnumerator QuickPulse(Transform tr, Vector3 normal)
{
if (tr == null) yield break;
Vector3 big = normal * 1.08f;
float t = 0f;
while (t < 1f)
{
t += Time.deltaTime / 0.08f;
tr.localScale = Vector3.Lerp(normal, big, EaseOutQuad(t));
yield return null;
}
t = 0f;
while (t < 1f)
{
t += Time.deltaTime / 0.08f;
tr.localScale = Vector3.Lerp(big, normal, EaseOutQuad(t));
yield return null;
}
tr.localScale = normal;
}
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 baseC = 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(baseC, 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, baseC, t));
yield return null;
}
txt.transform.localScale = original;
txt.color = baseC;
}
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;
}
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);
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 24738b79935ff2e4684b1e2523827057

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 15b1f064ebce8074c855ee805144ea4a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,82 @@
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class Mod10Resume : MonoBehaviour
{
[Header("UI TEXTS (ONLY NUMBERS)")]
public TMP_Text scoreText;
public TMP_Text maxScoreText;
public TMP_Text correctText;
public TMP_Text wrongText;
[Header("BUTTONS")]
public Button retryButton;
public Button exitButton;
[Header("AUDIO")]
public AudioSource sfx;
public AudioClip clickSound;
// Bu modun kendi ana anahtarı
private string modKey = "Mod10";
private int score;
private int maxScore;
private int correct;
private int wrong;
void Start()
{
LoadResults();
UpdateUI();
if (retryButton != null)
retryButton.onClick.AddListener(() => { PlaySFX(); Retry(); });
if (exitButton != null)
exitButton.onClick.AddListener(() => { PlaySFX(); ExitToMenu(); });
}
// ---------------------------------------------------------------
void LoadResults()
{
score = PlayerPrefs.GetInt(modKey + "_LastScore", 0);
maxScore = PlayerPrefs.GetInt(modKey + "_MaxScore", 0);
correct = PlayerPrefs.GetInt(modKey + "_Correct", 0);
wrong = PlayerPrefs.GetInt(modKey + "_Wrong", 0);
Debug.Log("MOD10 RESULT → " +
$"Score:{score} | Max:{maxScore} | C:{correct} | W:{wrong}");
}
// ---------------------------------------------------------------
void UpdateUI()
{
if (scoreText != null) scoreText.text = score.ToString();
if (maxScoreText != null) maxScoreText.text = maxScore.ToString();
if (correctText != null) correctText.text = correct.ToString();
if (wrongText != null) wrongText.text = wrong.ToString();
}
// ---------------------------------------------------------------
void PlaySFX()
{
if (sfx && clickSound)
sfx.PlayOneShot(clickSound);
}
// ---------------------------------------------------------------
void Retry()
{
// 🔥 MOD 10 OYUN SAHNESİNE GERİ DÖNÜŞ
SceneManager.LoadScene("Mod10");
}
// ---------------------------------------------------------------
void ExitToMenu()
{
SceneManager.LoadScene("Anamen");
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 943d61e94ac5fdc45b9ea6f4357d8d71

View file

@ -0,0 +1,807 @@
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class SentenceOrderGameScene : MonoBehaviour
{
[Header("TXT DOSYASI (6 Dil)")]
public TextAsset questionFile;
[Header("UI")]
public TMP_Text questionText;
public TMP_Text[] answerTexts;
public Button[] answerButtons;
public Button submitButton;
public TMP_Text selectedWordsText;
public TMP_Text scoreText;
public TMP_Text comboText;
public TMP_Text timerText;
public TMP_Text feedbackText;
[Header("EXTRA BUTTONS")]
public Button extraTimeButton;
public Button extraHintButton;
public Button extraSkipButton;
[Header("━━━ BACK BUTTON ━━━━━━━━━━━━━━━━━━━━━━━━")]
public Button backButton;
public string backSceneName = "ModSec 10";
[Header("RENKLER")]
public Color normalColor = new Color32(255, 255, 255, 70);
public Color selectedColor = new Color32(60, 110, 200, 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;
public float enterAnimTime = 0.22f;
// INTERNAL
private class SentenceEntry
{
public string[] sentence = new string[6];
}
private List<SentenceEntry> questions = new List<SentenceEntry>();
private string[] correctWords;
private string[] scrambledWords;
private int[] order;
private int selectedCount = 0;
private bool locked = false;
private int lastID = -1;
private int score = 0;
private int combo = 0;
private float timeLeft = 60f;
private float nextTimer = 0f;
// LANGUAGE & MOD KEY
private string lang;
private string modKey = "Mod10";
// Counters
private int correctCount = 0;
private int wrongCount = 0;
readonly Color timerNormalColor = Color.white;
readonly Color timerWarnColor = new Color32(255, 80, 80, 255);
Vector3[] originalButtonScales;
Vector3[] originalButtonPositions;
Coroutine[] buttonScaleCoroutines;
Coroutine[] buttonEnterCoroutines;
Coroutine feedbackCo;
// ------------------------------------------------------------
void Start()
{
lang = PlayerPrefs.GetString("QuestionLangCode", "en");
order = new int[answerButtons.Length];
if (questionFile == null)
{
Debug.LogError("SentenceOrderGameScene: TXT bağlanmamış!");
return;
}
CacheButtonData();
PrepareFeedbackText();
LoadTXT(questionFile.text);
Shuffle(questions);
submitButton.onClick.AddListener(OnSubmit);
extraTimeButton.onClick.AddListener(() => timeLeft += 5f);
extraHintButton.onClick.AddListener(OnHint);
extraSkipButton.onClick.AddListener(() => NextQuestion());
if (backButton != null)
{
backButton.onClick.RemoveAllListeners();
backButton.onClick.AddListener(() => SceneManager.LoadScene(backSceneName));
}
scoreText.text = "0";
comboText.text = "0x";
NextQuestion();
}
// ------------------------------------------------------------
void Update()
{
if (!locked)
{
timeLeft -= Time.deltaTime;
if (timeLeft <= 0)
{
timeLeft = 0;
GameOver();
}
}
UpdateTimerUI();
if (locked && nextTimer > 0)
{
nextTimer -= Time.deltaTime;
if (nextTimer <= 0)
NextQuestion();
}
}
// ------------------------------------------------------------
void CacheButtonData()
{
if (answerButtons == null) return;
int len = answerButtons.Length;
originalButtonScales = new Vector3[len];
originalButtonPositions = new Vector3[len];
buttonScaleCoroutines = new Coroutine[len];
buttonEnterCoroutines = new Coroutine[len];
for (int i = 0; i < len; i++)
{
if (answerButtons[i] == null) continue;
originalButtonScales[i] = answerButtons[i].transform.localScale;
originalButtonPositions[i] = answerButtons[i].transform.localPosition;
answerButtons[i].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(string raw)
{
foreach (string line in raw.Trim().Split('\n'))
{
if (string.IsNullOrWhiteSpace(line)) continue;
string[] p = line.Split(',');
if (p.Length < 6) continue;
SentenceEntry e = new SentenceEntry();
for (int i = 0; i < 6; i++)
e.sentence[i] = p[i].Trim();
questions.Add(e);
}
}
// ------------------------------------------------------------
void NextQuestion()
{
nextTimer = 0f;
locked = false;
selectedCount = 0;
if (feedbackText != null)
feedbackText.text = "";
if (selectedWordsText != null)
selectedWordsText.text = "";
for (int i = 0; i < order.Length; i++)
order[i] = 0;
for (int i = 0; i < answerButtons.Length; i++)
{
StopButtonCoroutines(i);
answerButtons[i].interactable = true;
answerButtons[i].image.color = FullAlpha(normalColor);
answerButtons[i].transform.localScale = originalButtonScales[i];
answerButtons[i].transform.localPosition = originalButtonPositions[i];
answerButtons[i].gameObject.SetActive(false);
}
// random
int qID = Random.Range(0, questions.Count);
if (qID == lastID && questions.Count > 1)
qID = (qID + 1) % questions.Count;
lastID = qID;
SentenceEntry entry = questions[qID];
int L = GetLangIndex();
string s = entry.sentence[L];
questionText.text = s;
StartCoroutine(FadeInText(questionText));
correctWords = s.Split(' ');
int wc = Mathf.Min(correctWords.Length, answerButtons.Length);
System.Array.Resize(ref correctWords, wc);
scrambledWords = (string[])correctWords.Clone();
Shuffle(scrambledWords);
for (int i = 0; i < wc; i++)
{
answerButtons[i].gameObject.SetActive(true);
answerTexts[i].text = scrambledWords[i];
int id = i;
answerButtons[i].onClick.RemoveAllListeners();
answerButtons[i].onClick.AddListener(() => OnClickWord(id));
buttonEnterCoroutines[i] = StartCoroutine(ButtonEnterAnim(answerButtons[i], i));
}
}
// ------------------------------------------------------------
void OnClickWord(int id)
{
if (locked) return;
int wc = correctWords.Length;
if (order[id] != 0)
{
int old = order[id];
order[id] = 0;
for (int i = 0; i < wc; i++)
if (order[i] > old)
order[i]--;
selectedCount--;
}
else
{
selectedCount++;
order[id] = selectedCount;
}
RefreshUI();
}
// ------------------------------------------------------------
void RefreshUI()
{
int wc = correctWords.Length;
List<string> seq = new List<string>();
for (int i = 0; i < wc; i++)
{
if (order[i] > 0)
{
answerButtons[i].image.color = FullAlpha(selectedColor);
answerTexts[i].text = order[i] + ". " + scrambledWords[i];
StartScaleAnim(i, originalButtonScales[i] * selectedScale);
}
else
{
answerButtons[i].image.color = FullAlpha(normalColor);
answerTexts[i].text = scrambledWords[i];
StartScaleAnim(i, originalButtonScales[i]);
}
}
for (int orderNum = 1; orderNum <= wc; orderNum++)
for (int j = 0; j < wc; j++)
if (order[j] == orderNum)
seq.Add(scrambledWords[j]);
if (selectedWordsText != null)
selectedWordsText.text = string.Join(" | ", seq);
}
// ------------------------------------------------------------
void OnSubmit()
{
if (locked) return;
int wc = correctWords.Length;
if (selectedCount < wc)
{
SetFeedback("Select all words!", wrongColor);
return;
}
locked = true;
bool ok = true;
for (int orderNum = 1; orderNum <= wc; orderNum++)
for (int i = 0; i < wc; i++)
if (order[i] == orderNum && scrambledWords[i] != correctWords[orderNum - 1])
ok = false;
for (int i = 0; i < wc; i++)
answerButtons[i].interactable = false;
if (ok)
{
correctCount++;
combo++;
score += 50 + (combo - 1) * 10;
timeLeft += 2f;
for (int i = 0; i < wc; i++)
{
answerButtons[i].image.color = FullAlpha(correctColor);
StartCoroutine(CorrectPulse(answerButtons[i], i));
}
SetFeedback(combo >= 3 ? $"TRUE {combo}x COMBO!" : "TRUE", correctColor);
if (comboText != null) StartCoroutine(ComboAnim(comboText));
}
else
{
wrongCount++;
combo = 0;
for (int i = 0; i < wc; i++)
{
answerButtons[i].image.color = FullAlpha(wrongColor);
StartCoroutine(ShakeButton(answerButtons[i], i));
}
SetFeedback("FALSE", wrongColor);
}
scoreText.text = score.ToString();
comboText.text = combo + "x";
if (scoreText != null) StartCoroutine(ScorePopAnim(scoreText));
nextTimer = 1f;
}
// ------------------------------------------------------------
// HINT: İlk kelimeyi otomatik seçer
// ------------------------------------------------------------
void OnHint()
{
if (locked) return;
int wc = correctWords.Length;
// Önce tüm seçimleri sıfırla
selectedCount = 0;
for (int i = 0; i < wc; i++)
order[i] = 0;
// Doğru ilk kelime
string firstWord = correctWords[0];
// Scrambled içinde doğru kelimenin index'ini bul
for (int i = 0; i < wc; i++)
{
if (scrambledWords[i] == firstWord)
{
order[i] = 1;
selectedCount = 1;
StartCoroutine(CorrectPulse(answerButtons[i], i));
break;
}
}
RefreshUI();
SetFeedback("Hint used!", selectedColor);
}
// ------------------------------------------------------------
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 GameOver()
{
// 🔥 Mod Select / Leaderboard ekranına direkt bağlanacak basit key
PlayerPrefs.SetInt("Mod10Skor", score);
// kayıt sistemi
PlayerPrefs.SetString("LastPlayedMod", modKey);
PlayerPrefs.SetInt(modKey + "_LastScore", score);
int oldMax = PlayerPrefs.GetInt(modKey + "_MaxScore", 0);
if (score > oldMax)
PlayerPrefs.SetInt(modKey + "_MaxScore", score);
PlayerPrefs.SetInt(modKey + "_Correct", correctCount);
PlayerPrefs.SetInt(modKey + "_Wrong", wrongCount);
PlayerPrefs.Save();
// 🔥 MOD 10 SONUÇ SAHNESİ
SceneManager.LoadScene("Mod10Resume");
}
// ------------------------------------------------------------
int GetLangIndex()
{
return lang switch
{
"tr" => 0,
"en" => 1,
"es" => 2,
"de" => 3,
"fr" => 4,
"pt" => 5,
_ => 1
};
}
// ------------------------------------------------------------
void Shuffle<T>(IList<T> arr)
{
for (int i = 0; i < arr.Count; i++)
{
int r = Random.Range(i, arr.Count);
(arr[i], arr[r]) = (arr[r], arr[i]);
}
}
// ================== ANIMATION HELPERS ==================
void StartScaleAnim(int index, Vector3 targetScale)
{
if (index < 0 || index >= answerButtons.Length) return;
if (answerButtons[index] == null) return;
if (buttonScaleCoroutines[index] != null)
StopCoroutine(buttonScaleCoroutines[index]);
buttonScaleCoroutines[index] = StartCoroutine(ScaleButton(answerButtons[index], targetScale));
}
void StopButtonCoroutines(int index)
{
if (buttonScaleCoroutines != null && index < buttonScaleCoroutines.Length && buttonScaleCoroutines[index] != null)
{
StopCoroutine(buttonScaleCoroutines[index]);
buttonScaleCoroutines[index] = null;
}
if (buttonEnterCoroutines != null && index < buttonEnterCoroutines.Length && buttonEnterCoroutines[index] != null)
{
StopCoroutine(buttonEnterCoroutines[index]);
buttonEnterCoroutines[index] = null;
}
}
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 ButtonEnterAnim(Button btn, int delayIndex)
{
if (btn == null) yield break;
int idx = System.Array.IndexOf(answerButtons, btn);
if (idx < 0) yield break;
yield return new WaitForSeconds(delayIndex * 0.05f);
Vector3 targetPos = originalButtonPositions[idx];
Vector3 startPos = targetPos + Vector3.up * 30f;
Vector3 targetScale = originalButtonScales[idx];
Vector3 startScale = targetScale * 0.85f;
btn.transform.localPosition = startPos;
btn.transform.localScale = startScale;
float t = 0f;
while (t < 1f)
{
t += Time.deltaTime / Mathf.Max(0.01f, enterAnimTime);
float ease = EaseOutBack(t);
btn.transform.localPosition = Vector3.Lerp(startPos, targetPos, ease);
btn.transform.localScale = Vector3.Lerp(startScale, targetScale, ease);
yield return null;
}
btn.transform.localPosition = targetPos;
btn.transform.localScale = targetScale;
}
IEnumerator CorrectPulse(Button btn, int idx)
{
if (btn == null) yield break;
if (idx < 0 || idx >= originalButtonScales.Length) yield break;
Vector3 normal = originalButtonScales[idx];
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, int idx)
{
if (btn == null) yield break;
if (idx < 0 || idx >= originalButtonPositions.Length) yield break;
Vector3 origin = originalButtonPositions[idx];
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;
}
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);
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 5d1f4458536ed634b97019cf3c7abb27

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5861da0019dff9a42a4a83d14f1722c8
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,846 @@
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class AnalogyLogicGameScene : MonoBehaviour
{
[Header("TXT (6 Language Analogy Data)")]
public TextAsset analogyFile;
[Header("UI")]
public TMP_Text questionText;
public TMP_Text[] answerTexts;
public Button[] answerButtons;
public Button submitButton;
public TMP_Text feedbackText;
public TMP_Text scoreText;
public TMP_Text comboText;
public TMP_Text timerText;
public TMP_Text selectedWordsText;
[Header("EXTRAS")]
public Button extraTimeButton;
public Button extraHintButton;
public Button extraSkipButton;
[Header("━━━ BACK BUTTON ━━━━━━━━━━━━━━━━━━━━━━━━")]
public Button backButton;
public string backSceneName = "ModSec 11";
[Header("COLORS")]
public Color normalColor = new Color32(255, 255, 255, 70);
public Color selectedColor = new Color32(60, 110, 200, 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;
public float enterAnimTime = 0.22f;
// 0=TR, 1=EN, 2=ES, 3=DE, 4=FR, 5=PT
private string langCode; // "tr","en"...
private int langIndex; // 05
private class AnalogyQ
{
// data[language, field] -> 0:A 1:B 2:C 3:COR 4:W1 5:W2 6:W3
public string[,] data = new string[6, 7];
}
private List<AnalogyQ> questions = new List<AnalogyQ>();
private int correctIndex = -1;
private int selectedIndex = -1;
private bool locked = false;
private int lastQ = -1;
private int score = 0;
private int combo = 0;
private int correctCount = 0;
private int wrongCount = 0;
private float timeLeft = 60f;
private float nextTimer = 0f;
private string modKey = "Mod11";
readonly Color timerNormalColor = Color.white;
readonly Color timerWarnColor = new Color32(255, 80, 80, 255);
Vector3[] originalButtonScales;
Vector3[] originalButtonPositions;
Coroutine[] buttonScaleCoroutines;
Coroutine[] buttonEnterCoroutines;
Coroutine feedbackCo;
// ================================================================
void Start()
{
// Uses the same system as SentenceOrderGameScene
langCode = PlayerPrefs.GetString("QuestionLangCode", "en");
langIndex = GetLangIndex();
if (analogyFile == null)
{
Debug.LogError("AnalogyLogicGameScene: analogyFile is not assigned!");
if (questionText != null)
questionText.text = "TXT NOT FOUND!";
enabled = false;
return;
}
LoadTXT6Lang(analogyFile.text);
if (questions.Count == 0)
{
Debug.LogError("AnalogyLogicGameScene: TXT is empty or invalid!");
if (questionText != null)
questionText.text = "EMPTY FILE!";
enabled = false;
return;
}
if (answerButtons == null || answerButtons.Length < 4 ||
answerTexts == null || answerTexts.Length < 4)
{
Debug.LogError("AnalogyLogicGameScene: 4 answerButtons / answerTexts are required.");
enabled = false;
return;
}
CacheButtonData();
PrepareFeedbackText();
Shuffle(questions);
if (submitButton != null)
submitButton.onClick.AddListener(OnSubmit);
if (extraTimeButton != null)
extraTimeButton.onClick.AddListener(() => timeLeft += 5f);
if (extraHintButton != null)
extraHintButton.onClick.AddListener(OnHint);
if (extraSkipButton != null)
extraSkipButton.onClick.AddListener(NextQuestion);
if (backButton != null)
{
backButton.onClick.RemoveAllListeners();
backButton.onClick.AddListener(() => SceneManager.LoadScene(backSceneName));
}
if (scoreText != null)
scoreText.text = "0";
if (comboText != null)
comboText.text = "0x";
NextQuestion();
}
// ================================================================
void CacheButtonData()
{
if (answerButtons == null) return;
int len = answerButtons.Length;
originalButtonScales = new Vector3[len];
originalButtonPositions = new Vector3[len];
buttonScaleCoroutines = new Coroutine[len];
buttonEnterCoroutines = new Coroutine[len];
for (int i = 0; i < len; i++)
{
if (answerButtons[i] == null) continue;
originalButtonScales[i] = answerButtons[i].transform.localScale;
originalButtonPositions[i] = answerButtons[i].transform.localPosition;
answerButtons[i].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;
}
// ================================================================
// 6-LANGUAGE BLOCK TXT READER
// Each question: 6 lines (TR, EN, ES, DE, FR, PT)
// Line format: A,B,C,COR,W1,W2,W3
// ================================================================
void LoadTXT6Lang(string raw)
{
string[] lines = raw.Split('\n');
for (int i = 0; i < lines.Length;)
{
if (string.IsNullOrWhiteSpace(lines[i]))
{
i++;
continue;
}
if (i + 5 >= lines.Length)
break;
AnalogyQ q = new AnalogyQ();
bool validBlock = true;
for (int L = 0; L < 6; L++)
{
string line = lines[i + L].Trim('\r', '\n', ' ');
if (string.IsNullOrEmpty(line))
{
validBlock = false;
break;
}
string[] p = line.Split(',');
if (p.Length != 7)
{
Debug.LogWarning($"AnalogyLogicGameScene: line {i + L} does not contain 7 parts, block skipped.");
validBlock = false;
break;
}
for (int k = 0; k < 7; k++)
q.data[L, k] = p[k].Trim();
}
if (validBlock)
questions.Add(q);
i += 6;
}
}
// ================================================================
void Update()
{
if (!locked)
{
timeLeft -= Time.deltaTime;
if (timeLeft <= 0f)
{
timeLeft = 0f;
GameOver();
}
}
UpdateTimerUI();
if (locked && nextTimer > 0f)
{
nextTimer -= Time.deltaTime;
if (nextTimer <= 0f)
NextQuestion();
}
}
// ================================================================
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 NextQuestion()
{
locked = false;
selectedIndex = -1;
nextTimer = 0f;
if (selectedWordsText != null)
selectedWordsText.text = "";
if (feedbackText != null)
feedbackText.text = "";
for (int i = 0; i < answerButtons.Length; i++)
{
if (answerButtons[i] == null) continue;
StopButtonCoroutines(i);
answerButtons[i].interactable = true;
answerButtons[i].transform.localScale = originalButtonScales[i];
answerButtons[i].transform.localPosition = originalButtonPositions[i];
if (answerButtons[i].image != null)
answerButtons[i].image.color = FullAlpha(normalColor);
}
if (questions.Count == 0)
{
GameOver();
return;
}
int id = Random.Range(0, questions.Count);
if (id == lastQ && questions.Count > 1)
id = (id + 1) % questions.Count;
lastQ = id;
AnalogyQ q = questions[id];
string A = q.data[langIndex, 0];
string B = q.data[langIndex, 1];
string C = q.data[langIndex, 2];
string COR = q.data[langIndex, 3];
string W1 = q.data[langIndex, 4];
string W2 = q.data[langIndex, 5];
string W3 = q.data[langIndex, 6];
if (questionText != null)
{
questionText.text = $"{A} : {B} = {C} : ?";
StartCoroutine(FadeInText(questionText));
}
List<string> opts = new List<string> { COR, W1, W2, W3 };
Shuffle(opts);
correctIndex = opts.IndexOf(COR);
for (int i = 0; i < 4; i++)
{
if (answerTexts[i] != null)
answerTexts[i].text = opts[i];
int x = i;
if (answerButtons[i] != null)
{
answerButtons[i].onClick.RemoveAllListeners();
answerButtons[i].onClick.AddListener(() => OnSelect(x));
buttonEnterCoroutines[i] = StartCoroutine(ButtonEnterAnim(answerButtons[i], i));
}
}
}
// ================================================================
void OnSelect(int id)
{
if (locked) return;
if (selectedIndex == id) return;
if (selectedIndex >= 0 && selectedIndex < answerButtons.Length && answerButtons[selectedIndex] != null)
{
if (answerButtons[selectedIndex].image != null)
answerButtons[selectedIndex].image.color = FullAlpha(normalColor);
StartScaleAnim(selectedIndex, originalButtonScales[selectedIndex]);
}
selectedIndex = id;
if (answerButtons[id] != null)
{
if (answerButtons[id].image != null)
answerButtons[id].image.color = FullAlpha(selectedColor);
StartScaleAnim(id, originalButtonScales[id] * selectedScale);
}
if (selectedWordsText != null && answerTexts[id] != null)
selectedWordsText.text = answerTexts[id].text;
}
// ================================================================
void OnSubmit()
{
if (locked) return;
if (selectedIndex == -1) return;
locked = true;
bool ok = (selectedIndex == correctIndex);
foreach (var b in answerButtons)
if (b != null) b.interactable = false;
if (ok)
{
correctCount++;
combo++;
score += 50 + combo * 10;
timeLeft += 2f;
if (answerButtons[selectedIndex] != null && answerButtons[selectedIndex].image != null)
answerButtons[selectedIndex].image.color = FullAlpha(correctColor);
StartCoroutine(CorrectPulse(answerButtons[selectedIndex], selectedIndex));
SetFeedback(combo >= 3 ? $"{Local("correct")} {combo}x COMBO!" : Local("correct"), correctColor);
if (comboText != null) StartCoroutine(ComboAnim(comboText));
}
else
{
wrongCount++;
combo = 0;
score -= 20;
if (score < 0) score = 0;
if (answerButtons[selectedIndex] != null && answerButtons[selectedIndex].image != null)
answerButtons[selectedIndex].image.color = FullAlpha(wrongColor);
StartCoroutine(ShakeButton(answerButtons[selectedIndex], selectedIndex));
if (correctIndex >= 0 && correctIndex < answerButtons.Length &&
answerButtons[correctIndex] != null && answerButtons[correctIndex].image != null)
{
answerButtons[correctIndex].image.color = FullAlpha(correctColor);
StartCoroutine(CorrectPulse(answerButtons[correctIndex], correctIndex));
}
SetFeedback(Local("wrong"), wrongColor);
}
if (scoreText != null)
{
scoreText.text = score.ToString();
StartCoroutine(ScorePopAnim(scoreText));
}
if (comboText != null)
comboText.text = combo + "x";
nextTimer = 1f;
}
// ================================================================
void OnHint()
{
if (locked) return;
if (lastQ < 0 || lastQ >= questions.Count) return;
string hint = questions[lastQ].data[langIndex, 3]; // correct answer
if (!string.IsNullOrEmpty(hint))
hint = hint.Length > 1 ? hint[0] + "..." : hint;
SetFeedback("Hint: " + hint, selectedColor);
}
// ================================================================
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 GameOver()
{
// 🔥 Simple key that the Mod Select / Leaderboard screen can bind to directly
PlayerPrefs.SetInt("Mod11Skor", score);
PlayerPrefs.SetString("LastPlayedMod", modKey);
PlayerPrefs.SetInt(modKey + "_LastScore", score);
int best = PlayerPrefs.GetInt(modKey + "_MaxScore", 0);
if (score > best)
PlayerPrefs.SetInt(modKey + "_MaxScore", score);
PlayerPrefs.SetInt(modKey + "_Correct", correctCount);
PlayerPrefs.SetInt(modKey + "_Wrong", wrongCount);
PlayerPrefs.Save();
SceneManager.LoadScene("Mod11Resume");
}
// ================================================================
int GetLangIndex()
{
return langCode switch
{
"tr" => 1,
"en" => 0,
"es" => 2,
"de" => 3,
"fr" => 4,
"pt" => 5,
_ => 1 // default EN
};
}
// ================================================================
string Local(string key)
{
int L = GetLangIndex(); // Same as QuestionLangCode
switch (key)
{
case "correct":
return new[]
{
"Correct!", "Correct!", "Correct!", "Correct!", "Correct!", "Correct!"
}[L];
case "wrong":
return new[]
{
"Wrong!", "Wrong!", "Wrong!", "Wrong!", "Wrong!", "Wrong!"
}[L];
}
return key;
}
// ================================================================
void Shuffle<T>(IList<T> arr)
{
for (int i = 0; i < arr.Count; i++)
{
int r = Random.Range(i, arr.Count);
(arr[i], arr[r]) = (arr[r], arr[i]);
}
}
// ================== ANIMATION HELPERS ==================
void StartScaleAnim(int index, Vector3 targetScale)
{
if (index < 0 || index >= answerButtons.Length) return;
if (answerButtons[index] == null) return;
if (buttonScaleCoroutines[index] != null)
StopCoroutine(buttonScaleCoroutines[index]);
buttonScaleCoroutines[index] = StartCoroutine(ScaleButton(answerButtons[index], targetScale));
}
void StopButtonCoroutines(int index)
{
if (buttonScaleCoroutines != null && index < buttonScaleCoroutines.Length && buttonScaleCoroutines[index] != null)
{
StopCoroutine(buttonScaleCoroutines[index]);
buttonScaleCoroutines[index] = null;
}
if (buttonEnterCoroutines != null && index < buttonEnterCoroutines.Length && buttonEnterCoroutines[index] != null)
{
StopCoroutine(buttonEnterCoroutines[index]);
buttonEnterCoroutines[index] = null;
}
}
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 ButtonEnterAnim(Button btn, int delayIndex)
{
if (btn == null) yield break;
int idx = System.Array.IndexOf(answerButtons, btn);
if (idx < 0) yield break;
yield return new WaitForSeconds(delayIndex * 0.06f);
Vector3 targetPos = originalButtonPositions[idx];
Vector3 startPos = targetPos + Vector3.up * 35f;
Vector3 targetScale = originalButtonScales[idx];
Vector3 startScale = targetScale * 0.85f;
btn.transform.localPosition = startPos;
btn.transform.localScale = startScale;
float t = 0f;
while (t < 1f)
{
t += Time.deltaTime / Mathf.Max(0.01f, enterAnimTime);
float ease = EaseOutBack(t);
btn.transform.localPosition = Vector3.Lerp(startPos, targetPos, ease);
btn.transform.localScale = Vector3.Lerp(startScale, targetScale, ease);
yield return null;
}
btn.transform.localPosition = targetPos;
btn.transform.localScale = targetScale;
}
IEnumerator CorrectPulse(Button btn, int idx)
{
if (btn == null) yield break;
if (idx < 0 || idx >= originalButtonScales.Length) yield break;
Vector3 normal = originalButtonScales[idx];
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, int idx)
{
if (btn == null) yield break;
if (idx < 0 || idx >= originalButtonPositions.Length) yield break;
Vector3 origin = originalButtonPositions[idx];
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;
}
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);
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: ff5c022bf505d8a4cbd87bc660103cf2

View file

@ -0,0 +1,154 @@
using System.Collections;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class Mod11Resume : MonoBehaviour
{
[Header("UI TEXTS (ONLY NUMBERS)")]
public TMP_Text scoreText;
public TMP_Text maxScoreText;
public TMP_Text correctText;
public TMP_Text wrongText;
[Header("BUTTONS")]
public Button retryButton;
public Button exitButton;
[Header("AUDIO")]
public AudioSource sfx;
public AudioClip clickSound;
[Header("━━━ ANIMATION SETTINGS ━━━━━━━━━━━━━━━━━")]
public float countUpDuration = 0.8f;
public float popInDelay = 0.08f;
public float popInTime = 0.3f;
// 🔥 Bu modun özel PlayerPrefs anahtarı
private string modKey = "Mod11";
private int score;
private int maxScore;
private int correct;
private int wrong;
// ============================================================
void Start()
{
LoadResults();
PrepareTexts();
if (retryButton != null)
retryButton.onClick.AddListener(() => { PlaySFX(); Retry(); });
if (exitButton != null)
exitButton.onClick.AddListener(() => { PlaySFX(); ExitToMenu(); });
StartCoroutine(PlayRevealSequence());
}
// ============================================================
void LoadResults()
{
score = PlayerPrefs.GetInt(modKey + "_LastScore", 0);
maxScore = PlayerPrefs.GetInt(modKey + "_MaxScore", 0);
correct = PlayerPrefs.GetInt(modKey + "_Correct", 0);
wrong = PlayerPrefs.GetInt(modKey + "_Wrong", 0);
Debug.Log($"[MOD11 RESULT] Score={score} | Max={maxScore} | Correct={correct} | Wrong={wrong}");
}
// ============================================================
void PrepareTexts()
{
SetTextZero(scoreText);
SetTextZero(maxScoreText);
SetTextZero(correctText);
SetTextZero(wrongText);
}
void SetTextZero(TMP_Text txt)
{
if (txt == null) return;
txt.text = "0";
txt.transform.localScale = Vector3.zero;
}
// ============================================================
IEnumerator PlayRevealSequence()
{
yield return StartCoroutine(RevealStat(scoreText, score));
yield return new WaitForSeconds(popInDelay);
yield return StartCoroutine(RevealStat(maxScoreText, maxScore));
yield return new WaitForSeconds(popInDelay);
yield return StartCoroutine(RevealStat(correctText, correct));
yield return new WaitForSeconds(popInDelay);
yield return StartCoroutine(RevealStat(wrongText, wrong));
}
IEnumerator RevealStat(TMP_Text txt, int targetValue)
{
if (txt == null) yield break;
float t = 0f;
while (t < 1f)
{
t += Time.deltaTime / Mathf.Max(0.01f, popInTime);
txt.transform.localScale = Vector3.Lerp(Vector3.zero, Vector3.one, EaseOutBack(t));
if (targetValue == 0) txt.text = "0";
yield return null;
}
txt.transform.localScale = Vector3.one;
if (targetValue > 0)
{
float ct = 0f;
while (ct < 1f)
{
ct += Time.deltaTime / Mathf.Max(0.01f, countUpDuration);
txt.text = Mathf.RoundToInt(Mathf.Lerp(0, targetValue, EaseOutQuad(ct))).ToString();
yield return null;
}
}
txt.text = targetValue.ToString();
}
// ============================================================
void PlaySFX()
{
if (sfx && clickSound)
sfx.PlayOneShot(clickSound);
}
// ============================================================
void Retry()
{
// 🔥 Mod11 oyun sahnesine geri dön
SceneManager.LoadScene("Mod11");
}
// ============================================================
void ExitToMenu()
{
SceneManager.LoadScene("Anamen");
}
// ============================================================
float EaseOutBack(float t)
{
t = Mathf.Clamp01(t);
float c1 = 1.70158f, 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);
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 1781e8376e88df94187d95b3c65889d3

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 792af35de8483a3408d24c7c79e3e76b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,144 @@
using System.Collections;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class Mod12Resume : MonoBehaviour
{
[Header("UI TEXTS (ONLY NUMBERS)")]
public TMP_Text scoreText;
public TMP_Text maxScoreText;
public TMP_Text correctText;
public TMP_Text wrongText;
[Header("BUTTONS")]
public Button retryButton;
public Button exitButton;
[Header("AUDIO")]
public AudioSource sfx;
public AudioClip clickSound;
[Header("━━━ ANIMATION SETTINGS ━━━━━━━━━━━━━━━━━")]
public float countUpDuration = 0.8f;
public float popInDelay = 0.08f;
public float popInTime = 0.3f;
private string modKey = "Mod12";
private int score;
private int maxScore;
private int correct;
private int wrong;
void Start()
{
LoadResults();
PrepareTexts();
if (retryButton)
retryButton.onClick.AddListener(() => { PlaySFX(); Retry(); });
if (exitButton)
exitButton.onClick.AddListener(() => { PlaySFX(); ExitToMenu(); });
StartCoroutine(PlayRevealSequence());
}
void LoadResults()
{
score = PlayerPrefs.GetInt(modKey + "_Score", 0);
maxScore = PlayerPrefs.GetInt(modKey + "_MaxScore", 0);
correct = PlayerPrefs.GetInt(modKey + "_Correct", 0);
wrong = PlayerPrefs.GetInt(modKey + "_Wrong", 0);
Debug.Log($"[MOD12 RESULT] Score={score} | Max={maxScore} | Correct={correct} | Wrong={wrong}");
}
void PrepareTexts()
{
SetTextZero(scoreText);
SetTextZero(maxScoreText);
SetTextZero(correctText);
SetTextZero(wrongText);
}
void SetTextZero(TMP_Text txt)
{
if (txt == null) return;
txt.text = "0";
txt.transform.localScale = Vector3.zero;
}
IEnumerator PlayRevealSequence()
{
yield return StartCoroutine(RevealStat(scoreText, score));
yield return new WaitForSeconds(popInDelay);
yield return StartCoroutine(RevealStat(maxScoreText, maxScore));
yield return new WaitForSeconds(popInDelay);
yield return StartCoroutine(RevealStat(correctText, correct));
yield return new WaitForSeconds(popInDelay);
yield return StartCoroutine(RevealStat(wrongText, wrong));
}
IEnumerator RevealStat(TMP_Text txt, int targetValue)
{
if (txt == null) yield break;
float t = 0f;
while (t < 1f)
{
t += Time.deltaTime / Mathf.Max(0.01f, popInTime);
txt.transform.localScale = Vector3.Lerp(Vector3.zero, Vector3.one, EaseOutBack(t));
if (targetValue == 0) txt.text = "0";
yield return null;
}
txt.transform.localScale = Vector3.one;
if (targetValue > 0)
{
float ct = 0f;
while (ct < 1f)
{
ct += Time.deltaTime / Mathf.Max(0.01f, countUpDuration);
txt.text = Mathf.RoundToInt(Mathf.Lerp(0, targetValue, EaseOutQuad(ct))).ToString();
yield return null;
}
}
txt.text = targetValue.ToString();
}
void PlaySFX()
{
if (sfx && clickSound)
sfx.PlayOneShot(clickSound);
}
void Retry()
{
SceneManager.LoadScene("Mod12");
}
void ExitToMenu()
{
SceneManager.LoadScene("Anamen");
}
float EaseOutBack(float t)
{
t = Mathf.Clamp01(t);
float c1 = 1.70158f, 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);
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 569283d0e752d7f4484717cd84e953c7

View file

@ -0,0 +1,662 @@
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<WordPair> words = new List<WordPair>();
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);
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 59d2c4636dd071b498167e354fc0b612

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0b4d822743fa66c4a8c54880728ec78c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,164 @@
using System.Collections;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class Mod7Resume : MonoBehaviour
{
[Header("UI TEXTS (ONLY NUMBERS)")]
public TMP_Text scoreText;
public TMP_Text maxScoreText;
public TMP_Text correctText;
public TMP_Text wrongText;
[Header("BUTTONS")]
public Button retryButton;
public Button exitButton;
[Header("AUDIO")]
public AudioSource sfx;
public AudioClip clickSound;
[Header("━━━ ANIMATION SETTINGS ━━━━━━━━━━━━━━━━━")]
public float countUpDuration = 0.8f;
public float popInDelay = 0.08f;
public float popInTime = 0.3f;
private string modKey = "Mod7";
private int score;
private int maxScore;
private int correct;
private int wrong;
void Start()
{
LoadResults();
PrepareTexts();
if (retryButton != null)
retryButton.onClick.AddListener(() => { PlaySFX(); Retry(); });
if (exitButton != null)
exitButton.onClick.AddListener(() => { PlaySFX(); ExitToMenu(); });
StartCoroutine(PlayRevealSequence());
}
// ---------------------------------------------------------------
void LoadResults()
{
score = PlayerPrefs.GetInt(modKey + "_LastScore", 0);
maxScore = PlayerPrefs.GetInt(modKey + "_MaxScore", 0);
correct = PlayerPrefs.GetInt(modKey + "_Correct", 0);
wrong = PlayerPrefs.GetInt(modKey + "_Wrong", 0);
}
// ---------------------------------------------------------------
void PrepareTexts()
{
SetTextZero(scoreText);
SetTextZero(maxScoreText);
SetTextZero(correctText);
SetTextZero(wrongText);
}
void SetTextZero(TMP_Text txt)
{
if (txt == null) return;
txt.text = "0";
txt.transform.localScale = Vector3.zero;
}
// ---------------------------------------------------------------
IEnumerator PlayRevealSequence()
{
yield return StartCoroutine(RevealStat(scoreText, score));
yield return new WaitForSeconds(popInDelay);
yield return StartCoroutine(RevealStat(maxScoreText, maxScore));
yield return new WaitForSeconds(popInDelay);
yield return StartCoroutine(RevealStat(correctText, correct));
yield return new WaitForSeconds(popInDelay);
yield return StartCoroutine(RevealStat(wrongText, wrong));
}
IEnumerator RevealStat(TMP_Text txt, int targetValue)
{
if (txt == null) yield break;
// pop-in scale
Vector3 normal = Vector3.one;
float t = 0f;
while (t < 1f)
{
t += Time.deltaTime / Mathf.Max(0.01f, popInTime);
txt.transform.localScale = Vector3.Lerp(Vector3.zero, normal, EaseOutBack(t));
if (targetValue == 0)
txt.text = "0";
yield return null;
}
txt.transform.localScale = normal;
// count-up
if (targetValue > 0)
{
float ct = 0f;
while (ct < 1f)
{
ct += Time.deltaTime / Mathf.Max(0.01f, countUpDuration);
int shown = Mathf.RoundToInt(Mathf.Lerp(0, targetValue, EaseOutQuad(ct)));
txt.text = shown.ToString();
yield return null;
}
}
txt.text = targetValue.ToString();
}
// ---------------------------------------------------------------
void PlaySFX()
{
if (sfx && clickSound)
sfx.PlayOneShot(clickSound);
}
// ---------------------------------------------------------------
void Retry()
{
// 🔥 Mod 7 oyun sahnesine dön
SceneManager.LoadScene("Mod7");
}
// ---------------------------------------------------------------
void ExitToMenu()
{
SceneManager.LoadScene("Anamen");
}
// ---------------------------------------------------------------
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);
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 56be283e892927547817c76f96c0329e

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: e08b0cfd78da3f94b9cd70dfecc1eca4

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3d888a15222d70a4ab1849caa1545618
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,126 @@
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using UnityEngine.SceneManagement;
public class Mod9Resume : MonoBehaviour
{
[Header("UI TEXTS")]
public TMP_Text scoreText;
public TMP_Text maxScoreText;
public TMP_Text correctText;
public TMP_Text wrongText;
[Header("BUTTONS")]
public Button retryButton;
public Button exitButton;
[Header("AUDIO")]
public AudioSource sfx;
public AudioClip clickSound;
[Header("━━━ ANIMATION SETTINGS ━━━━━━━━━━━━━━━━━")]
public float countUpDuration = 0.8f;
public float popInDelay = 0.08f;
public float popInTime = 0.3f;
private string modKey = "Mod9_Synonym";
int score, maxScore, correct, wrong;
void Start()
{
LoadResults();
PrepareTexts();
retryButton.onClick.AddListener(() => { PlaySFX(); SceneManager.LoadScene("Mod9"); });
exitButton.onClick.AddListener(() => { PlaySFX(); SceneManager.LoadScene("Anamen"); });
StartCoroutine(PlayRevealSequence());
}
void LoadResults()
{
score = PlayerPrefs.GetInt(modKey + "_LastScore", 0);
maxScore = PlayerPrefs.GetInt(modKey + "_MaxScore", 0);
correct = PlayerPrefs.GetInt(modKey + "_Correct", 0);
wrong = PlayerPrefs.GetInt(modKey + "_Wrong", 0);
}
void PrepareTexts()
{
SetTextZero(scoreText);
SetTextZero(maxScoreText);
SetTextZero(correctText);
SetTextZero(wrongText);
}
void SetTextZero(TMP_Text txt)
{
if (txt == null) return;
txt.text = "0";
txt.transform.localScale = Vector3.zero;
}
IEnumerator PlayRevealSequence()
{
yield return StartCoroutine(RevealStat(scoreText, score));
yield return new WaitForSeconds(popInDelay);
yield return StartCoroutine(RevealStat(maxScoreText, maxScore));
yield return new WaitForSeconds(popInDelay);
yield return StartCoroutine(RevealStat(correctText, correct));
yield return new WaitForSeconds(popInDelay);
yield return StartCoroutine(RevealStat(wrongText, wrong));
}
IEnumerator RevealStat(TMP_Text txt, int targetValue)
{
if (txt == null) yield break;
float t = 0f;
while (t < 1f)
{
t += Time.deltaTime / Mathf.Max(0.01f, popInTime);
txt.transform.localScale = Vector3.Lerp(Vector3.zero, Vector3.one, EaseOutBack(t));
if (targetValue == 0) txt.text = "0";
yield return null;
}
txt.transform.localScale = Vector3.one;
if (targetValue > 0)
{
float ct = 0f;
while (ct < 1f)
{
ct += Time.deltaTime / Mathf.Max(0.01f, countUpDuration);
txt.text = Mathf.RoundToInt(Mathf.Lerp(0, targetValue, EaseOutQuad(ct))).ToString();
yield return null;
}
}
txt.text = targetValue.ToString();
}
void PlaySFX()
{
if (sfx && clickSound)
sfx.PlayOneShot(clickSound);
}
float EaseOutBack(float t)
{
t = Mathf.Clamp01(t);
float c1 = 1.70158f, 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);
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 6f34180d9fade5c4fa76a9c5939efad7

View file

@ -0,0 +1,844 @@
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine.SceneManagement;
public class WordMatchMod9 : MonoBehaviour
{
[Header("UI - QUESTIONS (LEFT)")]
[SerializeField] private Button[] questionButtons;
[SerializeField] private TMP_Text[] questionTexts;
[Header("UI - ANSWERS (RIGHT)")]
[SerializeField] private Button[] answerButtons;
[SerializeField] private TMP_Text[] answerTexts;
[Header("UI - OTHER")]
[SerializeField] private Button submitButton;
[SerializeField] private TMP_Text scoreText;
[SerializeField] private TMP_Text comboText;
[SerializeField] private TMP_Text timeText;
[SerializeField] private TMP_Text feedbackText;
[Header("━━━ BACK BUTTON ━━━━━━━━━━━━━━━━━━━━━━━━")]
public Button backButton;
public string backSceneName = "ModSec 9";
[Header("WORD DATA")]
[SerializeField] private TextAsset synonymFile;
[Header("COLORS")]
public Color baseColor = new Color32(230, 230, 230, 255);
public Color[] pairColors = new Color[]
{
new Color32(120,180,255,255),
new Color32(255,200,120,255),
new Color32(160,255,160,255),
new Color32(255,150,150,255),
new Color32(210,150,255,255),
};
public Color correctColor = new Color32(0, 160, 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;
public float enterAnimTime = 0.22f;
Dictionary<string, string> activeMap = new Dictionary<string, string>();
int[] questionToAnswer = new int[5];
int[] questionColorIdx = new int[5];
int[] answerColorIdx = new int[5];
int selectedQuestion = -1;
float timeLeft = 90f;
bool isTimeUp = false;
bool isRoundProcessing = false;
int score = 0;
int combo = 0;
int correctCount = 0;
int wrongCount = 0;
List<KeyValuePair<string, string>> selectedPairs = new List<KeyValuePair<string, string>>();
string modKey = "Mod9_Synonym";
private string qLang;
readonly Color timerNormalColor = Color.white;
readonly Color timerWarnColor = new Color32(255, 80, 80, 255);
Vector3[] questionOriginalScales;
Vector3[] answerOriginalScales;
Vector3[] questionOriginalPositions;
Vector3[] answerOriginalPositions;
Coroutine[] questionScaleCo;
Coroutine[] answerScaleCo;
Coroutine[] questionEnterCo;
Coroutine[] answerEnterCo;
Coroutine feedbackCo;
// ---------------------------------------------------------
void Start()
{
qLang = PlayerPrefs.GetString("QuestionLangCode", "en");
LoadSynonymFile();
CacheButtonData();
PrepareFeedbackText();
if (submitButton != null)
{
submitButton.onClick.RemoveAllListeners();
submitButton.onClick.AddListener(OnSubmit);
}
if (backButton != null)
{
backButton.onClick.RemoveAllListeners();
backButton.onClick.AddListener(() => SceneManager.LoadScene(backSceneName));
}
ResetMaps();
LoadRound();
scoreText.text = score.ToString();
comboText.text = combo + "x";
timeLeft = 90f;
isTimeUp = false;
}
// ---------------------------------------------------------
void Update()
{
if (isTimeUp)
{
UpdateTimerUI();
return;
}
timeLeft -= Time.deltaTime;
if (timeLeft < 0f) timeLeft = 0f;
UpdateTimerUI();
if (timeLeft <= 0f)
{
isTimeUp = true;
ProcessSubmit(true);
StartCoroutine(GoResume());
}
}
// ---------------------------------------------------------
void UpdateTimerUI()
{
if (timeText == null) return;
timeText.text = Mathf.CeilToInt(timeLeft).ToString();
if (timeLeft <= 10f)
{
timeText.color = FullAlpha(Color.Lerp(timerWarnColor, Color.white, Mathf.PingPong(Time.time * 3f, 1f)));
timeText.transform.localScale = Vector3.one * (1f + Mathf.Sin(Time.time * 10f) * 0.05f);
}
else
{
timeText.color = FullAlpha(timerNormalColor);
timeText.transform.localScale = Vector3.one;
}
}
// ---------------------------------------------------------
void LoadSynonymFile()
{
activeMap.Clear();
if (synonymFile == null)
{
Debug.LogError("Mod9: synonymFile atanmadı!");
return;
}
string[] lines = synonymFile.text.Split('\n');
int li = LangIndex(qLang);
for (int i = 0; i + 1 < lines.Length; i += 2)
{
string A = lines[i].Trim();
string B = lines[i + 1].Trim();
if (string.IsNullOrWhiteSpace(A) || string.IsNullOrWhiteSpace(B)) continue;
if (!A.Contains(",") || !B.Contains(",")) continue;
string[] wA = A.Split(',');
string[] wB = B.Split(',');
if (wA.Length < 6 || wB.Length < 6) continue;
string q = wA[li].Trim();
string a = wB[li].Trim();
if (!activeMap.ContainsKey(q))
activeMap.Add(q, a);
}
}
int LangIndex(string c)
{
switch (c)
{
case "tr": return 0;
case "en": return 1;
case "es": return 2;
case "de": return 3;
case "fr": return 4;
case "pt": return 5;
}
return 1;
}
// ---------------------------------------------------------
void CacheButtonData()
{
int n = questionButtons.Length;
questionOriginalScales = new Vector3[n];
answerOriginalScales = new Vector3[n];
questionOriginalPositions = new Vector3[n];
answerOriginalPositions = new Vector3[n];
questionScaleCo = new Coroutine[n];
answerScaleCo = new Coroutine[n];
questionEnterCo = new Coroutine[n];
answerEnterCo = new Coroutine[n];
for (int i = 0; i < n; i++)
{
if (questionButtons[i] != null)
{
questionOriginalScales[i] = questionButtons[i].transform.localScale;
questionOriginalPositions[i] = questionButtons[i].transform.localPosition;
questionButtons[i].transition = Selectable.Transition.None;
}
if (answerButtons[i] != null)
{
answerOriginalScales[i] = answerButtons[i].transform.localScale;
answerOriginalPositions[i] = answerButtons[i].transform.localPosition;
answerButtons[i].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 LoadRound()
{
ResetVisuals();
ResetMaps();
isRoundProcessing = false;
var all = activeMap.ToList();
Shuffle(all);
selectedPairs = all.Take(5).ToList();
for (int i = 0; i < 5; i++)
{
questionTexts[i].text = selectedPairs[i].Key;
int id = i;
questionButtons[i].onClick.RemoveAllListeners();
questionButtons[i].onClick.AddListener(() => SelectQuestion(id));
}
List<string> answers = selectedPairs.Select(p => p.Value).ToList();
Shuffle(answers);
for (int i = 0; i < 5; i++)
{
answerTexts[i].text = answers[i];
int id = i;
answerButtons[i].onClick.RemoveAllListeners();
answerButtons[i].onClick.AddListener(() => SelectAnswer(id));
}
for (int i = 0; i < 5; i++)
{
if (questionEnterCo[i] != null) StopCoroutine(questionEnterCo[i]);
questionEnterCo[i] = StartCoroutine(ButtonEnterAnim(questionButtons[i], questionOriginalScales[i], questionOriginalPositions[i], i, -1));
if (answerEnterCo[i] != null) StopCoroutine(answerEnterCo[i]);
answerEnterCo[i] = StartCoroutine(ButtonEnterAnim(answerButtons[i], answerOriginalScales[i], answerOriginalPositions[i], i, 1));
if (questionTexts[i] != null) StartCoroutine(FadeInText(questionTexts[i]));
if (answerTexts[i] != null) StartCoroutine(FadeInText(answerTexts[i]));
}
}
// ---------------------------------------------------------
void ResetVisuals()
{
for (int i = 0; i < 5; i++)
{
StopButtonAnims(i);
questionButtons[i].image.color = FullAlpha(baseColor);
answerButtons[i].image.color = FullAlpha(baseColor);
questionButtons[i].transform.localScale = questionOriginalScales[i];
answerButtons[i].transform.localScale = answerOriginalScales[i];
questionButtons[i].transform.localPosition = questionOriginalPositions[i];
answerButtons[i].transform.localPosition = answerOriginalPositions[i];
}
if (feedbackText != null) feedbackText.text = "";
}
void StopButtonAnims(int i)
{
if (questionScaleCo[i] != null) { StopCoroutine(questionScaleCo[i]); questionScaleCo[i] = null; }
if (answerScaleCo[i] != null) { StopCoroutine(answerScaleCo[i]); answerScaleCo[i] = null; }
if (questionEnterCo[i] != null) { StopCoroutine(questionEnterCo[i]); questionEnterCo[i] = null; }
if (answerEnterCo[i] != null) { StopCoroutine(answerEnterCo[i]); answerEnterCo[i] = null; }
}
void ResetMaps()
{
for (int i = 0; i < 5; i++)
{
questionToAnswer[i] = -1;
questionColorIdx[i] = -1;
answerColorIdx[i] = -1;
}
}
// ---------------------------------------------------------
void SelectQuestion(int q)
{
if (isRoundProcessing || isTimeUp) return;
selectedQuestion = q;
StartScaleAnim(questionButtons, questionScaleCo, questionOriginalScales, q, questionOriginalScales[q] * selectedScale);
}
void SelectAnswer(int a)
{
if (isRoundProcessing || isTimeUp) return;
if (selectedQuestion == -1) return;
int prevQuestion = selectedQuestion;
if (questionToAnswer[selectedQuestion] == a)
{
questionToAnswer[selectedQuestion] = -1;
questionColorIdx[selectedQuestion] = -1;
answerColorIdx[a] = -1;
RefreshColors();
selectedQuestion = -1;
ResetScaleAnim(questionButtons, questionScaleCo, questionOriginalScales, prevQuestion);
ResetScaleAnim(answerButtons, answerScaleCo, answerOriginalScales, a);
return;
}
for (int i = 0; i < 5; i++)
{
if (questionToAnswer[i] == a && i != selectedQuestion)
{
questionToAnswer[i] = -1;
questionColorIdx[i] = -1;
ResetScaleAnim(questionButtons, questionScaleCo, questionOriginalScales, i);
}
}
int oldA = questionToAnswer[selectedQuestion];
if (oldA != -1)
{
answerColorIdx[oldA] = -1;
ResetScaleAnim(answerButtons, answerScaleCo, answerOriginalScales, oldA);
}
questionToAnswer[selectedQuestion] = a;
int c = selectedQuestion % pairColors.Length;
questionColorIdx[selectedQuestion] = c;
answerColorIdx[a] = c;
RefreshColors();
StartCoroutine(PairPulse(prevQuestion, a));
ResetScaleAnim(questionButtons, questionScaleCo, questionOriginalScales, prevQuestion);
selectedQuestion = -1;
}
void RefreshColors()
{
for (int i = 0; i < 5; i++)
{
questionButtons[i].image.color =
questionColorIdx[i] == -1 ? FullAlpha(baseColor) : FullAlpha(pairColors[questionColorIdx[i]]);
answerButtons[i].image.color =
answerColorIdx[i] == -1 ? FullAlpha(baseColor) : FullAlpha(pairColors[answerColorIdx[i]]);
}
}
// ---------------------------------------------------------
void OnSubmit()
{
if (isRoundProcessing || isTimeUp) return;
ProcessSubmit(false);
}
void ProcessSubmit(bool fromTimeout)
{
isRoundProcessing = true;
int roundCorrect = 0;
for (int q = 0; q < 5; q++)
{
int a = questionToAnswer[q];
if (a == -1)
{
questionButtons[q].image.color = FullAlpha(wrongColor);
StartCoroutine(ShakeButton(questionButtons[q], questionOriginalPositions[q]));
wrongCount++;
continue;
}
string qWord = questionTexts[q].text;
string correctA = activeMap[qWord];
string chosenA = answerTexts[a].text;
if (chosenA == correctA)
{
roundCorrect++;
correctCount++;
questionButtons[q].image.color = FullAlpha(correctColor);
answerButtons[a].image.color = FullAlpha(correctColor);
StartCoroutine(CorrectPulse(questionButtons[q], questionOriginalScales[q]));
StartCoroutine(CorrectPulse(answerButtons[a], answerOriginalScales[a]));
}
else
{
wrongCount++;
questionButtons[q].image.color = FullAlpha(wrongColor);
answerButtons[a].image.color = FullAlpha(wrongColor);
StartCoroutine(ShakeButton(questionButtons[q], questionOriginalPositions[q]));
StartCoroutine(ShakeButton(answerButtons[a], answerOriginalPositions[a]));
}
}
int gained = roundCorrect * 20;
score += gained;
Color feedbackColor;
if (roundCorrect == 5)
{
combo++;
feedbackText.text = combo >= 2 ? $"PERFECT! {combo}x COMBO!" : "PERFECT!";
feedbackColor = correctColor;
}
else if (roundCorrect > 0)
{
combo = 0;
feedbackText.text = "+" + gained + " Points";
feedbackColor = correctColor;
}
else
{
combo = 0;
feedbackText.text = "Try Again!";
feedbackColor = wrongColor;
}
feedbackText.color = FullAlpha(feedbackColor);
if (feedbackOnTop)
{
Vector3 pos = feedbackText.transform.localPosition;
pos.y = feedbackTopY;
feedbackText.transform.localPosition = pos;
}
if (feedbackCo != null) StopCoroutine(feedbackCo);
feedbackCo = StartCoroutine(FeedbackAnim(feedbackText));
scoreText.text = score.ToString();
comboText.text = combo + "x";
if (scoreText != null) StartCoroutine(ScorePopAnim(scoreText));
if (combo > 0 && comboText != null) StartCoroutine(ComboAnim(comboText));
SaveProgress();
if (!fromTimeout)
StartCoroutine(NextRound());
}
// ---------------------------------------------------------
void SaveProgress()
{
// 🔥 Mod Select / Leaderboard ekranına direkt bağlanacak basit key
PlayerPrefs.SetInt("Mod9Skor", score);
PlayerPrefs.SetInt(modKey + "_LastScore", score);
int best = PlayerPrefs.GetInt(modKey + "_MaxScore", 0);
if (score > best)
PlayerPrefs.SetInt(modKey + "_MaxScore", score);
PlayerPrefs.SetInt(modKey + "_Correct", correctCount);
PlayerPrefs.SetInt(modKey + "_Wrong", wrongCount);
PlayerPrefs.Save();
}
IEnumerator NextRound()
{
yield return new WaitForSeconds(0.8f);
LoadRound();
}
IEnumerator GoResume()
{
yield return new WaitForSeconds(1f);
SceneManager.LoadScene("Mod9Resume");
}
void Shuffle<T>(List<T> list)
{
for (int i = list.Count - 1; i > 0; i--)
{
int j = Random.Range(0, i + 1);
(list[i], list[j]) = (list[j], list[i]);
}
}
// ================== ANIMATION HELPERS ==================
void StartScaleAnim(Button[] buttons, Coroutine[] coArr, Vector3[] originalScales, int idx, Vector3 targetScale)
{
if (idx < 0 || idx >= buttons.Length || buttons[idx] == null) return;
if (coArr[idx] != null) StopCoroutine(coArr[idx]);
coArr[idx] = StartCoroutine(ScaleButton(buttons[idx], targetScale, idx, coArr));
}
void ResetScaleAnim(Button[] buttons, Coroutine[] coArr, Vector3[] originalScales, int idx)
{
if (idx < 0 || idx >= buttons.Length || buttons[idx] == null) return;
StartScaleAnim(buttons, coArr, originalScales, idx, originalScales[idx]);
}
IEnumerator ScaleButton(Button btn, Vector3 targetScale, int idx, Coroutine[] coArr)
{
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;
coArr[idx] = null;
}
IEnumerator ButtonEnterAnim(Button btn, Vector3 targetScale, Vector3 targetPos, int delayIndex, int sideSign)
{
if (btn == null) yield break;
yield return new WaitForSeconds(delayIndex * 0.05f);
Vector3 startPos = targetPos + new Vector3(sideSign * 40f, 0f, 0f);
Vector3 startScale = targetScale * 0.85f;
btn.transform.localPosition = startPos;
btn.transform.localScale = startScale;
float t = 0f;
while (t < 1f)
{
t += Time.deltaTime / Mathf.Max(0.01f, enterAnimTime);
float ease = EaseOutBack(t);
btn.transform.localPosition = Vector3.Lerp(startPos, targetPos, ease);
btn.transform.localScale = Vector3.Lerp(startScale, targetScale, ease);
yield return null;
}
btn.transform.localPosition = targetPos;
btn.transform.localScale = targetScale;
}
IEnumerator PairPulse(int questionIdx, int answerIdx)
{
if (questionIdx >= 0 && questionIdx < questionButtons.Length)
yield return StartCoroutine(QuickPulse(questionButtons[questionIdx].transform, questionOriginalScales[questionIdx]));
if (answerIdx >= 0 && answerIdx < answerButtons.Length)
yield return StartCoroutine(QuickPulse(answerButtons[answerIdx].transform, answerOriginalScales[answerIdx]));
}
IEnumerator QuickPulse(Transform tr, Vector3 normal)
{
if (tr == null) yield break;
Vector3 big = normal * 1.08f;
float t = 0f;
while (t < 1f)
{
t += Time.deltaTime / 0.08f;
tr.localScale = Vector3.Lerp(normal, big, EaseOutQuad(t));
yield return null;
}
t = 0f;
while (t < 1f)
{
t += Time.deltaTime / 0.08f;
tr.localScale = Vector3.Lerp(big, normal, EaseOutQuad(t));
yield return null;
}
tr.localScale = normal;
}
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, magnitude = 12f, 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 baseC = 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(baseC, 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, baseC, t));
yield return null;
}
txt.transform.localScale = original;
txt.color = baseC;
}
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;
}
Color FullAlpha(Color c)
{
c.a = 1f;
return c;
}
float EaseOutBack(float t)
{
t = Mathf.Clamp01(t);
float c1 = 1.70158f, 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);
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: ebec7d06e1d313b43a00264a336593c9