private void AddBallsIfThereIsBomb(List <BallSlot> ballsToDestroySlots) { BallSlot ballSlot = ballsToDestroySlots.FirstOrDefault(bs => bs.ball.type == BallType.Bomb); if (ballSlot) { int indexOfBombSlot = Array.IndexOf(BallSlotsByDistance, ballSlot); for (int i = 1; i <= gameProperties.bombRadius; i++) { int leftIndex = indexOfBombSlot - i; int rightIndex = indexOfBombSlot + i; if (leftIndex >= 0 && BallSlotsByDistance[leftIndex].ball && !ballsToDestroySlots.Contains(BallSlotsByDistance[leftIndex])) { ballsToDestroySlots.Add(BallSlotsByDistance[leftIndex]); } if (rightIndex < BallSlotsByDistance.Length && BallSlotsByDistance[rightIndex].ball && !ballsToDestroySlots.Contains(BallSlotsByDistance[rightIndex])) { ballsToDestroySlots.Add(BallSlotsByDistance[rightIndex]); } } } }
public void LandBall(BallSlot collidedSlot, Ball landingBall) { BallSlot[] ballSlotsByDistance = BallSlotsByDistance; int indexOfCollidedSlot = Array.IndexOf(ballSlotsByDistance, collidedSlot); int firstEmptySlotIndexAfter = FirstEmptySlotIndexAfter(indexOfCollidedSlot, ballSlotsByDistance); for (int i = firstEmptySlotIndexAfter; i > indexOfCollidedSlot + 1; i--) { ballSlotsByDistance[i].AssignBall(ballSlotsByDistance[i - 1].ball); } if (collidedSlot.distanceTraveled < pathCreator.path.GetClosestDistanceAlongPath(landingBall.transform.position)) { ballSlotsByDistance[indexOfCollidedSlot + 1].AssignBall(landingBall); } else { ballSlotsByDistance[indexOfCollidedSlot + 1].AssignBall(collidedSlot.ball); collidedSlot.AssignBall(landingBall); } landingBall.Land(); foreach (BallSlot ballSlot in ballSlotsByDistance .Where(bs => bs.ball && bs.ball.state == BallState.InSlot)) { ballSlot.ball.MoveToSlot(); } StartCoroutine(DestroyMatchingBallsCo(landingBall.slot)); }
public void OnClickBallSlot(BallSlot Ball) { if (Ball.myBall == null) { if (heldObject == null) { return; } else { Ball.myBall = heldObject.GetComponent <Ball>(); Ball.ballSprite.color = Color.white; if (heldObject.GetComponent <SpriteRenderer>()) { Ball.ballSprite.sprite = heldObject.GetComponent <SpriteRenderer>().sprite; } else { Ball.ballSprite.sprite = heldObject.GetComponentInChildren <SpriteRenderer>().sprite; } heldObjectSprite.color = Color.clear; heldObjectSprite.sprite = null; heldObject = null; } } else { if (heldObject == null) { heldObject = Ball.myBall.gameObject; if (heldObject.GetComponent <SpriteRenderer>()) { heldObjectSprite.sprite = heldObject.GetComponent <SpriteRenderer>().sprite; } else { heldObjectSprite.sprite = heldObject.GetComponentInChildren <SpriteRenderer>().sprite; } heldObjectSprite.color = Color.white; Ball.ballSprite.sprite = null; Ball.ballSprite.color = Color.clear; Ball.myBall = null; } else { GameObject temp = heldObject; heldObject = Ball.myBall.gameObject; if (heldObject.GetComponent <SpriteRenderer>()) { heldObjectSprite.sprite = heldObject.GetComponent <SpriteRenderer>().sprite; } else { heldObjectSprite.sprite = heldObject.GetComponentInChildren <SpriteRenderer>().sprite; } Ball.myBall = temp.GetComponent <Ball>(); Ball.ballSprite.sprite = temp.GetComponent <SpriteRenderer>().sprite; } } }
private static List <BallSlot> GetAdjacentSlotsOnSameRow(BallSlot slot) { List <BallSlot> slots = new List <BallSlot>(6); slots.Add(new BallSlot(GetClampedRowIndex(slot.RowIndex), GetClampledColumnIndex(slot.RowIndex, slot.ColumnIndex - 1))); slots.Add(new BallSlot(GetClampedRowIndex(slot.RowIndex), GetClampledColumnIndex(slot.RowIndex, slot.ColumnIndex + 1))); return(slots); }
private void GetAllPieceOfSameColorAlignedAtSlot(BallSlot ballSlot, Ball.BallColor color, List <BallSlot> slots) { Ball ball = GetBallAtSlot(ballSlot.RowIndex, ballSlot.ColumnIndex); if (ball != null && ball.Color == color && !slots.Contains(ballSlot)) { slots.Add(ballSlot); GetAllAdjacentSlots(ballSlot).ForEach(slot => GetAllPieceOfSameColorAlignedAtSlot(slot, color, slots)); } }
private void FallBallAtSlot(BallSlot slot) { Ball ball = GetBallAtSlot(slot); if (ball != null) { ball.FallDown(); DeletedBalls.Add(ball); } Balls[slot.RowIndex][slot.ColumnIndex] = null; }
private void OnTriggerEnter2D(Collider2D other) { if (other.CompareTag("Ball Slot")) { BallSlot ballSlot = other.GetComponent <BallSlot>(); if (ballSlot.ball) { ballSlot.ball.state = BallState.Destroying; ballSlot.ball = null; } } }
private List <BallSlot> GetAllBallsAdjacentToSlot(BallSlot ballSlot) { List <BallSlot> slots = new List <BallSlot>(6); foreach (BallSlot slot in GetAllAdjacentSlots(ballSlot)) { if (GetBallAtSlot(slot) != null) { slots.Add(slot); } } return(slots); }
private void OnTriggerEnter2D(Collider2D other) { if (!other.CompareTag("Ball Slot")) { return; } BallSlot ballSlot = other.GetComponent <BallSlot>(); if (!ballSlot.ball || state != BallState.Shooting) { return; } board.LandBall(ballSlot, this); circleCollider2D.enabled = false; }
private IEnumerator DestroyMatchingBallsCo(BallSlot landedBallSlot) { isDestroyingMatchingBalls = true; List <BallSlot> ballsToDestroySlots; BallSlot collidedBallSlot = landedBallSlot; do { yield return(new WaitUntil(() => BallSlotsByDistance.All(bs => !bs.ball || bs.ball.state != BallState.Landing && bs.ball.state != BallState.SwitchingSlots))); ballsToDestroySlots = GetSimilarBalls(collidedBallSlot); if (ballsToDestroySlots.Count < 3) { break; } AddBallsIfThereIsBomb(ballsToDestroySlots); if (ballsToDestroySlots.FindIndex(bs => bs.ball.type == BallType.Reverse) != -1) { StartCoroutine(StartReverseCo()); } if (ballsToDestroySlots.FindIndex(bs => bs.ball.type == BallType.TimeSlow) != -1) { StartCoroutine(TimeSlowCo()); } foreach (BallSlot ballsToDestroySlot in ballsToDestroySlots) { ballsToDestroySlot.ball.StartDestroying(); ballsToDestroySlot.AssignBall(null); } collidedBallSlot = ballsToDestroySlots[0]; yield return(new WaitForSeconds(0.5f)); MoveSeparatedBallsBack(); } while (ballsToDestroySlots.Count >= 3 && collidedBallSlot); yield return(new WaitUntil(() => BallSlotsByDistance.All(bs => !bs.ball || bs.ball.state != BallState.SwitchingSlots))); isDestroyingMatchingBalls = false; }
private static List <BallSlot> GetAllAdjacentLowerSlots(BallSlot slot) { List <BallSlot> slots = new List <BallSlot>(6); if (slot.RowIndex % 2 == 0) { slots.Add(new BallSlot(GetClampedRowIndex(slot.RowIndex + 1), GetClampledColumnIndex(slot.RowIndex + 1, slot.ColumnIndex - 1))); slots.Add(new BallSlot(GetClampedRowIndex(slot.RowIndex + 1), GetClampledColumnIndex(slot.RowIndex + 1, slot.ColumnIndex))); } else { slots.Add(new BallSlot(GetClampedRowIndex(slot.RowIndex + 1), GetClampledColumnIndex(slot.RowIndex + 1, slot.ColumnIndex))); slots.Add(new BallSlot(GetClampedRowIndex(slot.RowIndex + 1), GetClampledColumnIndex(slot.RowIndex + 1, slot.ColumnIndex + 1))); } return(slots); }
private List <BallSlot> GetSimilarBalls(BallSlot landedBallSlot) { List <BallSlot> ballsToDestroySlots = new List <BallSlot> { landedBallSlot }; if (!landedBallSlot.ball) { return(ballsToDestroySlots); } int indexOfLandedBallSlot = Array.IndexOf(BallSlotsByDistance, landedBallSlot); for (int i = indexOfLandedBallSlot - 1; i >= 0; i--) { BallSlot ballSlot = BallSlotsByDistance[i]; if (ballSlot.ball && !ballsToDestroySlots.Contains(ballSlot) && BallUtil.GetBallColorByType(ballSlot.ball.type) == BallUtil.GetBallColorByType(landedBallSlot.ball.type)) { ballsToDestroySlots.Add(ballSlot); } else { break; } } for (int i = indexOfLandedBallSlot + 1; i < BallSlotsByDistance.Length; i++) { BallSlot ballSlot = BallSlotsByDistance[i]; if (ballSlot.ball && !ballsToDestroySlots.Contains(ballSlot) && BallUtil.GetBallColorByType(ballSlot.ball.type) == BallUtil.GetBallColorByType(landedBallSlot.ball.type)) { ballsToDestroySlots.Add(ballSlot); } else { break; } } return(ballsToDestroySlots.OrderBy(bs => bs.distanceTraveled).ToList()); }
private void ProduceBallsOnTrack() { if (isReverse) { return; } BallSlot zeroSlot = BallSlotsByDistance[0]; if (!zeroSlot.ball) { Ball ball = ballFactory.CreateBallAt(zeroSlot.transform.position, ballFactory.GetRandomBallType()); zeroSlot.AssignBall(ball); ball.transform.parent = zeroSlot.transform; ball.transform.localScale = Vector3.zero; ball.state = BallState.Spawning; } }
private void InitBallSlots() { float pathLength = pathCreator.path.length; int slotsCount = (int)pathLength; float step = pathLength / slotsCount; ballSlots = new BallSlot[slotsCount]; for (int i = 0; i < slotsCount; i++) { float distanceTraveled = i * step; Vector3 slotPos = pathCreator.path.GetPointAtDistance(distanceTraveled); BallSlot ballSlot = Instantiate(ballSlotPrefab, slotPos, Quaternion.identity); ballSlot.distanceTraveled = distanceTraveled; ballSlot.transform.parent = ballSlotsContainer.transform; ballSlots[i] = ballSlot; } }
private List <BallSlot> GetAllBallsWithNoUpperAndSameRowAdjacentBalls(int rowIndex, int columnIndex) { List <BallSlot> slots = new List <BallSlot>(); for (int i = 1; i < NUMBER_OF_ROWS; i++) { List <BallSlot> slotListCandidate = new List <BallSlot>(); for (int j = 0; j < GetNumberOfColumnForRow(i); j++) { BallSlot slot = new BallSlot(i, j); if ((rowIndex != i || columnIndex != j) && GetBallAtSlot(slot) != null) { if (GetBallsForSlots(GetAllAdjacentUpperSlots(slot)).All(ball => ball == null)) { slotListCandidate.Add(slot); if (j + 1 >= GetNumberOfColumnForRow(i)) { slots.AddRange(slotListCandidate); } } else { slotListCandidate = new List <BallSlot>(); } } else if (slotListCandidate.Count > 0) { slots.AddRange(slotListCandidate); } } } return(slots); }
private Ball GetBallAtSlot(BallSlot slot) { return(GetBallAtSlot(slot.RowIndex, slot.ColumnIndex)); }
public void SetBallToNearestSlot(Ball ball, BallSlot interSectingSlot) { int nearestRowIndex; int nearestColumnIndex; List<BallSlot> emptySlots; if (interSectingSlot != null) { // Get the nearest empty slots. emptySlots = GetAllAdjacentLowerSlots(interSectingSlot); emptySlots.AddRange(GetAdjacentSlotsOnSameRow(interSectingSlot)); } else // The ball reached the ceiling { emptySlots = GetAllTopSlots(); } emptySlots.RemoveAll(slot => GetBallAtSlot(slot) != null); emptySlots.Sort(delegate(BallSlot slot, BallSlot otherSlot) { float length1 = (GetSlotCenter(slot) - ball.Position).Length(); float length2 = (GetSlotCenter(otherSlot) - ball.Position).Length(); return length1.CompareTo(length2); }); if (emptySlots.Count > 0) { try { nearestRowIndex = emptySlots.ElementAt(0).RowIndex; nearestColumnIndex = emptySlots.ElementAt(0).ColumnIndex; SetBallAtPosition(nearestRowIndex, nearestColumnIndex, ball); DestroyAlignedPieceAtSlot(nearestRowIndex, nearestColumnIndex); int numOfBallsFallen = FallDownAllBallsWithNoUpperAdjacentBalls(nearestRowIndex, nearestColumnIndex); CurrentScore.Value += (numOfBallsFallen > 0) ? (int)Math.Pow(2, numOfBallsFallen) * 10 : 0; CheckIfPlayerWins(); CheckIfPlayerLost(); } catch (SlotOccupiedException ex) { } } else { //Set All balls to Dark foreach (List<Ball> list in Balls) { foreach (Ball b in list) { if (b != null) { b.GoDark(); } } } Observer.ForEach(observer => observer.OnPlayerLoses()); } }
private Vector3 GetSlotCenter(BallSlot slot) { return (slot.RowIndex % 2 == 0) ? Position + new Vector3(slot.RowIndex * Ball.BALL_RADIUS*2 + Ball.BALL_RADIUS, slot.ColumnIndex * Ball.BALL_RADIUS*2 + Ball.BALL_RADIUS, Ball.BALL_RADIUS) : Position + new Vector3(slot.RowIndex * Ball.BALL_RADIUS*2 + Ball.BALL_RADIUS, ODD_ROW_OFFSET + slot.ColumnIndex * Ball.BALL_RADIUS*2 + Ball.BALL_RADIUS, Ball.BALL_RADIUS); }
private static List<BallSlot> GetAdjacentSlotsOnSameRow(BallSlot slot) { List<BallSlot> slots = new List<BallSlot>(6); slots.Add(new BallSlot(GetClampedRowIndex(slot.RowIndex), GetClampledColumnIndex(slot.RowIndex, slot.ColumnIndex - 1))); slots.Add(new BallSlot(GetClampedRowIndex(slot.RowIndex), GetClampledColumnIndex(slot.RowIndex, slot.ColumnIndex + 1))); return slots; }
private Vector2 GetSlotCenter(BallSlot slot) { return (slot.RowIndex % 2 == 0) ? Position + new Vector2(slot.ColumnIndex * Ball.RECTANGLE_WIDTH + Ball.RECTANGLE_WIDTH / 2, slot.RowIndex * Ball.RECTANGLE_HEIGHT + Ball.RECTANGLE_HEIGHT / 2) : Position + new Vector2(ODD_ROW_OFFSET + slot.ColumnIndex * Ball.RECTANGLE_WIDTH + Ball.RECTANGLE_WIDTH / 2, slot.RowIndex * Ball.RECTANGLE_HEIGHT + Ball.RECTANGLE_HEIGHT / 2); }
private Ball GetBallAtSlot(BallSlot slot) { return GetBallAtSlot(slot.RowIndex, slot.ColumnIndex); }
private List<BallSlot> GetAllBallsWithNoUpperAndSameRowAdjacentBalls(int rowIndex, int columnIndex) { List<BallSlot> slots = new List<BallSlot>(); for (int i = 1; i < NUMBER_OF_ROWS; i++) { List<BallSlot> slotListCandidate = new List<BallSlot>(); for (int j = 0; j < GetNumberOfColumnForRow(i); j++) { BallSlot slot = new BallSlot(i, j); if((rowIndex != i || columnIndex != j) && GetBallAtSlot(slot) != null) { if(GetBallsForSlots(GetAllAdjacentUpperSlots(slot)).All(ball => ball == null)) { slotListCandidate.Add(slot); if (j + 1 >= GetNumberOfColumnForRow(i)) { slots.AddRange(slotListCandidate); } } else { slotListCandidate = new List<BallSlot>(); } } else if (slotListCandidate.Count > 0) { slots.AddRange(slotListCandidate); } } } return slots; }
private List<BallSlot> GetAllBallsAdjacentToSlot(BallSlot ballSlot) { List<BallSlot> slots = new List<BallSlot>(6); foreach (BallSlot slot in GetAllAdjacentSlots(ballSlot)) { if (GetBallAtSlot(slot) != null) { slots.Add(slot); } } return slots; }
private static List<BallSlot> GetAllAdjacentUpperSlots(BallSlot slot) { List<BallSlot> slots = new List<BallSlot>(6); if (slot.RowIndex % 2 == 0) { slots.Add(new BallSlot(GetClampedRowIndex(slot.RowIndex - 1), GetClampledColumnIndex(slot.RowIndex - 1, slot.ColumnIndex - 1))); slots.Add(new BallSlot(GetClampedRowIndex(slot.RowIndex - 1), GetClampledColumnIndex(slot.RowIndex - 1, slot.ColumnIndex))); } else { slots.Add(new BallSlot(GetClampedRowIndex(slot.RowIndex - 1), GetClampledColumnIndex(slot.RowIndex - 1, slot.ColumnIndex))); slots.Add(new BallSlot(GetClampedRowIndex(slot.RowIndex - 1), GetClampledColumnIndex(slot.RowIndex - 1, slot.ColumnIndex + 1))); } return slots; }
private Vector2 GetSlotCenter(BallSlot slot) { return((slot.RowIndex % 2 == 0) ? Position + new Vector2(slot.ColumnIndex * Ball.RECTANGLE_WIDTH + Ball.RECTANGLE_WIDTH / 2, slot.RowIndex * Ball.RECTANGLE_HEIGHT + Ball.RECTANGLE_HEIGHT / 2) : Position + new Vector2(ODD_ROW_OFFSET + slot.ColumnIndex * Ball.RECTANGLE_WIDTH + Ball.RECTANGLE_WIDTH / 2, slot.RowIndex * Ball.RECTANGLE_HEIGHT + Ball.RECTANGLE_HEIGHT / 2)); }
public bool Equals(BallSlot otherSlot) { return RowIndex == otherSlot.RowIndex && ColumnIndex == otherSlot.ColumnIndex; }
public void SetBallToNearestSlot(Ball ball, BallSlot interSectingSlot) { int nearestRowIndex; int nearestColumnIndex; if (interSectingSlot != null) { // Get the nearest empty slot. List <BallSlot> emptySlots = GetAllAdjacentLowerSlots(interSectingSlot); emptySlots.AddRange(GetAdjacentSlotsOnSameRow(interSectingSlot)); emptySlots.RemoveAll(slot => GetBallAtSlot(slot) != null); Vector2 ballCenter = new Vector2(ball.Rectangle.Center.X, ball.Rectangle.Center.Y); emptySlots.Sort(delegate(BallSlot slot, BallSlot otherSlot) { float length1 = (GetSlotCenter(slot) - ballCenter).Length(); float length2 = (GetSlotCenter(otherSlot) - ballCenter).Length(); return(length1.CompareTo(length2)); }); if (emptySlots.Count > 0) { if (emptySlots.ElementAt(0).RowIndex > GetCurrentLowestRowIndexLimit()) { //Set All balls to Dark foreach (List <Ball> list in Balls) { foreach (Ball hangingBall in list) { if (hangingBall != null) { hangingBall.GoDark(); } } } Observer.ForEach(observer => observer.OnPlayerLoses()); } nearestRowIndex = emptySlots.ElementAt(0).RowIndex; nearestColumnIndex = emptySlots.ElementAt(0).ColumnIndex; } else { // There is no room left to place that ball. //Set All balls to Dark foreach (List <Ball> list in Balls) { foreach (Ball hangingBall in list) { if (hangingBall != null) { hangingBall.GoDark(); } } } Observer.ForEach(observer => observer.OnPlayerLoses()); nearestColumnIndex = interSectingSlot.ColumnIndex; nearestRowIndex = interSectingSlot.RowIndex; } } else // The ball reached the ceiling { float nearestRowRatio = Math.Abs(ball.Rectangle.Center.Y - Position.Y) / (Ball.RECTANGLE_HEIGHT * NUMBER_OF_ROWS); nearestRowIndex = (int)MathHelper.Clamp((float)Math.Floor(nearestRowRatio * NUMBER_OF_ROWS), 0, NUMBER_OF_ROWS - 1); if (nearestRowIndex % 2 == 0) { float nearestColumnRatio = Math.Abs(ball.Rectangle.Center.X - Position.X) / Bounds.Rectangle.Width; nearestColumnIndex = (int)MathHelper.Clamp((float)Math.Floor(nearestColumnRatio * NUMBER_OF_COLUMNS_EVEN), 0, NUMBER_OF_COLUMNS_EVEN - 1); } else { float nearestColumnRatio = Math.Abs(ball.Rectangle.Center.X + ODD_ROW_OFFSET - Position.X) / (Bounds.Rectangle.Width - 2 * ODD_ROW_OFFSET); nearestColumnIndex = (int)MathHelper.Clamp((float)Math.Floor(nearestColumnRatio * NUMBER_OF_COLUMNS_ODD), 0, NUMBER_OF_COLUMNS_ODD - 1); } } try { if (GetAllBallsAdjacentToSlot(new BallSlot(nearestRowIndex, nearestColumnIndex)).Count == 0) { nearestColumnIndex = (ball.Direction.X > 0) ? GetClampledColumnIndex(nearestRowIndex, nearestColumnIndex + 1) : GetClampledColumnIndex(nearestRowIndex, nearestColumnIndex - 1); if (GetAllBallsAdjacentToSlot(new BallSlot(nearestRowIndex, nearestColumnIndex)).Count == 0) { nearestColumnIndex = (ball.Direction.X > 0) ? GetClampledColumnIndex(nearestRowIndex, nearestColumnIndex - 2) : GetClampledColumnIndex(nearestRowIndex, nearestColumnIndex + 2); } } SetBallAtPosition(nearestRowIndex, nearestColumnIndex, ball); DestroyAlignedPieceAtSlot(nearestRowIndex, nearestColumnIndex); int numOfBallsFallen = FallDownAllBallsWithNoUpperAdjacentBalls(nearestRowIndex, nearestColumnIndex); CurrentScore.Value += (numOfBallsFallen > 0) ? (int)Math.Pow(2, numOfBallsFallen) * 10 : 0; CheckIfPlayerWins(); } catch (SlotOccupiedException ex) { //nearestRowIndex = GetClampedRowIndex(nearestRowIndex+1); //SetBallAtPosition(GetClampedRowIndex(nearestRowIndex), // GetClampledColumnIndex(nearestRowIndex, nearestColumnIndex), // ball); } }
public bool Equals(BallSlot otherSlot) { return(RowIndex == otherSlot.RowIndex && ColumnIndex == otherSlot.ColumnIndex); }
private void GetAllPieceOfSameColorAlignedAtSlot(BallSlot ballSlot, Ball.BallColor color, List<BallSlot> slots) { Ball ball = GetBallAtSlot(ballSlot.RowIndex, ballSlot.ColumnIndex); if (ball != null && ball.Color == color && !slots.Contains(ballSlot)) { slots.Add(ballSlot); GetAllAdjacentSlots(ballSlot).ForEach(slot => GetAllPieceOfSameColorAlignedAtSlot(slot, color, slots)); } }
public void SetBallToNearestSlot(Ball ball, BallSlot interSectingSlot) { int nearestRowIndex; int nearestColumnIndex; if (interSectingSlot != null) { // Get the nearest empty slot. List<BallSlot> emptySlots = GetAllAdjacentLowerSlots(interSectingSlot); emptySlots.AddRange(GetAdjacentSlotsOnSameRow(interSectingSlot)); emptySlots.RemoveAll(slot => GetBallAtSlot(slot) != null); Vector2 ballCenter = new Vector2(ball.Rectangle.Center.X, ball.Rectangle.Center.Y); emptySlots.Sort(delegate(BallSlot slot, BallSlot otherSlot) { float length1 = (GetSlotCenter(slot) - ballCenter).Length(); float length2 = (GetSlotCenter(otherSlot) - ballCenter).Length(); return length1.CompareTo(length2); }); if (emptySlots.Count > 0) { if (emptySlots.ElementAt(0).RowIndex > GetCurrentLowestRowIndexLimit()) { //Set All balls to Dark foreach (List<Ball> list in Balls) { foreach (Ball hangingBall in list) { if (hangingBall != null) { hangingBall.GoDark(); } } } Observer.ForEach(observer => observer.OnPlayerLoses()); } nearestRowIndex = emptySlots.ElementAt(0).RowIndex; nearestColumnIndex = emptySlots.ElementAt(0).ColumnIndex; } else { // There is no room left to place that ball. //Set All balls to Dark foreach (List<Ball> list in Balls) { foreach (Ball hangingBall in list) { if (hangingBall != null) { hangingBall.GoDark(); } } } Observer.ForEach(observer => observer.OnPlayerLoses()); nearestColumnIndex = interSectingSlot.ColumnIndex; nearestRowIndex = interSectingSlot.RowIndex; } } else // The ball reached the ceiling { float nearestRowRatio = Math.Abs(ball.Rectangle.Center.Y - Position.Y) / (Ball.RECTANGLE_HEIGHT * NUMBER_OF_ROWS); nearestRowIndex = (int)MathHelper.Clamp((float)Math.Floor(nearestRowRatio * NUMBER_OF_ROWS), 0, NUMBER_OF_ROWS - 1); if (nearestRowIndex % 2 == 0) { float nearestColumnRatio = Math.Abs(ball.Rectangle.Center.X - Position.X) / Bounds.Rectangle.Width; nearestColumnIndex = (int)MathHelper.Clamp((float)Math.Floor(nearestColumnRatio * NUMBER_OF_COLUMNS_EVEN), 0, NUMBER_OF_COLUMNS_EVEN - 1); } else { float nearestColumnRatio = Math.Abs(ball.Rectangle.Center.X + ODD_ROW_OFFSET - Position.X) / (Bounds.Rectangle.Width - 2 * ODD_ROW_OFFSET); nearestColumnIndex = (int)MathHelper.Clamp((float)Math.Floor(nearestColumnRatio * NUMBER_OF_COLUMNS_ODD), 0, NUMBER_OF_COLUMNS_ODD - 1); } } try { if (GetAllBallsAdjacentToSlot(new BallSlot(nearestRowIndex, nearestColumnIndex)).Count == 0) { nearestColumnIndex = (ball.Direction.X > 0) ? GetClampledColumnIndex(nearestRowIndex, nearestColumnIndex + 1) : GetClampledColumnIndex(nearestRowIndex, nearestColumnIndex - 1); if (GetAllBallsAdjacentToSlot(new BallSlot(nearestRowIndex, nearestColumnIndex)).Count == 0) { nearestColumnIndex = (ball.Direction.X > 0) ? GetClampledColumnIndex(nearestRowIndex, nearestColumnIndex - 2) : GetClampledColumnIndex(nearestRowIndex, nearestColumnIndex + 2); } } SetBallAtPosition(nearestRowIndex, nearestColumnIndex, ball); DestroyAlignedPieceAtSlot(nearestRowIndex, nearestColumnIndex); int numOfBallsFallen = FallDownAllBallsWithNoUpperAdjacentBalls(nearestRowIndex, nearestColumnIndex); CurrentScore.Value += (numOfBallsFallen > 0) ? (int)Math.Pow(2, numOfBallsFallen) * 10 : 0; CheckIfPlayerWins(); } catch (SlotOccupiedException ex) { //nearestRowIndex = GetClampedRowIndex(nearestRowIndex+1); //SetBallAtPosition(GetClampedRowIndex(nearestRowIndex), // GetClampledColumnIndex(nearestRowIndex, nearestColumnIndex), // ball); } }