It’s only getting harder! In the previous post I built a naive way of clearing lines, by simply offsetting all blocks above a cleared line by 1. This sometimes left “hanging blocks”, like the one on the left side in the video. It didn’t feel satisfying. I played a few Tetris variants and went back to the Tetris wiki and made key improvements to make the game feel more fun. I implemented “Sticky” line clear logic (seen on the right in the video) with cascading clears. I also added animation delays so clears aren’t instantaneous, and a save/load feature to test specific stack configurations.

Learning:
- I refactored the code a LOT! and that is okay :) First, I created a “Grid Array” class object and moved all properties and methods related to Grid manipulation under it. So now I have a clean structure with:
- a Tetromino class to store properties and methods of falling tetromino shapes,
- a Grid Array class object to manage the stack of frozen blocks,
- a Board object that interfaces between the logic/calculation layer and what is rendered on the screen. It contains all rendering methods
- The “Sticky” line clear logic took an entire day. It may not be the most optimized way, but this is how I did it: I separated the line-clear code from the block movement code, then used a flood fill algorithm to identify groups of connected blocks and drop them until they hit a collision (hitting either the floor or another frozen group of blocks).
- Learned how to Save a game by saving the Grid state as a json file and reading it back when starting the game.
- The State Machine Necessity: Handling animations is a challenge. Adding
awaitfor animations created parallel threads that broke the game loop (e.g., flags not resetting). I had to enforce strict Game State Enums (PLAY, PAUSE, ANIMATE) to ensure events only trigger when allowed. - In the beginning I made a choice to use TileMapLayer to display blocks instead of RigidBody2D as it was simpler. In Hindsight I feel that doing animations with blocks would have been much easier with RigidBody2D and leveraging the power of Godot’s physics engine.
- Maintain clear separation of calculation/game logic and rendering on screen by using Signals (especially when signaling up or towards a peer node) to trigger rendering actions when events happen (like line clears or moving blocks down 1 block at a time)
As Next Steps, I will add Wall-kicks, a scoring system, a proper Game Over loop, and more cosmetic changes to make the game feel more fun.
How would you usually manage game states and ensure that the gameplay is not affects by animations? Especially when games get more complex?
Instead of a TileMapLayer, would it be better to use RigidBody2D along with the physics engine to manage moving blocks and animations?
Time spent so far: 25 hours.