/// <summary> /// Called by Orb that has beginning to get dragged /// </summary> /// <param name="orb">Orb instance that get drag</param> /// <param name="row">Row number of the Orb instance</param> /// <param name="column">Column number of the Orb instance</param> public static void OnBeginDrag(Orb orb, int row, int column) { // Check if player movement should be processed if (Coordinator.Coordinator.GetOrbMovable()) { spawnTrackingOrb(orb); orb.OnSelectedOrb(); selectedOrb = orb; originalSelectedType = orb.getType(); Coordinator.Coordinator.NotifyRoundStarted(); foreach (Orb o in orbs) { o.ActivateExtendedHitbox(); } } }
/// <summary> /// Matches any orbs within a 1D array of Orbs /// </summary> /// <param name="orbs">1D array of Orb instance that are on the same row or column</param> /// <param name="currentlyMatching">List of Orb instance that we are currently matching, either have not reaches 3 orbs yet, or have reached 3 orbs but is not terminated by another orb with a different color</param> /// <param name="matched">List of list of Orb instance that has already been matched</param> /// <returns>List that includes lists of matched orb instance along a row or column</returns> private List <List <Orb> > matchRowColumn(Orb[] orbs, List <Orb> currentlyMatching, List <List <Orb> > matched) { Orb currentOrb = orbs[0]; if (currentlyMatching.Count == 0 || currentOrb.getType() == currentlyMatching[0].getType()) { // Continue matching as the orb has the same type as those already in the list currentlyMatching.Add(currentOrb); } else { // Match terminated here if (currentlyMatching.Count >= 3) { // Matched 3 orbs or more --> Successfully matched // Push it into the matched arraylist // A new list is created since we are about to Clear this list, and Add() only add a memory reference that will also be wiped matched.Add(new List <Orb>(currentlyMatching)); } // Clear existing matching list currentlyMatching.Clear(); // Initiate new matching currentlyMatching.Add(currentOrb); } if (orbs.Length == 1) { if (currentlyMatching.Count >= 3) { // Matched 3 orbs or more --> Successfully matched // Push it into the matched arraylist matched.Add(new List <Orb>(currentlyMatching)); } // Matched the entire row / column already return(matched); } else { // Continue matching // Create a new Orb[] but without the processed array Orb[] truncatedOrbs = new Orb[orbs.Length - 1]; Array.Copy(orbs, 1, truncatedOrbs, 0, truncatedOrbs.Length); // Call this method again with the new list and shortened array return(matchRowColumn(truncatedOrbs, currentlyMatching, matched)); } }
/// <summary> /// Called continuously during the drag to swap Orb if required /// </summary> /// <param name="ev">Current pointer data</param> public static void OnDrag(PointerEventData ev) { // Check if player movement should be processed if (Coordinator.Coordinator.GetOrbMovable()) { // Activate timer if not done so already if (!timerActivated) { // Attach event listener Canvas.HealthBar.instance.TimeReached += PostTimerReached; // Activate timer Canvas.HealthBar.instance.RequestCountdown(); // Set flag timerActivated = true; } // Update tracker position Vector3 pointerPos = Camera.main.ScreenToWorldPoint(new Vector3(ev.position.x, ev.position.y, 10)); pointerPos.z = trackingZ; currentTracker.transform.position = pointerPos; // Check if any orbs has to be swapped // Do a ray cast from the pointer position and try to find a game object RaycastHit2D hit; hit = Physics2D.Raycast(pointerPos, Vector2.zero); // Set raycaster object to be the collider or null (if nothing was raycasted to) GameObject raycastedObj = hit.collider == null ? null : hit.collider.gameObject; if (raycastedObj != null) { Orb newSelectedOrb = raycastedObj.GetComponent <Orb>(); if (newSelectedOrb != null && newSelectedOrb != selectedOrb) { // Swap the type of the 2 orb selectedOrb.OnSwap(newSelectedOrb.getType()); newSelectedOrb.OnSwap(selectedOrb.getType()); // Select the new orb selectedOrb.OnDeselectOrb(); newSelectedOrb.OnSelectedOrb(); selectedOrb = newSelectedOrb; // Set orb swapped in this drag orbSwapped = true; // Play movement sound Sound.SoundSystem.instance.playMovementSFX(); } } } }
/// <summary> /// Initiate a rearrangement of Orb where some or all Orb are eliminated /// </summary> /// <param name="unarranged">Raw Orb 2D array with some Orb eliminated</param> public void rearrangeOrb(Orb[,] unarranged) { // Calculate the distance in y-axis in world space between each Orb float distanceBetweenOrb = unarranged[0, 0].transform.position.y - unarranged[1, 0].transform.position.y; // Loop through all Orbs, column by column for (int i = 0; i < unarranged.GetLength(1); i++) { // Loop through each column from bottom to top (i.e. from j = 4 to j = 0) for (int j = unarranged.GetLength(0) - 1; j >= 0; j--) { Orb orb = unarranged[j, i]; if (orb.getType() == -1) { // Orb are eliminated // Loop through all Orbs above this orb in the same column and look for any orb above it to fall down to this position // Suppose j = 4, then we have to check from k = 3 to k = 0 for (int k = j - 1; k >= 0; k--) { // Check if that orb has type not equals to -1 (i.e. not eliminated) if (unarranged[k, i].getType() != -1) { // If not eliminated, that orb should fall to the current location // Set tht current orb to have that type orb.setType(unarranged[k, i].getType()); // Eliminate the Orb that has now fall to some position below unarranged[k, i].eliminate(); // Spawn DummyOrb that do the drop animation, and store it in the list DummyOrb d = DummyOrb.Factory(unarranged[k, i].transform.position, unarranged[k, i].GetComponent <SpriteRenderer>().sprite, unarranged[k, i].transform.localScale); d.StartTranslate(orb.transform.position); dummyOrbs.Add(d); // Listen to AnimationDone d.AnimationDone += animationCallback; // Increment counter pendingAnimation++; // We are done with this orb break; } // This Orb is also eliminated, look for 1 higher Orb then } // Triggered if there are non-eliminated Orb above this current Orb if (orb.getType() == -1) { // No orbs are above this orb to fall down to this position // Loop through all Orbs above this Orb for (int k = j; k >= 0; k--) { // Set the current Orb and every Orb above this Orb to a random type int newType = Orb.GetRandomNumber(1, 5); unarranged[k, i].setType(newType); // Spawn a DummyOrb that translate to the position for that animation // Calculate the Orb position, it should be just above the Orb itself seperated by the distance between each normal Orb Vector3 dummyOrbPos = unarranged[k, i].transform.position; dummyOrbPos.y += distanceBetweenOrb; // Spawn DummyOrb that do the drop animation, and store it in the list DummyOrb d = DummyOrb.Factory(dummyOrbPos, unarranged[k, i].GetComponent <SpriteRenderer>().sprite, unarranged[k, i].transform.localScale); d.StartTranslate(unarranged[k, i].transform.position); dummyOrbs.Add(d); // Listen to AnimationDone d.AnimationDone += animationCallback; // Increment counter pendingAnimation++; } // We are done with the entire column at this point, no point to run this loop any further since all Orb within this column is set break; } } else { // Orbs are not eliminated, but we are still spawning a non-moving dummyOrb for that // This only applies to Orb at the bottom that are not eliminated staticDummyOrbs.Add(DummyOrb.Factory(orb.transform.position, orb.GetComponent <SpriteRenderer>().sprite, orb.transform.localScale)); } } } }