proto_rts/Assets/Scripts/Building.cs

131 lines
2.8 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
// TODO: The actual building logic and the construction logic should be separated!
[RequireComponent(typeof(BoxCollider2D), typeof(SpriteRenderer))]
public class Building : MonoBehaviour
{
private struct WorkOrder
{
public float startTime;
public float duration;
public Action completed;
}
[Serializable]
public struct UnitCommand
{
public Unit unit;
public Key keyControl;
public int cost;
public float buildDuration;
}
[NonSerialized] public BoxCollider2D buildingCollider;
public int maxQueueCount;
public float constructionTime;
public bool startBuilt;
public int buildingCost;
public List<UnitCommand> buildableUnits;
[NonSerialized] public bool isUnderConstruction = true;
private readonly Queue<WorkOrder> _workQueue = new Queue<WorkOrder>();
private WorkOrder _currentWorkOrder;
private bool _hasCurrentWorkOrder;
// In seconds.
private float _currentConstructionProgress;
private readonly Color _constructionColor = Color.black;
private SpriteRenderer _sprite;
private Transform _transform;
private void Start()
{
buildingCollider = GetComponent<BoxCollider2D>();
_sprite = GetComponent<SpriteRenderer>();
isUnderConstruction = !startBuilt;
_transform = transform;
}
public void UpdateBuildProgress(float amount)
{
if (isUnderConstruction)
{
_currentConstructionProgress += amount;
if (_currentConstructionProgress >= constructionTime)
{
isUnderConstruction = false;
}
_sprite.color = Color.Lerp(_constructionColor, Color.white,
_currentConstructionProgress / constructionTime);
}
}
private void Update()
{
if (_hasCurrentWorkOrder)
{
if (Time.time > _currentWorkOrder.startTime + _currentWorkOrder.duration)
{
_currentWorkOrder.completed();
_hasCurrentWorkOrder = false;
}
}
else
{
// Could probably do all this once we complete the order.
// Would also need to do it when we receive an order.
if (_workQueue.Count > 0)
{
_currentWorkOrder = _workQueue.Dequeue();
_currentWorkOrder.startTime = Time.time;
_hasCurrentWorkOrder = true;
}
}
}
public void ProcessKeyInput(Key key)
{
if (isUnderConstruction)
{
return;
}
foreach (var command in buildableUnits)
{
if (command.keyControl == key)
{
if (command.cost > Team.Minerals)
{
// TODO: announcer.
Debug.LogWarning("You've not enough minerals");
break;
}
if (maxQueueCount > _workQueue.Count)
{
Team.Minerals -= command.cost;
_workQueue.Enqueue(new WorkOrder
{
startTime = Time.time,
duration = command.buildDuration,
completed = () =>
{
var unitGo = Instantiate(command.unit,
_transform.position, _transform.rotation);
Team.AllUnits.Add(unitGo);
}
});
}
}
}
}
}