public static void ClearBalls(BallGrid ballGrid) { for (int z = ballGrid.zMax; z >= ballGrid.zMin; z--) { for (int y = ballGrid.yMin; y <= ballGrid.yMax; y++) { int xLeft = ballGrid.xMin; int xRight = ballGrid.xMax; if (Utils.IsOdd(ballGrid.xSize)) { if ((ballGrid.xSize + 1) % 4 == 0) { if ((Utils.IsEven(z) && Utils.IsEven(y)) || (Utils.IsOdd(z) && Utils.IsOdd(y))) { xLeft++; } } else { if ((Utils.IsEven(z) && Utils.IsOdd(y)) || (Utils.IsEven(y) && Utils.IsOdd(z))) { xRight--; } } } for (int x = xLeft; x <= xRight; x++) { DestroyImmediate(ballGrid.GetGridBall(new Vector3i(x, y, z))); } } } }
public void Setup() { UseSubstituteLogging(); _useSubstitueGameManager = UseSubstitueGameManager(); _ballFactory = Substitute.For <IBallFactory>(); _ballGrid = new BallGrid(_ballFactory, new OrphanedBallFinder(), null); }
public override void OnInspectorGUI() { DrawDefaultInspector(); BallGrid ballGrid = (BallGrid)target; if (GUILayout.Button("Generate")) { BallGridEditor.GenerateRandomBallGrid(ballGrid); } if (GUILayout.Button("Clear Balls")) { BallGridEditor.ClearBalls(ballGrid); } }
public bool Move(Vector3Int move, BallGrid grid) { if (grid == null) { return(false); } if (move.x + x < grid.gridSize.x && move.y + y < grid.gridSize.y && move.z + z < grid.gridSize.z && move.x + x >= 0 && move.y + y >= 0 && move.z + z >= 0) { var oldGridPoints = GridPoints(); x += move.x; y += move.y; z += move.z; var newGridPoints = GridPoints(); foreach (Vector3Int gridPoint in newGridPoints) { if (grid.tileGrid[gridPoint.x, gridPoint.y, gridPoint.z] == null || grid.tileGrid[gridPoint.x, gridPoint.y, gridPoint.z] == this) { } else { x -= move.x; y -= move.y; z -= move.z; return(false); } } foreach (Vector3Int gridPoint in oldGridPoints) { grid.tileGrid[gridPoint.x, gridPoint.y, gridPoint.z] = null; } foreach (Vector3Int gridPoint in newGridPoints) { grid.tileGrid[gridPoint.x, gridPoint.y, gridPoint.z] = this; } OnValidate(); return(true); } return(false); }
public static void GenerateRandomBallGrid(BallGrid ballGrid) { for (int z = ballGrid.zMax; z >= ballGrid.zMin; z--) { Transform wallTF = ballGrid.GetOrCreateLayer(z); int yBottom = ballGrid.yMin; int yTop = ballGrid.yMax; for (int y = yBottom; y <= yTop; y++) { Transform rowTF = ballGrid.GetOrCreateRow(z, y, wallTF); int xLeft = ballGrid.xMin; int xRight = ballGrid.xMax; if (Utils.IsOdd(ballGrid.xSize)) { if ((ballGrid.xSize + 1) % 4 == 0) { if ((Utils.IsEven(z) && Utils.IsEven(y)) || (Utils.IsOdd(z) && Utils.IsOdd(y))) { xLeft++; } } else { if ((Utils.IsEven(z) && Utils.IsOdd(y)) || (Utils.IsEven(y) && Utils.IsOdd(z))) { xRight--; } } } for (int x = xLeft; x <= xRight; x++) { Transform colTF = ballGrid.GetOrCreateColumn(x, rowTF); GridBall gridBall = BallGridEditor.GenerateGridBall(colTF); gridBall.RefreshGridCoords(); } } } }
public GridBall SnapTo(BallGrid ballGrid, GridBallSensorNode sensorNode) { this._state = State.Snapping; this.StopCoroutine("CountdownToRecycle"); this.ballCollider.enabled = false; this.ballRigidBody.velocity = Vector3.zero; this.ballRigidBody.angularVelocity = Vector3.zero; // instantiate a grid ball in the correct spot and recycle this ball GridBall gridBall = sensorNode.GetComponentInParent <GridBall>(); Vector3i direction = new Vector3i( Mathf.RoundToInt(Utils.RoundAwayFromZero(sensorNode.transform.localPosition.x)), Mathf.RoundToInt(Utils.RoundAwayFromZero(sensorNode.transform.localPosition.y)), Mathf.RoundToInt(Utils.RoundAwayFromZero(sensorNode.transform.localPosition.z)) ); Vector3i newPos = BallGrid.GetNeighborCoords(new Vector3i(gridBall.gridCoords), direction); Transform wallTF = ballGrid.GetOrCreateLayer(Mathf.RoundToInt(newPos.z)); Transform rowTF = ballGrid.GetOrCreateRow(Mathf.RoundToInt(newPos.z), Mathf.RoundToInt(newPos.y), wallTF); Transform colTF = ballGrid.GetOrCreateColumn(Mathf.RoundToInt(newPos.x), rowTF); GridBall newGridBall = colTF.GetComponentInChildren <GridBall>(); if (newGridBall == null) { newGridBall = GridBall.Generate(colTF, wasBallShot: true); newGridBall.RefreshGridCoords(); } else { Debug.LogWarningFormat("grid ball already exists at zyx {0}", newPos.ToString()); } newGridBall.SetColor(this.ballColor); this.Recycle(); return(newGridBall); }
public static void GenerateWalls(BallGrid ballGrid) { Transform extentsTF = ballGrid.transform.FindChild("Extents"); // shift the walls over slightly for any even sized rows (because the grid ends up offset) float zShift = ballGrid.zMax + ballGrid.zMin; float yShift = ballGrid.yMax + ballGrid.yMin; float xShift = ballGrid.xMax + ballGrid.xMin; if (ballGrid.xSize % 2 == 0 && xShift == 0) { xShift = 1f; } if ((ballGrid.xSize + 1) % 4 == 0) { xShift++; } extentsTF.transform.localPosition = new Vector3( xShift * (BallGrid.GRID_SPACING_X / 2f), yShift * (BallGrid.GRID_SPACING_Y / 2f), zShift * (BallGrid.GRID_SPACING_Z / 2f) ); float zPadding = (ballGrid.zSize / 2f * BallGrid.GRID_SPACING_Z) + 0.68f; float yPadding = (ballGrid.ySize / 2f * BallGrid.GRID_SPACING_Y) + 0.63f; float xPadding = (ballGrid.xSize / 2f * BallGrid.GRID_SPACING_X) + 0.63f; float zWallDim = (ballGrid.zSize + 1f) / 2f; float yWallDim = (ballGrid.ySize + 1f) / 2f; float xWallDim = (ballGrid.xSize + 1f) / 2f; Transform zMinExtentTF = extentsTF.FindChild("z min"); if (ballGrid.zMinWall) { zMinExtentTF.transform.localPosition = Vector3.back * zPadding; WallCube wallCube = BallGridEditor.GenerateWallCube(zMinExtentTF, Vector3.zero); wallCube.transform.localScale = new Vector3(xWallDim, yWallDim, 1f); } Transform zMaxExtentTF = extentsTF.FindChild("z max"); if (ballGrid.zMaxWall) { zMaxExtentTF.transform.localPosition = Vector3.forward * zPadding; WallCube wallCube = BallGridEditor.GenerateWallCube(zMaxExtentTF, Vector3.zero); wallCube.transform.localScale = new Vector3(xWallDim, yWallDim, 1f); } Transform yMinExtentTF = extentsTF.FindChild("y min"); if (ballGrid.yMinWall) { yMinExtentTF.transform.localPosition = Vector3.down * yPadding; WallCube wallCube = BallGridEditor.GenerateWallCube(yMinExtentTF, Vector3.zero); wallCube.transform.localScale = new Vector3(xWallDim, 1f, zWallDim); } Transform yMaxExtentTF = extentsTF.FindChild("y max"); if (ballGrid.yMaxWall) { yMaxExtentTF.transform.localPosition = Vector3.up * yPadding; WallCube wallCube = BallGridEditor.GenerateWallCube(yMaxExtentTF, Vector3.zero); wallCube.transform.localScale = new Vector3(xWallDim, 1f, zWallDim); } Transform xMinExtentTF = extentsTF.FindChild("x min"); if (ballGrid.xMinWall) { xMinExtentTF.transform.localPosition = Vector3.left * xPadding; WallCube wallCube = BallGridEditor.GenerateWallCube(xMinExtentTF, Vector3.zero); wallCube.transform.localScale = new Vector3(1f, yWallDim, zWallDim); } Transform xMaxExtentTF = extentsTF.FindChild("x max"); if (ballGrid.xMaxWall) { xMaxExtentTF.transform.localPosition = Vector3.right * xPadding; WallCube wallCube = BallGridEditor.GenerateWallCube(xMaxExtentTF, Vector3.zero); wallCube.transform.localScale = new Vector3(1f, yWallDim, zWallDim); } }
public IEnumerator PopChainLoop(GridBall newGridBall) { // set this before we lose a reference to it when the new grid ball pops BallGrid currentBallGrid = newGridBall.ballGrid; currentBallGrid.SetState(BallGrid.State.Popping); List <GridBall> ballCluster = new List <GridBall>() { newGridBall }; List <GridBall> searched = new List <GridBall>(ballCluster); Queue <GridBall> searchQueue = new Queue <GridBall>(ballCluster); List <GridBall> adjacentBallsThatSurvived = new List <GridBall>(); while (searchQueue.Count > 0) { GridBall curBall = searchQueue.Dequeue(); if (curBall.ballColor == newGridBall.ballColor) { if (!ballCluster.Contains(curBall)) { ballCluster.Add(curBall); } foreach (GridBall gb in curBall.neighbors) { if (!searched.Contains(gb)) { searched.Add(gb); searchQueue.Enqueue(gb); } } } else { if (!adjacentBallsThatSurvived.Contains(curBall)) { adjacentBallsThatSurvived.Add(curBall); } } } if (ballCluster.Count >= 3) { foreach (GridBall gb in ballCluster) { gb.RemoveFromWall(); yield return(new WaitForSeconds(POP_DELAY)); } } int loopSafety = 0; List <GridBall> searched2 = new List <GridBall>(); while (adjacentBallsThatSurvived.Count > 0) { GridBall survivorBall = adjacentBallsThatSurvived[0]; searched2.Add(survivorBall); adjacentBallsThatSurvived.RemoveAt(0); survivorBall.CheckIfConnectedToWall(); if (!survivorBall.isConnectedToWall) { foreach (GridBall gb in survivorBall.neighbors) { if (!searched2.Contains(gb) && !adjacentBallsThatSurvived.Contains(gb)) { adjacentBallsThatSurvived.Add(gb); } } survivorBall.RemoveFromWall(); yield return(new WaitForSeconds(POP_DELAY)); } loopSafety++; if (loopSafety > 10000) { Debug.LogError("loop safety!"); break; } } currentBallGrid.SetState(BallGrid.State.Default); }