125 lines
3.8 KiB
C#
125 lines
3.8 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
|
|
public abstract class DraggablePlaceholder : MonoBehaviour
|
|
{
|
|
public int Food { get; set; }
|
|
public int Rock { get; set; }
|
|
public int Wood { get; set; }
|
|
|
|
protected const string OutlineColor = "_OutlineColor";
|
|
|
|
[SerializeField]
|
|
protected Color _validColor = Color.green;
|
|
[SerializeField]
|
|
protected Color _invalidColor = Color.red;
|
|
|
|
protected Camera _mainCamCache;
|
|
protected Rect _lvlBoundsCache;
|
|
protected bool _canBePlacedHere;
|
|
|
|
protected static bool alreadyHasUnit = false;
|
|
|
|
private List<SpriteRenderer> _outlineRenderers = new List<SpriteRenderer>();
|
|
public List<SpriteRenderer> OutlineRenderers
|
|
{
|
|
get => _outlineRenderers;
|
|
}
|
|
|
|
private List<SpriteRenderer> _allRenderers = new List<SpriteRenderer>();
|
|
|
|
/// <summary>
|
|
/// calculate level boundaries and finds main camera.
|
|
/// </summary>
|
|
protected virtual void Start()
|
|
{
|
|
_mainCamCache = Camera.main;
|
|
_lvlBoundsCache = LevelManager.Instance.CurrentLevel.CalculateBounds();
|
|
_lvlBoundsCache.xMax += 1;
|
|
_lvlBoundsCache.yMax += 1;
|
|
|
|
_allRenderers = GetComponentsInChildren<SpriteRenderer>().ToList();
|
|
UpdatePosition();
|
|
}
|
|
|
|
/// <summary>
|
|
/// check for mouse click being released (and tries to place object)<br/>
|
|
/// also updates placeholder's position and shows if position is valid
|
|
/// </summary>
|
|
protected virtual void Update()
|
|
{
|
|
if (!Input.GetMouseButton(0))
|
|
{
|
|
if (_canBePlacedHere && !alreadyHasUnit)
|
|
{
|
|
ResourceManager.Instance.Remove(Rock, Wood, Food);
|
|
Place();
|
|
alreadyHasUnit = true;
|
|
}
|
|
Destroy(gameObject);
|
|
}
|
|
alreadyHasUnit = AlreadyHasUnit();
|
|
_canBePlacedHere = CanBePlacedHere();
|
|
UpdatePosition();
|
|
|
|
ShowValidity();
|
|
}
|
|
|
|
/// <summary>
|
|
/// sets the position of the placeholder on the grid so it follows the mouse
|
|
/// </summary>
|
|
protected virtual void UpdatePosition()
|
|
{
|
|
var mousePos = Vector3Int.RoundToInt(_mainCamCache.ScreenToWorldPoint(Input.mousePosition));
|
|
mousePos.z = 0;
|
|
|
|
if (!_lvlBoundsCache.Contains(mousePos))
|
|
{
|
|
_allRenderers.ForEach(x => x.enabled = false);
|
|
}
|
|
else
|
|
{
|
|
_allRenderers.ForEach(x => x.enabled = true);
|
|
}
|
|
transform.position = mousePos;
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// helps determine if a unit can be placed on the tile sitting at unit's position (out of bound? obstacle? invalid tile?<br/>
|
|
/// default behaviour is : you cant place anything over any already existing thing<br/>
|
|
/// override to change this behaviour
|
|
/// </summary>
|
|
public virtual bool CanBePlacedHere()
|
|
{
|
|
return !LevelManager.Instance.Has<ILevelObject>(obj => obj.Position.IsContainedIn(transform.position))
|
|
&& _lvlBoundsCache.Contains(transform.position)
|
|
&& ResourceManager.Instance.EnoughFor(Rock, Wood, Food);
|
|
}
|
|
|
|
public virtual bool AlreadyHasUnit()
|
|
{
|
|
return !_lvlBoundsCache.Contains(transform.position);
|
|
}
|
|
|
|
/// <summary>
|
|
/// how your character will appear depending on the validity of the tile you want to put them on<br/>
|
|
/// default behaviour is changes color of all sprite renderers of the Outline Transform to red if invalid, green otherwise
|
|
/// </summary>
|
|
/// <param name="isValidPosition"></param>
|
|
/// <returns></returns>
|
|
public virtual void ShowValidity()
|
|
{
|
|
Color getColor() => _canBePlacedHere ? _validColor : _invalidColor;
|
|
|
|
foreach (var child in _outlineRenderers)
|
|
{
|
|
child.material.SetColor(OutlineColor, getColor());
|
|
}
|
|
}
|
|
public abstract void Place();
|
|
}
|