This tutorial is meant for educational purposes only to showcase how to build certain types of games. Please respect the copyrights/trademarks of others!
Some time ago I did a blog post about a brick game (like Arkanoid) and its adaptation to Windows Phone using XNA. Couple of weeks ago, I attempted to recreate it from scratch using the Unity game engine and, to no surprise, it was pretty a piece of cake. Below you can see a screenshot from the start screen of the game.
Game has been tested on Windows Phone/Store apps. For instructions on how to deploy your existing game onto Windows Store/Phone, check out the Microsoft Virtual Academy video here: http://www.microsoftvirtualacademy.com/training-courses/porting-unity-games-to-windows-store-and-windows-phone
Let’s do a lap around the project. First of all, we have one and only one scene, the game one.
- a Camera, set to Orthographic projection (most suitable for 2D games)
- a directional light
- a GameManager gameobject which holds the GameManager script, in charge of running our game
- the Ball which goes around on the level
- the Paddle which is the means that the user will utilize in order to prevent the Ball from touching the floor
- the Floor, which if collided with the Ball will decrease player’s lives
- the SideBlocks which just make the Ball stay in our level
- the Status Text GameObject which will display text messages
- and, of course, the Blocks which have to be hit by the Ball (via user’s assistance) and are organized in four BlockRow objects
Purpose of the game is for the Ball to hit all Blocks on the level. If we do that, we won! If the fall hits on the floor for a number of times (that is called lives), then we lose. In both cases, the only option is to start our game from the beginning. Now, let’s explore each GameObject’s code individually. Needless to mention, entire codebase was written in Visual Studio (check the free Community edition here). For debugging purposes, don’t forget to check the Visual Studio tools for Unity here.
The LeftBlock, RightBlock and UpperBlock are quads with a 2D Box Collider. Plus, they physics material is the BouncyMaterial (0 friction and 1 bounciness) so that there is no velocity (or more accurately, energy) loss upon each collision that the ball takes place. So, the Ball just bounces when it hits one of the 3 blocks.
The Floor is our “lose life” trigger. It contains the FloorScript which, on Ball impact (more accurately, GameObjects tagged as “Ball”), notifies our GameManager (discussed later) that we lost a life. The GameManager is passed as a parameter to the FloorScript.
The Paddle is a Quad that is equipped with a BoxCollider2D component plus the PaddleScript script component. The PaddleScript handles the input from the user (both touch and keyboard) taking into account the position of the Left Block and Right Block (its position is clamped between the positions of the two border blocks). Another option could probably be to make the Paddle a kinematic RigidBody2D and AddForce (or increase its x-axis velocity) depending on user’s input.
The Block is a quad prefab with a BoxCollider2D component and a BlockScript. It is also tagged with “Block”.
The BlockScript has a InitializeColor method (that creates a new color for the Block’s material) and a CollisionExit2D method that basically increases score, subtracts 1 from the “alive” blocks in our game manager and sets the Block as inactive. We did not use the Destroy method since we will re-enable all the Blocks when the user restarts the game (either if she loses or if she wins).
The Ball is a Sprite with a CircleCollider2D component and Rigidbody2D and BallScript components, being tagged as “Ball”. At the beginning of the game, we give the Ball zero speed on the X axis and a random speed at the Y axis. We are also constantly checking if the speed of the ball on either axis is too small. If this occurs, we give the ball a small “boost” (this is basically a hack, I’m still investigating whether this could be done any better).
Finally, let’s visit the GameManager script. At the bottom of it, you can see that we have an enumeration called GameState. It contains the names of the 5 states we have in the game. They are Start, Playing, Won, LostALife and LostAllLives. Having a state manager is a common practice when we’re building games, since we want to have different actions and possible user interactions upon the state that our game is currently experiencing.
We also store references to our Blocks and we have some static fields about our current lives, score and “alive” blocks.
DecreaseLives method (which is called by the FloorScript) just stops the ball (velocity = 0), checks for the lives available and sets the game state accordingly. Moreover, it sets the appropriate text on the Status text GameObject, depending on the course of the game.
The Update method takes into account the game’s state. It checks for keyboard or touch input at the states where user input is required (i.e. Start, Won, LostALife and LostAllLives). You’ll notice that it does absolutely nothing at the Playing state, since this is the state that the user gives input to the Paddle, which, as we saw, is handled by the PaddleScript.
In the Start method, we get references of all Block GameObjects on our game and a reference to the ball script whereas the InputTaken method returns true if the user has touched or clicked on the screen. Plus, we find the Status Text GameObject.
Last, but not least, the Restart method does a couple of basic things
- loops in all the blocks, sets them active and changes their color
- resets the lives and score counter
You can play completed game here: http://unitysamples.azurewebsites.net/BrickGame.html
Check the project on GitHub: https://github.com/dgkanatsios/BrickGame