Game Scene
Most everything interesting is part of the UI, so it’s all under the “Canvas” object.
Pause Menu
I’ve prepared a simple pause menu here. We don’t really need it for anything.
Grid
The bulk of the game all falls under the object called “Grid”.
It’s got a rectangular image on it to represent the game board.
You’ll also see a GemGrid component. Let’s go look at that.
GemGrid.cs
Public Variables
public class GemGrid : MonoBehaviour
{
public GameObject[] m_gemPrefab;
public int m_width = 6;
public int m_height = 6;
public float m_gridSize = 50.0f;
public GameObject m_gemPopSound;
public GameObject m_pauseMenu;
m_gemPrefab is an array of prefabs for the “gems”. They are actually fruits with faces on them.
m_width and m_height describe the size of the grid. The default is a 6x6 grid of 36 “gems”.
m_gridSize is the spacing between cells in the grid… the space between “gems”.
m_gemPopSound is a GameObject which may seem weird for a sound. We’re using a prefab with an AudioSource on it. We do that to leverage the randomization features we built into SimpleAnim in the previous lab.
m_pauseMenu is the pause menu.
Private Variables
Gem[,] m_grid;
float[] m_yOffset;
bool m_isAnimating = true;
bool m_isPaused = false;
When the game begins, we fill in the grid with Gems and save them in the 2D array m_grid.
These gems come in from the top and fall down to settle in the grid.
y_Offset is used to keep track of that spawn-in point above the grid.
Start()
void Start()
{
m_grid = new Gem[m_width, m_height];
m_yOffset = new float[m_width];
SetPause(false);
FillGrid();
}
The Start() function just initializes the variables and calls FillGrid() to spawn in the gems.
This is mostly relevant for the Designer task at the end where the width and height may be allowed to vary.
Update()
void Update()
{
for (int i = 0; i < m_width; ++i)
{
m_yOffset[i] = 0.0f;
}
// wait for the falling to stop
bool falling = false;
for (int y = 0; y < m_height; ++y)
{
for (int x = 0; x < m_width; ++x)
{
if (null != m_grid[x, y] && m_grid[x, y].IsFalling())
{
falling = true;
m_isAnimating = true;
}
}
}
if (false == falling)
{
if (false == CheckMatch())
{
m_isAnimating = false;
}
}
// keys
if (Input.GetKeyDown(KeyCode.Escape))
{ // this doubles as the option key in the android navigation bar
SetPause(!m_isPaused);
}
}
Here we go through the grid and check whether the gems are settled yet or not.
While the gems are falling, we mark m_isAnimating as true.
Once the gems are all settled, we call CheckMatch().
CheckMatch()
bool CheckMatch()
{
// a list of gems to be broken
List<Gem> breakGems = new List<Gem>();
{ // TODO
// check for matches of 3 or more gems in the vertical direction
// check for matches of 3 or more gems in the horizontal direction
}
{ // TODO call BreakGem() on all the gems in your list of gems to break
// If there are any, play the gem popping sound
// If any gems broke, return true to indicate we need to re-enter the "falling" stage
}
return false; // returning false indicates everything is static
}
This is where we’re going to do most of our work.
For now, it’s mostly empty.
The Rest
I’ve set up a lot of other helper functions like:
void SpawnGem(int x, int y)
void FillGrid()
public void BreakGem(int x, int y)
public void Swap(int x1, int y1, int x2, int y2)
Gem.cs
Most of the Gem class is set up for you.
It has falling behavior, animations, and breaking capabilities.
What we need to fill in will be the user-interaction parts.
public class Gem : MonoBehaviour
// TODO Add pointer down and pointer up handlers
// TODO add drag handlers
{
public int m_gemType;
public GameObject m_popAnim;
public float m_gravity = 10.0f;
public float m_maxSpeed = 100.0f;
...
// TODO OnPointerDown
// If the grid is animating, don't do anything
// If the grid is still, set the bool "Touched" on the animator to true
// TODO OnPointerUp
// Set the "Touched" on the animator to false
// TODO OnBeginDrag
// Set m_isDragging true
// Reset m_dragDelta to zero
// TODO OnDrag
// accumulate m_dragDelta
// if m_dragDelta accumulates more than s_swipeDist in any single direction,
// call m_grid.Swap()
// TODO OnEndDrag
// Set m_isDragging to false
// Set the "Touched" bool on the animator to false
}