Skip to content

Instantly share code, notes, and snippets.

@Trinkes
Created May 24, 2021 00:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Trinkes/a21a1718596baf3139984dcbe8d83317 to your computer and use it in GitHub Desktop.
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
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;
}
}
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);
}
}
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