using UnityEngine;
using System.Collections.Generic;
using System;
///
/// This component is responsible for creating scenery props randomly selected from sceneryPrefabs
/// The randomness does not use the RandomSingleton
. 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.
///
public class SceneryGenerator : MonoBehaviour
{
public static SceneryGenerator Instance;
///
/// 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
///
public LootTable sceneryPrefabs;
public int minSpacing = 300;
public int maxSpacing = 600;
///
/// Tweak this value to get a parallax effect
///
public float speed = 150;
///
/// 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)
///
public float zValue;
Transform _anchor;
List _sceneryPropsTransforms = new List();
List _sceneryProps = new List();
float _nextSceneryX;
float _originalSpeed;
bool _isSpawning;
public bool _isPlaying = false;
const int STOP_SPAWNING_AT_TIME_LEFT = 18;
#region Unity Callbacks
void Awake()
{
Instance = this;
_anchor = SkinDownloadManager.Instance.sceneryAnchor;
_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.localPosition += new Vector3(deltaX, 0, 0);
//check if needs to be removed
if (sceneryPropTransform.localPosition.x + sceneryProp.MinX > GameConstants.GAME_WIDTH/2)
{
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();
Vector3 originalPos = sceneryPropTransform.localPosition;
originalPos.x = _nextSceneryX - sceneryProp.MaxX;
originalPos.z = zValue;
Vector3 originalScale = sceneryPropTransform.localScale;
sceneryPropTransform.parent = _anchor;
sceneryPropTransform.localPosition = 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)
{
UITexture uiTexture = sceneryPropTransform.GetComponent();
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;
}
}
}
}