Creating Moving Tiles Transition Effect with Code
Remember this scene from the first Transformer movie? Bumblebee touched the corner of the Cube, and a myriad of little moving and folding cubes appeared on its surface as the colossal AllSpark quickly shrank in size. That effect dazzled me! If you have not seen that movie, there was a similar scene in the first Harry Potter movie, where bricks shuffled around as a wall transformed into a gateway to Diagon Alley. Cool, innit?
I was really tempted to program a similar effect as a transition from one image to another. But I was a bit hesitant. I only had a rough idea of what it might look like, but not a clue about how it was supposed to work. Nevertheless, I decided to go for it.
Below is the result, followed by the explanation of how I made it.
Problem 1 - Specifying a Fuzzy Problem:
Visually, I wanted a state of chaos with a lot of tiles moving asynchronously. The logic to drive that undoubtedly appeared nebulous. To crack it, I zoomed in, starting with the most basic building block: defining behavioral rules for a single tile. Then, I built it upwards by adding layer after layer of logic until the big picture was complete. The next rule expands or complements the previous rule. Growing the complexity in this gradual order helped to keep the logic consistent and cohesive.
In a nutshell, the first image is made up of a grid of tiles which will move around to gradually reveal the second image.
Rules concerning tile behaviors:
- There are two actions a tile can take: sliding to an adjacent tile position, flipping at its current position.
- A tile randomly picks whether to slide or flip, but sliding is preferred when possible.
- Sliding direction is randomly picked among up, down, left, and right.
- Flipping direction is randomly picked between vertical or horizontal.
- When a tile slides away, a portion of the second image will be uncovered at its original position.
- When a tile flips, the backside will be a portion of the second image.
- No action can start from a position where the second image has been revealed.
- No tile can slide towards a position where the second image has been revealed.
- No tile can slide towards a position that is occupied by an on-going action.
Rules concerning video sequence:
- Both actions, sliding and flipping, take 10 frames to complete.
- Tiles start their actions in rounds. Within the same round, a group of tiles start and end their actions at the same time.
- The interval between kicking off each new round is 5 frames, so that the next group of tiles will start to move before the previous group finishes.
- In each round, the tiles are randomly selected from positions where the second image has yet been revealed.
- The number of tiles selected for each round increases quickly over time, stays on the peak for a short while, and then decreases again. (E.g., in the beginning, 2 tiles start to take actions at the same time, then 4, then 8, then 16, ....)
Derivative rules (based on combinations of previous rules):
- Once an action has initiated from a tile position, that position becomes permanently locked.
- During a sliding action, the target position becomes temporarily locked for 10 frames.
- There is no limit imposed on how many times a tile can slide, but it can only flip once.
Problem 2 - Turning the Rules into an Algorithm:
The apparent complexity of the rules was the initial barrier to the solution. But the entry point to the solution was not the rules, but what the algorithm needed to accomplish and what are the logical steps get there.
The overall objective is to paint a sequence of frames. The objective can be subdivided into four tasks.
- Select the tiles that will take actions.
- Check permissible actions and make a choice.
- Update frames.
- Update resources (tile data, grid data, etc.).
Preparation: Both first and the second image are pre-divided into tiles. A three-dimensional (tile column index, tile row index, frame number) Boolean array tracks whether certain tile position is locked on certain frame.
Once I understood the big picture of the algorithm, the rules were incorporated to flesh it out.
Task 1: Every 5 frames, a round begins. A group of tiles are selected from positions that are not locked on the current frame. The number of tiles selected depends on the round index.
Task 2: A tile randomly chooses to slide or flip, but the former has a higher probability. If it decides to slide, it cannot slide to a locked adjacent position. If all four neighbors are locked, it must flip instead. After applying the restrictions and random factors, the action type and direction are finalized.
Task 3: Based a tile’s action, update the graphics of the affected area on the next 10 frames.
Task 4: Update the position of a tile that has moved. Clear a tile’s data if it has flipped, or another tile has moved on top of it. Update the Boolean array to lock a position for either all subsequent frames (if an action is starting from this position), or for the next 10 frames (if another tile is sliding to this position).
These tasks loop until all the frames are finalized.
There are different ways to approach this, thanks to a discussion I had with a friend of mine a few years after I wrote the program. What I explained above was my solution. It follows rounds of tiles through their individual action cycles. The alternative solution follows frames and updates individual tiles on each frame.
The algorithm is not specific to image resolution. It is currently specific to total tile number and total frame number. But those can be made adaptable as well.