Page 32/36 describe centers of cubes. Actual edges of cubes will be 0.5 units higher but it will be considered in collision detection. To detect user input we will use  IsKeyDown  function contained in  Keyboard  unit. This is simple method how to capture keyboard input. We will define five possible user actions: T3DTInput = (inpNone,inpMoveL,inpMoveR,inpRotateL,inpRotateR); var UserInput: T3DTInput; Keyboard status will be captured in cadencer progress event and stored in global variable UserInput. UserInput:=inpNone; if IsKeyDown(VK_LEFT) then UserInput:=inpMoveL; ... I would like to say a few words about capturing keyboard and mouse input. Always use necessary   minimum   of   code   to   capture   the   controller   input   in   global   variable.   Especially OnMouseMove event can cause big slowdown if you write too much code in it. Windows consider mouse movements first priority and try to execute its code before other procedures. If you write complicated code  in this event the system becomes flooded with this code trying to execute it with the smallest mouse movements. Not enough computing power remains for cadencer progress. All you should write in OnMouseMove is MouseX := X; MouseY := Y; Information about current score is updated every cadencer step with  TGLHUDText  object placed in upper left corner. T3DTBlock class The core of the program is going to be our new class derived from TGLDummyCube. This class will represent individual blocks. The dummy cube will take care of movements and rotations of the whole block. It will have TGLCube children as boxes in the block. Each cube will compare its Z position with FloodLevels to detect collisions. We are going to use Round function to snap the cubes position on X grid. The block will be initially created at position [0,0,0]. One central TGLCube will be added to every block again at position [0,0,0]. Random number of cubes will be added in four directions. The block will form a cross, L-shape or line. Five cubes in a row maximum. Cubes should be 0.95 units in size and positioned at [1,0,0], [2,0,0], [0,0,1], [0,0,2], [-1,0,0] and so on. All cubes will have Y position 0 at all times. After all cubes are created the block is repositioned to starting position well above playing field with random X position. Boolean value called Active will represent status of the block. At beginning block will be active (descending), once it will land on ground or other blocks we will set Active to false. If the cube is active it is moved tiny bit down the Z axis during block’s progress event: Position.Z := Position.Z – deltaTime * speed. Then we check for collisions. We have to process all children and compare their absolute positions with both sides (X<-5 and X>5) and bottom (Z<0) of the playing field. We also have to check against other blocks already in the playing field: var absPos: TVector; GLScene beginner's guide, Jan Zizka, 2005