using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Tetromino {
private Grid grid;
public enum TetrominoShape { I, J, L, O, S, T, Z };
public TetrominoShape shape;
private Color colour;
public int[,] blockPositions;
private int rotation;
private Collectable[] collectables = new Collectable[4];
// Constructor
public Tetromino () {
shape = (TetrominoShape)Random.Range(0, 6);
switch (shape) {
case TetrominoShape.I:
colour = Color.red;
break;
case TetrominoShape.J:
colour = Color.blue;
break;
case TetrominoShape.L:
colour = new Color(1, .5f, 0);
break;
case TetrominoShape.O:
colour = Color.yellow;
break;
case TetrominoShape.S:
colour = Color.magenta;
break;
case TetrominoShape.T:
colour = Color.cyan;
break;
case TetrominoShape.Z:
colour = Color.green;
break;
}
rotation = 0;
}
// Adds collactable to tetronimo list. When it is added to the grid it will be added to the newly created block
public bool AddCollectable (Collectable newCollectable) {
for (int i = 0; i < 4; i++) {
if (collectables[i] == null) {
collectables[i] = newCollectable;
return true;
}
}
return false;
}
// Add this tetromino to a grid. New Blocks will be constructed.
public bool AddToGrid (Grid _grid) {
grid = _grid;
blockPositions = GetBlockPositions();
for (int i = 0; i < 4; i++) {
bool added = grid.AddBlock(blockPositions[i, 0], blockPositions[i, 1], colour);
if (!added) {
return false;
}
// Add collectables to blocks
if (collectables[i]) {
grid.GetBlock(blockPositions[i, 0], blockPositions[i, 1]).AddCollectable(collectables[i]);
collectables[i].SetActive(false);
}
}
return true;
}
// Public move function
public bool Move (int xOffset, int yOffset) {
int[,] targetPositions = (int[,])blockPositions.Clone();
for (int i = 0; i < 4; i++) {
targetPositions[i, 0] += xOffset;
targetPositions[i, 1] += yOffset;
}
bool tetrominoCanMove = ((GameGrid) grid).TransformTetromino(blockPositions, targetPositions);
if (tetrominoCanMove) {
blockPositions = targetPositions;
}
return tetrominoCanMove;
}
// Public rotate function
public bool Rotate () {
//O can not rotate
if (shape == TetrominoShape.O) {
return true;
}
//calculate new positions for rotated tetromino
int[,] targetPositions = new int[4, 2];
int[,] relativePosition = new int[4, 2];
int rotationBlock = GetRotationBlock();
for (int i = 0; i < 4; i++) {
relativePosition[i, 0] = blockPositions[i, 0] - blockPositions[rotationBlock, 0];
relativePosition[i, 1] = blockPositions[i, 1] - blockPositions[rotationBlock, 1];
targetPositions[i, 0] = blockPositions[rotationBlock, 0] + relativePosition[i, 1];
targetPositions[i, 1] = blockPositions[rotationBlock, 1] - relativePosition[i, 0];
}
//I gets repositioned on rotation
if (shape == TetrominoShape.I) {
if (rotation % 2 == 1) {
for (int i = 0; i < 4; i++) {
targetPositions[i, 0]--;
}
}
}
bool tetrominoCanMove = ((GameGrid)grid).TransformTetromino(blockPositions, targetPositions);
if (tetrominoCanMove) {
rotation = ++rotation % 4;
blockPositions = targetPositions;
}
return tetrominoCanMove;
}
// Gets called on initialisation.
private int[,] GetBlockPositions() {
int[,] positions = new int[,] { };
switch (shape) {
case TetrominoShape.I:
positions = new int[,] { { -1, 0 }, { 0, 0 }, { 1, 0 }, { 2, 0 } };
break;
case TetrominoShape.J:
positions = new int[,] { { -1, 0 }, { 0, 0 }, { 1, 0 }, { 1, -1 } };
break;
case TetrominoShape.L:
positions = new int[,] { { -1, -1 }, { -1, 0 }, { 0, 0 }, { 1, 0 } };
break;
case TetrominoShape.O:
positions = new int[,] { { 0, 0 }, { 0, -1 }, { 1, 0 }, { 1, -1 } };
break;
case TetrominoShape.S:
positions = new int[,] { { -1, -1 }, { 0, -1 }, { 0, 0 }, { 1, 0 } };
break;
case TetrominoShape.T:
positions = new int[,] { { -1, 0 }, { 0, 0 }, { 0, -1 }, { 1, 0 } };
break;
case TetrominoShape.Z:
positions = new int[,] { { -1, 0 }, { 0, 0 }, { 0, -1 }, { 1, -1 } };
break;
}
for (int i = 0; i < 4; i++) {
positions[i, 0] += grid.spawnPosition[0];
positions[i, 1] += grid.spawnPosition[1];
}
return positions;
}
// Get anchor block for tetromino rotation, Tetrominos can't always rotate around its center
// Returns the index of the block to rotate around
private int GetRotationBlock() {
switch (shape) {
case TetrominoShape.I:
if (rotation < 2) return 2;
return 1;
case TetrominoShape.J:
return 1;
case TetrominoShape.L:
return 2;
case TetrominoShape.S:
if (rotation < 2) return 1;
return 2;
case TetrominoShape.T:
return 1;
case TetrominoShape.Z:
if (rotation < 2) return 1;
return 2;
}
return 0;
}
}