BackgroundManager.cs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. using UnityEngine;
  2. using System.Collections.Generic;
  3. using System;
  4. using UnityEngine.UI;
  5. using System.Collections;
  6. /// <summary>
  7. /// This component is responsible for creating a seamless background
  8. /// </summary>
  9. public class BackgroundManager : MonoBehaviour
  10. {
  11. public static BackgroundManager Instance;
  12. public Transform backgroundPrefab;
  13. public Texture[] backgroundTextures;
  14. public Transform anchor;
  15. public float speed = -100;
  16. public bool shuffle = false;
  17. public float scaleFactor = 1;
  18. const int NUM_OF_BACKGROUNDS = 3;
  19. public RectTransform BackResolution;
  20. public Canvas Canvas;
  21. float _backgroundWidth;
  22. List<Transform> _backgrounds;
  23. int _nextTextureIndex;
  24. float _originalSpeed;
  25. public bool _isPlaying;
  26. void Awake()
  27. {
  28. Instance = this;
  29. _originalSpeed = speed;
  30. NotificationCenter.AddListener(GameStart, NotificationType.GameStart);
  31. NotificationCenter.AddListener(OnChangeScrollingSpeed, NotificationType.ChangeScrollingSpeed);
  32. NotificationCenter.AddListener(OnApplySkinBackground, NotificationType.ApplySkinBackgrounds);
  33. NotificationCenter.AddListener(OnEndLife, NotificationType.EndLife);
  34. NotificationCenter.AddListener(OnGetLife, NotificationType.GetLife);
  35. }
  36. private void OnGetLife(Notification note)
  37. {
  38. //_isPlaying = true;
  39. }
  40. private void GameStart(Notification note)
  41. {
  42. _isPlaying = true;
  43. }
  44. void OnDestroy()
  45. {
  46. NotificationCenter.RemoveListener(GameStart, NotificationType.GameStart);
  47. NotificationCenter.RemoveListener(OnChangeScrollingSpeed, NotificationType.ChangeScrollingSpeed);
  48. NotificationCenter.RemoveListener(OnApplySkinBackground, NotificationType.ApplySkinBackgrounds);
  49. NotificationCenter.RemoveListener(OnEndLife, NotificationType.EndLife);
  50. NotificationCenter.RemoveListener(OnGetLife, NotificationType.GetLife);
  51. }
  52. private void OnEndLife(Notification note)
  53. {
  54. _isPlaying = false;
  55. }
  56. void Start()
  57. {
  58. StartCoroutine(Init());
  59. }
  60. IEnumerator Init()
  61. {
  62. yield return new WaitForEndOfFrame();
  63. _backgrounds = new List<Transform>(NUM_OF_BACKGROUNDS);
  64. //We need to calculate the background width, taking into consideration the scale change done to fix the aspect ratio problem (See AspectRatioFixer)
  65. //This will make sure that the whole background will be visible on any device
  66. _backgroundWidth = RectTransformUtility.PixelAdjustRect(BackResolution, Canvas).size.x;
  67. GameConstants.GAME_HEIGHT = (int)RectTransformUtility.PixelAdjustRect(BackResolution, Canvas).size.y;
  68. GameConstants.GAME_WIDTH = (int)_backgroundWidth;
  69. int nextZ = 0;
  70. for (int i = NUM_OF_BACKGROUNDS-1; i >= 0; i--)
  71. {
  72. RectTransform background = (RectTransform)Instantiate(backgroundPrefab);
  73. background.gameObject.SetActive(true);
  74. RawImage uiTexture = background.GetComponentInChildren<RawImage>();
  75. //make a clone of the material, otherwise the background instances would be pointing to the same material
  76. Material materialClone = new Material(uiTexture.material);
  77. uiTexture.material = materialClone;
  78. background.SetParent(anchor);
  79. background.localPosition = Vector3.zero;
  80. background.localScale = Vector3.one;
  81. background.sizeDelta = RectTransformUtility.PixelAdjustRect(BackResolution, Canvas).size;
  82. //background.localScale = new Vector3(scaleFactor, scaleFactor, background.localScale.z);
  83. background.anchoredPosition = new Vector3(_backgroundWidth* scaleFactor * (i-1), 0,0); //-1 so we have one on the left, one in the middle and one on the right
  84. _backgrounds.Add(background);
  85. SetNextTextureForBackground(background);
  86. }
  87. }
  88. void Update()
  89. {
  90. if (!_isPlaying)
  91. {
  92. return;
  93. }
  94. bool shouldUpdateZPositions = false;
  95. foreach (Transform b in _backgrounds)
  96. {
  97. //move background
  98. b.localPosition += new Vector3(speed*Time.deltaTime, 0, 0);
  99. //check if needs to be wrapped
  100. if (b.localPosition.x - _backgroundWidth/2 > GameConstants.GAME_WIDTH/2)
  101. {
  102. b.localPosition -= new Vector3(_backgroundWidth * NUM_OF_BACKGROUNDS, 0);
  103. shouldUpdateZPositions = true;
  104. SetNextTextureForBackground(b);
  105. }
  106. }
  107. //if (shouldUpdateZPositions)
  108. //{
  109. // UpdateZPositions();
  110. //}
  111. }
  112. void OnChangeScrollingSpeed(Notification note)
  113. {
  114. float scrollingSpeedFactor = (float)note.data;
  115. speed = _originalSpeed * scrollingSpeedFactor;
  116. }
  117. /// <summary>
  118. /// Updates the Z positions of the backgrounds, so that the first background on the right will be closer to the camera.
  119. /// The prefabs are made in such a way so that there is a bit of clamping bleeding on the right of the plane.
  120. /// This helps avoid flickering of the edges by overlapping the planes. The order of rendering is enforced through
  121. /// setting the Z positions accordingly. Without this fix of using overlapping planes, the flickering would occur due to
  122. /// moving the backgrounds at non-pixel perfect updates per frame.
  123. /// </summary>
  124. void UpdateZPositions()
  125. {
  126. Transform pushedToBack = _backgrounds[0];
  127. _backgrounds.RemoveAt(0);
  128. _backgrounds.Add(pushedToBack);
  129. int nextZ = (int)backgroundPrefab.localPosition.z;
  130. for (int i = _backgrounds.Count-1; i >= 0; i--)
  131. {
  132. Transform b = _backgrounds[i];
  133. Vector3 newPos = b.localPosition;
  134. newPos.z = nextZ--;
  135. b.localPosition = newPos;
  136. }
  137. }
  138. void SetNextTextureForBackground(Transform background)
  139. {
  140. //choose a random texture
  141. RawImage uiSprite = background.GetComponentInChildren<RawImage>();
  142. if (shuffle)
  143. {
  144. _nextTextureIndex = UnityEngine.Random.Range(0, backgroundTextures.Length);
  145. } else
  146. {
  147. --_nextTextureIndex;
  148. if (_nextTextureIndex < 0)
  149. {
  150. _nextTextureIndex = backgroundTextures.Length-1;
  151. }
  152. }
  153. uiSprite.texture = backgroundTextures[_nextTextureIndex];
  154. }
  155. void OnApplySkinBackground(Notification note)
  156. {
  157. Texture[] textures = (Texture[])note.data;
  158. backgroundTextures = textures;
  159. foreach (Transform background in _backgrounds)
  160. {
  161. SetNextTextureForBackground(background);
  162. }
  163. }
  164. }