220 lines
10 KiB
C#
220 lines
10 KiB
C#
|
|
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);
|
|||
|
|
}
|