GameController
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...