private void GetIslandBalls(List <Island> islands, BallPrefabController ball) { Island island = islands.FirstOrDefault(i => i.balls.Contains(ball)); if (island == null) { island = new Island(); island.balls.Add(ball); islands.Add(island); if (ball.position.x == 0) { island.aloneIsland = false; } } List <BallPrefabController> neighbors = GetExistingNeighbors(ball); foreach (BallPrefabController neighbor in neighbors) { if (island.balls.Contains(neighbor)) { continue; } island.balls.Add(neighbor); if (neighbor.position.x == 0) { island.aloneIsland = false; } GetIslandBalls(islands, neighbor); } }
/// <summary> /// Usuwa piłkę z logiki /// </summary> /// <param name="ball"></param> private void RemoveBall(BallPrefabController ball) { balls[ball.position.x, ball.position.y] = null; ballConfigurations[ball.ballConfiguration]--; if (ballConfigurations[ball.ballConfiguration] < 1) { ballConfigurations.Remove(ball.ballConfiguration); } }
/// <summary> /// Próbuje przypisać pozycje dla piłki, zwraca true jeżeli się powiedzie /// </summary> /// <param name="ball"></param> /// <param name="row"></param> /// <param name="column"></param> /// <returns></returns> private bool TrySetBallPosition(BallPrefabController ball, Vector2Int position) { if (IsPositionExistAndEmpty(position)) { balls[position.x, position.y] = ball; ball.Set(position, GetBallPosition(position.x, position.y)); return(true); } return(false); }
public void ReUse(BallPrefabController ball) { if (ball.GetType() == typeof(PlayerBallPrefabController)) { usedPlayerBalls.Add(ball as PlayerBallPrefabController); } else { usedBalls.Add(ball); } }
/// <summary> /// Dodaje do przekaznej listy sąsiadów od ball którzy mają ten sam BallConfiguration co ball /// </summary> /// <param name="sameBalls"></param> /// <param name="neighbors"></param> /// <param name="ball"></param> private void AddSameBalls(List <BallPrefabController> sameBalls, List <BallPrefabController> neighbors, BallPrefabController ball) { List <Vector2Int> positions = new List <Vector2Int>(6); GetNeighborsPositions(positions, ball); List <BallPrefabController> newBalls = new List <BallPrefabController>(6); foreach (Vector2Int p in positions) { if (p.x < 0 || p.x > ballsRows - 1 || p.y < 0 || p.y > columns - 1) { continue; } BallPrefabController b = balls[p.x, p.y]; if (b == null) { continue; } if (b.ballConfiguration.Equals(ball.ballConfiguration)) { if (!sameBalls.Contains(b)) { newBalls.Add(b); } } else { if (!neighbors.Contains(b)) { neighbors.Add(b); } } // if (b != null && // b.ballConfiguration.Equals(ball.ballConfiguration) && // !sameBalls.Contains(b)) // newBalls.Add(b); } sameBalls.AddRange(newBalls); foreach (BallPrefabController newBall in newBalls) { AddSameBalls(sameBalls, neighbors, newBall); } }
private List <BallPrefabController> GetExistingNeighbors(BallPrefabController ball) { List <Vector2Int> positions = new List <Vector2Int>(6); GetNeighborsPositions(positions, ball); positions = positions.FindAll(IsPositionExistAndFull); List <BallPrefabController> result = new List <BallPrefabController>(positions.Count); foreach (Vector2Int p in positions) { result.Add(balls[p.x, p.y]); } return(result); }
/// <summary> /// Sprawdza czy dla przypisanej do player ball pozycji następuje zbicie. /// Jeżeli tak to zbija i punktuje. /// </summary> /// <param name="ball"></param> /// <returns></returns> private void Score(BallPrefabController ball) { List <BallPrefabController> scoredBalls = new List <BallPrefabController> { ball }; List <BallPrefabController> neighbors = new List <BallPrefabController>(); //sprawdz takie same piłki AddSameBalls(scoredBalls, neighbors, ball); //jeżeli są conajmniej 3 if (scoredBalls.Count < 3) { EmitRow(); if (CheckLose()) { gameController.Loose(); } else { comboCount = 0; emitedPlayerBallsCount++; playerBallEmiter.NextBall(); } return; } comboCount++; //usuń referencje foreach (BallPrefabController b in scoredBalls) { RemoveBall(b); } //samotne wyspy piłek List <Island> aloneIslands = new List <Island>(); GetIslandBalls(neighbors, aloneIslands); //usun referencje foreach (Island island in aloneIslands) { foreach (BallPrefabController b in island.balls) { RemoveBall(b); } } //zniszcz StartCoroutine(DestroyBalls(scoredBalls, aloneIslands)); }
/// <summary> /// Rozpoczyna emitowanie kólek /// </summary> /// <returns></returns> public IEnumerator StartEmit() { if (Screen.orientation == ScreenOrientation.Portrait || Screen.orientation == ScreenOrientation.PortraitUpsideDown) { columns = PORTRAIT_COLUMNS; } else { columns = LANDSCAPE_COLUMNS; } rows = BALLS_TO_EMIT / columns; //TODO hardcoding ballsRows = rows * ALL_ROWS_MULTIPLIER + 1; balls = new BallPrefabController[ballsRows, columns]; usedBalls = new List <BallPrefabController>(ballsRows * columns); usedPlayerBalls = new List <PlayerBallPrefabController>(10); ballConfigurations = new Dictionary <BallConfiguration, int>(configurations.Count); foreach (BallConfiguration ballConfiguration in configurations) { ballConfigurations.Add(ballConfiguration, 0); } for (int row = 0; row < rows; row++) { for (int column = 0; column < columns; column++) { BallPrefabController newBall = Instantiate(ballPrefab); newBall.transform.SetParent(transform, false); balls[row, column] = newBall; newBall.Set(new Vector2Int(row, column), GetBallPosition(row, column), GetRandomBallConfiguration()); yield return(null); } } nextBallEmit = Random.Range(ADD_BALL_MIN, ADD_BALL_MAX); playerBallEmiter.StartEmit(); }
protected void OnCollisionEnter2D(Collision2D coll) { if (emiter == null) { return; } BallPrefabController ball = coll.gameObject.GetComponent <BallPrefabController>(); if (ball == null && !coll.gameObject.name.Equals(TOP_ZONE_COLLIDER)) { return; } rigidbody2d.constraints = RigidbodyConstraints2D.FreezePositionY | RigidbodyConstraints2D.FreezePositionX; emiter.OnPlayerBallStay(ball); emiter = null; }
private void GetNeighborsPositions(List <Vector2Int> positions, BallPrefabController ball) { positions.Add(new Vector2Int(ball.position.x, ball.position.y - 1)); positions.Add(new Vector2Int(ball.position.x, ball.position.y + 1)); positions.Add(new Vector2Int(ball.position.x + 1, ball.position.y)); positions.Add(new Vector2Int(ball.position.x - 1, ball.position.y)); if ((firstBallPaddingLeft && ball.position.x % 2 == 0) || (!firstBallPaddingLeft && ball.position.x % 2 == 1)) //zmiana { positions.Add(new Vector2Int(ball.position.x + 1, ball.position.y - 1)); positions.Add(new Vector2Int(ball.position.x - 1, ball.position.y - 1)); } else { positions.Add(new Vector2Int(ball.position.x + 1, ball.position.y + 1)); positions.Add(new Vector2Int(ball.position.x - 1, ball.position.y + 1)); } }
public void EmitRow() { if (emitedPlayerBallsCount - lastBallEmit != nextBallEmit) { return; } firstBallPaddingLeft = !firstBallPaddingLeft; MoveAllBallsDown(); lastBallEmit = emitedPlayerBallsCount + nextBallEmit; nextBallEmit = Random.Range(ADD_BALL_MIN, ADD_BALL_MAX); List <BallPrefabController> ballsToEmit = new List <BallPrefabController>(columns); int count = usedBalls.Count; for (int i = count - 1; i >= 0 && count - i <= columns; i--) { usedBalls[i].ReUse(); ballsToEmit.Add(usedBalls[i]); usedBalls.RemoveAt(i); } count = ballsToEmit.Count; for (int i = count; i < columns; i++) { BallPrefabController newBall = Instantiate(ballPrefab); newBall.transform.SetParent(transform, false); ballsToEmit.Add(newBall); } for (int column = 0; column < columns; column++) { balls[0, column] = ballsToEmit[column]; ballsToEmit[column].Set(new Vector2Int(0, column), GetBallPosition(0, column), GetNextBallConfiguration()); ballConfigurations[ballsToEmit[column].ballConfiguration]++; } }
/// <summary> /// Wywołuje player ball gdy doleci do kólek /// </summary> public void OnPlayerBallStay(BallPrefabController collisionBall) { //przekazanie do obliczenia pozycji w emiterze kólek ballsEmiter.OnPlayerBallStay(playerBall, collisionBall); }
/// <summary> /// Metoda którą wywołuje pierwotnie player ball gdy doleci do kólek i zatrzyma swoją pozycję. /// Zwraca true jeżeli koniec gry. /// </summary> /// <param name="ball"></param> public void OnPlayerBallStay(BallPrefabController ball, BallPrefabController collisionBall) { ballConfigurations[ball.ballConfiguration]++; //dobieranie pozycji dla piłki float row = -((ball.rectTransform.anchoredPosition.y - sizeAdjuster.ballRadius) / sizeAdjuster.rowHeight); int rowInt = (int)(row - 0.5f); //kolizja z sufitem if (collisionBall == null) { rowInt = 0; } Vector2Int position = null; float column; if ((firstBallPaddingLeft && rowInt % 2 == 0) || (!firstBallPaddingLeft && rowInt % 2 == 1))//zmiana { column = (ball.rectTransform.anchoredPosition.x - sizeAdjuster.ballRadius) / sizeAdjuster.ballDiameter; } else { column = (ball.rectTransform.anchoredPosition.x - sizeAdjuster.ballDiameter) / sizeAdjuster.ballDiameter; } int columnInt = (int)(column + 0.5f); if (columnInt < 0) { columnInt = 0; } else if (columnInt >= columns) { columnInt = columns - 1; } position = new Vector2Int(rowInt, columnInt); if (!IsPositionExistAndEmpty(position)) { if (collisionBall != null) { float diff = int.MaxValue; List <Vector2Int> possiblePositions = new List <Vector2Int>(6); GetNeighborsPositions(possiblePositions, collisionBall); possiblePositions = possiblePositions.FindAll(IsPositionExistAndEmpty); foreach (Vector2Int p in possiblePositions) { float rowDiff = Math.Abs(p.x - row); if (rowDiff < diff) { position = p; diff = rowDiff; } } if ((firstBallPaddingLeft && position.x % 2 == 0) || (!firstBallPaddingLeft && position.x % 2 == 1)) //zmiana { column = (ball.rectTransform.anchoredPosition.x - sizeAdjuster.ballRadius) / sizeAdjuster.ballDiameter; } else { column = (ball.rectTransform.anchoredPosition.x - sizeAdjuster.ballDiameter) / sizeAdjuster.ballDiameter; } foreach (Vector2Int p in possiblePositions) { float sumdiff = Math.Abs(p.x - row + p.y - column); if (sumdiff < diff) { position = p; diff = sumdiff; } } } else { //TODO dla kolizji z sufitem, ale chyba wszystko zawsze działa } } //spróbuj ustawić pozycje if (TrySetBallPosition(ball, position)) { //punktuj! Score(ball); } else { //co prawda nie wchodzi tu raczej ale jakby co to: ball.DestroyBall(this, 0); playerBallEmiter.NextBall(); Debug.LogError("Could not change ball position for row = " + row + "(" + rowInt + ") and column = " + column + "(" + columnInt + ")"); } }