123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- using UnityEngine;
- using System.Collections.Generic;
- using System;
- /// <summary>
- /// This component is responsible for creating a seamless background
- /// </summary>
- public class BackgroundManager : MonoBehaviour
- {
- public static BackgroundManager Instance;
- public Transform backgroundPrefab;
- public Texture[] backgroundTextures;
- public Transform anchor;
- public float speed = -100;
- public bool shuffle = false;
- const int NUM_OF_BACKGROUNDS = 3;
- float _backgroundWidth;
- List<Transform> _backgrounds;
- int _nextTextureIndex;
- float _originalSpeed;
- public bool _isPlaying;
- void Awake()
- {
- Instance = this;
- _originalSpeed = speed;
-
- NotificationCenter.AddListener(GameStart, NotificationType.GameStart);
- NotificationCenter.AddListener(OnChangeScrollingSpeed, NotificationType.ChangeScrollingSpeed);
- NotificationCenter.AddListener(OnApplySkinBackground, NotificationType.ApplySkinBackgrounds);
- NotificationCenter.AddListener(OnEndLife, NotificationType.EndLife);
- NotificationCenter.AddListener(OnGetLife, NotificationType.GetLife);
- }
- private void OnGetLife(Notification note)
- {
- //_isPlaying = true;
- }
- private void GameStart(Notification note)
- {
- _isPlaying = true;
- }
- void OnDestroy()
- {
- NotificationCenter.RemoveListener(GameStart, NotificationType.GameStart);
- NotificationCenter.RemoveListener(OnChangeScrollingSpeed, NotificationType.ChangeScrollingSpeed);
- NotificationCenter.RemoveListener(OnApplySkinBackground, NotificationType.ApplySkinBackgrounds);
- NotificationCenter.RemoveListener(OnEndLife, NotificationType.EndLife);
- NotificationCenter.RemoveListener(OnGetLife, NotificationType.GetLife);
- }
- private void OnEndLife(Notification note)
- {
- _isPlaying = false;
- }
- void Start()
- {
- _backgrounds = new List<Transform>(NUM_OF_BACKGROUNDS);
- //We need to calculate the background width, taking into consideration the scale change done to fix the aspect ratio problem (See AspectRatioFixer)
- //This will make sure that the whole background will be visible on any device
- _backgroundWidth = backgroundPrefab.transform.localScale.x * AspectRatioFixer.ScaleChange;
- int nextZ = (int)backgroundPrefab.localPosition.z;
- for (int i = NUM_OF_BACKGROUNDS-1; i >= 0; i--)
- {
- Transform background = (Transform)Instantiate(backgroundPrefab);
- UITexture uiTexture = background.GetComponentInChildren<UITexture>();
- //make a clone of the material, otherwise the background instances would be pointing to the same material
- Material materialClone = new Material(uiTexture.material);
- uiTexture.material = materialClone;
- background.parent = anchor;
- background.localScale = new Vector3(_backgroundWidth, _backgroundWidth, background.localScale.z);
- background.localPosition = new Vector3(_backgroundWidth * (i-1), 0, nextZ++); //-1 so we have one on the left, one in the middle and one on the right
- _backgrounds.Add(background);
- SetNextTextureForBackground(background);
- }
- }
- void Update()
- {
- if (!_isPlaying)
- {
- return;
- }
- bool shouldUpdateZPositions = false;
- foreach (Transform b in _backgrounds)
- {
- //move background
- b.localPosition += new Vector3(speed*Time.deltaTime, 0, 0);
- //check if needs to be wrapped
- if (b.localPosition.x - _backgroundWidth/2 > GameConstants.GAME_WIDTH/2)
- {
- b.localPosition -= new Vector3(_backgroundWidth * NUM_OF_BACKGROUNDS, 0);
- shouldUpdateZPositions = true;
- SetNextTextureForBackground(b);
- }
- }
- if (shouldUpdateZPositions)
- {
- UpdateZPositions();
- }
- }
- void OnChangeScrollingSpeed(Notification note)
- {
- float scrollingSpeedFactor = (float)note.data;
- speed = _originalSpeed * scrollingSpeedFactor;
- }
- /// <summary>
- /// Updates the Z positions of the backgrounds, so that the first background on the right will be closer to the camera.
- /// The prefabs are made in such a way so that there is a bit of clamping bleeding on the right of the plane.
- /// This helps avoid flickering of the edges by overlapping the planes. The order of rendering is enforced through
- /// setting the Z positions accordingly. Without this fix of using overlapping planes, the flickering would occur due to
- /// moving the backgrounds at non-pixel perfect updates per frame.
- /// </summary>
- void UpdateZPositions()
- {
- Transform pushedToBack = _backgrounds[0];
- _backgrounds.RemoveAt(0);
- _backgrounds.Add(pushedToBack);
- int nextZ = (int)backgroundPrefab.localPosition.z;
- for (int i = _backgrounds.Count-1; i >= 0; i--)
- {
- Transform b = _backgrounds[i];
- Vector3 newPos = b.localPosition;
- newPos.z = nextZ--;
- b.localPosition = newPos;
- }
- }
- void SetNextTextureForBackground(Transform background)
- {
- //choose a random texture
- UITexture uiTexture = background.GetComponentInChildren<UITexture>();
- if (shuffle)
- {
- _nextTextureIndex = UnityEngine.Random.Range(0, backgroundTextures.Length);
- } else
- {
- --_nextTextureIndex;
- if (_nextTextureIndex < 0)
- {
- _nextTextureIndex = backgroundTextures.Length-1;
- }
- }
- uiTexture.mainTexture = backgroundTextures[_nextTextureIndex];
- }
-
- void OnApplySkinBackground(Notification note)
- {
- Texture2D[] textures = (Texture2D[])note.data;
- backgroundTextures = textures;
-
- foreach (Transform background in _backgrounds)
- {
- SetNextTextureForBackground(background);
- }
- }
- }
|