Sticky blocks were perhaps the trickiest element to implement in Blockwick 2, especially considering our desire for “pixel-perfect” collisions. Here is a quick breakdown of how we pulled them off.
First build a hierarchal array of blocks. Then move each dynamic block towards its goal (with a lag if not root block). Then collide each dynamic block against static colliders. Each block that collides with static collider is flagged and locked from moving in that direction. Then collide dynamics blocks against each other causing any lock flags to propagate. Each collider’s lock flags expire after a few physics steps using simple bitwise operations.
Pros: Stable simulations in most cases. Fairly efficient for pixel perfect collisions. Cons: Rounded corner collisions are not handled very well. No rotations.
Blockwick 2 is rendered completely with 2D sprites except for one special block type, the Flip Block. With so many possible arrangements of colors and animations, using 2D sprites would have been far too complicated and tedious to implement. Using a 3D asset made the most sense as we need to be able to select a color for all six sides and animate the block flipping over as it rolls around the board. The animation is especially important as it allows the player to understand that with each move the block is rolling rather than sliding.
First, our designer, David, modeled the 3D asset in Blender. Once in Unity, we needed to rotate the Flip Block around the X-axis to match our the angle of three dimensional illusion from our 2D sprite.
Since our 2D tile grid is non-square, even with the flip block rotated, it still lines up perfectly with all the 2D sprites. Now we light the Flip Block(s) with a single directional light rotated an angle based upon the length of the block shadows. It’s a good start, but our shading if far too dark and not at matching the style of the rest of the scene. So we crank our ambient light color all the way to pure white and adjust the intensity of our directional light. This is now essentially mimicking the screen shader used to render the normal Color Block sprites. Finally, we adjust the specular colors for materials that are applied to the faces of the Flip Block for a bit of fine tuning.
There you go, a 3D-lit object mimicking the style of the 2D game. Check out blockwick.com to see it in action.
To make dragging blocks user-friendly, rounded corners for our collision objects are key. Getting stuck on a corner is frustrating and detractive. We want people to solve puzzles not fight with the game.
As this was our first project using Unity 3D, I was excited to use the built-in physics and save some time. Setting up the shapes and mechanics was simple enough, but after a week of prototyping, it was clear that standard game physics were not going to cut it. Physics instabilities, catches on invisible corners, extra processing for things like rotations, forces, collision event callbacks, etc. It was too general a solution for a specific problem.
All of the above considered, it was necessary to create a custom physics solutions that only took into account what we needed: rounded corners and non-overlapping collisions.
I just need two types of collision shapes, edges and corners. An edge is simply a box with a normal vector. A corner is a circle and box that defines what quadrant of the circle to use. The one constraint of the system is that blocks should never move farther than the radius of a corner. That’s pretty much it!
Now, all we have to do is move the selected block towards the touch location and iterate over the collider arrays, moving the colliders away from each other based on edge normals and corner quadrants. To move blocks faster do more physics steps each frame.
Blockwick 2 is coming to iOS and Android next Thursday, March 5th. Check out Blockwick.com for more information.
The idea of short walls was conceived fairly early in the design process, but would require the use of a custom shader if the idea was to work and aid in the illusion of depth.
The first step was to build alpha texture that could be used as a mask. Since the walls are static in each scene we needed only generate the mask once when the puzzle scene is loaded. To do this we create an appropriately large texture based on texture and screen resolutions and render the alpha of each wall sprite to that new texture. Voila.
Second, each frame the scene is rendered normally. After which, a second camera renders only the shadows using a shader that offsets the shadows vertically and multiplies the sprite texture by the mask texture to mask out any pixels that are not over a wall sprite.
That’s it! Fast, easy shadows that look 3D.
As creatives, we daily face the predicament of compromise. How good is good enough? I’ve come to a tentative conclusion: nothing is perfect, but you can get extremely close. The key is to stop refining, tinkering, and polishing once you get close enough that anything more is negligible. Does a 1% change in opacity on the icon’s shine really make a significant difference?
[Note: Be careful. As you develop your skills, your concept of perfection keeps evolving. And you can get just as stuck chasing degrees of perfection this way. In order to launch a product, you have to draw the line somewhere.]