Flutter Puzzle Hack: Handling interaction between elements with z-index
Introduction
Flutter Puzzle Hack seeks to implement the classic sliding tile puzzle in Flutter. Here is the demo video from the organiser:
There are 2 angles of gameplay
1. A direct top down view
2. View from an angle
The Problem
In both situations, we will face a common problem — handling how the tiles interact and overlay on each other.
To further understand the problem, let’s look at some images.
Here is how a tile looks like.
Here is how we expect the puzzle to look like. Notice the interlocking components of the puzzle are overlayed nicely.
However, after a few moves, we realize that the puzzle looks like this instead. Notice the interlocking components are overlayed incorrectly, in real life, the tiles would not slide at all.
This is because when elements are loaded, the ones that are loaded later will be placed on top of earlier elements. In CSS, this concept is known as z-index, elements with a greater z-index will be placed on top of elements with lower z-index.
In the puzzle, the tiles are generated with a fixed z-index depending on their position in the element tree. After a few moves, this original z-index might not hold true anymore, leading to the issue we observe above.
Solution
To solve this, we use the Flutter gem Indexed, which allows us to change the z-index of elements on the fly.
At all times, every tiles must have a greater z-index than the tile on its left and bottom. Like this:
This must also hold true when the tile is in motion. In our current example, it does not. Notice that, when the tile on the bottommost row slides up, it’s z-index of 3 is equivalent to the tile on the left of the new position.
What if we increment the z-index before moving? This is also wrong as the z-index of 4 is equivalent to the tile on the right.
Recall the rule that we have set above: “At all times, every tiles must have a greater z-index than the tile on its left and bottom.” Whenever we fail to respect this rule, the layout or animation of the tiles will turn out funky. The game is playable for sure, just that it doesn’t respect real life physics.
To resolve this, we set each z-index increment to be in steps of 10 instead of 1. When the tile is in motion, increment/decrement it by 5.
Increment when we are moving up or right. Decrement when we are moving down or left.
When it reaches the intended position, increment/decrement it by another 5, and we will get to the correct z-index for the position.
Product
A shoutout to Rive for the awesome animation capabilities too!
Issues
We notice that this may lag a little in debug mode, but it should be fine in release (hopefully lol).