128 lines
4.3 KiB
C#

using UnityEngine;
using GatherAndDefend.LevelEditor;
using System.Collections;
using UnityEngine.Tilemaps;
using System.Threading.Tasks;
using System;
using GatherAndDefend.Events;
using static LevelManager;
/// <param name="position">The position the tile should be placed on</param>
/// <param name="tile">the tile we should place</param>
/// <param name="tilePlacement">the action of placing the tile on the tilemap</param>
/// <returns></returns>
public delegate Task PlacementAnimationHandler(GatherAndDefend.LevelEditor.TileData tileData, Action tilePlacement, Func<bool> shouldKillTask);
public class LevelManagerScript : SingletonBehaviour<LevelManagerScript>
{
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<LevelLoadedEvent>().Attach(Instance_LevelLoaded);
EventAggregator.Instance.GetEvent<ExitingLevelEvent>().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<ExitingLevelEvent>().Detach(KillLoading);
updateAction = null;
}
void Update()
{
updateAction?.Invoke();
// Gala hack to win level instantly
if (Input.GetKeyDown(KeyCode.Alpha0))
{
EventAggregator.Instance.GetEvent<LastWaveCompletedEvent>().Invoke();
}
}
private void Instance_LevelLoaded(Level level)
{
//only when the level is loaded do we start updating
updateAction = LevelManager.Instance.UpdateLevel;
}
/// <summary>
/// the tile falls from the top of the screen, up to it's position on the tilemap
/// </summary>
/// <param name="position">where it should land</param>
/// <param name="tile">what the tile represents</param>
/// <param name="putTileOnTilemap">the action of actually placing the tile</param>
/// <returns></returns>
public static async Task PlacementAnimation(GatherAndDefend.LevelEditor.TileData tile, Action putTileOnTilemap, Func<bool> 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<SpriteRenderer>();
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();
}
}