Project_WL/Assets/FarmingIsland/Scripts/Island/Island.cs

151 lines
4.8 KiB
C#

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using DG.Tweening;
namespace CryingSnow.FarmingIsland
{
[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
public class Island : MonoBehaviour
{
[Tooltip("Indicates whether the island is unlocked and available for the player to access or purchase.")]
public bool IsUnlocked;
[Tooltip("Specifies if this island is a bridge, determining its mesh and visual appearance.")]
public bool IsBridge;
[Tooltip("Indicates whether this island has a procedurally generated road connecting it to other islands.")]
public bool HasRoad;
[Tooltip("Another island that needs to be unlocked first before this island can be purchased.")]
[SerializeField] private Island constraint;
[Tooltip("The visual mesh representing the road on the island.")]
[SerializeField] private MeshFilter roadMesh;
[Tooltip("Colliders placed on the north, west, east, and south sides of the island, toggled based on neighboring islands.")]
[SerializeField] private BoxCollider[] cardinalColliders;
public event System.Action OnActivated;
public event System.Action OnPropsInitialized;
public Island Constraint => constraint;
private int islandSize => IslandManager.Instance.IslandSize;
private MeshFilter meshFilter;
private List<IProp> props = new List<IProp>();
private void Awake()
{
meshFilter = GetComponent<MeshFilter>();
props = GetComponentsInChildren<IProp>(true).ToList();
if (!HasRoad && !IsBridge)
{
this.roadMesh.gameObject.SetActive(false);
}
}
private void Start()
{
if (IsUnlocked) StartCoroutine(InitializeProps(true));
}
private IEnumerator InitializeProps(bool instant)
{
int animated = 0;
props.ForEach(prop =>
{
prop.Animate(instant, () => animated++);
if (prop.Location != Location.None)
{
var position = GetPosition();
if (prop.Location == Location.Fish)
{
var rightPosition = transform.TransformPoint(Vector3.right * islandSize);
position = Vector3Int.RoundToInt(rightPosition);
}
else if (prop.Location == Location.Dock)
{
var backPosition = transform.TransformPoint(Vector3.back * islandSize);
position = Vector3Int.RoundToInt(backPosition);
}
IslandManager.Instance.RegisterLocation(position, prop.Location);
}
});
yield return new WaitWhile(() => animated < props.Count);
OnPropsInitialized?.Invoke();
}
public Vector3Int GetPosition()
{
return Vector3Int.RoundToInt(transform.position);
}
public void ConfigureIsland(Mesh islandMesh, Mesh roadMesh, bool[] adjacentIslands)
{
meshFilter.mesh = islandMesh;
if (HasRoad && !IsBridge)
{
this.roadMesh.mesh = roadMesh;
}
int[] rotatedIndices = GetRotatedIndices();
for (int i = 0; i < cardinalColliders.Length; i++)
{
cardinalColliders[rotatedIndices[i]].enabled = !adjacentIslands[i];
}
}
private int[] GetRotatedIndices()
{
// Original order: North (0), West (1), East (2), South (3)
int[] indices = { 0, 1, 2, 3 };
// Calculate the number of 90-degree steps
int rotationSteps = Mathf.RoundToInt(transform.eulerAngles.y / 90f) % 4;
// Rotate indices based on the rotation steps
for (int i = 0; i < rotationSteps; i++)
{
int temp = indices[0];
indices[0] = indices[1];
indices[1] = indices[3];
indices[3] = indices[2];
indices[2] = temp;
}
return indices;
}
public void Activate()
{
transform.localScale = Vector3.zero;
gameObject.SetActive(true);
transform.DOJump(transform.position, 2f, 1, 1f)
.SetEase(Ease.OutBounce);
transform.DOScale(Vector3.one, 1f)
.SetEase(Ease.OutBounce)
.OnComplete(() =>
{
IsUnlocked = true;
OnActivated?.Invoke();
StartCoroutine(InitializeProps(false));
});
}
}
}