# Splitting a tetris game apart - where to put time-management?

I am creating a tetris game in C++ & SDL, and I'm trying to do it "good" by making it object-oriented and keeping scopes small. So far I have the following structure:

• A main with some lowlevel SDL set up and handling input
• A game class that keeps track of score and provides the interface for main (move block down, etc)
• A map class that keeps track of the current game field, which blocks are where. Used by the game class.
• A block class that consists of the current falling block, used by game.
• A renderer class abstracting low level SDL to a format where you render "tetris blocks". Used by map and block.

Now I have a though time where to place the time-management of this game. For example, where should be decided when a block bumps the bottom of the screen how long it takes the current block locks in place and a new block spawns?

I also have an other unrelated question, is there some place where you can find some standard data on tetris like standard score tables, rulesets, timings, etc?

my Tetris loop looks a bit like this:

blockDown = false    // a boolean flag, we'll need this in a minute
timer = 0
while true:
get user input, try to rotate and move blocks left/right
timer += timeSinceLastTick
if timer > 1 second:
timer -= 1 second
step()


So the player can try moving or rotating the block at their own pace while once every second the step() function is being called (emphasis lies on TRY!! If the block can't move, ignore the input!). It looks roughly like this:

function step():
try to move block down
if that doesn't succeed:
if blockDown:
enter next block
else:
blockDown = true
else:
blockDown = false


Again, the emphasis is on TRY to move the block down. If it doesn't work, because it would collide with a block under it, set the blockDown variable to true (Now the player has until the next execution of step() to rotate the block or move it left and right). If this means that by the next execution the block can move down again, set blockDown to false again. Last case: The block can't be moved down and the blockDown flag is already set to true, the player already had his chance: Leave the block where it is and insert the next one.

Edit: Of course I'm not actually using try / catch statements for this. The move() and rotate() functions simply return true or false :-))

I would create a separate class called CollisionDetection or something that would check if the block reached the bottom of the screen or collided with other blocks, and if there was a collision, update the overall block data to add the current falling shape's blocks and create the next shape. The same class could contain a method to check if lines are completed and act accordingly.

Pseudocode for collision detection:

if shape is colliding with bottom of the screen or other blocks:
undo collision
if collision was from the bottom:
add the blocks owned by the shape to the overall block data
create next shape


Pseudocode for line check:

foreach lines in block data
if line is filled
clear line
move down the blocks above
give according score to player(depending on the amount of lines cleared with this shape)


I would call the methods from this class from your Game class.

This is how I made my own Tetris. As for the standard information for Tetris, I would be interested in finding such information too. If you don't get an appropriate answer from this question, I think you should make a separate question.

• I already have collision detection, lines, score, level - all done. I'm just doubting on where to put the time-management code in the program. – orlp May 2 '11 at 2:59
• By time management, do you mean updating the current shape's position every few seconds or more than that? – Jesse Emond May 2 '11 at 3:01
• Yeah, updating shape, and controlling the time when the block has bumped the bottom and you are allowed to nudge it. – orlp May 2 '11 at 3:03
• @Jesse Emond: If you are interested in my code, you can download it here: nclabs.org/downloads/tetris.zip – orlp May 2 '11 at 3:07
• I just took a quick look and indeed it looks clean! :) But for the part where you update the shape's position (if (fastfall && ...), you could simply make a function within your game class called updateShape which would take the time of the last update as a parameter and would be in charge of updating the shape's position based on the time. Maybe that's just me, but I think the way you implement timing is more related to the game itself than the overall program and such details should be hidden from the main() function and only the game class should manage them. – Jesse Emond May 2 '11 at 3:21