Created
May 24, 2021 00:12
-
-
Save Trinkes/a21a1718596baf3139984dcbe8d83317 to your computer and use it in GitHub Desktop.
Block Adventure - Bug fix where user can drop a shape different from the one he dragged
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
public class Grid : MonoBehaviour | |
{ | |
[SerializeField] private ShapeStorage shapeStorage; | |
[SerializeField] public int rows = 0; | |
[SerializeField] private int columns = 0; | |
[SerializeField] private float squareGap = 0.1f; | |
[SerializeField] private GameObject gridSquare; | |
[SerializeField] private Vector2 startPosition = new Vector2(0.0f, 0.0f); | |
[SerializeField] private float squareScale = 0.5f; | |
[SerializeField] | |
private float everySquareOffset = 0.0f; | |
public SquareTextureData squareTextureData; | |
private Vector2 _offset = new Vector2(0.0f, 0.0f); | |
private List<GameObject> _gridSquares = new List<GameObject>(); | |
private LineIndicator lineIndicator; | |
private Config.SquareCorlor currentActiveSquareColor = Config.SquareCorlor.NOT_SET; | |
private void OnEnable() | |
{ | |
GameEvents.checkIfShapeCanBePlaced += checkIfShapeCanBePlaced; | |
GameEvents.updateSquareColor += onUpdateSquareColor; | |
} | |
private void OnDisable() | |
{ | |
GameEvents.updateSquareColor -= onUpdateSquareColor; | |
GameEvents.checkIfShapeCanBePlaced -= checkIfShapeCanBePlaced; | |
} | |
void Start() | |
{ | |
lineIndicator = GetComponent<LineIndicator>(); | |
CreateGrid(); | |
currentActiveSquareColor = squareTextureData.activeSquareTextures[0].squareColor; | |
} | |
private void onUpdateSquareColor(Config.SquareCorlor color) | |
{ | |
currentActiveSquareColor = color; | |
} | |
private void CreateGrid() | |
{ | |
SpawnGridSquares(); | |
SetGridSquarePositions(); | |
} | |
private void SpawnGridSquares() | |
{ | |
int squareIndex = 0; | |
for (var row = 0; row < rows; ++row) | |
{ | |
for (var column = 0; column < columns; ++column) | |
{ | |
GameObject square = Instantiate(gridSquare) as GameObject; | |
_gridSquares.Add(square); | |
square.GetComponent<GridSquare>().squareIndex = squareIndex; | |
square.transform.SetParent(this.transform); | |
square.transform.localScale = new Vector3(squareScale, squareScale, squareScale); | |
square.GetComponent<GridSquare>().setImage(lineIndicator.getGridScoreIndex(squareIndex) % 2 == 0); | |
squareIndex++; | |
} | |
} | |
} | |
private void SetGridSquarePositions() | |
{ | |
int columnNumber = 0; | |
int rowNumber = 0; | |
Vector2 squareGapNumber = new Vector2(0.0f, 0.0f); | |
bool rowMoved = false; | |
var squareRect = _gridSquares[0].GetComponent<RectTransform>(); | |
_offset.x = squareRect.rect.width * squareRect.transform.localScale.x + everySquareOffset; | |
_offset.y = squareRect.rect.height * squareRect.transform.localScale.y + everySquareOffset; | |
foreach (var square in _gridSquares) | |
{ | |
if (columnNumber + 1 > columns) | |
{ | |
squareGapNumber.x = 0; | |
// go to next column | |
columnNumber = 0; | |
rowNumber++; | |
rowMoved = false; | |
} | |
var posXoffset = _offset.x * columnNumber + (squareGapNumber.x * squareGap); | |
var posYoffset = _offset.y * rowNumber + (squareGapNumber.y * squareGap); | |
if (columnNumber > 0 && columnNumber % 3 == 0) | |
{ | |
squareGapNumber.x++; | |
posXoffset += squareGap; | |
} | |
if (rowNumber > 0 && rowNumber % 3 == 0 && rowMoved == false) | |
{ | |
rowMoved = true; | |
squareGapNumber.y++; | |
posYoffset += squareGap; | |
} | |
square.GetComponent<RectTransform>().anchoredPosition = new Vector2(startPosition.x + posXoffset, startPosition.y - posYoffset); | |
square.GetComponent<RectTransform>().localPosition = new Vector3(startPosition.x + posXoffset, startPosition.y - posYoffset, 0.0f); | |
columnNumber++; | |
} | |
} | |
private void checkIfShapeCanBePlaced() | |
{ | |
var squareIndexes = new List<int>(); | |
foreach (var square in _gridSquares) | |
{ | |
var gridSquare = square.GetComponent<GridSquare>(); | |
if (gridSquare.selected && !gridSquare.squareOccupied) | |
{ | |
squareIndexes.Add(gridSquare.squareIndex); | |
gridSquare.selected = false; | |
} | |
} | |
var currentSelectedShape = shapeStorage.getCurrentSelectedShape(); | |
if (currentSelectedShape == null) // there is no selected shape | |
{ | |
return; | |
} | |
var shapeSelected = lineIndicator.getFullShapePosition(squareIndexes.ToArray()); | |
var rowData = getSquareCombination(shapeSelected.getX(), shapeSelected.getY(), shapeSelected.getColumnSize(), shapeSelected.getRowSize()); | |
if (currentSelectedShape.totalSquareNumber == squareIndexes.Count && rowData != null && isBoardCorrectlySelected(currentSelectedShape.currentShapeData, rowData, squareIndexes)) | |
{ | |
foreach (var squareIndex in squareIndexes) | |
{ | |
_gridSquares[squareIndex].GetComponent<GridSquare>().placeShapeOnTheBoard(currentActiveSquareColor); | |
} | |
var shapeLeft = 0; | |
foreach (var shape in shapeStorage.shapeList) | |
{ | |
if (shape.isOnStartPosition() && shape.isAnyOfShapeSquareActive()) | |
{ | |
shapeLeft++; | |
} | |
} | |
if (shapeLeft == 0) | |
{ | |
GameEvents.requestNewShapes(); | |
} | |
else | |
{ | |
GameEvents.setShapeInactive(); | |
} | |
checkIfAnyLineIsCompleted(); | |
} | |
else | |
{ | |
GameEvents.moveShapeToStartPosition(); | |
} | |
} | |
// check if the shape the user is trying to place on the board matches the one he grabbed | |
private bool isBoardCorrectlySelected(ShapeData currentShapeData, List<int> squareCombination, List<int> squareSelectedShape) | |
{ | |
if (currentShapeData.columns * currentShapeData.rows != squareCombination.Count) | |
{ | |
return false; | |
} | |
List<int> reservedIndexes = new List<int>(squareSelectedShape.Count); | |
int squareIndexIterIndex = 0; | |
for (int i = 0; i < currentShapeData.board.Length; i++) | |
{ | |
for (int j = 0; j < currentShapeData.board[i].column.Length; j++) | |
{ | |
if (currentShapeData.board[i].column[j]) | |
{ | |
reservedIndexes.Add(squareCombination[squareIndexIterIndex]); | |
} | |
squareIndexIterIndex++; | |
} | |
} | |
for (int i = 0; i < reservedIndexes.Count; i++) | |
{ | |
if (reservedIndexes[i] != squareSelectedShape[i]) | |
{ | |
return false; | |
} | |
} | |
return true; | |
} | |
void checkIfAnyLineIsCompleted() | |
{ | |
List<int[]> lines = new List<int[]>(); | |
// columns | |
foreach (var column in lineIndicator.columnIndexes) | |
{ | |
lines.Add(lineIndicator.getVerticalLine(column)); | |
} | |
// rows | |
for (int row = 0; row < 9; row++) | |
{ | |
List<int> data = new List<int>(9); | |
for (int index = 0; index < 9; index++) | |
{ | |
data.Add(lineIndicator.lineData[row, index]); | |
} | |
lines.Add(data.ToArray()); | |
} | |
// squares | |
for (int square = 0; square < 9; square++) | |
{ | |
List<int> data = new List<int>(9); | |
for (int index = 0; index < 9; index++) | |
{ | |
data.Add(lineIndicator.squareData[square, index]); | |
} | |
lines.Add(data.ToArray()); | |
} | |
var completedLines = checkIfSquaresAreCompleted(lines); | |
if (completedLines > 2) | |
{ | |
//TODO: Play Bonus animation | |
} | |
var totalScores = 10 * completedLines; | |
GameEvents.addScores(totalScores); | |
checkIfPlayerLost(); | |
} | |
private int checkIfSquaresAreCompleted(List<int[]> data) | |
{ | |
List<int[]> completedLines = new List<int[]>(); | |
var linesCompleted = 0; | |
foreach (var line in data) | |
{ | |
var lineCompleted = true; | |
foreach (var squareIndex in line) | |
{ | |
var comp = _gridSquares[squareIndex].GetComponent<GridSquare>(); | |
if (!comp.squareOccupied) | |
{ | |
lineCompleted = false; | |
} | |
} | |
if (lineCompleted) | |
{ | |
completedLines.Add(line); | |
} | |
} | |
foreach (var line in completedLines) | |
{ | |
var completed = false; | |
foreach (var squareIndex in line) | |
{ | |
var comp = _gridSquares[squareIndex].GetComponent<GridSquare>(); | |
comp.deactivate(); | |
completed = true; | |
} | |
foreach (var squareIndex in line) | |
{ | |
var comp = _gridSquares[squareIndex].GetComponent<GridSquare>(); | |
comp.clearOccupied(); | |
} | |
if (completed) | |
{ | |
linesCompleted++; | |
} | |
} | |
return linesCompleted; | |
} | |
private void checkIfPlayerLost() | |
{ | |
var validShapes = 0; | |
for (int index = 0; index < shapeStorage.shapeList.Count; index++) | |
{ | |
var isShapeActive = shapeStorage.shapeList[index].isAnyOfShapeSquareActive(); | |
if (checkIfShapeCanBePlacedOnGrid(shapeStorage.shapeList[index]) && isShapeActive) | |
{ | |
shapeStorage.shapeList[index]?.activateShape(); | |
validShapes++; | |
} | |
} | |
if (validShapes == 0) | |
{ | |
GameEvents.gameOver(false); | |
} | |
} | |
private bool checkIfShapeCanBePlacedOnGrid(Shape currentShape) | |
{ | |
var currentShapeData = currentShape.currentShapeData; | |
var shapeColumns = currentShapeData.columns; | |
var shapeRows = currentShapeData.rows; | |
// all indexes of filled up squares | |
List<int> originalFilledUpSquares = new List<int>(); | |
var squareIndex = 0; | |
for (int rowIndex = 0; rowIndex < shapeRows; rowIndex++) | |
{ | |
for (int columnIndex = 0; columnIndex < shapeColumns; columnIndex++) | |
{ | |
if (currentShapeData.board[rowIndex].column[columnIndex]) | |
{ | |
originalFilledUpSquares.Add(squareIndex); | |
} | |
squareIndex++; | |
} | |
} | |
if (currentShape.totalSquareNumber != originalFilledUpSquares.Count) | |
{ | |
Debug.LogError("Number of filled up squares are not the same as original shape have."); | |
} | |
// above reviewed | |
var squareList = getAllSquaresCombination(shapeColumns, shapeRows); | |
bool canBePlaced = false; | |
foreach (var number in squareList) | |
{ | |
bool shapeCanBePlacedOnTheBoard = true; | |
foreach (var squareIndexToCheck in originalFilledUpSquares) | |
{ | |
var comp = _gridSquares[number[squareIndexToCheck]].GetComponent<GridSquare>(); | |
if (comp.squareOccupied) | |
{ | |
shapeCanBePlacedOnTheBoard = false; | |
} | |
} | |
if (shapeCanBePlacedOnTheBoard) | |
{ | |
canBePlaced = true; | |
} | |
} | |
return canBePlaced; | |
} | |
private List<int[]> getAllSquaresCombination(int columns, int rows)//reviewed | |
{ | |
var squareList = new List<int[]>(); | |
var lastColumnIndex = 0; | |
var lastRowIndex = 0; | |
int safeIndex = 0; | |
while (lastRowIndex + (rows - 1) < 9) | |
{ | |
var rowData = getSquareCombination(lastRowIndex, lastColumnIndex, columns, rows); | |
if (rowData != null) | |
{ | |
squareList.Add(rowData.ToArray()); | |
} | |
lastColumnIndex++; | |
if (lastColumnIndex + (columns - 1) >= 9) | |
{ | |
lastRowIndex++; | |
lastColumnIndex = 0; | |
} | |
safeIndex++; | |
if (safeIndex > 100) | |
{ | |
break; | |
} | |
} | |
return squareList; | |
} | |
//get the indexes of the shape that will be placed on the board | |
private List<int> getSquareCombination(int x, int y, int columns, int rows) | |
{ | |
if ((x -1) + rows > 9 || (y -1) + columns > 9) | |
{ | |
return null; | |
} | |
var rowData = new List<int>(); | |
for (int row = x; row < x + rows; row++) | |
{ | |
for (int column = y; column < y + columns; column++) | |
{ | |
rowData.Add(lineIndicator.lineData[row, column]); | |
} | |
} | |
return rowData; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
public class LineIndicator : MonoBehaviour | |
{ | |
public int[,] lineData = new int[9, 9] | |
{ | |
{ 0, 1, 2, 3, 4, 5, 6, 7, 8 }, | |
{ 9, 10, 11, 12, 13, 14, 15, 16, 17 }, | |
{ 18, 19, 20, 21, 22, 23, 24, 25, 26 }, | |
{ 27, 28, 29, 30, 31, 32, 33, 34, 35 }, | |
{ 36, 37, 38, 39, 40, 41, 42, 43, 44 }, | |
{ 45, 46, 47, 48, 49, 50, 51, 52, 53 }, | |
{ 54, 55, 56, 57, 58, 59, 60, 61, 62 }, | |
{ 63, 64, 65, 66, 67, 68, 69, 70, 71 }, | |
{ 72, 73, 74, 75, 76, 77, 78, 79, 80 } | |
}; | |
public int[,] squareData = new int[9, 9] | |
{ | |
{ 0, 1, 2, 9, 10, 11, 18, 19, 20}, | |
{ 3, 4, 5, 12, 13, 14, 21, 22, 23}, | |
{ 6, 7, 8, 15, 16, 17, 24, 25, 26}, | |
{27, 28, 29, 36, 37, 38, 45, 46, 47}, | |
{30, 31, 32, 39, 40, 41, 48, 49, 50}, | |
{33, 34, 35, 42, 43, 44, 51, 52, 53}, | |
{54, 55, 56, 63, 64, 65, 72, 73, 74}, | |
{57, 58, 59, 66, 67, 68, 75, 76, 77}, | |
{60, 61, 62, 69, 70, 71, 78, 79, 80}, | |
}; | |
[HideInInspector] | |
public int[] columnIndexes = new int[9] | |
{ | |
0,1,2,3,4,5,6,7,8 | |
}; | |
public int[] getVerticalLine(int squareIndex) | |
{ | |
int[] line = new int[9]; | |
var squarePositionColumn = getSquarePosition(squareIndex).Item2; | |
for (int index = 0; index < 9; index++) | |
{ | |
line[index] = lineData[index, squarePositionColumn]; | |
} | |
return line; | |
} | |
public (int, int) getSquarePosition(int squareIndex) | |
{ | |
int positionRow = -1; | |
int positionColumn = -1; | |
for (int row = 0; row < 9; row++) | |
{ | |
for (int column = 0; column < 9; column++) | |
{ | |
if (lineData[row, column] == squareIndex) | |
{ | |
positionRow = row; | |
positionColumn = column; | |
} | |
} | |
} | |
return (positionRow, positionColumn); | |
} | |
public int getGridScoreIndex(int square) | |
{ | |
for (int row = 0; row < 9; row++) | |
{ | |
for (int col = 0; col < 9; col++) | |
{ | |
if (squareData[row, col] == square) | |
{ | |
return row; | |
} | |
} | |
} | |
return -1; | |
} | |
// get the meta data about the shape that will be placed on the board | |
public ShapeSelected getFullShapePosition(int[] shapePositions) | |
{ | |
var x = 200; | |
var y = 200; | |
HashSet<int> columns = new HashSet<int>(); | |
HashSet<int> rows = new HashSet<int>(); | |
foreach (var position in shapePositions) | |
{ | |
var boardLocation = getSquarePosition(position); | |
rows.Add(boardLocation.Item1); | |
columns.Add(boardLocation.Item2); | |
if (boardLocation.Item1 < x) | |
{ | |
x = boardLocation.Item1; | |
} | |
if (boardLocation.Item2 < y) | |
{ | |
y = boardLocation.Item2; | |
} | |
} | |
return new ShapeSelected(x,y,columns.Count, rows.Count); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class ShapeSelected | |
{ | |
int x, y, columnSize, rowSize; | |
public ShapeSelected(int x, int y, int columnSize, int rowSize) | |
{ | |
this.x = x; | |
this.y = y; | |
this.columnSize = columnSize; | |
this.rowSize = rowSize; | |
} | |
public int getX() | |
{ | |
return x; | |
} | |
public int getY() | |
{ | |
return y; | |
} | |
public int getColumnSize() | |
{ | |
return columnSize; | |
} | |
public int getRowSize() | |
{ | |
return rowSize; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment