Advertisement
Guest User

Untitled

a guest
Nov 17th, 2019
110
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.13 KB | None | 0 0
  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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement