Skip to content

Commit

Permalink
Add core game logic
Browse files Browse the repository at this point in the history
  • Loading branch information
adamgraham committed Aug 10, 2021
1 parent 26d8573 commit f83de2b
Show file tree
Hide file tree
Showing 9 changed files with 972 additions and 728 deletions.
1,201 changes: 473 additions & 728 deletions Assets/Scenes/Tetris.unity

Large diffs are not rendered by default.

148 changes: 148 additions & 0 deletions Assets/Scripts/Board.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
using UnityEngine;
using UnityEngine.Tilemaps;

public class Board : MonoBehaviour
{
public Tilemap tilemap { get; private set; }
public Piece activePiece { get; private set; }

public TetrominoData[] tetrominoes;
public Vector2Int boardSize = new Vector2Int(10, 20);
public Vector3Int spawnPosition = new Vector3Int(-1, 8, 0);

public RectInt Bounds {
get
{
Vector2Int position = new Vector2Int(-this.boardSize.x / 2, -this.boardSize.y / 2);
return new RectInt(position, this.boardSize);
}
}

private void Awake()
{
this.tilemap = GetComponentInChildren<Tilemap>();
this.activePiece = GetComponentInChildren<Piece>();

for (int i = 0; i < this.tetrominoes.Length; i++) {
this.tetrominoes[i].Initialize();
}
}

private void Start()
{
SpawnPiece();
}

public void SpawnPiece()
{
int random = Random.Range(0, this.tetrominoes.Length);
TetrominoData data = this.tetrominoes[random];

this.activePiece.Initialize(this, this.spawnPosition, data);
Set(this.activePiece);
}

public void Set(Piece piece)
{
for (int i = 0; i < piece.cells.Length; i++)
{
Vector3Int tilePosition = piece.cells[i] + piece.position;
this.tilemap.SetTile(tilePosition, piece.data.tile);
}
}

public void Clear(Piece piece)
{
for (int i = 0; i < piece.cells.Length; i++)
{
Vector3Int tilePosition = piece.cells[i] + piece.position;
this.tilemap.SetTile(tilePosition, null);
}
}

public bool IsValidPosition(Piece piece, Vector3Int position)
{
RectInt bounds = this.Bounds;

// The position is only valid if every cell is valid
for (int i = 0; i < piece.cells.Length; i++)
{
Vector3Int tilePosition = piece.cells[i] + position;

// An out of bounds tile is invalid
if (!bounds.Contains((Vector2Int)tilePosition)) {
return false;
}

// A tile already occupies the position, thus invalid
if (this.tilemap.HasTile(tilePosition)) {
return false;
}
}

return true;
}

public void ClearLines()
{
RectInt bounds = this.Bounds;
int row = bounds.yMin;

// Clear from bottom to top
while (row < bounds.yMax)
{
// Only advance to the next row if the current is not cleared
// because the tiles above will fall down when a row is cleared
if (IsLineFull(row)) {
LineClear(row);
} else {
row++;
}
}
}

public bool IsLineFull(int row)
{
RectInt bounds = this.Bounds;

for (int col = bounds.xMin; col < bounds.xMax; col++)
{
Vector3Int position = new Vector3Int(col, row, 0);

// The line is not full if a tile is missing
if (!this.tilemap.HasTile(position)) {
return false;
}
}

return true;
}

public void LineClear(int row)
{
RectInt bounds = this.Bounds;

// Clear all tiles in the row
for (int col = bounds.xMin; col < bounds.xMax; col++)
{
Vector3Int position = new Vector3Int(col, row, 0);
this.tilemap.SetTile(position, null);
}

// Shift every row above down one
while (row < bounds.yMax)
{
for (int col = bounds.xMin; col < bounds.xMax; col++)
{
Vector3Int position = new Vector3Int(col, row + 1, 0);
TileBase above = this.tilemap.GetTile(position);

position = new Vector3Int(col, row, 0);
this.tilemap.SetTile(position, above);
}

row++;
}
}

}
11 changes: 11 additions & 0 deletions Assets/Scripts/Board.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

76 changes: 76 additions & 0 deletions Assets/Scripts/Ghost.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
using UnityEngine;
using UnityEngine.Tilemaps;

public class Ghost : MonoBehaviour
{
public Tile tile;
public Board board;
public Piece trackingPiece;

public Tilemap tilemap { get; private set; }
public Vector3Int[] cells { get; private set; }
public Vector3Int position { get; private set; }

private void Awake()
{
this.tilemap = GetComponentInChildren<Tilemap>();
this.cells = new Vector3Int[4];
}

private void LateUpdate()
{
Clear();
Copy();
Drop();
Set();
}

private void Clear()
{
for (int i = 0; i < this.cells.Length; i++)
{
Vector3Int tilePosition = this.cells[i] + this.position;
this.tilemap.SetTile(tilePosition, null);
}
}

private void Copy()
{
for (int i = 0; i < this.cells.Length; i++) {
this.cells[i] = this.trackingPiece.cells[i];
}
}

private void Drop()
{
Vector3Int position = this.trackingPiece.position;

int current = position.y;
int bottom = -this.board.boardSize.y / 2 - 1;

this.board.Clear(this.trackingPiece);

for (int row = current; row >= bottom; row--)
{
position.y = row;

if (this.board.IsValidPosition(this.trackingPiece, position)) {
this.position = position;
} else {
break;
}
}

this.board.Set(this.trackingPiece);
}

private void Set()
{
for (int i = 0; i < this.cells.Length; i++)
{
Vector3Int tilePosition = this.cells[i] + this.position;
this.tilemap.SetTile(tilePosition, this.tile);
}
}

}
11 changes: 11 additions & 0 deletions Assets/Scripts/Ghost.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit f83de2b

Please sign in to comment.