Schwizzle, my first “Game in a Week”, is a single screen puzzle game that is similar to a Rubik’s Cube or a Jig-Saw. The inspiration for Schwizzle came from
When I was at school I was very interested in technical drawing and wanted to be an architect. My interest in design has stayed with me and when I use ‘Stumble Upon’ design is in my list of interests, be it software design, GUI design, fabric design or in this case interior design. The painted wall in the above image immediately captured my imagination and I could see the circles rotating and interacting. Schwizzle was born and became the first “Game in a Week”. Here is my development diary for that week.
The goal for today was to procedurally generate the pieces required for the game board. Schwizzle will be played in 2D however I find it allot easier to generate 3D assets as Decade Engine has allot of useful functionality added during development of procedural planets so Ive decided to use 3D assets for the board and simply render from above to make the game playable in 2D.
The first piece added is what I call a twister. This is the circle without the interconnecting pieces. Based on the code for generating a torus, the interconnecting segments are calculated by finding the 2 intersection points between 2 circles and removing any geometry from this area. The twister is symmetric and therefore the complete object doesn’t have to be generated. By generating a 45 degree segment it is possible to flip and rotate the segment around the origin to complete the shape. I do this in software and combine all vertices into a single vertex buffer (VBO’s are more efficient in rendering 1 large object than multiple smaller objects).
After the twister I procedurally generated the interconnecting pieces, that I call gems. This uses the same interconnecting circle logic to find the 2 endpoints of the gem and build the geometry in-between. Similarly to constructing the twister only a portion of the gem is actually calculated. A quarter of the gem is generated algorithmically then it is flipped and rotated 3 times to create the other 3/4.
Time taken: 2.5 hours
Today procedural board generation was added. At an introductory level the game board will be 2×1 or 2×2 and it will grow in size to add increasing levels of difficult for the user. Whenever a board is generated each piece is placed in its correct position relative to its neighbor. It also queries its neighbor to find any shared gems so that multiple gems are not created in the same place. Each twister/gem combination has an outer radius of 1.0f so boards increase in world space the larger they get. To ensure that the complete board is visible on screen at the same time I position my camera at the center of the board and rotate it 90 degrees so that it is looking straight down. The camera then changes its Y position and using its frustum ensures that it is at the optimal height to see the entire board in 1 screen.
There are 2 kinds of gems in the game.
- Gems that have 1 parent and are a solid color. These gems will be at the board edges.
- Gems that have 2 parents and are multicolored. These gems are multicolored, a combination of each of its parents colors.
Time taken: 1.5 hours
Once the board has been built and the camera positioned to view the entire board on 1 screen, I can use the view-port, view matrix and projection matrix to project from world space into screen space. This enables me get the bounds of each twister in screen coordinates that I can then use to calculate if the mouse/finger is over a twister and apply a rotation to respective twister if it is clicked/touched and moved. (Another option would be to add the geometry to the physics engine and do a mesh/ray intersection to select the chosen twister however this would be less performant and adds the physics engine as an unnecessary dependency)
By using the center of the selected twister I can calculate the angle between 2 vectors;
- The previous mouse position to the center of the twister
- The current mouse position to the center of the twister
float SignedAngleBetweenInDegrees(const Vector2& v1, const Vector2& v2)
float perpDot = v1.X * v2.Y - v1.Y * v2.X;
return RAD_TO_DEG(atan(perpDot / DotProduct(v1, v2)));
and use this angle to rotate the selected twister. A twister can only rest at 4 orientations (90 degrees, 180 degrees, 270 degrees, or 0/360 degrees) so when the user lets go of a twister I find the twisters closest resting place and orientate it to there. At present the twister immediately reorientates to sit correctly and it can be a little confusing. Perhaps it should rotate from its released position to its correct resting position over a number of milliseconds. To better see how movement on the board pieces work please refer to the video at the end of this page.
Even at simple levels the game is more difficult than I had imagined, but I suppose a Rubik’s Cube had a steep entry path too. Anyone can pick up a cube and start playing with it just as anyone will understand within a few seconds how to play Schwizzle however playing it successfully and solving the boards is another matter and it requires further testing.
Time taken: 2.0 hours
The only development completed today was to add procedural jumbling of the board at the start of each game. A single jumble is to rotate a twister by 90 degrees clockwise or anticlockwise. With instant rotation of the pieces 10000 random jumbles can be completed in a second or two.
The rest of the evening was spent playing the game at various board sizes. What seems apparent is that the difficulty of the game doesn’t really increase as the board gets larger, it just takes more time to solve. I feel that this is a fundamental design issue. For a game to have a long lifespan on someones device it needs to constantly challenge the user instead of just requiring more time to complete. The ideal would be that all games take a few minutes (since games on mobile devices tend to be short) but the skills required to complete the level increase.
Although it is disappointing to find that my game isn’t as much fun or as much of a challenge as I thought it would be, it is a testament to my “Game in a Week” philosophy. After 4 days and only 9 hours of development I already have a testable version of my game and have found some issues. Using the old, flawed development cycles of working on ‘something’ else and getting around to the core of the game eventually it could be months before I see these issues and after so much effort the realization that the game isn’t working as expected could destabilize motivation to continue or lead someone to release a game they aren’t happy with it because so much effort has gone into making it.
Time taken: 3.5 hours (3 hours or playing the game, 30 minutes to development)
Textures have been added to Schwizzle which makes the game appear more like a Jig-Saw. The addition of textures has drastically increased the difficulty of the game. When using flat colored pieces, only the orientation of the multicolored gems was of concern. The twisters and the single colored gems could be in any orientation and the board would still be solved. It would also be possible for same colored gems to swap position and still result in a successful board because the user cannot be expected to differentiate between to identical colored gems.
With the addition of textures, everything must be returned to its exact location for the board to be solved. If edge gems (the gems that are a single color and interchangeable in the non-textured version) are not in their correct position and orientation the image does not form correctly and the board is not solved. With the extra difficulty comes extra reward. Returning a colored board to its original position is nice but there is a great feeling of success upon your final twist when the jumbled image aligns and pops out at you for the very first time.
In the image above you can see 2 twisters and 7 gems however only 1 of each has been generated and transformed into each position at render time. This adds a small challenge with texture coordinates.
- I cant give each vertex its correct texture coordinates at creation time because its texture coordinates will vary depending on which instance of the object is being rendered.
- I don’t want to have to constantly update the vertex buffer with the correct texture coordinates for each respective object.
My solution was to give each vertex texture coordinates depending on its position relative to the bounds if its parent object, in the x and z axis. Any vertex sitting on the objects minimum bounds will get a texture coordinate of 0:0, any vertex sitting on the objects maximum bounds will get a texture coordinate of 1:1 and similarly for any vertex in between. Once the board has been generated and the camera positioned I project the min and max bounds of each instance to screen space and store each as unit vectors (as if the screen has size of 1:1).
The rest of the work happens in the vertex shader used to render the objects. As well as passing the texture coordinate as part of the vertex I also pass the calculated minUV and maxUV as uniforms and then calculate the true texture coordinate for each vertex.
float width = uvMax.x - uvMin.x;
float height = uvMax.y - uvMin.y;
_uv0.x = uvMin.x + (width * UV0.y);
_uv0.y = uvMax.y - (height * UV0.x);
Time taken: 2.0 hours
To date only 1 board time has been used, a solid grid of x by y dimensions. I always felt that adding different board types would give bit of variety to the game and would also possibly add different challenges. Today I added 2 such board types.
With a small number of twisters and gems the Cross Board is pretty quick to work with however it does add a challenge that isn’t present in the Grid Board. The center piece can be a challenge to orientate correctly and often while testing I’ve had to backtrack and destroy my solved portion of the board in order to solve the center twister.
The Cross Box Board is a simple extension to the Cross Board. As well as the cross there is a boarder with 4 challenging corner twisters. As well as Cross Board and Cross Box Board I can imagine boards that are a single line of twisters and snake over the available space. I also think a board that has walls vertically through the middle of the board except for the middle twister would be challenging to move all pieces though the “door”.
Time taken: 1.5 hours
What a fun week! 13 hours of development and play testing over 6 days and I have a fully playable game which has been build for OS X and iOS. It is a little disappointing that the game doesn’t have the evolving challenge that I thought it would but on the other hand I must appreciate that I started to see this on day 3 (after 6 hours of development) and was confident on day 4 (after 9 hours). Compare that to 6 months of development and still not knowing if your game is fun.
Not all hope in Schwizzle has been lost. I’m going to push a build to Test-flight and get some 3rd party feedback. If you would like to try the game please contact me via the menu above and I’ll get you a build (Android, iOS, OS X, Linux, Windows or Raspberry Pi). Feedback is always appreciated. I really like the game dynamic and think that the puzzle concept is unique and interesting. Over the past few days I’ve been thinking about modifications to Schwizzle that would make it a more universally fun game to play. You’ll have to check back later though to see Schwizzle Game in a Week Part 2.
Post Week Notes:
- I have published the textured/jigsaw version of the iOS game to Test-Flight. A number of friends have played it on iPhone’s and iPad’s and the response has been overwhelming positive. The game only had 1 texture and 1 board (2×1). Initial feedback was a mixture of frustration and curiosity with the users finding the game too difficult but yet captivating and playable. After a period of play something happened and they could easily solve the 2×1 board. The user usually wanted a more difficult board to challenge them further. 1 comment received was “The game is really hard but it keeps pulling me back to try again. When I solved the image for the first time there was a huge sense of achievement that I want again with a more difficult puzzle.”
- I’ve been playing the jigsaw puzzle for a few days and even though it does seem very difficult at the start, taking a number of minutes to solve the simplest board (2×1), you do learn and today I solved a 5×4 board.