using UnityEngine; using GatherAndDefend.LevelEditor; using System.Collections; using UnityEngine.Tilemaps; using System.Threading.Tasks; using System; using GatherAndDefend.Events; using static LevelManager; /// The position the tile should be placed on /// the tile we should place /// the action of placing the tile on the tilemap /// public delegate Task PlacementAnimationHandler(GatherAndDefend.LevelEditor.TileData tileData, Action tilePlacement, Func shouldKillTask); public class LevelManagerScript : SingletonBehaviour { private Action updateAction = null; public bool loadOnStart = false; public Level firstLevel; [SerializeField] private SpriteRenderer _worldBackgroundSpriteRenderer; [SerializeField] private Sprite[] _worldBackgrounds; async void Start() { //only when the level is loaded do we start updating EventAggregator.Instance.GetEvent().Attach(Instance_LevelLoaded); EventAggregator.Instance.GetEvent().Attach(KillLoading); if (PlayerPrefs.GetInt(LoadingManager.LevelToLoad) >= 12) { _worldBackgroundSpriteRenderer.sprite = _worldBackgrounds[1]; } if (loadOnStart && firstLevel) { await LevelManager.Instance.LoadLevel(firstLevel, PlacementAnimation); } } void OnDestroy() { EventAggregator.Instance.GetEvent().Detach(KillLoading); updateAction = null; } void Update() { updateAction?.Invoke(); // Gala hack to win level instantly if (Input.GetKeyDown(KeyCode.Alpha0)) { EventAggregator.Instance.GetEvent().Invoke(); } } private void Instance_LevelLoaded(Level level) { //only when the level is loaded do we start updating updateAction = LevelManager.Instance.UpdateLevel; } /// /// the tile falls from the top of the screen, up to it's position on the tilemap /// /// where it should land /// what the tile represents /// the action of actually placing the tile /// public static async Task PlacementAnimation(GatherAndDefend.LevelEditor.TileData tile, Action putTileOnTilemap, Func shouldKillTask) { const string layer = "Unit"; float speed = 0; float acceleration = -9.81f; //create the falling GameObject that will placehold for the tile var tilePlaceholder = new GameObject("tile"); tilePlaceholder.transform.SetParent(Instance.transform); var rend = tilePlaceholder.AddComponent(); rend.sortingOrder = 10; rend.sortingLayerName = layer; if (tile.Tile is LevelTile) { rend.sprite = (tile.Tile as LevelTile).Sprite; } else { rend.sprite = (tile.Tile as Tile).sprite; } //position the tile over the board (past the camera's FOV) tilePlaceholder.transform.position = tile.Position + Vector3.up * Camera.main.orthographicSize * 2; var delta = tilePlaceholder.transform.position - tile.Position; var direction = delta.normalized; var signY = delta.y / Mathf.Abs(delta.y); while (true) { //if the placeholder was destroyed, stop if (!tilePlaceholder) break; //make the placeholder fall and check if we went past the target position speed += acceleration * Time.deltaTime; tilePlaceholder.transform.position += speed * Time.deltaTime * direction; var newDelta = tilePlaceholder.transform.position - tile.Position; var newSign = newDelta.y / Mathf.Abs(newDelta.y); if (newSign != signY) break; if (shouldKillTask()) { return; } await Task.Yield(); } //place the tile and destroy the placeholder putTileOnTilemap.Invoke(); Destroy(tilePlaceholder); } void KillLoading() { LevelManager.Instance.KillLoading(); } }