GameController
unknown
plain_text
2 years ago
14 kB
5
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...