SceneryGenerator.cs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. using UnityEngine;
  2. using System.Collections.Generic;
  3. using System;
  4. /// <summary>
  5. /// This component is responsible for creating scenery props randomly selected from <code>sceneryPrefabs</code>
  6. /// The randomness does not use the <code>RandomSingleton</code>. This is due to the fact that we don't have control
  7. /// of order of execution (unless we use Execution Order feature which we find hacky). So since it doesn't affect the
  8. /// gameplay as such, for now we decided to use Unity's random which is independent from RandomSingleton used to
  9. /// generate the enemies.
  10. /// </summary>
  11. public class SceneryGenerator : MonoBehaviour
  12. {
  13. public static SceneryGenerator Instance;
  14. /// <summary>
  15. /// Prefabs will be randomly selected from here with gamedesigner-set weights
  16. /// To create prefabs, the sprites will probably be normal textures, rather than part of an atlas. This is because
  17. /// they will be quite big and would defeat the purpose of putting them in an atlas. So in NGUI you can create
  18. /// a texture widget, where you just drag and drop the texture on the widget's texture field. You might need
  19. /// to change the shader so it's transparent as well. The widget's pivot needs to be set carefully.
  20. /// The horizontal pivolt must always be set to the right pivot. If it's a top-bottom prop, leave the vertical pivot to middle.
  21. /// Otherwise set it accordingly, e.g. if it's a prop coming from the top, set the vertical pivot to top.
  22. /// Reset the transform's position to zero
  23. /// </summary>
  24. public LootTable sceneryPrefabs;
  25. public int minSpacing = 300;
  26. public int maxSpacing = 600;
  27. /// <summary>
  28. /// Tweak this value to get a parallax effect
  29. /// </summary>
  30. public float speed = 150;
  31. /// <summary>
  32. /// This is the z value used for the generated props, where together with the appropriate speed
  33. /// will achieve a parallax effect.
  34. /// For foreground we are currently using -2 (in front of bullets)
  35. /// For midground we are currently using 9 (just in front of backgrounds)
  36. /// </summary>
  37. public float zValue;
  38. Transform _anchor;
  39. List<Transform> _sceneryPropsTransforms = new List<Transform>();
  40. List<SceneryProp> _sceneryProps = new List<SceneryProp>();
  41. float _nextSceneryX;
  42. float _originalSpeed;
  43. bool _isSpawning;
  44. public bool _isPlaying = false;
  45. const int STOP_SPAWNING_AT_TIME_LEFT = 18;
  46. #region Unity Callbacks
  47. void Awake()
  48. {
  49. Instance = this;
  50. _anchor = SkinDownloadManager.Instance.sceneryAnchor;
  51. _originalSpeed = speed;
  52. if (enabled) //for debugging purposes so we can disable the component at design time for a debug session
  53. {
  54. enabled = false;
  55. NotificationCenter.AddListener(OnGameStart, NotificationType.GameStart);
  56. NotificationCenter.AddListener(OnEndLife, NotificationType.EndLife);
  57. NotificationCenter.AddListener(OnGetLife, NotificationType.GetLife);
  58. NotificationCenter.AddListener(OnGameOver, NotificationType.GameOver);
  59. NotificationCenter.AddListener(OnChangeScrollingSpeed, NotificationType.ChangeScrollingSpeed);
  60. NotificationCenter.AddListener(OnTimeLeftUpdate, NotificationType.TimeLeftUpdate);
  61. }
  62. }
  63. private void OnGetLife(Notification note)
  64. {
  65. //_isPlaying = true;
  66. }
  67. private void OnEndLife(Notification note)
  68. {
  69. _isPlaying = false;
  70. }
  71. void OnDestroy()
  72. {
  73. NotificationCenter.RemoveListener(OnGameStart, NotificationType.GameStart);
  74. NotificationCenter.RemoveListener(OnGameOver, NotificationType.GameOver);
  75. NotificationCenter.RemoveListener(OnChangeScrollingSpeed, NotificationType.ChangeScrollingSpeed);
  76. NotificationCenter.RemoveListener(OnTimeLeftUpdate, NotificationType.TimeLeftUpdate);
  77. NotificationCenter.RemoveListener(OnEndLife, NotificationType.EndLife);
  78. NotificationCenter.RemoveListener(OnGetLife, NotificationType.GetLife);
  79. }
  80. void Update()
  81. {
  82. if (!BackgroundManager.Instance._isPlaying)
  83. {
  84. return;
  85. }
  86. float deltaX = speed * Time.deltaTime;
  87. if (_isSpawning)
  88. {
  89. _nextSceneryX += deltaX;
  90. //if the next scenery marker is visible, create the next prop
  91. if (_nextSceneryX > -GameConstants.GAME_WIDTH/2)
  92. {
  93. CreateNextSceneryProp();
  94. }
  95. }
  96. for (int i = _sceneryPropsTransforms.Count-1; i >= 0; i--)
  97. {
  98. Transform sceneryPropTransform = _sceneryPropsTransforms[i];
  99. SceneryProp sceneryProp = _sceneryProps[i];
  100. //move scenery
  101. sceneryPropTransform.localPosition += new Vector3(deltaX, 0, 0);
  102. //check if needs to be removed
  103. if (sceneryPropTransform.localPosition.x + sceneryProp.MinX > GameConstants.GAME_WIDTH/2)
  104. {
  105. sceneryProp.Despawn();
  106. _sceneryPropsTransforms.RemoveAt(i);
  107. _sceneryProps.RemoveAt(i);
  108. }
  109. }
  110. }
  111. #endregion
  112. #region Notification Callbacks
  113. void OnGameStart(Notification note)
  114. {
  115. enabled = true;
  116. _isSpawning = true;
  117. _isPlaying = true;
  118. _nextSceneryX -= UnityEngine.Random.Range(minSpacing, maxSpacing);
  119. }
  120. void OnGameOver(Notification note)
  121. {
  122. enabled = false;
  123. foreach (SceneryProp s in _sceneryProps)
  124. {
  125. s.Despawn();
  126. }
  127. _sceneryPropsTransforms.Clear();
  128. _sceneryProps.Clear();
  129. }
  130. void OnChangeScrollingSpeed(Notification note)
  131. {
  132. float scrollingSpeedFactor = (float)note.data;
  133. speed = _originalSpeed * scrollingSpeedFactor;
  134. }
  135. void OnTimeLeftUpdate(Notification note)
  136. {
  137. float timeLeft = (float)note.data;
  138. //Stop spawning stuff so that it doesn't intermingle with the end of level scenery
  139. if (_isSpawning && timeLeft <= STOP_SPAWNING_AT_TIME_LEFT)
  140. {
  141. _isSpawning = false;
  142. }
  143. }
  144. #endregion
  145. void CreateNextSceneryProp()
  146. {
  147. Transform sceneryPropTransform = sceneryPrefabs.GetRandomItem();
  148. SceneryProp sceneryProp = sceneryPropTransform.GetComponent<SceneryProp>();
  149. Vector3 originalPos = sceneryPropTransform.localPosition;
  150. originalPos.x = _nextSceneryX - sceneryProp.MaxX;
  151. originalPos.z = zValue;
  152. Vector3 originalScale = sceneryPropTransform.localScale;
  153. sceneryPropTransform.parent = _anchor;
  154. sceneryPropTransform.localPosition = originalPos;
  155. sceneryPropTransform.localScale = originalScale;
  156. _sceneryPropsTransforms.Add(sceneryPropTransform);
  157. _sceneryProps.Add(sceneryProp);
  158. _nextSceneryX += sceneryProp.MinX;
  159. _nextSceneryX -= UnityEngine.Random.Range(minSpacing, maxSpacing);
  160. //add some randomness in flipping on the X axis
  161. bool isXFlipped = UnityEngine.Random.value < 0.5f;
  162. if (isXFlipped)
  163. {
  164. UITexture uiTexture = sceneryPropTransform.GetComponent<UITexture>();
  165. if (uiTexture != null) //if it is null, it must be some composite scenery prop with multiple UITextures... just skip it in that case
  166. {
  167. Rect r = uiTexture.uvRect;
  168. r.x = 1;
  169. r.width = -1;
  170. uiTexture.uvRect = r;
  171. }
  172. }
  173. }
  174. }