SHARE
TWEET

Untitled

a guest Nov 17th, 2019 83 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.UI;
  5.  
  6. namespace AHG.QuizRedux
  7. {
  8.     public class QuizManager : MonoBehaviour
  9.     {
  10. #pragma warning disable CS0649
  11.         [Header("Панель проведения викторины")]
  12.         [SerializeField] private GameObject questionPanel;
  13.         [SerializeField] private GameObject questionImgObj;
  14.         [SerializeField] private Text questionText;
  15.         [SerializeField] private Text timerText;
  16.         [SerializeField] private CanvasGroup answerBtnsGroup;
  17.         [SerializeField] private Button[] answerBtns;
  18.         [SerializeField] private Image questionImage;
  19.         [SerializeField] private GameObject questionImageFullPanel;
  20.         [SerializeField] private Image questionImageFull;
  21.         [SerializeField] private Text questionImgText;
  22.         [Header("Панель правильности ответа")]
  23.         [SerializeField] private Image answerPanelImg;
  24.         [SerializeField] private Text answerStateText;
  25.         [SerializeField] private Image answerStateImage;
  26.         [SerializeField] private Text questionCounterText;
  27.         [SerializeField] private Sprite[] answerStateIcons;
  28. #pragma warning restore CS0649
  29.  
  30.         private const string ANIM_SHOW_QUESTION = "ShowQuestion", ANIM_HIDE_QUESTION = "HideQuestion", ANIM_SHOW_ANSWER = "ShowAnswer",
  31.             ANIM_HIDE_ANSWER = "HideAnswer", ANIM_SHOW_FIMAGE = "ShowFullImage", ANIM_HIDE_FIMAGE = "HideFullImage";
  32.         private readonly string[] ANSWER_TYPES_TITLES = { "Правильный ответ", "Неправильный ответ", "Время вышло" };
  33.  
  34.         private Category currentCategory;
  35.         private Question currentQuestion;
  36.  
  37.         private Coroutine timerCoroutine;
  38.  
  39.         private Queue<Question> questionsQueue = new Queue<Question>();
  40.  
  41.         #region Singleton
  42.         public static QuizManager Instance { get; private set; }
  43.         private void InitSingleton()
  44.         {
  45.             if (Instance == null)
  46.                 Instance = this;
  47.         }
  48.         #endregion
  49.  
  50.         private void Awake() {
  51.             InitSingleton();
  52.         }
  53.         /// <summary>
  54.         ///Старт игры с указанной категорией.
  55.         /// </summary>
  56.         /// <param name="category">Категория для старта игры.</param>
  57.         public void Play(Category category)
  58.         {
  59.             if (currentCategory != null) return;
  60.             currentCategory = category;
  61.             GenerateQuestions();
  62.         }
  63.         /// <summary>
  64.         /// Переключить показ изображения в большем размере.
  65.         /// </summary>
  66.         /// <param name="full">Показать изображение в большем размере?</param>
  67.         public void ToggleImageView(bool full)
  68.         {
  69.             if (full) questionImageFull.sprite = currentQuestion.Image;
  70.             GameManager.Instance.PlayAnimation(full ? ANIM_SHOW_FIMAGE : ANIM_HIDE_FIMAGE, 3);
  71.         }
  72.         /// <summary>
  73.         /// Сгенерировать новый список вопросов.
  74.         /// </summary>
  75.         private void GenerateQuestions()
  76.         {
  77.             List<Question> questions = new List<Question>(currentCategory.Questions);
  78.             for (int i = 0; i < currentCategory.Questions.Count; i++)
  79.             {
  80.                 int id = Random.Range(0, questions.Count);
  81.                 Question q = new Question(questions[id].Text, questions[id].Image, new string[3], -1);
  82.                 int correctAnswerID = questions[id].CorrectAnswerID;
  83.                 List<string> answers = new List<string>(questions[id].Answers);
  84.                 for (int a = 0; a < q.Answers.Length; a++)
  85.                 {
  86.                     int answerID = Random.Range(0, answers.Count);
  87.                     q.Answers[a] = answers[answerID];
  88.                     if (q.CorrectAnswerID == -1)
  89.                     {
  90.                         if (answerID == correctAnswerID) q.CorrectAnswerID = a;
  91.                         else if (answerID < correctAnswerID) correctAnswerID--;
  92.                     }
  93.                     answers.RemoveAt(answerID);
  94.                 }
  95.                 questionsQueue.Enqueue(q);
  96.                 questions.RemoveAt(id);
  97.             }
  98.             ShowQuestion();
  99.         }
  100.         /// <summary>
  101.         /// Показать случайный вопрос из списка.
  102.         /// </summary>
  103.         private void ShowQuestion()
  104.         {
  105.             Time = currentCategory.AnswerTime;
  106.             answerBtnsGroup.interactable = false;
  107.             if (questionsQueue.Count > 0)
  108.             {
  109.                 currentQuestion = questionsQueue.Dequeue();
  110.                 if (currentQuestion.Image != null) questionImage.sprite = currentQuestion.Image;
  111.                 questionImgObj.SetActive(currentQuestion.Image != null);
  112.                 questionText.gameObject.SetActive(currentQuestion.Image == null);
  113.                 questionText.text = questionImgText.text = currentQuestion.Text;
  114.                 for (int i = 0; i < currentQuestion.Answers.Length; i++)
  115.                     answerBtns[i].GetComponentInChildren<Text>().text = currentQuestion.Answers[i];
  116.                 GameManager.Instance.PlayAnimation(ANIM_SHOW_QUESTION);
  117.                 GameManager.Instance.WaitForSeconds(GameManager.Instance.GetAnimationLength(ANIM_SHOW_QUESTION), () => {
  118.                     answerBtnsGroup.interactable = true;
  119.                     ToggleTimer(true);
  120.                 });
  121.             }
  122.             else
  123.             {
  124.                 // Тут можно добавить действия при окончании категории.
  125.                 ResetQuiz();
  126.             }
  127.         }
  128.         /// <summary>
  129.         /// Выбрать вариант ответа.
  130.         /// </summary>
  131.         /// <param name="id">Идентификатор ответа.</param>
  132.         public void SelectAnswer(int id) => StartCoroutine(
  133.             IESelectAnswer(Time > 0 && id == currentQuestion.CorrectAnswerID ? AnswerType.Correct : AnswerType.Wrong));
  134.  
  135.         private IEnumerator IESelectAnswer(AnswerType type)
  136.         {
  137.             ToggleTimer(false);
  138.             answerBtnsGroup.interactable = false;
  139.             if (type != AnswerType.TimeOver) yield return new WaitForSeconds(1);
  140.             answerStateImage.sprite = answerStateIcons[type == AnswerType.Correct ? 0 : 1];
  141.             GameManager.Instance.PlayAnimation(ANIM_HIDE_QUESTION);
  142.             if (questionImageFullPanel.activeSelf) ToggleImageView(false);
  143.             answerStateText.text = ANSWER_TYPES_TITLES[(int)type];
  144.             int crntQuestionIndex = currentCategory.Questions.Count - questionsQueue.Count;
  145.             questionCounterText.text = $"{crntQuestionIndex}/{currentCategory.Questions.Count}";
  146.             answerPanelImg.color = type == AnswerType.Correct ? Colors.Green : Colors.LightRed;
  147.             GameManager.Instance.PlayAnimation(ANIM_SHOW_ANSWER, 2);
  148.             yield return new WaitForSeconds(GameManager.Instance.GetAnimationLength(ANIM_SHOW_ANSWER));
  149.             yield return new WaitForSeconds(2);
  150.             // Это сделано лишь для удобного разделения по методам.
  151.             switch (type)
  152.             {
  153.                 case AnswerType.Wrong: WrongAnswer(); break;
  154.                 case AnswerType.TimeOver: TimeOver(); break;
  155.                 case AnswerType.Correct: CorrectAnswer(); break;
  156.             }
  157.         }
  158.         /// <summary>
  159.         /// Метод, который вызывается при окончании времени.
  160.         /// </summary>
  161.         private void TimeOver()
  162.         {
  163.             // Тут можно добавить действия при окончании времени.
  164.             ResetQuiz();
  165.         }
  166.         /// <summary>
  167.         /// Метод, который вызывается при неправильном ответе.
  168.         /// </summary>
  169.         private void WrongAnswer()
  170.         {
  171.             // Тут можно добавить действия при неправильном ответе.
  172.             ResetQuiz();
  173.         }
  174.         /// <summary>
  175.         /// Метод, который вызывается при правильном ответе.
  176.         /// </summary>
  177.         private void CorrectAnswer()
  178.         {
  179.             // Тут можно добавить действия при правильном ответе.
  180.             GameManager.Instance.PlayAnimation(ANIM_HIDE_ANSWER, 2);
  181.             ShowQuestion();
  182.         }
  183.         /// <summary>
  184.         /// Восстановить викторину к начальному состоянию.
  185.         /// </summary>
  186.         private void ResetQuiz()
  187.         {
  188.             GameManager.Instance.PlayAnimation(ANIM_HIDE_ANSWER, 2);
  189.             GameManager.Instance.WaitForSeconds(GameManager.Instance.GetAnimationLength(ANIM_SHOW_ANSWER), () => {
  190.                 GameManager.Instance.ToggleHeader(false);
  191.                 questionsQueue.Clear();
  192.                 currentQuestion = null; currentCategory = null;
  193.             });
  194.         }
  195.         /// <summary>
  196.         /// Переключить таймер.
  197.         /// </summary>
  198.         /// <param name="start">Запустить таймер?</param>
  199.         private void ToggleTimer(bool start)
  200.         {
  201.             if (timerCoroutine != null)
  202.             {
  203.                 StopCoroutine(timerCoroutine);
  204.                 timerCoroutine = null;
  205.             }
  206.             if (start) timerCoroutine = StartCoroutine(IETimer());
  207.         }
  208.  
  209.         private IEnumerator IETimer()
  210.         {
  211.             while (Time > 0)
  212.             {
  213.                 yield return new WaitForSeconds(1);
  214.                 Time--;
  215.             }
  216.             StartCoroutine(IESelectAnswer(AnswerType.TimeOver));
  217.         }
  218.  
  219.         private int _time;
  220.         private int Time
  221.         {
  222.             get { return _time; }
  223.             set
  224.             {
  225.                 _time = value;
  226.                 timerText.text = _time.ToString();
  227.             }
  228.         }
  229.     }
  230. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top