SameGame engine made with Unity and C# – adding animations + commented code
Talking about SameGame game, C#, Game development and Unity3D.
Do you like my tutorials?
Then consider supporting me on Ko-fi.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Script : MonoBehaviour {
// the tile itself
public GameObject tileObject;
// array with game colors
private Color[] colors = new Color[4];
// howw many rows?
private int numRows = 8;
// how many columns?
private int numCols = 8;
// two dimensional array which will contain the game table
private GameObject[,] tilesArray = new GameObject[8, 8];
// this List (basically an array with a twist) will be used to store flood fill results.
private List<Vector2> filled;
// tilesToMove is used to see how many tiles we have to move with LeanTween
private int tilesToMove = 0;
// can the player pick a tile?
private bool canPick = true;
void Start () {
// defining colors to be used as tile tint
colors [0] = new Color(1f, 0f, 0f, 1f);
colors [1] = new Color(0f, 1f, 0f, 1f);
colors [2] = new Color(0f, 0f, 1f, 1f);
colors [3] = new Color(1f, 1f, 0f, 1f);
// looping through the whole table
for (int i = 0; i < numRows; i++) {
for (int j = 0; j < numCols; j++){
// function to create a tile
createTile (i, j);
}
}
}
// this function is executed at each frame
void Update () {
// if the player clicked/touched AND can pick a tile…
if (Input.GetButtonDown (“Fire1”) && canPick) {
// getting mouse position
Vector2 firePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
// each tile has a collider to determine if mouse position overlaps
Collider2D hitCollider = Physics2D.OverlapPoint(firePosition);
// if there is a collider, that is if we clicked a tile…
if (hitCollider) {
// filled List is set to empty list
filled = new List<Vector2> ();
// running flood fill algorithm
floodFill (hitCollider.GetComponent<tileScript> ().coordinate, hitCollider.GetComponent<tileScript> ().value);
// if there are more than one tile in the flood fill result…
if (filled.Count > 1) {
// player can’t pick anymore at the moment
canPick = false;
// looping through filled List
for (int i = 0; i < filled.Count; i++) {
// destroying the game object
Destroy (tilesArray [(int)filled [i].y, (int)filled [i].x]);
// setting list entry to null
tilesArray [(int)filled [i].y, (int)filled [i].x] = null;
}
// fill vertical holes, if any
fillVerticalHoles ();
}
}
}
}
void createTile(int row, int col){
// creation of a new tileObject instance
GameObject tile = Instantiate(tileObject);
// determining vertical position
float yPos = 3.5f – 1f * row;
// determining horizontal position
float xPos = -3.5f + 1f * col;
// placing the tile at the proper position
tile.transform.position = new Vector2 (xPos, yPos);
// choosing a random color
int tileColor = Random.Range (0, colors.Length);
// setting value property with the chosen color
tile.GetComponent<tileScript> ().value = tileColor;
// saving coordinate property
tile.GetComponent<tileScript> ().coordinate = new Vector2 (col, row);
// applying the tint color to the tile
tile.GetComponent<Renderer> ().material.color = colors [tileColor];
// adding the tile to tilesArray array
tilesArray [row,col] = tile;
}
// function to fill holes by making tiles fall down
void fillVerticalHoles(){
for (int i = numRows – 2; i >= 0; i–) {
for (int j = 0; j < numCols; j++) {
if (tilesArray [i, j] != null) {
int holesBelow = 0;
for (int z = i + 1; z < numRows; z++) {
if (tilesArray [z, j] == null) {
holesBelow++;
}
}
if (holesBelow>0) {
tilesToMove ++;
moveTile (i, j, i + holesBelow, j);
}
}
}
}
if(tilesToMove==0){
fillHorizontalHoles();
}
}
// function to fill holes horizontally, that is to move columns to the left to replace missing columns
void fillHorizontalHoles(){
for (int i = 0; i < numCols – 1; i++) {
if (tilesInColumn (i) == 0) {
for (int j = i + 1; j < numCols; j++) {
if (tilesInColumn (j) != 0) {
for (int z = 0; z < numRows; z++) {
if (tilesArray [z, j] != null) {
tilesToMove ++;
moveTile (z, j, z, i);
}
}
break;
}
}
}
}
if(tilesToMove==0){
canPick = true;
}
}
// function to move a tile, this is where LeanTween comes into play
void moveTile(int fromRow, int fromCol, int toRow, int toCol){
tilesArray [toRow, toCol] = tilesArray [fromRow, fromCol];
tilesArray [toRow, toCol].GetComponent<tileScript> ().coordinate = new Vector2 (toCol, toRow);
// vertical tween
if(fromRow != toRow){
LeanTween.moveY (tilesArray [toRow, toCol], 3.5f – 1f * toRow, 0.5f).setOnComplete(completeYMovement);
}
// horizontal tween
else{
LeanTween.moveX (tilesArray [toRow, toCol], -3.5f + 1f * toCol, 0.5f).setEase(LeanTweenType.easeOutBounce).setOnComplete(completeXMovement);
}
tilesArray [fromRow, fromCol] = null;
}
// this function is executed each time a vertical tween is completed.
// we decrease tilesToMove and once it reaches zero (no more tiles to move)
// we call fillHorizontalHoles function to move tiles horizontally, if we have to.
void completeYMovement(){
tilesToMove –;
if(tilesToMove == 0){
fillHorizontalHoles ();
}
}
// this function is executed each time an horizontal tween is completed.
// we decrease tilesToMove and once it reaches zero (no more tiles to move)
// we set canPick to true so the player can pick again
void completeXMovement(){
tilesToMove –;
if(tilesToMove == 0){
canPick = true;
}
}
// function to count how many tiles we have in a column, simply counting values different than “null”
int tilesInColumn(int col){
int result = 0;
for (int i = 0; i < numRows; i++) {
if (tilesArray [i, col] != null) {
result++;
}
}
return result;
}
// flood fill function, for more information
// http://emanueleferonato.com/2008/06/06/flash-flood-fill-implementation/
void floodFill(Vector2 p, int n){
if (p.x < 0 || p.y < 0 || p.x > numCols – 1 || p.y > numRows – 1) {
return;
}
if (tilesArray [(int)p.y, (int)p.x] != null && tilesArray [(int)p.y, (int)p.x].GetComponent<tileScript> ().value == n && !filled.Contains(p)) {
filled.Add (p);
floodFill (new Vector2 (p.x + 1, p.y),n);
floodFill (new Vector2 (p.x – 1, p.y),n);
floodFill (new Vector2 (p.x, p.y + 1),n);
floodFill (new Vector2 (p.x, p.y – 1),n);
}
}
}
You can also download the entire project and play with it. Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.