123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- using UnityEngine;
- using System.Collections.Generic;
- using System;
- using UnityEngine.UI;
- /// <summary>
- /// This component is responsible for creating scenery props randomly selected from <code>sceneryPrefabs</code>
- /// The randomness does not use the <code>RandomSingleton</code>. This is due to the fact that we don't have control
- /// of order of execution (unless we use Execution Order feature which we find hacky). So since it doesn't affect the
- /// gameplay as such, for now we decided to use Unity's random which is independent from RandomSingleton used to
- /// generate the enemies.
- /// </summary>
- public class SceneryGenerator : MonoBehaviour
- {
- public static SceneryGenerator Instance;
- /// <summary>
- /// Prefabs will be randomly selected from here with gamedesigner-set weights
- /// To create prefabs, the sprites will probably be normal textures, rather than part of an atlas. This is because
- /// they will be quite big and would defeat the purpose of putting them in an atlas. So in NGUI you can create
- /// a texture widget, where you just drag and drop the texture on the widget's texture field. You might need
- /// to change the shader so it's transparent as well. The widget's pivot needs to be set carefully.
- /// The horizontal pivolt must always be set to the right pivot. If it's a top-bottom prop, leave the vertical pivot to middle.
- /// Otherwise set it accordingly, e.g. if it's a prop coming from the top, set the vertical pivot to top.
- /// Reset the transform's position to zero
- /// </summary>
- public LootTable sceneryPrefabs;
- public int minSpacing = 300;
- public int maxSpacing = 600;
-
- /// <summary>
- /// Tweak this value to get a parallax effect
- /// </summary>
- public float speed = 150;
- /// <summary>
- /// This is the z value used for the generated props, where together with the appropriate speed
- /// will achieve a parallax effect.
- /// For foreground we are currently using -2 (in front of bullets)
- /// For midground we are currently using 9 (just in front of backgrounds)
- /// </summary>
- public float zValue;
- Transform _anchor;
- List<Transform> _sceneryPropsTransforms = new List<Transform>();
- List<SceneryProp> _sceneryProps = new List<SceneryProp>();
- float _nextSceneryX = 0;
- float _originalSpeed;
- bool _isSpawning;
- public bool _isPlaying = false;
- const int STOP_SPAWNING_AT_TIME_LEFT = 18;
- #region Unity Callbacks
- void Awake()
- {
- Instance = this;
- _anchor = LevelsManager.Instance.levelEndAnchor;
- _originalSpeed = speed;
- if (enabled) //for debugging purposes so we can disable the component at design time for a debug session
- {
- enabled = false;
- NotificationCenter.AddListener(OnGameStart, NotificationType.GameStart);
- NotificationCenter.AddListener(OnEndLife, NotificationType.EndLife);
- NotificationCenter.AddListener(OnGetLife, NotificationType.GetLife);
- NotificationCenter.AddListener(OnGameOver, NotificationType.GameOver);
- NotificationCenter.AddListener(OnChangeScrollingSpeed, NotificationType.ChangeScrollingSpeed);
- NotificationCenter.AddListener(OnTimeLeftUpdate, NotificationType.TimeLeftUpdate);
- }
- }
- private void OnGetLife(Notification note)
- {
- //_isPlaying = true;
- }
- private void OnEndLife(Notification note)
- {
- _isPlaying = false;
- }
- void OnDestroy()
- {
- NotificationCenter.RemoveListener(OnGameStart, NotificationType.GameStart);
- NotificationCenter.RemoveListener(OnGameOver, NotificationType.GameOver);
- NotificationCenter.RemoveListener(OnChangeScrollingSpeed, NotificationType.ChangeScrollingSpeed);
- NotificationCenter.RemoveListener(OnTimeLeftUpdate, NotificationType.TimeLeftUpdate);
- NotificationCenter.RemoveListener(OnEndLife, NotificationType.EndLife);
- NotificationCenter.RemoveListener(OnGetLife, NotificationType.GetLife);
- }
- void Update()
- {
- if (!BackgroundManager.Instance._isPlaying)
- {
- return;
- }
- float deltaX = speed * Time.deltaTime;
- if (_isSpawning)
- {
- _nextSceneryX += deltaX;
- //if the next scenery marker is visible, create the next prop
- if (_nextSceneryX > -GameConstants.GAME_WIDTH/2)
- {
- CreateNextSceneryProp();
- }
- }
- for (int i = _sceneryPropsTransforms.Count-1; i >= 0; i--)
- {
- Transform sceneryPropTransform = _sceneryPropsTransforms[i];
- SceneryProp sceneryProp = _sceneryProps[i];
- //move scenery
- sceneryPropTransform.GetComponent<RectTransform>().anchoredPosition += new Vector2(deltaX, 0);
- //check if needs to be removed
- if (sceneryPropTransform.GetComponent<RectTransform>().anchoredPosition.x> GameConstants.GAME_WIDTH)
- {
- sceneryProp.Despawn();
- _sceneryPropsTransforms.RemoveAt(i);
- _sceneryProps.RemoveAt(i);
- }
- }
- }
- #endregion
- #region Notification Callbacks
- void OnGameStart(Notification note)
- {
- enabled = true;
- _isSpawning = true;
- _isPlaying = true;
- _nextSceneryX -= UnityEngine.Random.Range(minSpacing, maxSpacing);
- }
- void OnGameOver(Notification note)
- {
- enabled = false;
- foreach (SceneryProp s in _sceneryProps)
- {
- s.Despawn();
- }
- _sceneryPropsTransforms.Clear();
- _sceneryProps.Clear();
- }
- void OnChangeScrollingSpeed(Notification note)
- {
- float scrollingSpeedFactor = (float)note.data;
- speed = _originalSpeed * scrollingSpeedFactor;
- }
- void OnTimeLeftUpdate(Notification note)
- {
- float timeLeft = (float)note.data;
- //Stop spawning stuff so that it doesn't intermingle with the end of level scenery
- if (_isSpawning && timeLeft <= STOP_SPAWNING_AT_TIME_LEFT)
- {
- _isSpawning = false;
- }
- }
- #endregion
- void CreateNextSceneryProp()
- {
- Transform sceneryPropTransform = sceneryPrefabs.GetRandomItem();
- SceneryProp sceneryProp = sceneryPropTransform.GetComponent<SceneryProp>();
- Vector3 originalPos = sceneryPropTransform.GetComponent<RectTransform>().anchoredPosition;
- originalPos.x = _nextSceneryX /*- sceneryProp.MaxX*/;
- originalPos.z = zValue;
- Vector3 originalScale = sceneryPropTransform.localScale;
- sceneryPropTransform.SetParent(_anchor);
- sceneryPropTransform.GetComponent<RectTransform>().anchoredPosition = originalPos;
- sceneryPropTransform.localScale = originalScale;
- _sceneryPropsTransforms.Add(sceneryPropTransform);
- _sceneryProps.Add(sceneryProp);
- //_nextSceneryX += sceneryProp.MinX;
- _nextSceneryX -= UnityEngine.Random.Range(minSpacing, maxSpacing);
- //add some randomness in flipping on the X axis
- bool isXFlipped = UnityEngine.Random.value < 0.5f;
- if (isXFlipped)
- {
- RawImage uiTexture = sceneryPropTransform.GetComponent<RawImage>();
- if (uiTexture != null) //if it is null, it must be some composite scenery prop with multiple UITextures... just skip it in that case
- {
-
- Rect r = uiTexture.uvRect;
- r.x = 1;
- r.width = -1;
- uiTexture.uvRect = r;
- }
- }
- }
- }
|