Usual tetris game has 2D arrays for arena/piece and collision check with matrix comparison. To add smooth movement and auto alignment of pieces:

  • x and y are pixels on the screen
    • xMatrix [the cell that piece in it related to the x value]
    • yMatrix [the cell that piece in it related to the y value]
    • xCheck [(x +- amount) cell equivalent for collision check]
    • yCheck [(y +- amount) cell equivalent for collision check]
    • xOffset [x mod cell size]
    • yOffset [y mod cell size]

With These Updates New Game Loop:

if not collide(down)
    piece.y += amount

if left
    if not collide(left)
        piece.x -= amount

else if right
    if not collide(right)
        piece.x += amount

if key_release

if offset
    piece.x +- amount

is playable. But causes glitches on corner movements and out-of-bound errors for repetitive key presses sometimes. What can be the improvements on this code or what changes needed to be done?

  • 1
    \$\begingroup\$ " Are below additions to the standart game enough for achieving something like the link?" is fairly opinion oriented, but the secondary question about the glitchy movement is reasonable. This would be a good candidate for editing-out the off-topic question and preserving the on-topic one, @TomTsagk \$\endgroup\$
    – user1430
    Oct 23, 2018 at 16:49

2 Answers 2


This approach will make you drown in details with every new feature you'll want to add so maybe you could find some better way.

First, let's notice that this smooth Tetris is still grid-based. The frame-by-frame movement may be smooth but in the game logic you still can't move by half of the grid. With this in mind you can move all this smoothness to separate layer that's only visual.

  • You can start with 2D array of bools for empty/filled fields.
  • Implement your piece with x,y position as index of field in grid (not pixels!). Implement entire movement logic, like in old-school Tetris. When the piece goes down it fill up you 2D array. At this point you have a working Tetris clone.
  • Add smoothness:

At this point you have a piece and movement code, so at some point you do something like:

piece.x += 1;

You need to split piece position into logical position and visual. You can leave current x as logical one so we need to add visual:

int x;
float drawX;

Then we need to update piece position frame-by-frame like:

if( piece.drawX < piece.x ) {
   piece.drawX += speed;
   if( piece.drawX > piece.x )   // Did we went too far?
       piece.drawX = piece.x;

This way your logic stays completely the same and it operates on x/y values, which are the target positions for your piece. Every frame you check the current position and if the piece didn't reach the target you move it further and drawing is done with drawX position instead of x.


As far as I can tell, gameplay-wise this is yet another Tetris clone. It appears like pieces move smoothly, but they still collide on a cell-by-cell basis.

It seems like the gameplay itself is just the same, but the visual representation uses interpolation.

If you want to replicate this for educational purposes, then it might be a good opportunity to learn how to separate your game mechanics from your visual representation. A clean software architecture almost always does this separation. The reason is that by loosely coupling your rendering with your mechanics you can make changes to one without having to think much about what the other is doing. So it is something you should definitely learn how to do well.

In this case it would mean that each block has two representation:

  • A logical representation which includes all the information relevant for gameplay. Coordinates would be cell coordinates. The logical representation is updated by the game update loop based on the game mechanics and the player input.
  • A visual representation which includes all the information relevant for rendering. Coordinates would be pixel coordinates. The rendering loop checks if the visual representation still matches the logical representation and updates it accordingly. Then the rendering loop renders it.

Your rendering loop would check the logical representation of the block and convert its coordinates to pixel coordinates. This tells it where the block should be. It then compares those intended coordinates with the actual pixel coordinates of the block. If they differ, it moves the pixel coordinates a bit closer to the intended coordinates.

Or in other words: The sprites chase the invisible blocks they represent.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .