GameController

 avatar
unknown
plain_text
2 years ago
14 kB
3
Indexable
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameController : MonoBehaviour 
{
    public static GameController instance;

    public GameObject parentGameObject; // You'll set this in the Unity Editor.
    public Slot[] slots;
    
    private List<Slot> sortedSlots;

    private Vector3 _target;
    private Item carryingItem;

    private Dictionary<int, Slot> slotDictionary;
	public GridGenerator gridGenerator;
	
	private Vector3 previousCameraPosition;
    private Quaternion previousCameraRotation;
    private float updateThreshold = 1f; // Update the slots if the camera has moved or rotated more than this amount
    public Vector3 itemOffset = new Vector3(0, 5f, 0);
    private Item hoveredItem = null;



    private void Awake() 
    {
        instance = this;
        // Utils.InitResources();
    }

    private void Start() 
    {
		        previousCameraPosition = Camera.main.transform.position;
        previousCameraRotation = Camera.main.transform.rotation;
	UpdateSlots();
    }
	
public void UpdateSlots()
{
    slots = parentGameObject.GetComponentsInChildren<Slot>();

    slotDictionary = new Dictionary<int, Slot>();

    // Copy the array to a list for easier manipulation
    sortedSlots = new List<Slot>();

    // Get the camera's frustum planes
    Plane[] planes = GeometryUtility.CalculateFrustumPlanes(Camera.main);

    foreach (Slot slot in slots)
    {
        // Get the renderer component of the slot
        Renderer renderer = slot.GetComponent<Renderer>();

        // Check if the renderer's bounds are in the camera's frustum
        if (renderer != null && GeometryUtility.TestPlanesAABB(planes, renderer.bounds))
        {
            // If the slot is in the camera's frustum, add it to the sortedSlots list
            sortedSlots.Add(slot);
        }
    }

    // Get the camera position
    Vector3 cameraPosition = Camera.main.transform.position;

    // Sort the slots by their distance from the camera
    sortedSlots.Sort((slot1, slot2) =>
    {
        float distance1 = Vector3.Distance(cameraPosition, slot1.transform.position);
        float distance2 = Vector3.Distance(cameraPosition, slot2.transform.position);
        return distance1.CompareTo(distance2);
    });

    for (int i = 0; i < sortedSlots.Count; i++)
    {
        sortedSlots[i].id = i;
        slotDictionary.Add(i, sortedSlots[i]);
    }
}

		    public bool IsDraggingItem()
    {
        return carryingItem != null;
    }

    private bool isDragging = false; // Add this line at the top of the GameController class
private Coroutine dragCoroutine; // Add this line at the top of the GameController class

private void Update() 
{
    if (Vector3.Distance(Camera.main.transform.position, previousCameraPosition) > updateThreshold ||
        Quaternion.Angle(Camera.main.transform.rotation, previousCameraRotation) > updateThreshold)
    {
        UpdateSlots();

        previousCameraPosition = Camera.main.transform.position;
        previousCameraRotation = Camera.main.transform.rotation;
    }

    if (Input.GetMouseButtonDown(0))
    {
        dragCoroutine = StartCoroutine(DragDelay());
    }

    if (Input.GetMouseButtonUp(0))
    {
        if (dragCoroutine != null)
        {
            StopCoroutine(dragCoroutine);
            dragCoroutine = null;
        }

        if (isDragging) // If a drag was detected, reset the flag and don't process the tap
        {
            isDragging = false;
            SendRayCast();
        }
        else
        {
            // Process the tap here
            SendRayCastForTap();
        }
    }

    if (isDragging && carryingItem)
    {
        OnItemSelected();
    }

    if (Input.GetKeyDown(KeyCode.Space))
    {
        PlaceRandomItem();
    }


    if (Input.GetKeyDown(KeyCode.Delete))
    {
        if (hoveredItem != null)
        {
            // Destroy the item and clear the slot
            Slot parentSlot = hoveredItem.parentSlot;
            if (parentSlot != null)
            {
                parentSlot.currentItem = null;
                parentSlot.state = SlotState.Empty;
            }
            Destroy(hoveredItem.gameObject);
            hoveredItem = null;
        }
    }

}


IEnumerator DragDelay()
{
    yield return new WaitForSeconds(0.075f); // Wait for 150ms before starting the drag
    isDragging = true;
    SendRayCast();
}

void SendRayCastForTap()
{
    RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero);

    // We hit something
    if(hit.collider != null)
    {
        var slot = hit.transform.GetComponent<Slot>();

        // If the item is a crafter, spawn a random item in a nearby slot
        if (slot.currentItem != null && slot.currentItem.IsCrafter)
        {
            Debug.Log("Crafter item tapped");
            SpawnRandomItemNearCrafter(slot);
        }
    }
}

void SpawnRandomItemNearCrafter(Slot crafterSlot)
{
    // Get the list of slots from the GridGenerator
    List<Slot> slots = gridGenerator.GetSlots();

    // Find an empty slot near the crafter
    Slot emptySlot = null;
    float closestDistance = float.MaxValue;
    foreach (Slot slot in slots)
    {
        if (slot.state == SlotState.Empty)
        {
            float distance = Vector3.Distance(crafterSlot.transform.position, slot.transform.position);
            if (distance < closestDistance)
            {
                closestDistance = distance;
                emptySlot = slot;
            }
        }
    }

    // If an empty slot was found, place a random item there
    if (emptySlot != null)
    {
        int randomItem = RandomNumberBetween(1, 3, 6);
        emptySlot.CreateItem(randomItem);
    }
}


void SendRayCast()
{
    RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero);

    // We hit something
    if(hit.collider != null)
    {
        // We are grabbing the item in a full slot
        var slot = hit.transform.GetComponent<Slot>();
        if (slot != null)
        {
            hoveredItem = slot.currentItem; // Update the hoveredItem field

            if (slot.state == SlotState.Full && carryingItem == null && isDragging) // Only pick up the item if a drag is detected
            {
                carryingItem = slot.currentItem;
                carryingItem.transform.localScale = Vector3.one * 1.3f;
                slot.currentItem = null;
                slot.state = SlotState.Empty;
            }
            // We are dropping an item to empty slot
            else if (slot.state == SlotState.Empty && carryingItem != null)
            {
                carryingItem.transform.SetParent(slot.transform);
                carryingItem.transform.position = slot.transform.position + itemOffset;
                carryingItem.transform.localScale = Vector3.one;
                slot.currentItem = carryingItem;
                slot.state = SlotState.Full;
                carryingItem.parentSlot = slot; // Update the parentSlot of the carryingItem
                carryingItem = null;
            }

            // We are dropping to full
            else if (slot.state == SlotState.Full && carryingItem != null)
            {
                // Check item in the slot
                if (slot.currentItem.id == carryingItem.id && carryingItem.Mergeable)
                {
                    print("merged");
                    OnItemMergedWithTarget(slot.id);
                }
                else
                {
                    OnItemCarryFail();
                }
            }
        }
    }
    else
    {
        hoveredItem = null; // Clear the hoveredItem field if the mouse is not over an item

        if (!carryingItem)
        {
            return;
        }
        OnItemCarryFail();
    }
}





void OnItemSelected()
{
    _target = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    _target.z = 0;
    var delta = 10 * Time.deltaTime;

    delta *= Vector3.Distance(transform.position, _target);
    carryingItem.transform.position = Vector3.MoveTowards(carryingItem.transform.position, _target, delta);

    // Check if the original slot is occupied
    if (carryingItem.parentSlot != null && carryingItem.parentSlot.state == SlotState.Full)
    {
        // Find an alternative available slot
        Slot alternativeSlot = FindAlternativeAvailableSlot(carryingItem.parentSlot);

        if (alternativeSlot != null)
        {
            // Move the item to the alternative slot
            carryingItem.transform.SetParent(alternativeSlot.transform);
            carryingItem.transform.position = alternativeSlot.transform.position + itemOffset;
            carryingItem.parentSlot = alternativeSlot;
        }
        else
        {
            // No alternative slot available, destroy the item
            Destroy(carryingItem.gameObject);
            Debug.LogWarning("Bubbling Not Implemented. No available slot to move the item to. Item destroyed.");
        }
    }
}

Slot FindAlternativeAvailableSlot(Slot originalSlot)
{
    int originalIndex = originalSlot.id;

    // Iterate over the slots starting from the next slot
    for (int i = originalIndex + 1; i < sortedSlots.Count; i++)
    {
        Slot slot = sortedSlots[i];
        if (slot.state == SlotState.Empty)
        {
            return slot; // Return the first available slot
        }
    }

    // If no available slot is found, return null
    return null;
}


void OnItemMergedWithTarget(int targetSlotId)
{
    var slot = GetSlotById(targetSlotId);

    // Destroy the original item
    if (slot.currentItem != null)
    {
        Destroy(slot.currentItem.gameObject);
    }

    // Create the new item
    slot.CreateItem(carryingItem.id + 1);

    // Destroy the carrying item
    if (carryingItem != null)
    {
        Destroy(carryingItem.gameObject);
    }
}

void OnItemCarryFail()
{
    if (carryingItem != null)
    {
        // Return the item to its parent slot
        if (carryingItem.parentSlot != null)
        {
            StartCoroutine(MoveItemToSlot(carryingItem, carryingItem.parentSlot));
        }
    }

    carryingItem = null;
}


Slot GetSlotByPosition(Vector3 position)
{
    foreach (Slot slot in slots)
    {
        if (slot.transform.position == position)
        {
            return slot;
        }
    }

    return null;
}


IEnumerator MoveItemToSlot(Item item, Slot slot)
{
    // Check if the slot is empty
    if (slot.state != SlotState.Empty)
    {
        Debug.Log("Cannot move item to a full slot");
        yield break;
    }

    float duration = 0.25f; // Duration of the movement in seconds
    float elapsed = 0f;
    Vector3 startPosition = item.transform.position;
    Vector3 endPosition = slot.transform.position + itemOffset;

    while (elapsed < duration)
    {
        elapsed += Time.deltaTime;
        float t = elapsed / duration;

        item.transform.position = Vector3.Lerp(startPosition, endPosition, t);
        yield return null;
    }

    // Ensure the item is exactly at the end position when the movement is done
    item.transform.position = endPosition;
    item.transform.localScale = Vector3.one;
    slot.currentItem = item;
    slot.state = SlotState.Full;
}




IEnumerator RevealOriginalItem()
{
    var slot = GetSlotById(carryingItem.id);
    float duration = 0.25f; // The duration of the movement
    float elapsed = 0;

    Vector3 originalScale = carryingItem.transform.localScale;
    Vector3 targetScale = Vector3.one; // The original item's scale

    while (elapsed < duration)
    {
        carryingItem.transform.position = Vector3.Lerp(carryingItem.transform.position + itemOffset, slot.transform.position + itemOffset, elapsed / duration);
        carryingItem.transform.localScale = Vector3.Lerp(originalScale, targetScale, elapsed / duration);
        elapsed += Time.deltaTime;
        yield return null;
    }

    Destroy(carryingItem.gameObject);
    slot.ItemReturned();
}






void PlaceRandomItem()
{
    if (AllSlotsOccupied())
    {
        Debug.Log("No empty slot available!");
        return;
    }

    // Get the mouse position in world coordinates
    Vector3 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    mousePosition.z = 0;

    // Find the slot closest to the mouse position
    Slot closestSlot = null;
    float closestDistance = float.MaxValue;
    foreach (Slot slot in sortedSlots)
    {
        if (slot.state == SlotState.Empty)
        {
            float distance = Vector3.Distance(mousePosition, slot.transform.position);
            if (distance < closestDistance)
            {
                closestDistance = distance;
                closestSlot = slot;
            }
        }
    }

    // If a closest slot was found, create an item there
    if (closestSlot != null)
    {
        int randomItem = RandomNumberBetween(0, 1, 3, 6);
        closestSlot.CreateItem(randomItem);
    }
    else
    {
        Debug.Log("No empty slot found!");
    }
}


private int RandomNumberBetween(params int[] numbers)
{
    int randomIndex = UnityEngine.Random.Range(0, numbers.Length);
    return numbers[randomIndex];
}


	
	

    bool AllSlotsOccupied()
    {
        foreach (var slot in slots)
        {
            if (slot.state == SlotState.Empty)
            {
                //empty slot found
                return false;
            }
        }
        //no slot empty 
        return true;
    }

    Slot GetSlotById(int id)
    {
        return slotDictionary[id];
    }
}
Editor is loading...