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:
commit
ecb1c9edea
1455 changed files with 933295 additions and 0 deletions
8
Assets/Scripts/2.0.meta
Normal file
8
Assets/Scripts/2.0.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c010e549562230f489cf0bdcea04c3e2
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1127
Assets/Scripts/2.0/GalaxyGameScene.cs
Normal file
1127
Assets/Scripts/2.0/GalaxyGameScene.cs
Normal file
File diff suppressed because it is too large
Load diff
2
Assets/Scripts/2.0/GalaxyGameScene.cs.meta
Normal file
2
Assets/Scripts/2.0/GalaxyGameScene.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 59b9a2ac56496444bac7b43b2c8e916d
|
||||
1134
Assets/Scripts/2.0/LLGameScene.cs
Normal file
1134
Assets/Scripts/2.0/LLGameScene.cs
Normal file
File diff suppressed because it is too large
Load diff
2
Assets/Scripts/2.0/LLGameScene.cs.meta
Normal file
2
Assets/Scripts/2.0/LLGameScene.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 77da8ebed4f07fe4fad686635f694c51
|
||||
86
Assets/Scripts/2.0/LanguageSettingsController.cs
Normal file
86
Assets/Scripts/2.0/LanguageSettingsController.cs
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using TMPro;
|
||||
using UnityEngine.SceneManagement;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class LanguageSettingsController : MonoBehaviour
|
||||
{
|
||||
[Header("━━━ DROPDOWNLAR ━━━━━━━━━━━━━━━━━━━━━━━")]
|
||||
public TMP_Dropdown questionDropdown;
|
||||
public TMP_Dropdown answerDropdown;
|
||||
|
||||
[Header("━━━ BUTONLAR ━━━━━━━━━━━━━━━━━━━━━━━━━━")]
|
||||
public Button saveAndBackButton;
|
||||
|
||||
[Header("━━━ AUDIO ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")]
|
||||
public AudioClip clickSound;
|
||||
public AudioSource sfxSource;
|
||||
|
||||
void Start()
|
||||
{
|
||||
PopulateDropdowns();
|
||||
|
||||
questionDropdown.value = PlayerPrefs.GetInt("QuestionLangID", 1);
|
||||
answerDropdown.value = PlayerPrefs.GetInt("AnswerLangID", 0);
|
||||
|
||||
questionDropdown.RefreshShownValue();
|
||||
answerDropdown.RefreshShownValue();
|
||||
|
||||
saveAndBackButton.onClick.AddListener(() => { PlayClick(); SaveAndBack(); });
|
||||
}
|
||||
|
||||
void PopulateDropdowns()
|
||||
{
|
||||
List<string> languageNames = new List<string>
|
||||
{
|
||||
"Türkçe", // 0
|
||||
"English", // 1
|
||||
"Español", // 2
|
||||
"Deutsch", // 3
|
||||
"Français", // 4
|
||||
"Português" // 5
|
||||
};
|
||||
|
||||
questionDropdown.ClearOptions();
|
||||
answerDropdown.ClearOptions();
|
||||
|
||||
questionDropdown.AddOptions(languageNames);
|
||||
answerDropdown.AddOptions(languageNames);
|
||||
}
|
||||
|
||||
void SaveAndBack()
|
||||
{
|
||||
int qID = questionDropdown.value;
|
||||
int aID = answerDropdown.value;
|
||||
|
||||
PlayerPrefs.SetInt("QuestionLangID", qID);
|
||||
PlayerPrefs.SetInt("AnswerLangID", aID);
|
||||
PlayerPrefs.SetString("QuestionLangCode", ToCode(qID));
|
||||
PlayerPrefs.SetString("AnswerLangCode", ToCode(aID));
|
||||
PlayerPrefs.SetString("AppLanguage", ToCode(qID));
|
||||
PlayerPrefs.Save();
|
||||
|
||||
SceneManager.LoadScene("Anamen");
|
||||
}
|
||||
|
||||
void PlayClick()
|
||||
{
|
||||
if (sfxSource != null && clickSound != null)
|
||||
sfxSource.PlayOneShot(clickSound);
|
||||
}
|
||||
|
||||
string ToCode(int id)
|
||||
{
|
||||
return id switch
|
||||
{
|
||||
0 => "tr",
|
||||
1 => "en",
|
||||
2 => "es",
|
||||
3 => "de",
|
||||
4 => "fr",
|
||||
5 => "pt",
|
||||
_ => "en"
|
||||
};
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/2.0/LanguageSettingsController.cs.meta
Normal file
2
Assets/Scripts/2.0/LanguageSettingsController.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3cbf52aaa9ea95145b92e9f010db66dd
|
||||
11
Assets/Scripts/2.0/LanguageType.cs
Normal file
11
Assets/Scripts/2.0/LanguageType.cs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
using UnityEngine;
|
||||
|
||||
public enum LanguageType
|
||||
{
|
||||
TR = 1,
|
||||
EN = 2,
|
||||
ES = 3,
|
||||
DE = 4,
|
||||
FR = 5,
|
||||
PT = 6
|
||||
}
|
||||
2
Assets/Scripts/2.0/LanguageType.cs.meta
Normal file
2
Assets/Scripts/2.0/LanguageType.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 32b83b44bd3dd0d4a8f5186eaf12aeca
|
||||
220
Assets/Scripts/2.0/LevelSelectController.cs
Normal file
220
Assets/Scripts/2.0/LevelSelectController.cs
Normal file
|
|
@ -0,0 +1,220 @@
|
|||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using TMPro;
|
||||
using UnityEngine.SceneManagement;
|
||||
using System.Collections;
|
||||
|
||||
public class LevelSelectController : MonoBehaviour
|
||||
{
|
||||
[Header("━━━ UI ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")]
|
||||
public Button[] levelButtons;
|
||||
public TMP_Text[] levelNameTexts;
|
||||
public TMP_Text[] levelScoreTexts;
|
||||
|
||||
[Header("━━━ BACK BUTONU ━━━━━━━━━━━━━━━━━━━━━━━")]
|
||||
public Button backButton;
|
||||
public string backSceneName = "Anamen";
|
||||
|
||||
[Header("━━━ AUDIO ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")]
|
||||
public AudioSource sfxSource;
|
||||
public AudioClip clickSound;
|
||||
|
||||
[Header("━━━ ANİMASYON ━━━━━━━━━━━━━━━━━━━━━━━━━")]
|
||||
[Range(0.005f, 0.1f)] public float buttonAniSpeed = 0.02f;
|
||||
|
||||
private int langIndex;
|
||||
private Vector3[] originalScales;
|
||||
private Vector3[] originalPositions;
|
||||
|
||||
// ============================================================
|
||||
private readonly string[,] levelNames = new string[,]
|
||||
{
|
||||
{ "Temel Selamlaşma ve İnsanlar","Basic Greetings & People","Saludos Básicos y Personas","Grundbegrüßungen & Menschen","Salutations de Base & Personnes","Saudações Básicas e Pessoas" },
|
||||
{ "Günlük Ev Nesneleri","Daily Household Items","Objetos del Hogar Diarios","Tägliche Haushaltsgegenstände","Objets Quotidiens de la Maison","Objetos Domésticos Diários" },
|
||||
{ "Yiyecekler ve İçecekler","Food & Drinks","Comida y Bebida","Essen & Getränke","Nourriture & Boissons","Comidas e Bebidas" },
|
||||
{ "Renkler, Şekiller ve Boyutlar","Colors, Shapes & Sizes","Colores, Formas y Tamaños","Farben, Formen & Größen","Couleurs, Formas & Tailles","Cores, Formas e Tamanhos" },
|
||||
{ "Zaman, Günler ve Mevsimler","Time, Days & Seasons","Tiempo, Días y Estaciones","Zeit, Tage & Jahreszeiten","Temps, Jours & Saisons","Tempo, Dias e Estações" },
|
||||
{ "Ev İçi Alanlar ve Temizlik","Home Areas & Cleaning","Áreas del Hogar y Limpieza","Hausbereiche & Reinigung","Espaces de Maison & Nettoyage","Áreas da Casa e Limpeza" },
|
||||
{ "Okul, Eğitim ve Ders Araçları","School, Education & Supplies","Escuela, Educación y Útiles","Schule, Bildung & Materialien","École, Éducation & Fournitures","Escola, Educação e Materiais" },
|
||||
{ "Vücut Parçaları ve Sağlık","Body Parts & Health","Partes del Cuerpo y Salud","Körperteile & Gesundheit","Parties du Corps & Santé","Partes do Corpo e Saúde" },
|
||||
{ "Doğa, Hava ve Çevre Unsurları","Nature, Weather & Environment","Naturaleza, Clima y Medio Ambiente","Natur, Wetter & Umwelt","Nature, Météo & Environnement","Natureza, Clima e Meio Ambiente" },
|
||||
{ "Evcil ve Vahşi Hayvanlar","Pets & Wild Animals","Mascotas y Animales Salvajes","Haustiere & Wildtiere","Animaux Domestiques & Sauvages","Animais Domésticos e Selvagens" },
|
||||
{ "Ulaşım Araçları ve Trafik","Transportation & Traffic","Transporte y Tráfico","Transport & Verkehr","Transport & Circulation","Transporte e Trânsito" },
|
||||
{ "Alışveriş ve Mağazalar","Shopping & Stores","Compras y Tiendas","Einkaufen & Geschäfte","Shopping & Magasins","Compras e Lojas" },
|
||||
{ "Spor Dalları ve Ekipmanları","Sports & Equipment","Deportes y Equipamiento","Sportarten & Ausrüstung","Sports & Équipement","Esportes e Equipamentos" },
|
||||
{ "Meslekler ve İş Alanları","Jobs & Work Fields","Profesiones y Áreas Laborales","Berufe & Arbeitsfelder","Métiers & Domaines de Travail","Profissões e Áreas de Trabalho" },
|
||||
{ "Şehir, Yerler ve Binalar","City, Places & Buildings","Ciudad, Lugares y Edificios","Stadt, Orte & Gebäude","Ville, Lieux & Bâtiments","Cidade, Lugares e Edifícios" },
|
||||
{ "Duygular, Durumlar ve Karakter","Emotions, States & Character","Emociones, Estados y Carácter","Gefühle, Zustände & Charakter","Émotions, États & Caractère","Emoções, Estados e Caráter" },
|
||||
{ "Seyahat, Tatil ve Turizm","Travel, Vacation & Tourism","Viajes, Vacaciones y Turismo","Reisen, Urlaub & Tourismus","Voyage, Vacances & Tourisme","Viagem, Férias e Turismo" },
|
||||
{ "Teknoloji, İnternet ve Cihazlar","Technology, Internet & Devices","Tecnología, Internet y Dispositivos","Technologie, Internet & Geräte","Technologie, Internet & Appareils","Tecnologia, Internet e Dispositivos" },
|
||||
{ "Çevre Koruma ve Geri Dönüşüm","Environmental Protection & Recycling","Protección Ambiental y Reciclaje","Umweltschutz & Recycling","Protection de l'Environnement & Recyclage","Proteção Ambiental e Reciclagem" },
|
||||
{ "İleri Günlük İfadeler ve İş Hayatı","Advanced Daily Phrases & Work Life","Frases Avanzadas y Vida Laboral","Fortgeschrittene Alltagssätze & Arbeitsleben","Phrases Avançées & Vie Professionnelle","Frases Avançadas e Vida Profissional" }
|
||||
};
|
||||
|
||||
private readonly string[] scoreLabel =
|
||||
{
|
||||
"Puan","Score","Puntuación","Punkte","Score","Pontuação"
|
||||
};
|
||||
|
||||
// ============================================================
|
||||
void Start()
|
||||
{
|
||||
string ansLang = PlayerPrefs.GetString("AnswerLangCode", "tr").ToLower();
|
||||
langIndex = GetLangIndex(ansLang);
|
||||
|
||||
CacheButtonData();
|
||||
SetupLevelNames();
|
||||
LoadScoresToUI();
|
||||
BindButtons();
|
||||
|
||||
// ─── Buton giriş animasyonu ───────────────
|
||||
for (int i = 0; i < levelButtons.Length; i++)
|
||||
StartCoroutine(ButtonEnterAnim(levelButtons[i], i));
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
int GetLangIndex(string code)
|
||||
{
|
||||
return code switch
|
||||
{
|
||||
"tr" => 0,
|
||||
"en" => 1,
|
||||
"es" => 2,
|
||||
"de" => 3,
|
||||
"fr" => 4,
|
||||
"pt" => 5,
|
||||
_ => 1
|
||||
};
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
void CacheButtonData()
|
||||
{
|
||||
if (levelButtons == null) return;
|
||||
originalScales = new Vector3[levelButtons.Length];
|
||||
originalPositions = new Vector3[levelButtons.Length];
|
||||
for (int i = 0; i < levelButtons.Length; i++)
|
||||
{
|
||||
if (levelButtons[i] == null) continue;
|
||||
originalScales[i] = levelButtons[i].transform.localScale;
|
||||
originalPositions[i] = levelButtons[i].transform.localPosition;
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
void SetupLevelNames()
|
||||
{
|
||||
if (levelNameTexts == null) return;
|
||||
for (int i = 0; i < levelNameTexts.Length; i++)
|
||||
if (levelNameTexts[i] != null)
|
||||
levelNameTexts[i].text = levelNames[i, langIndex];
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
void BindButtons()
|
||||
{
|
||||
if (levelButtons == null) return;
|
||||
|
||||
for (int i = 0; i < levelButtons.Length; i++)
|
||||
{
|
||||
if (levelButtons[i] == null) continue;
|
||||
int id = i + 1;
|
||||
levelButtons[i].onClick.RemoveAllListeners();
|
||||
levelButtons[i].onClick.AddListener(() =>
|
||||
{
|
||||
PlayClick();
|
||||
PlayerPrefs.SetInt("SelectedLevel", id);
|
||||
PlayerPrefs.Save();
|
||||
SceneManager.LoadScene("LLGameScene_Level");
|
||||
});
|
||||
}
|
||||
|
||||
if (backButton != null)
|
||||
backButton.onClick.AddListener(() => { PlayClick(); SceneManager.LoadScene(backSceneName); });
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
void LoadScoresToUI()
|
||||
{
|
||||
if (levelScoreTexts == null) return;
|
||||
for (int i = 0; i < levelScoreTexts.Length; i++)
|
||||
{
|
||||
if (levelScoreTexts[i] == null) continue;
|
||||
int levelID = i + 1;
|
||||
int highScore = PlayerPrefs.GetInt("HighScore_Level_" + levelID, 0);
|
||||
|
||||
if (highScore >= 2000)
|
||||
{
|
||||
levelScoreTexts[i].text = $"{scoreLabel[langIndex]}: 2000 / 2000";
|
||||
levelScoreTexts[i].color = Color.green;
|
||||
}
|
||||
else
|
||||
{
|
||||
levelScoreTexts[i].text = $"{scoreLabel[langIndex]}: {highScore} / 2000";
|
||||
levelScoreTexts[i].color = Color.red;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
void PlayClick()
|
||||
{
|
||||
if (sfxSource != null && clickSound != null)
|
||||
sfxSource.PlayOneShot(clickSound);
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// ANİMASYONLAR
|
||||
// ============================================================
|
||||
IEnumerator ButtonEnterAnim(Button btn, int delayIndex)
|
||||
{
|
||||
if (btn == null || originalScales == null) yield break;
|
||||
int idx = System.Array.IndexOf(levelButtons, btn);
|
||||
if (idx < 0 || idx >= originalScales.Length) yield break;
|
||||
|
||||
yield return new WaitForSeconds(delayIndex * 0.08f);
|
||||
|
||||
Vector3 targetPos = originalPositions[idx];
|
||||
Vector3 startPos = targetPos + Vector3.up * 60f;
|
||||
Vector3 targetScale = originalScales[idx];
|
||||
|
||||
btn.transform.localPosition = startPos;
|
||||
btn.transform.localScale = Vector3.zero;
|
||||
|
||||
float t = 0f;
|
||||
while (t < 1f)
|
||||
{
|
||||
t = Mathf.Min(t + buttonAniSpeed * 0.13f, 1f);
|
||||
float ease = EaseOutBack(t);
|
||||
btn.transform.localPosition = Vector3.Lerp(startPos, targetPos, ease);
|
||||
btn.transform.localScale = Vector3.Lerp(Vector3.zero, targetScale, ease);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
btn.transform.localPosition = targetPos;
|
||||
btn.transform.localScale = targetScale;
|
||||
}
|
||||
|
||||
IEnumerator PunchScale(Button btn, int idx)
|
||||
{
|
||||
if (btn == null || originalScales == null) yield break;
|
||||
if (idx < 0 || idx >= originalScales.Length) yield break;
|
||||
Vector3 original = originalScales[idx];
|
||||
Vector3 big = original * 1.08f;
|
||||
float t = 0f;
|
||||
while (t < 1f) { t = Mathf.Min(t + 0.15f, 1f); btn.transform.localScale = Vector3.Lerp(original, big, EaseOutQuad(t)); yield return null; }
|
||||
t = 0f;
|
||||
while (t < 1f) { t = Mathf.Min(t + 0.12f, 1f); btn.transform.localScale = Vector3.Lerp(big, original, EaseOutQuad(t)); yield return null; }
|
||||
btn.transform.localScale = original;
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
float EaseOutBack(float 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) => 1f - (1f - t) * (1f - t);
|
||||
}
|
||||
2
Assets/Scripts/2.0/LevelSelectController.cs.meta
Normal file
2
Assets/Scripts/2.0/LevelSelectController.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1bdc7981307c4924f9526f3bba47b417
|
||||
53
Assets/Scripts/2.0/ModeSelectController.cs
Normal file
53
Assets/Scripts/2.0/ModeSelectController.cs
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
public class ModeSelectController : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Button[] modButtons = new Button[30];
|
||||
[SerializeField] private Button backButton;
|
||||
[SerializeField] private string mainMenuScene = "Anamen";
|
||||
[SerializeField] private AudioSource audioSource;
|
||||
[SerializeField] private AudioClip clickSound;
|
||||
|
||||
[Header("MOD Sahneleri")]
|
||||
[SerializeField] private string[] modScenes = new string[30];
|
||||
|
||||
void Start()
|
||||
{
|
||||
// Bind mod buttons
|
||||
for (int i = 0; i < 30; i++)
|
||||
{
|
||||
if (modButtons[i] != null)
|
||||
{
|
||||
int modID = i + 1;
|
||||
modButtons[i].onClick.AddListener(() => SelectMode(modID));
|
||||
}
|
||||
}
|
||||
|
||||
// Back button
|
||||
if (backButton != null)
|
||||
backButton.onClick.AddListener(() => LoadScene(mainMenuScene));
|
||||
}
|
||||
|
||||
void SelectMode(int modID)
|
||||
{
|
||||
PlaySound();
|
||||
PlayerPrefs.SetInt("SelectedMode", modID);
|
||||
PlayerPrefs.Save();
|
||||
|
||||
string sceneName = modScenes[modID - 1];
|
||||
LoadScene(sceneName);
|
||||
}
|
||||
|
||||
void LoadScene(string sceneName)
|
||||
{
|
||||
SceneManager.LoadScene(sceneName);
|
||||
}
|
||||
|
||||
void PlaySound()
|
||||
{
|
||||
if (audioSource && clickSound)
|
||||
audioSource.PlayOneShot(clickSound);
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/2.0/ModeSelectController.cs.meta
Normal file
2
Assets/Scripts/2.0/ModeSelectController.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d46006198cd5c3b4d8c76badb7f20a2c
|
||||
101
Assets/Scripts/2.0/ResultScene_Galaxy.cs
Normal file
101
Assets/Scripts/2.0/ResultScene_Galaxy.cs
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using TMPro;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
public class ResultScene_Galaxy : MonoBehaviour
|
||||
{
|
||||
[Header("RESULT TEXTS")]
|
||||
public TMP_Text scoreText;
|
||||
public TMP_Text correctText;
|
||||
public TMP_Text wrongText;
|
||||
public TMP_Text statusText;
|
||||
|
||||
[Header("BUTTONS")]
|
||||
public Button retryButton;
|
||||
public Button mainMenuButton;
|
||||
|
||||
[Header("SCENES (Inspector'dan gir)")]
|
||||
public string retrySceneName = "GalaxyGameScene_Level"; // tekrar oyna -> oyun sahnesi
|
||||
public string mainMenuScene = "Anamen";
|
||||
|
||||
[Header("SUCCESS THRESHOLD")]
|
||||
public int successScoreThreshold = 2000;
|
||||
|
||||
[Header("AUDIO")]
|
||||
public AudioSource audioSource;
|
||||
public AudioClip clickSound;
|
||||
|
||||
private int score;
|
||||
private int correct;
|
||||
private int wrong;
|
||||
|
||||
void Start()
|
||||
{
|
||||
score = PlayerPrefs.GetInt("Mod3Score", 0);
|
||||
correct = PlayerPrefs.GetInt("Mod3Correct", 0);
|
||||
wrong = PlayerPrefs.GetInt("Mod3Wrong", 0);
|
||||
|
||||
if (scoreText != null) scoreText.text = score.ToString();
|
||||
if (correctText != null) correctText.text = correct.ToString();
|
||||
if (wrongText != null) wrongText.text = wrong.ToString();
|
||||
|
||||
if (statusText != null)
|
||||
{
|
||||
if (score >= successScoreThreshold)
|
||||
{
|
||||
statusText.text = "LEVEL PASSED";
|
||||
statusText.color = Color.green;
|
||||
}
|
||||
else
|
||||
{
|
||||
statusText.text = "FAILED";
|
||||
statusText.color = Color.red;
|
||||
}
|
||||
}
|
||||
|
||||
if (retryButton != null)
|
||||
{
|
||||
retryButton.onClick.RemoveAllListeners();
|
||||
retryButton.onClick.AddListener(() =>
|
||||
{
|
||||
PlayClick();
|
||||
LoadScene(retrySceneName);
|
||||
});
|
||||
}
|
||||
|
||||
if (mainMenuButton != null)
|
||||
{
|
||||
mainMenuButton.onClick.RemoveAllListeners();
|
||||
mainMenuButton.onClick.AddListener(() =>
|
||||
{
|
||||
PlayClick();
|
||||
LoadScene(mainMenuScene);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void LoadScene(string sceneName)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(sceneName))
|
||||
{
|
||||
Debug.LogError("ResultScene: Sahne adı boş! Inspector'dan doldur.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Application.CanStreamedLevelBeLoaded(sceneName))
|
||||
{
|
||||
Debug.LogError("ResultScene: '" + sceneName +
|
||||
"' sahnesi Build Settings'te yok ya da adı yanlış!");
|
||||
return;
|
||||
}
|
||||
|
||||
SceneManager.LoadScene(sceneName);
|
||||
}
|
||||
|
||||
void PlayClick()
|
||||
{
|
||||
if (audioSource && clickSound)
|
||||
audioSource.PlayOneShot(clickSound);
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/2.0/ResultScene_Galaxy.cs.meta
Normal file
2
Assets/Scripts/2.0/ResultScene_Galaxy.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1ec4b2e43350ee04097c45d54640af8f
|
||||
221
Assets/Scripts/2.0/ResultScene_TTE.cs
Normal file
221
Assets/Scripts/2.0/ResultScene_TTE.cs
Normal file
|
|
@ -0,0 +1,221 @@
|
|||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using TMPro;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
public class ResultScene_TTE : MonoBehaviour
|
||||
{
|
||||
[Header("UI Texts")]
|
||||
public TMP_Text levelNameText;
|
||||
public TMP_Text scoreText;
|
||||
public TMP_Text highScoreText;
|
||||
public TMP_Text correctText;
|
||||
public TMP_Text wrongText;
|
||||
public TMP_Text resultStatusText;
|
||||
|
||||
[Header("Buttons")]
|
||||
public Button retryButton;
|
||||
public Button levelMapButton;
|
||||
public Button mainMenuButton;
|
||||
|
||||
[Header("Audio")]
|
||||
public AudioSource audioSource;
|
||||
public AudioClip clickSound;
|
||||
|
||||
[Header("Scene Names")]
|
||||
[SerializeField] private string levelMapScene = "StageLevelMap";
|
||||
[SerializeField] private string mainMenuScene = "Anamen";
|
||||
[SerializeField] private string gameSceneName = "LLGameScene_Level";
|
||||
|
||||
private int score;
|
||||
private int correct;
|
||||
private int wrong;
|
||||
private int selectedLevel;
|
||||
|
||||
private int langIndex; // CEVAP DİLİ İNDEKSİ
|
||||
|
||||
// ===========================
|
||||
// 20 LEVEL ADI (6 DİL)
|
||||
// ===========================
|
||||
private readonly string[,] levelNames = new string[,]
|
||||
{
|
||||
{ "Temel Selamlaşma ve İnsanlar","Basic Greetings & People","Saludos Básicos y Personas","Grundbegrüßungen & Menschen","Salutations de Base & Personnes","Saudações Básicas e Pessoas" },
|
||||
{ "Günlük Ev Nesneleri","Daily Household Items","Objetos del Hogar Diarios","Tägliche Haushaltsgegenstände","Objets Quotidiens de la Maison","Objetos Domésticos Diários" },
|
||||
{ "Yiyecekler ve İçecekler","Food & Drinks","Comida y Bebida","Essen & Getränke","Nourriture & Boissons","Comidas e Bebidas" },
|
||||
{ "Renkler, Şekiller ve Boyutlar","Colors, Shapes & Sizes","Colores, Formas y Tamaños","Farben, Formen & Größen","Couleurs, Formes & Tailles","Cores, Formas e Tamanhos" },
|
||||
{ "Zaman, Günler ve Mevsimler","Time, Days & Seasons","Tiempo, Días y Estaciones","Zeit, Tage & Jahreszeiten","Temps, Jours & Saisons","Tempo, Dias e Estações" },
|
||||
{ "Ev İçi Alanlar ve Temizlik","Home Areas & Cleaning","Áreas del Hogar y Limpieza","Hausbereiche & Reinigung","Espaces de Maison & Nettoyage","Áreas da Casa e Limpeza" },
|
||||
{ "Okul, Eğitim ve Ders Araçları","School, Education & Supplies","Escuela, Educación y Útiles","Schule, Bildung & Materialien","École, Éducation & Fournitures","Escola, Educação e Materiais" },
|
||||
{ "Vücut Parçaları ve Sağlık","Body Parts & Health","Partes del Cuerpo y Salud","Körperteile & Gesundheit","Parties du Corps & Santé","Partes do Corpo e Saúde" },
|
||||
{ "Doğa, Hava ve Çevre Unsurları","Nature, Weather & Environment","Naturaleza, Clima y Medio Ambiente","Natur, Wetter & Umwelt","Nature, Météo & Environnement","Natureza, Clima e Meio Ambiente" },
|
||||
{ "Evcil ve Vahşi Hayvanlar","Pets & Wild Animals","Mascotas y Animales Salvajes","Haustiere & Wildtiere","Animaux Domestiques & Sauvages","Animais Domésticos e Selvagens" },
|
||||
{ "Ulaşım Araçları ve Trafik","Transportation & Traffic","Transporte y Tráfico","Transport & Verkehr","Transport & Circulation","Transporte e Trânsito" },
|
||||
{ "Alışveriş ve Mağazalar","Shopping & Stores","Compras y Tiendas","Einkaufen & Geschäfte","Shopping & Magasins","Compras e Lojas" },
|
||||
{ "Spor Dalları ve Ekipmanları","Sports & Equipment","Deportes y Equipamiento","Sportarten & Ausrüstung","Sports & Équipement","Esportes e Equipamentos" },
|
||||
{ "Meslekler ve İş Alanları","Jobs & Work Fields","Profesiones y Áreas Laborales","Berufe & Arbeitsfelder","Métiers & Domaines de Travail","Profissões e Áreas de Trabalho" },
|
||||
{ "Şehir, Yerler ve Binalar","City, Places & Buildings","Ciudad, Lugares y Edificios","Stadt, Orte & Gebäude","Ville, Lieux & Bâtiments","Cidade, Lugares e Edifícios" },
|
||||
{ "Duygular, Durumlar ve Karakter","Emotions, States & Character","Emociones, Estados y Carácter","Gefühle, Zustände & Charakter","Émotions, États & Caractère","Emoções, Estados e Caráter" },
|
||||
{ "Seyahat, Tatil ve Turizm","Travel, Vacation & Tourism","Viajes, Vacaciones y Turismo","Reisen, Urlaub & Tourismus","Voyage, Vacances & Tourisme","Viagem, Férias e Turismo" },
|
||||
{ "Teknoloji, İnternet ve Cihazlar","Technology, Internet & Devices","Tecnología, Internet y Dispositivos","Technologie, Internet & Geräte","Technologie, Internet & Appareils","Tecnologia, Internet e Dispositivos" },
|
||||
{ "Çevre Koruma ve Geri Dönüşüm","Environmental Protection & Recycling","Protección Ambiental y Reciclaje","Umweltschutz & Recycling","Protection de l'Environnement & Recyclage","Proteção Ambiental e Reciclagem" },
|
||||
{ "İleri Günlük İfadeler ve İş Hayatı","Advanced Daily Phrases & Work Life","Frases Avanzadas y Vida Laboral","Fortgeschrittene Alltagssätze & Arbeitsleben","Phrases Avancées & Vie Professionnelle","Frases Avançadas e Vida Profissional" }
|
||||
};
|
||||
|
||||
private readonly string[] labelScore = { " ", " ", " ", " ", " ", " " };
|
||||
private readonly string[] labelHighScore = { " ", " ", " ", " ", " ", " " };
|
||||
private readonly string[] labelCorrect = { " ", " ", " ", " ", " ", " " };
|
||||
private readonly string[] labelWrong = { " ", " ", " ", " ", " ", " " };
|
||||
private readonly string[] labelPassed = {
|
||||
"TEBRİKLER! 🎉 LEVEL GEÇİLDİ",
|
||||
"CONGRATULATIONS! 🎉 LEVEL CLEARED",
|
||||
"¡FELICIDADES! 🎉 NIVEL COMPLETADO",
|
||||
"GLÜCKWUNSCH! 🎉 LEVEL GESCHAFFT",
|
||||
"FÉLICITATIONS ! 🎉 NIVEAU RÉUSSI",
|
||||
"PARABÉNS! 🎉 NÍVEL CONCLUÍDO"
|
||||
};
|
||||
|
||||
private readonly string[] labelFailed = {
|
||||
"LEVEL BAŞARISIZ ❌",
|
||||
"LEVEL FAILED ❌",
|
||||
"NIVEL FALLIDO ❌",
|
||||
"LEVEL NICHT BESTANDEN ❌",
|
||||
"NIVEAU ÉCHOUÉ ❌",
|
||||
"NÍVEL REPROVADO ❌"
|
||||
};
|
||||
|
||||
// ============================================================
|
||||
void Start()
|
||||
{
|
||||
// 1) Dil indexini al
|
||||
string ansLang = PlayerPrefs.GetString("AnswerLangCode", "tr").ToLower();
|
||||
langIndex = GetLangIndex(ansLang);
|
||||
|
||||
// 2) Sonuçları yükle + high score kaydet
|
||||
LoadResults();
|
||||
SaveHighScore();
|
||||
|
||||
// 3) ÖNCE butonları bağla (Start hata alsa bile en azından buraya kadar gelsin)
|
||||
if (retryButton != null)
|
||||
{
|
||||
retryButton.onClick.RemoveAllListeners();
|
||||
retryButton.onClick.AddListener(OnRetry);
|
||||
}
|
||||
|
||||
if (levelMapButton != null)
|
||||
{
|
||||
levelMapButton.onClick.RemoveAllListeners();
|
||||
levelMapButton.onClick.AddListener(OnLevelMap);
|
||||
}
|
||||
|
||||
if (mainMenuButton != null)
|
||||
{
|
||||
mainMenuButton.onClick.RemoveAllListeners();
|
||||
mainMenuButton.onClick.AddListener(OnMainMenu);
|
||||
}
|
||||
|
||||
// 4) UI’ı güncelle (null-safe)
|
||||
UpdateUI();
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
int GetLangIndex(string code)
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
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 LoadResults()
|
||||
{
|
||||
score = PlayerPrefs.GetInt("Mod2Score", 0);
|
||||
correct = PlayerPrefs.GetInt("Mod2Correct", 0);
|
||||
wrong = PlayerPrefs.GetInt("Mod2Wrong", 0);
|
||||
|
||||
selectedLevel = Mathf.Clamp(PlayerPrefs.GetInt("SelectedLevel", 1), 1, 20);
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
void SaveHighScore()
|
||||
{
|
||||
string key = "HighScore_Level_" + selectedLevel;
|
||||
|
||||
int old = PlayerPrefs.GetInt(key, 0);
|
||||
if (score > old)
|
||||
{
|
||||
PlayerPrefs.SetInt(key, score);
|
||||
PlayerPrefs.Save();
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
void UpdateUI()
|
||||
{
|
||||
int safeLang = Mathf.Clamp(langIndex, 0, 5);
|
||||
int idx = Mathf.Clamp(selectedLevel - 1, 0, 19);
|
||||
|
||||
if (levelNameText != null)
|
||||
levelNameText.text = $"LEVEL {selectedLevel}\n{levelNames[idx, safeLang]}";
|
||||
|
||||
if (scoreText != null)
|
||||
scoreText.text = $"{labelScore[safeLang]} {score}";
|
||||
|
||||
if (highScoreText != null)
|
||||
highScoreText.text = $"{labelHighScore[safeLang]} {PlayerPrefs.GetInt("HighScore_Level_" + selectedLevel, 0)}";
|
||||
|
||||
if (correctText != null)
|
||||
correctText.text = $"{labelCorrect[safeLang]} {correct}";
|
||||
|
||||
if (wrongText != null)
|
||||
wrongText.text = $"{labelWrong[safeLang]} {wrong}";
|
||||
|
||||
if (resultStatusText != null)
|
||||
{
|
||||
if (score >= 2000)
|
||||
{
|
||||
resultStatusText.text = labelPassed[safeLang];
|
||||
resultStatusText.color = Color.green;
|
||||
}
|
||||
else
|
||||
{
|
||||
resultStatusText.text = labelFailed[safeLang];
|
||||
resultStatusText.color = Color.red;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
void OnRetry()
|
||||
{
|
||||
PlayClick();
|
||||
if (!string.IsNullOrEmpty(gameSceneName))
|
||||
SceneManager.LoadScene(gameSceneName);
|
||||
}
|
||||
|
||||
void OnLevelMap()
|
||||
{
|
||||
PlayClick();
|
||||
if (!string.IsNullOrEmpty(levelMapScene))
|
||||
SceneManager.LoadScene(levelMapScene);
|
||||
}
|
||||
|
||||
void OnMainMenu()
|
||||
{
|
||||
PlayClick();
|
||||
if (!string.IsNullOrEmpty(mainMenuScene))
|
||||
SceneManager.LoadScene(mainMenuScene);
|
||||
}
|
||||
|
||||
void PlayClick()
|
||||
{
|
||||
if (audioSource && clickSound)
|
||||
audioSource.PlayOneShot(clickSound);
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/2.0/ResultScene_TTE.cs.meta
Normal file
2
Assets/Scripts/2.0/ResultScene_TTE.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b574853e950b6cf48a084ac772956c65
|
||||
8
Assets/Scripts/3.0.meta
Normal file
8
Assets/Scripts/3.0.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9360ad261eb62e643b8376ff33da5be4
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Scripts/3.0/Mod4.meta
Normal file
8
Assets/Scripts/3.0/Mod4.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 361cc2564c58fe6449c1822064d12c32
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
804
Assets/Scripts/3.0/Mod4/ClozeGameScene.cs
Normal file
804
Assets/Scripts/3.0/Mod4/ClozeGameScene.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/3.0/Mod4/ClozeGameScene.cs.meta
Normal file
2
Assets/Scripts/3.0/Mod4/ClozeGameScene.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e2fc2555785ff244ca431198dfe8bc21
|
||||
168
Assets/Scripts/3.0/Mod4/Mod4Resume.cs
Normal file
168
Assets/Scripts/3.0/Mod4/Mod4Resume.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/3.0/Mod4/Mod4Resume.cs.meta
Normal file
2
Assets/Scripts/3.0/Mod4/Mod4Resume.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 323d69d6258982b41ad0ec9e34e0ba98
|
||||
8
Assets/Scripts/3.0/Mod5.meta
Normal file
8
Assets/Scripts/3.0/Mod5.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2b5728892019a2347bac5fea0b29df9a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
90
Assets/Scripts/3.0/Mod5/Mod5Resume.cs
Normal file
90
Assets/Scripts/3.0/Mod5/Mod5Resume.cs
Normal 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 key’i
|
||||
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");
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/3.0/Mod5/Mod5Resume.cs.meta
Normal file
2
Assets/Scripts/3.0/Mod5/Mod5Resume.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5aef591567d26be469298582b4dde11b
|
||||
1076
Assets/Scripts/3.0/Mod5/TetrisCategoryMod.cs
Normal file
1076
Assets/Scripts/3.0/Mod5/TetrisCategoryMod.cs
Normal file
File diff suppressed because it is too large
Load diff
2
Assets/Scripts/3.0/Mod5/TetrisCategoryMod.cs.meta
Normal file
2
Assets/Scripts/3.0/Mod5/TetrisCategoryMod.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a63c8afea6ac9ef49808e75ed89dc7cb
|
||||
8
Assets/Scripts/3.0/Mod6.meta
Normal file
8
Assets/Scripts/3.0/Mod6.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8bddf192a36777c4f89d9bc2f7c58312
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
177
Assets/Scripts/3.0/Mod6/Mod6Resume.cs
Normal file
177
Assets/Scripts/3.0/Mod6/Mod6Resume.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/3.0/Mod6/Mod6Resume.cs.meta
Normal file
2
Assets/Scripts/3.0/Mod6/Mod6Resume.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7732f4a1c046d054cadae9b2b5482c31
|
||||
897
Assets/Scripts/3.0/Mod6/WordMatchMod.cs
Normal file
897
Assets/Scripts/3.0/Mod6/WordMatchMod.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/3.0/Mod6/WordMatchMod.cs.meta
Normal file
2
Assets/Scripts/3.0/Mod6/WordMatchMod.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8009dfdd6ea39fb4e8299d3815d05377
|
||||
8
Assets/Scripts/3.0/Mod8.meta
Normal file
8
Assets/Scripts/3.0/Mod8.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ec4dd0c0e48b6d445aac4329391489cc
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
152
Assets/Scripts/3.0/Mod8/Mod8Resume.cs
Normal file
152
Assets/Scripts/3.0/Mod8/Mod8Resume.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/3.0/Mod8/Mod8Resume.cs.meta
Normal file
2
Assets/Scripts/3.0/Mod8/Mod8Resume.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2aa39617cac61c542b3904ef06fefa38
|
||||
876
Assets/Scripts/3.0/Mod8/WordMatchMod8.cs
Normal file
876
Assets/Scripts/3.0/Mod8/WordMatchMod8.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/3.0/Mod8/WordMatchMod8.cs.meta
Normal file
2
Assets/Scripts/3.0/Mod8/WordMatchMod8.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 24738b79935ff2e4684b1e2523827057
|
||||
8
Assets/Scripts/3.0/mod10.meta
Normal file
8
Assets/Scripts/3.0/mod10.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 15b1f064ebce8074c855ee805144ea4a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
82
Assets/Scripts/3.0/mod10/Mod10Resume.cs
Normal file
82
Assets/Scripts/3.0/mod10/Mod10Resume.cs
Normal 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");
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/3.0/mod10/Mod10Resume.cs.meta
Normal file
2
Assets/Scripts/3.0/mod10/Mod10Resume.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 943d61e94ac5fdc45b9ea6f4357d8d71
|
||||
807
Assets/Scripts/3.0/mod10/SentenceOrderGameScene.cs
Normal file
807
Assets/Scripts/3.0/mod10/SentenceOrderGameScene.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/3.0/mod10/SentenceOrderGameScene.cs.meta
Normal file
2
Assets/Scripts/3.0/mod10/SentenceOrderGameScene.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5d1f4458536ed634b97019cf3c7abb27
|
||||
8
Assets/Scripts/3.0/mod11.meta
Normal file
8
Assets/Scripts/3.0/mod11.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5861da0019dff9a42a4a83d14f1722c8
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
846
Assets/Scripts/3.0/mod11/AnalogyGameScene.cs
Normal file
846
Assets/Scripts/3.0/mod11/AnalogyGameScene.cs
Normal 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; // 0–5
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/3.0/mod11/AnalogyGameScene.cs.meta
Normal file
2
Assets/Scripts/3.0/mod11/AnalogyGameScene.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ff5c022bf505d8a4cbd87bc660103cf2
|
||||
154
Assets/Scripts/3.0/mod11/Mod11Resume.cs
Normal file
154
Assets/Scripts/3.0/mod11/Mod11Resume.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/3.0/mod11/Mod11Resume.cs.meta
Normal file
2
Assets/Scripts/3.0/mod11/Mod11Resume.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1781e8376e88df94187d95b3c65889d3
|
||||
8
Assets/Scripts/3.0/mod12.meta
Normal file
8
Assets/Scripts/3.0/mod12.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 792af35de8483a3408d24c7c79e3e76b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
144
Assets/Scripts/3.0/mod12/Mod12Resume.cs
Normal file
144
Assets/Scripts/3.0/mod12/Mod12Resume.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/3.0/mod12/Mod12Resume.cs.meta
Normal file
2
Assets/Scripts/3.0/mod12/Mod12Resume.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 569283d0e752d7f4484717cd84e953c7
|
||||
662
Assets/Scripts/3.0/mod12/TFTranslationGameScene.cs
Normal file
662
Assets/Scripts/3.0/mod12/TFTranslationGameScene.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/3.0/mod12/TFTranslationGameScene.cs.meta
Normal file
2
Assets/Scripts/3.0/mod12/TFTranslationGameScene.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 59d2c4636dd071b498167e354fc0b612
|
||||
8
Assets/Scripts/3.0/mod7.meta
Normal file
8
Assets/Scripts/3.0/mod7.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0b4d822743fa66c4a8c54880728ec78c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
164
Assets/Scripts/3.0/mod7/Mod7Resume.cs
Normal file
164
Assets/Scripts/3.0/mod7/Mod7Resume.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/3.0/mod7/Mod7Resume.cs.meta
Normal file
2
Assets/Scripts/3.0/mod7/Mod7Resume.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 56be283e892927547817c76f96c0329e
|
||||
1118
Assets/Scripts/3.0/mod7/TetrisTranslationDropMod.cs
Normal file
1118
Assets/Scripts/3.0/mod7/TetrisTranslationDropMod.cs
Normal file
File diff suppressed because it is too large
Load diff
2
Assets/Scripts/3.0/mod7/TetrisTranslationDropMod.cs.meta
Normal file
2
Assets/Scripts/3.0/mod7/TetrisTranslationDropMod.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e08b0cfd78da3f94b9cd70dfecc1eca4
|
||||
8
Assets/Scripts/3.0/mod9.meta
Normal file
8
Assets/Scripts/3.0/mod9.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3d888a15222d70a4ab1849caa1545618
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
126
Assets/Scripts/3.0/mod9/Mod9Resume.cs
Normal file
126
Assets/Scripts/3.0/mod9/Mod9Resume.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/3.0/mod9/Mod9Resume.cs.meta
Normal file
2
Assets/Scripts/3.0/mod9/Mod9Resume.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6f34180d9fade5c4fa76a9c5939efad7
|
||||
844
Assets/Scripts/3.0/mod9/WordMatchMod9.cs
Normal file
844
Assets/Scripts/3.0/mod9/WordMatchMod9.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/3.0/mod9/WordMatchMod9.cs.meta
Normal file
2
Assets/Scripts/3.0/mod9/WordMatchMod9.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ebec7d06e1d313b43a00264a336593c9
|
||||
8
Assets/Scripts/3.5.meta
Normal file
8
Assets/Scripts/3.5.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b91ba2dfe8cf306409c6ee34e3d2c255
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
71
Assets/Scripts/3.5/ModLeaderboard.cs
Normal file
71
Assets/Scripts/3.5/ModLeaderboard.cs
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
using System.Collections.Generic;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UI;
|
||||
public class ModLeaderboard : MonoBehaviour
|
||||
{
|
||||
[Header("━━━ UI SLOTS (10 satır) ━━━━━━━━━━━━━━━")]
|
||||
public TMP_Text[] rows;
|
||||
[Header("━━━ BUTONLAR ━━━━━━━━━━━━━━━━━━━━━━━━━━")]
|
||||
public Button mainMenuButton;
|
||||
[Header("━━━ MOD AYARI ━━━━━━━━━━━━━━━━━━━━━━━━━")]
|
||||
public string scoreKey = "GalaxyScore";
|
||||
//
|
||||
// Her mod için scoreKey değeri:
|
||||
// ─────────────────────────────
|
||||
// Galaxy Modu → "GalaxyScore"
|
||||
// Time Modu → "TimeScore"
|
||||
// Classic Modu → "ClassicScore"
|
||||
// Challenge Modu → "ChallengeScore"
|
||||
private readonly string[] botNames =
|
||||
{
|
||||
"ShadowWolf", "CrystalMind", "NightHunter",
|
||||
"BlueVortex", "IronSoul", "PixelGhost",
|
||||
"SilverClaw", "MegaCore", "NeonBlade", "DarkNova"
|
||||
};
|
||||
class LBEntry
|
||||
{
|
||||
public string name;
|
||||
public int score;
|
||||
public LBEntry(string n, int s) { name = n; score = s; }
|
||||
}
|
||||
void Start()
|
||||
{
|
||||
GenerateLeaderboard();
|
||||
if (mainMenuButton != null)
|
||||
mainMenuButton.onClick.AddListener(() =>
|
||||
SceneManager.LoadScene("Anamen"));
|
||||
}
|
||||
void GenerateLeaderboard()
|
||||
{
|
||||
List<LBEntry> list = new List<LBEntry>();
|
||||
int botLimit = Mathf.Min(rows.Length - 1, botNames.Length);
|
||||
for (int i = 0; i < botLimit; i++)
|
||||
list.Add(new LBEntry(botNames[i], Random.Range(3000, 12000)));
|
||||
string highKey = scoreKey + "_High";
|
||||
int lastScore = PlayerPrefs.GetInt(scoreKey, 0);
|
||||
int highScore = PlayerPrefs.GetInt(highKey, 0);
|
||||
if (lastScore > highScore)
|
||||
{
|
||||
highScore = lastScore;
|
||||
PlayerPrefs.SetInt(highKey, highScore);
|
||||
PlayerPrefs.Save();
|
||||
}
|
||||
list.Add(new LBEntry("YOU", highScore));
|
||||
list.Sort((a, b) => b.score.CompareTo(a.score));
|
||||
for (int i = 0; i < rows.Length; i++)
|
||||
{
|
||||
if (i < list.Count)
|
||||
{
|
||||
rows[i].text = list[i].name == "YOU"
|
||||
? $"<color=#00FF00>{i + 1}. {list[i].name} - {list[i].score}</color>"
|
||||
: $"{i + 1}. {list[i].name} - {list[i].score}";
|
||||
}
|
||||
else
|
||||
{
|
||||
rows[i].text = $"{i + 1}. ---";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/3.5/ModLeaderboard.cs.meta
Normal file
2
Assets/Scripts/3.5/ModLeaderboard.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 85e3141c0f135d94e9c099c2b7f5da74
|
||||
76
Assets/Scripts/3.5/ModSelectLanguageSettings.cs
Normal file
76
Assets/Scripts/3.5/ModSelectLanguageSettings.cs
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using TMPro;
|
||||
using UnityEngine.SceneManagement;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class ModSelectLanguageSettings : MonoBehaviour
|
||||
{
|
||||
[Header("━━━ DROPDOWNLAR ━━━━━━━━━━━━━━━━━━━━━━")]
|
||||
public TMP_Dropdown questionDropdown;
|
||||
public TMP_Dropdown answerDropdown;
|
||||
|
||||
[Header("━━━ BUTONLAR ━━━━━━━━━━━━━━━━━━━━━━━━━")]
|
||||
public Button closeButton;
|
||||
|
||||
void Start()
|
||||
{
|
||||
PopulateDropdowns();
|
||||
|
||||
questionDropdown.value = PlayerPrefs.GetInt("QuestionLangID", 1);
|
||||
answerDropdown.value = PlayerPrefs.GetInt("AnswerLangID", 0);
|
||||
|
||||
questionDropdown.RefreshShownValue();
|
||||
answerDropdown.RefreshShownValue();
|
||||
|
||||
closeButton.onClick.AddListener(SaveAndClose);
|
||||
}
|
||||
|
||||
void PopulateDropdowns()
|
||||
{
|
||||
List<string> languageNames = new List<string>
|
||||
{
|
||||
"Türkçe", // 0
|
||||
"English", // 1
|
||||
"Español", // 2
|
||||
"Deutsch", // 3
|
||||
"Français", // 4
|
||||
"Português" // 5
|
||||
};
|
||||
|
||||
questionDropdown.ClearOptions();
|
||||
answerDropdown.ClearOptions();
|
||||
|
||||
questionDropdown.AddOptions(languageNames);
|
||||
answerDropdown.AddOptions(languageNames);
|
||||
}
|
||||
|
||||
void SaveAndClose()
|
||||
{
|
||||
int qID = questionDropdown.value;
|
||||
int aID = answerDropdown.value;
|
||||
|
||||
PlayerPrefs.SetInt("QuestionLangID", qID);
|
||||
PlayerPrefs.SetInt("AnswerLangID", aID);
|
||||
PlayerPrefs.SetString("QuestionLangCode", ToCode(qID));
|
||||
PlayerPrefs.SetString("AnswerLangCode", ToCode(aID));
|
||||
PlayerPrefs.SetString("AppLanguage", ToCode(qID));
|
||||
PlayerPrefs.Save();
|
||||
|
||||
gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
string ToCode(int id)
|
||||
{
|
||||
return id switch
|
||||
{
|
||||
0 => "tr",
|
||||
1 => "en",
|
||||
2 => "es",
|
||||
3 => "de",
|
||||
4 => "fr",
|
||||
5 => "pt",
|
||||
_ => "en"
|
||||
};
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/3.5/ModSelectLanguageSettings.cs.meta
Normal file
2
Assets/Scripts/3.5/ModSelectLanguageSettings.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3eb2fcea3bc7c8b41b1842e752ce2168
|
||||
151
Assets/Scripts/3.5/ModWordListScreen.cs
Normal file
151
Assets/Scripts/3.5/ModWordListScreen.cs
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
using UnityEngine;
|
||||
using TMPro;
|
||||
using UnityEngine.UI;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
|
||||
public class ModWordListScreen : MonoBehaviour
|
||||
{
|
||||
[Header("━━━ LEVEL TXT DOSYALARI (6 DİL) ━━━━━━━")]
|
||||
public TextAsset[] levelFiles;
|
||||
|
||||
[Header("━━━ 20 KELİME SLOTU ━━━━━━━━━━━━━━━━━━━")]
|
||||
public TMP_Text[] wordTexts;
|
||||
|
||||
[Header("━━━ SAYFA BİLGİSİ ━━━━━━━━━━━━━━━━━━━━━")]
|
||||
public TMP_Text pageInfoText;
|
||||
|
||||
[Header("━━━ BUTONLAR ━━━━━━━━━━━━━━━━━━━━━━━━━━")]
|
||||
public Button nextButton;
|
||||
public Button closeButton;
|
||||
|
||||
[Header("━━━ AUDIO ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")]
|
||||
public AudioSource audioSource;
|
||||
public AudioClip clickSound;
|
||||
|
||||
private string questionLang;
|
||||
private string answerLang;
|
||||
|
||||
private int currentLevelIndex = 0;
|
||||
private int currentPageIndex = 0;
|
||||
|
||||
private int PAGE_SIZE;
|
||||
private List<WordPair> words = new();
|
||||
|
||||
private int MaxPageCount => (words.Count == 0) ? 1 : (words.Count - 1) / PAGE_SIZE + 1;
|
||||
|
||||
// ============================================================
|
||||
void Awake()
|
||||
{
|
||||
PAGE_SIZE = (wordTexts != null && wordTexts.Length > 0) ? wordTexts.Length : 20;
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
nextButton.onClick.AddListener(() => { PlayClick(); NextPage(); });
|
||||
closeButton.onClick.AddListener(() => { PlayClick(); gameObject.SetActive(false); });
|
||||
}
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
if (PAGE_SIZE == 0) return;
|
||||
|
||||
questionLang = PlayerPrefs.GetString("QuestionLangCode", "en");
|
||||
answerLang = PlayerPrefs.GetString("AnswerLangCode", "tr");
|
||||
|
||||
currentLevelIndex = 0;
|
||||
currentPageIndex = 0;
|
||||
|
||||
LoadLevel(currentLevelIndex);
|
||||
ShowPage();
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
void PlayClick()
|
||||
{
|
||||
if (audioSource && clickSound)
|
||||
audioSource.PlayOneShot(clickSound);
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
void LoadLevel(int index)
|
||||
{
|
||||
words.Clear();
|
||||
currentPageIndex = 0;
|
||||
|
||||
if (index < 0 || index >= levelFiles.Length)
|
||||
{
|
||||
currentLevelIndex = 0;
|
||||
LoadLevel(0);
|
||||
return;
|
||||
}
|
||||
|
||||
TextAsset txt = levelFiles[index];
|
||||
if (txt == null) return;
|
||||
|
||||
string[] lines = txt.text.Split(
|
||||
new[] { '\n', '\r' },
|
||||
StringSplitOptions.RemoveEmptyEntries
|
||||
);
|
||||
|
||||
foreach (string raw in lines)
|
||||
{
|
||||
string[] p = raw.Trim().Split(',');
|
||||
if (p.Length < 6) continue;
|
||||
|
||||
words.Add(new WordPair(
|
||||
p[0].Trim(), p[1].Trim(),
|
||||
p[2].Trim(), p[3].Trim(),
|
||||
p[4].Trim(), p[5].Trim()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
void ShowPage()
|
||||
{
|
||||
for (int i = 0; i < wordTexts.Length; i++)
|
||||
wordTexts[i].text = "";
|
||||
|
||||
int start = currentPageIndex * PAGE_SIZE;
|
||||
|
||||
for (int i = 0; i < PAGE_SIZE; i++)
|
||||
{
|
||||
int index = start + i;
|
||||
if (index >= words.Count || i >= wordTexts.Length) break;
|
||||
|
||||
WordPair w = words[index];
|
||||
wordTexts[i].text = $"{w.GetByCode(questionLang)} → {w.GetByCode(answerLang)}";
|
||||
}
|
||||
|
||||
UpdatePageInfo();
|
||||
}
|
||||
|
||||
void UpdatePageInfo()
|
||||
{
|
||||
pageInfoText.text = $"Page {currentPageIndex + 1}/{MaxPageCount}";
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
void NextPage()
|
||||
{
|
||||
if (currentPageIndex < MaxPageCount - 1)
|
||||
{
|
||||
currentPageIndex++;
|
||||
ShowPage();
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentLevelIndex < levelFiles.Length - 1)
|
||||
{
|
||||
currentLevelIndex++;
|
||||
LoadLevel(currentLevelIndex);
|
||||
ShowPage();
|
||||
return;
|
||||
}
|
||||
|
||||
currentLevelIndex = 0;
|
||||
LoadLevel(0);
|
||||
ShowPage();
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/3.5/ModWordListScreen.cs.meta
Normal file
2
Assets/Scripts/3.5/ModWordListScreen.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d7d689475375cc646bbae90bac8ed87a
|
||||
41
Assets/Scripts/3.5/MusicManager.cs
Normal file
41
Assets/Scripts/3.5/MusicManager.cs
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
using UnityEngine;
|
||||
|
||||
public class MusicManager : MonoBehaviour
|
||||
{
|
||||
[Header("━━━ MÜZIKLER (25 MP3) ━━━━━━━━━━━━━━━━━")]
|
||||
public AudioClip[] songs;
|
||||
|
||||
[Header("━━━ AUDIO SOURCE ━━━━━━━━━━━━━━━━━━━━━━")]
|
||||
public AudioSource audioSource;
|
||||
|
||||
private int lastIndex = -1;
|
||||
|
||||
// ============================================================
|
||||
void Start()
|
||||
{
|
||||
PlayRandom();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (!audioSource.isPlaying)
|
||||
PlayRandom();
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
void PlayRandom()
|
||||
{
|
||||
if (songs == null || songs.Length == 0) return;
|
||||
|
||||
int index;
|
||||
do
|
||||
{
|
||||
index = Random.Range(0, songs.Length);
|
||||
}
|
||||
while (index == lastIndex && songs.Length > 1); // aynı şarkı üst üste gelmesin
|
||||
|
||||
lastIndex = index;
|
||||
audioSource.clip = songs[index];
|
||||
audioSource.Play();
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/3.5/MusicManager.cs.meta
Normal file
2
Assets/Scripts/3.5/MusicManager.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5ee7bf0e8dcf55d49b30097a95df3c81
|
||||
8
Assets/Scripts/3.5/Prefabs.meta
Normal file
8
Assets/Scripts/3.5/Prefabs.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c7231500a58028042884bbf82d67a21d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
202
Assets/Scripts/3.5/Prefabs/ModSelectManager.cs
Normal file
202
Assets/Scripts/3.5/Prefabs/ModSelectManager.cs
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.SceneManagement;
|
||||
using TMPro;
|
||||
|
||||
[System.Serializable]
|
||||
public class ModData
|
||||
{
|
||||
public Sprite modSprite;
|
||||
public string sceneName;
|
||||
}
|
||||
|
||||
public class ModSelectManager : MonoBehaviour
|
||||
{
|
||||
[Header("━━━ MODLAR ━━━━━━━━━━━━━━━━━━━━━━━━━━━━")]
|
||||
public ModData[] mods;
|
||||
|
||||
[Header("━━━ KART BOYUTLARI ━━━━━━━━━━━━━━━━━━━━")]
|
||||
public float cardWidth = 900f;
|
||||
public float cardHeight = 500f;
|
||||
public float spacing = 40f;
|
||||
|
||||
[Header("━━━ PLAY BUTTON ━━━━━━━━━━━━━━━━━━━━━━━")]
|
||||
public string playButtonText = "PLAY";
|
||||
public float playButtonWidth = 400f;
|
||||
public float playButtonHeight = 100f;
|
||||
|
||||
void Start()
|
||||
{
|
||||
Canvas canvas = FindAnyObjectByType<Canvas>();
|
||||
|
||||
if (canvas == null)
|
||||
{
|
||||
GameObject canvasObj = new GameObject("Canvas");
|
||||
canvas = canvasObj.AddComponent<Canvas>();
|
||||
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
||||
|
||||
CanvasScaler scaler = canvasObj.AddComponent<CanvasScaler>();
|
||||
scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
|
||||
scaler.referenceResolution = new Vector2(1080, 1920);
|
||||
scaler.screenMatchMode = CanvasScaler.ScreenMatchMode.MatchWidthOrHeight;
|
||||
scaler.matchWidthOrHeight = 0.5f;
|
||||
|
||||
canvasObj.AddComponent<GraphicRaycaster>();
|
||||
}
|
||||
|
||||
GameObject oldScroll = GameObject.Find("ModScrollView");
|
||||
|
||||
if (oldScroll != null)
|
||||
Destroy(oldScroll);
|
||||
|
||||
GameObject scrollObj = new GameObject("ModScrollView");
|
||||
scrollObj.transform.SetParent(canvas.transform, false);
|
||||
|
||||
RectTransform scrollRect = scrollObj.AddComponent<RectTransform>();
|
||||
scrollRect.anchorMin = Vector2.zero;
|
||||
scrollRect.anchorMax = Vector2.one;
|
||||
scrollRect.offsetMin = Vector2.zero;
|
||||
scrollRect.offsetMax = Vector2.zero;
|
||||
|
||||
ScrollRect scroll = scrollObj.AddComponent<ScrollRect>();
|
||||
scroll.horizontal = false;
|
||||
scroll.vertical = true;
|
||||
scroll.movementType = ScrollRect.MovementType.Elastic;
|
||||
scroll.elasticity = 0.12f;
|
||||
scroll.inertia = true;
|
||||
scroll.decelerationRate = 0.135f;
|
||||
scroll.scrollSensitivity = 30f;
|
||||
|
||||
GameObject viewportObj = new GameObject("Viewport");
|
||||
viewportObj.transform.SetParent(scrollObj.transform, false);
|
||||
|
||||
RectTransform viewportRect = viewportObj.AddComponent<RectTransform>();
|
||||
viewportRect.anchorMin = Vector2.zero;
|
||||
viewportRect.anchorMax = Vector2.one;
|
||||
viewportRect.offsetMin = Vector2.zero;
|
||||
viewportRect.offsetMax = Vector2.zero;
|
||||
|
||||
Image viewportImage = viewportObj.AddComponent<Image>();
|
||||
viewportImage.color = new Color(0f, 0f, 0f, 0f);
|
||||
|
||||
Mask mask = viewportObj.AddComponent<Mask>();
|
||||
mask.showMaskGraphic = false;
|
||||
|
||||
GameObject contentObj = new GameObject("Content");
|
||||
contentObj.transform.SetParent(viewportObj.transform, false);
|
||||
|
||||
RectTransform contentRect = contentObj.AddComponent<RectTransform>();
|
||||
contentRect.anchorMin = new Vector2(0f, 1f);
|
||||
contentRect.anchorMax = new Vector2(1f, 1f);
|
||||
contentRect.pivot = new Vector2(0.5f, 1f);
|
||||
contentRect.anchoredPosition = Vector2.zero;
|
||||
contentRect.sizeDelta = Vector2.zero;
|
||||
|
||||
VerticalLayoutGroup vlg = contentObj.AddComponent<VerticalLayoutGroup>();
|
||||
vlg.spacing = spacing;
|
||||
vlg.padding = new RectOffset(50, 50, 50, 50);
|
||||
vlg.childAlignment = TextAnchor.UpperCenter;
|
||||
vlg.childControlWidth = false;
|
||||
vlg.childControlHeight = false;
|
||||
vlg.childForceExpandWidth = false;
|
||||
vlg.childForceExpandHeight = false;
|
||||
|
||||
ContentSizeFitter csf = contentObj.AddComponent<ContentSizeFitter>();
|
||||
csf.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
csf.horizontalFit = ContentSizeFitter.FitMode.Unconstrained;
|
||||
|
||||
scroll.viewport = viewportRect;
|
||||
scroll.content = contentRect;
|
||||
|
||||
if (mods == null || mods.Length == 0)
|
||||
{
|
||||
Debug.LogWarning("ModSelectManager: mods listesi boş.");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (ModData mod in mods)
|
||||
{
|
||||
if (mod == null)
|
||||
continue;
|
||||
|
||||
GameObject card = new GameObject("ModCard");
|
||||
card.transform.SetParent(contentObj.transform, false);
|
||||
|
||||
RectTransform cardRect = card.AddComponent<RectTransform>();
|
||||
cardRect.sizeDelta = new Vector2(cardWidth, cardHeight);
|
||||
|
||||
LayoutElement cardLayout = card.AddComponent<LayoutElement>();
|
||||
cardLayout.preferredWidth = cardWidth;
|
||||
cardLayout.preferredHeight = cardHeight;
|
||||
cardLayout.minWidth = cardWidth;
|
||||
cardLayout.minHeight = cardHeight;
|
||||
cardLayout.flexibleWidth = 0f;
|
||||
cardLayout.flexibleHeight = 0f;
|
||||
|
||||
Image cardImg = card.AddComponent<Image>();
|
||||
cardImg.color = new Color(0.1f, 0.1f, 0.2f, 1f);
|
||||
|
||||
GameObject imgObj = new GameObject("ModImage");
|
||||
imgObj.transform.SetParent(card.transform, false);
|
||||
|
||||
RectTransform imgRect = imgObj.AddComponent<RectTransform>();
|
||||
imgRect.anchorMin = Vector2.zero;
|
||||
imgRect.anchorMax = Vector2.one;
|
||||
imgRect.offsetMin = new Vector2(0f, 120f);
|
||||
imgRect.offsetMax = Vector2.zero;
|
||||
|
||||
Image modImg = imgObj.AddComponent<Image>();
|
||||
|
||||
if (mod.modSprite != null)
|
||||
modImg.sprite = mod.modSprite;
|
||||
|
||||
modImg.preserveAspect = true;
|
||||
modImg.raycastTarget = false;
|
||||
|
||||
GameObject btnObj = new GameObject("PlayButton");
|
||||
btnObj.transform.SetParent(card.transform, false);
|
||||
|
||||
RectTransform btnRect = btnObj.AddComponent<RectTransform>();
|
||||
btnRect.anchorMin = new Vector2(0.5f, 0f);
|
||||
btnRect.anchorMax = new Vector2(0.5f, 0f);
|
||||
btnRect.pivot = new Vector2(0.5f, 0f);
|
||||
btnRect.sizeDelta = new Vector2(playButtonWidth, playButtonHeight);
|
||||
btnRect.anchoredPosition = new Vector2(0f, 10f);
|
||||
|
||||
Image btnImg = btnObj.AddComponent<Image>();
|
||||
btnImg.color = new Color(0.1f, 0.7f, 0.2f, 1f);
|
||||
|
||||
Button btn = btnObj.AddComponent<Button>();
|
||||
|
||||
GameObject txtObj = new GameObject("Text");
|
||||
txtObj.transform.SetParent(btnObj.transform, false);
|
||||
|
||||
RectTransform txtRect = txtObj.AddComponent<RectTransform>();
|
||||
txtRect.anchorMin = Vector2.zero;
|
||||
txtRect.anchorMax = Vector2.one;
|
||||
txtRect.offsetMin = Vector2.zero;
|
||||
txtRect.offsetMax = Vector2.zero;
|
||||
|
||||
TextMeshProUGUI tmp = txtObj.AddComponent<TextMeshProUGUI>();
|
||||
tmp.text = playButtonText;
|
||||
tmp.fontSize = 50f;
|
||||
tmp.alignment = TextAlignmentOptions.Center;
|
||||
tmp.color = Color.white;
|
||||
tmp.raycastTarget = false;
|
||||
|
||||
string sceneName = mod.sceneName;
|
||||
|
||||
btn.onClick.RemoveAllListeners();
|
||||
btn.onClick.AddListener(() =>
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(sceneName))
|
||||
{
|
||||
Debug.LogWarning("ModSelectManager: sceneName boş.");
|
||||
return;
|
||||
}
|
||||
|
||||
SceneManager.LoadScene(sceneName);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/3.5/Prefabs/ModSelectManager.cs.meta
Normal file
2
Assets/Scripts/3.5/Prefabs/ModSelectManager.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a2b4db01ffdbb4c418ce084b87659f0f
|
||||
19
Assets/Scripts/3.5/SoundManager.cs
Normal file
19
Assets/Scripts/3.5/SoundManager.cs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
using UnityEngine;
|
||||
|
||||
public class SoundManager : MonoBehaviour
|
||||
{
|
||||
public static SoundManager instance;
|
||||
public AudioSource audioSource;
|
||||
public AudioClip clickSound;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
instance = this;
|
||||
}
|
||||
|
||||
public void PlayClick()
|
||||
{
|
||||
if (audioSource && clickSound)
|
||||
audioSource.PlayOneShot(clickSound);
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/3.5/SoundManager.cs.meta
Normal file
2
Assets/Scripts/3.5/SoundManager.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1a1f2461a1242e640a3493747a8569fe
|
||||
8
Assets/Scripts/4.0.meta
Normal file
8
Assets/Scripts/4.0.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3eaa755588ef6dc4d866d6d46bd31fc1
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Scripts/4.0/game.meta
Normal file
8
Assets/Scripts/4.0/game.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0e64226fc93230e468c6e079da9aae49
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1223
Assets/Scripts/4.0/game/DialogueComplete22Mod.cs
Normal file
1223
Assets/Scripts/4.0/game/DialogueComplete22Mod.cs
Normal file
File diff suppressed because it is too large
Load diff
2
Assets/Scripts/4.0/game/DialogueComplete22Mod.cs.meta
Normal file
2
Assets/Scripts/4.0/game/DialogueComplete22Mod.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 61dd7d6ceab294248b449636b8a1782e
|
||||
1076
Assets/Scripts/4.0/game/DialogueQuestion23Mod.cs
Normal file
1076
Assets/Scripts/4.0/game/DialogueQuestion23Mod.cs
Normal file
File diff suppressed because it is too large
Load diff
2
Assets/Scripts/4.0/game/DialogueQuestion23Mod.cs.meta
Normal file
2
Assets/Scripts/4.0/game/DialogueQuestion23Mod.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 538fa4417c4f71a46ac17c5757fd58e0
|
||||
1003
Assets/Scripts/4.0/game/ImageWord18Mod.cs
Normal file
1003
Assets/Scripts/4.0/game/ImageWord18Mod.cs
Normal file
File diff suppressed because it is too large
Load diff
2
Assets/Scripts/4.0/game/ImageWord18Mod.cs.meta
Normal file
2
Assets/Scripts/4.0/game/ImageWord18Mod.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 50748c22127712a49a561ea211e5e37f
|
||||
1205
Assets/Scripts/4.0/game/ImageWord19Mod.cs
Normal file
1205
Assets/Scripts/4.0/game/ImageWord19Mod.cs
Normal file
File diff suppressed because it is too large
Load diff
2
Assets/Scripts/4.0/game/ImageWord19Mod.cs.meta
Normal file
2
Assets/Scripts/4.0/game/ImageWord19Mod.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b3cc7e81eafd2c545b3e3bdf2caa5eae
|
||||
1288
Assets/Scripts/4.0/game/ImageWord20Mod.cs
Normal file
1288
Assets/Scripts/4.0/game/ImageWord20Mod.cs
Normal file
File diff suppressed because it is too large
Load diff
2
Assets/Scripts/4.0/game/ImageWord20Mod.cs.meta
Normal file
2
Assets/Scripts/4.0/game/ImageWord20Mod.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7224becc3185c2c4082b7a3239f14a17
|
||||
1366
Assets/Scripts/4.0/game/MissingLetters14Mod.cs
Normal file
1366
Assets/Scripts/4.0/game/MissingLetters14Mod.cs
Normal file
File diff suppressed because it is too large
Load diff
2
Assets/Scripts/4.0/game/MissingLetters14Mod.cs.meta
Normal file
2
Assets/Scripts/4.0/game/MissingLetters14Mod.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: eb226f785cec9b14d981b272d70f9b04
|
||||
1128
Assets/Scripts/4.0/game/ParagraphFill26Mod.cs
Normal file
1128
Assets/Scripts/4.0/game/ParagraphFill26Mod.cs
Normal file
File diff suppressed because it is too large
Load diff
2
Assets/Scripts/4.0/game/ParagraphFill26Mod.cs.meta
Normal file
2
Assets/Scripts/4.0/game/ParagraphFill26Mod.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: fe8c1b46957e6224c932624f5702a716
|
||||
1258
Assets/Scripts/4.0/game/ParagraphOrder27Mod.cs
Normal file
1258
Assets/Scripts/4.0/game/ParagraphOrder27Mod.cs
Normal file
File diff suppressed because it is too large
Load diff
2
Assets/Scripts/4.0/game/ParagraphOrder27Mod.cs.meta
Normal file
2
Assets/Scripts/4.0/game/ParagraphOrder27Mod.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a2a6355bbf47b3a4caca990aad5a9ada
|
||||
1211
Assets/Scripts/4.0/game/ParagraphReading24Mod.cs
Normal file
1211
Assets/Scripts/4.0/game/ParagraphReading24Mod.cs
Normal file
File diff suppressed because it is too large
Load diff
2
Assets/Scripts/4.0/game/ParagraphReading24Mod.cs.meta
Normal file
2
Assets/Scripts/4.0/game/ParagraphReading24Mod.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d2ec54f76aab0954eafe3db5d61be279
|
||||
1109
Assets/Scripts/4.0/game/ParagraphTrueFalse25Mod.cs
Normal file
1109
Assets/Scripts/4.0/game/ParagraphTrueFalse25Mod.cs
Normal file
File diff suppressed because it is too large
Load diff
2
Assets/Scripts/4.0/game/ParagraphTrueFalse25Mod.cs.meta
Normal file
2
Assets/Scripts/4.0/game/ParagraphTrueFalse25Mod.cs.meta
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f3452baaffc11c74aa6442f8fe9e9d46
|
||||
1369
Assets/Scripts/4.0/game/Pronunciation13Mod.cs
Normal file
1369
Assets/Scripts/4.0/game/Pronunciation13Mod.cs
Normal file
File diff suppressed because it is too large
Load diff
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue