This article has been brought to you by Microsoft
I had blogged in the past about a simple puzzle game in XNA. Nothing better than to recreate it in Unity with a tutorial, of course! To begin with, here’s a screenshot of the game running on the editor (see below).
Click to enlarge
The purpose of the game is to tap/click on the pieces next to the empty one so that they exchange positions. It goes on and on until you make the pieces appear as in the original photo.
Since you are reading this article, I suppose you most probably are a novice Unity user. Here's a link to a free Microsoft Virtual Academy video that might be useful.
To begin with, we’ll need a photo. The best way to save yourself from copyright issues and not having to read licenses etc is to use a photo that you took! So, we need to slice it. For this purpose, we’ll use Unity’s native 2D tools and its sprite editor.
Once we set the sprite mode to multiple, we can use the sprite editor to ‘slice’ our image. Since the image does not have an alpha channel, we’ll use Grid slicing. Moreover, we’ll name our exported sprites with a name that contains their location information (i.e. piece-0-0 => this implies that the sprite’s “correct” location is on the top left corner of our game). Plus, we’ll set each sprite’s pivot point to be top left, since this will help us in positioning.
In our game, we’ll use a Piece class that contains a) our GameObject (the sprite) and b) relevant information about its current and “correct” positions. Entire code was written in Visual Studio (check out the free Community edition here and the Microsoft Visual Studio Tools for Unity here).
We’ll also have an enumeration for the states of our game plus some constants for our columns and rows count.
Our hierarchy is pretty simple. We have the orthographic camera and our puzzle pieces (which we could also store as prefabs).
The Camera holds the Game script, which is the backbone of our game. We provide the 16 sprites as parameters to the script. Let’s check it out line by line.
At first, we set the state of the game and select a random piece to be blank. We set it as inactive. Then, we take the 16 sprites (imported in a 1D array) and insert them in a 2D array via the Piece class, by assigning all the necessary properties. Plus, we set their positions and add a BoxCollider2D component, if they don’t have one. Last, we set the blank piece to be null.
The GetScreenCoordinatesFromViewport method returns a Vector3 with the world location for each object. The way it works is this; since it’s scanning the viewport, you can imagine the lower left corner to have coordinates (0,0) and the upper right (1,1). So, for instance, a puzzle piece in the second row and in the third column would have coordinates (0.5, 0.75). Below the method we declare some helpful fields and objects for our game.
Our GUI is pretty basic, prompts the user to tap in order to start the game or restart it, if she or he has won.
Our Update method checks the game state. If we are in the start state and a tap occurs, we shuffle the available pieces and transition to the playing state. If we are in the playing state, we handle the player’s tap events. We also have an animating state, where our piece transitions from the original position to the blank one and finally, an ending state where the user can tap in order to restart the game.
The Shuffle method randomly swaps each puzzle pieces with another one.
The Swap method does the classic work of swapping two objects by using a temp reference. It also sets the correct transforms plus updating the current I and J information.
The CheckPieceInput, running on the playing state of our game, does a raycast upon each player’s tap in order to determine the object that was hit. It loops through all objects in the 2D array to find the correct one. [A prettier way would probably be to attach a MonoBehavior script to each Sprite and find its corresponding Piece reference via its help, but the implemented approach works, nonetheless].
Once we find the Piece that contains the sprite that the user has tapped on, we check its left, its top, its right and its bottom pieces, taking into consideration the game limits (i.e. not to leave the 2D array bounds). If one of them is null, then we have to move the sprite there. Once we find it, we transition to the animating state, where we animate the sprite’s movement to its new position.
The AnimateMovement method (which is running on the animating state) uses the Vector2.MoveTowards method to animate the sprite’s movement to its new location.
On the animating state we also call the CheckIfAnimationEnded method. This method checks if the sprite has completed its animation by comparing the distance of the two transforms. If this is the case, then we call the Swap method to have the moving piece moved properly to the new location plus for it to acquire the relevant current I and J properties. We then switch to the playing state and we also check if the user has won!
The CheckForVictory method checks all Pieces to determine whether all of them are in the correct positions. If one piece is found not to, then the method returns immediately. If all of them are in the correct positions, then the game transitions to the ending state.
As always, if you have any questions or comments feel free to reach to me. You can play the completed game here: http://unitysamples.azurewebsites.net/simplepuzzlegame.html Check the project on GitHub https://github.com/dgkanatsios/PuzzleGameUnity Thanks for reading!
P.S. Game has been tested on Windows Phone/Store. For instructions on how to deploy your existing game onto Windows Store/Phone, check out this free Microsoft Virtual Academy video here: http://www.microsoftvirtualacademy.com/training-courses/porting-unity-games-to-windows-store-and-windows-phone