## Breakout Urban

C#
Unity
⛋ 2D
Uni
06/18

My first Unity project, made with the help of Trent Williams and Tristan Bondici for a University project. This is a small game made in the space of approximately 6 weeks.

This game uses the core mechanics of Breakout with the added twist that the paddle is now a baseball bat and the ball has the ability to heat up or cool down based on which side of the bat it hits and what bricks it hits. At max-cold or max-heat, the ball will cause either a row or a column of bricks to be destroyed, respectively. The layout of the bricks is entirely randomised with each play-through.

Up until recently, this had no plans for further work or release beyond on itch.io. This has now changed, and I have taken it upon myself to use this game as a way to explore the Google Play Store app pipeline. I have spent about a month reworking a lot of the logic to run more efficiently and I am nearing release soon.

### Team:

Liam Dunstan - Designer, Programmer
Trent Williams - Designer, Artist, Secondary Programmer
Tristan Bondici - Designer, Sound Guy

1 / 7 2 / 7 3 / 7 4 / 7 5 / 7 6 / 7 7 / 7 ### Code Snippets

```                                ```void CreateBricks()
{
// first brick y-pos
float y = 7.16f;
// create parent object
Transform bricks = new GameObject().transform;

for (int i = 0; i < 6; i++)
{
// first brick x-pos
float x = -4.06f;
for (int j = 0; j < 6; j++)
{
// create brick and add necessary components
Transform brick = new GameObject().transform;
brick.parent = bricks;
brick.position = new Vector3(x, y, 0);
brick.name = "brick " + (i + 1) + ", " + (j + 1);

// set values for components
brick.gameObject.GetComponent<BoxCollider>().isTrigger = true;
brick.gameObject.GetComponent<BoxCollider>().size = new Vector3(1.6f, 0.7f, 0.2f);
SpriteRenderer brSpr = brick.gameObject.GetComponent<SpriteRenderer>();
BrickScript brScr = brick.gameObject.GetComponent<BrickScript>();

// random value for brick type
float rand = Random.Range(0f, 1f);

// 50% chance of being normal brick
if (0 <= rand && rand < 0.5f)
{
// 6 variants for normal bricks randomly selected per brick
int rand = Random.Range(1, 7);

switch (rand)
{
...
}

}
// 25% chance of being "hot" brick
else if (0.5 <= rand && rand < 0.75f)
{
brSpr.sprite = hotBrick;
brScr.damageBrickOne = hotBrickDamageOne;
brScr.damageBrickTwo = hotBrickDamageTwo;
brick.gameObject.tag = "Hot Brick";
}
// 25% chance of being "cold" brick
else
{
brSpr.sprite = coldBrick;
brScr.damageBrickOne = coldBrickDamageOne;
brScr.damageBrickTwo = coldBrickDamageTwo;
brick.gameObject.tag = "Cold Brick";
}
x += 1.63f;
}
y -= 0.7f;
}
bricks.name = "bricks";
}```
```

#### Excerpt from GameplayController.cs

This snippet outlines the creation process for the bricks. Note how each brick has its type randomised, creating a dynamic set of bricks. This occurs at the beginning of every play-through.

This is how brick creation was handled in the original prototype.

```                                ```private void CreateBricks()
{
float xPos = 0;
float yPos = 0;

for (int x = 0; x < 6; x++)
{
for (int y = 0; y < 6; y++)
{
BrickScript brick = null;
float rand = Random.value;

if (rand < 0.5f)
{
int rand2 = Random.Range(1, 7);

switch (rand2)
{
// instantiate brick gameobjects from prefab and set their positions
}
}
else if (rand >= 0.5f && rand < 0.75f)
{
brick = Instantiate(hotBrickPrefab, bricksParent).GetComponent();
brick.transform.localPosition = new Vector3(xPos, yPos, -1);
}
else
{
brick = Instantiate(coldBrickPrefab, bricksParent).GetComponent();
brick.transform.localPosition = new Vector3(xPos, yPos, -1);
}

yPos -= 0.7f;
}

xPos += 1.63f;
yPos = 0;
}
}```
```

#### Excerpt from GameManager.cs

This snippet has the same functionality as the previous one, but is the way how brick creation at the start of each play-through is handled in the planned mobile release.

This is included to demonstrate my improvement in just a couple of years. By using prefabs effectively and zero-ing the initial positions with the help of a reference to the parent transform, you can see the code is considerably cleaner and more efficient.

```                                ```void Update()
{
// if left arrow is pressed
if (Input.GetKeyUp(KeyCode.LeftArrow))
{
// set initial angle and swingState variable
transform.eulerAngles = new Vector3(-180, 0, 269);
swingState = -1;
batSwingSource.Play();

// call transition method
StartCoroutine(RotateMe(Vector3.back * 178, 0.2f));
}
// if right arrow is pressed
if (Input.GetKeyUp(KeyCode.RightArrow))
{
// set initial angle and swingState variable
transform.eulerAngles = new Vector3(-180, 0, 91);
swingState = 1;
batSwingSource.Play();

// call transition method
StartCoroutine(RotateMe(Vector3.forward * 178, 0.2f));
}
}

/// <summary>
/// method for transitioning the angle of the bat
/// </summary>
/// <param name="byAngles"> Rotation direction and distance </param>
/// <param name="inTime"> Time to complete rotation </param>
/// <returns></returns>
IEnumerator RotateMe(Vector3 byAngles, float inTime)
{
var fromAngle = transform.rotation;
var toAngle = Quaternion.Euler(transform.eulerAngles + byAngles);

for (var t = 0f; t < 1; t += Time.deltaTime / inTime)
{
transform.rotation = Quaternion.Slerp(fromAngle, toAngle, t);
yield return null;
}
swingState = 0;
}```
```

#### Excerpt from BatScript.cs

The code for making the bat swing from one side to the other requires setting an initial angle, either pointing to the left of the screen or the right.

The `swingState` variable is a public property used by the ball's script for rebound velocity purposes.

The `RotateMe` method runs as a coroutine and takes parameters of `byAngles` - how far to rotate and in which direction - and `inTime` - the time it should take to complete the rotation. Once the rotation is complete the bat's `swingState` is reset.