Home
Code & Snippets
Tutorials
GUI Docs
Projects
Drawings & Sketches
Links
Bio & Resume

Kindly hosted by


Support This Project


Tetris Tutorial: Part #1

Hello there and welcome to first tutorial on how to make a decent Tetris game. There tutorials will not go into Windows window setup or DirectX/OpenGL specific initialization or drawing – I assume that you know how to do it already, so if you don’t, I suggest you read some tutorials on them.

So, let’s get started. We define our classes:
CTetrisBlock – basic block from which the figures are consist from.
CTetrisFigure – a figure, a composure of blocks that you control
CTetrisGame – a game class that handles all Tetris logic and data

So, let’s do it step by step. First is the CTetrisBlock class:

class CTetrisBlock
{
  public:
  // Our basic functions for initialization/drawing/destroying
  void Create();
  void Draw();
  void Destroy();

  // Constructor & Destructor
  CTetrisBlock();
  virtual ~CTetrisBlock();

  // Get/Set procedures for block position
  int GetPosX();
  int GetPosY();

  void SetPosX(int x);
  void SetPosY(int y);

  private:
  // Block position on the game’ grid (remember, our game is Tetris?)
  int m_iPosX, m_iPosY;
};

Pretty simple so far. Going into the Draw() function, we see that it is as simple as it can get:

void CTetrisBlock::Draw()
{
  // Calculate block’ quad using pre-defined variables
  sQUAD quad;
  quad.m_iLeft = m_iPosX * (BLOCK_SIZE + BLOCK_SPACING) + BLOCK_SPACING;
  quad.m_iRight = quad.m_iLeft + BLOCK_SIZE - BLOCK_SPACING;
  quad.m_iTop = m_iPosY * (BLOCK_SIZE + BLOCK_SPACING) - BLOCK_SPACING;
  quad.m_iBottom = quad.m_iTop - BLOCK_SIZE + BLOCK_SPACING;
  
  // Drawing the block’ quad here using OpenGL API...
  glColor3d(1,1,1);
  glBegin(GL_QUADS);
  glVertex3f(quad.m_iLeft, quad.m_iBottom, 0);
  glVertex3f(quad.m_iRight, quad.m_iBottom, 0);
  glVertex3f(quad.m_iRight, quad.m_iTop, 0);
  glVertex3f(quad.m_iLeft, quad.m_iTop, 0);
  glEnd();
}

Ok, I assume there’s no need to go into Get/Set functions, since they are only 1 line long and are pretty straightforward.
Now, let’s take a look at CtetrisFigure class:

class CTetrisFigure 
{

  public:
  // Basic initialization/drawing/destruction functions
  void Create(int num_blocks);
  void Draw();
  void Destroy();

  // Block retrieval procedures
  CTetrisBlock *GetBlock(int x, int y);
  CTetrisBlock *GetBlock(int index);

  // Constructor & Destructor
  CTetrisFigure();
  virtual ~CTetrisFigure();

  int GetBlockCount();

  protected:
  // A double pointer array to blocks – we do
  // that so it would be easier for us to do all
  // interchanges and retrieval of blocks in-game.
  CTetrisBlock **m_ppBlocks;
  int m_iBlocksCount;
};

This class is very simple, since it only deals with array of blocks for now (it will be more complicated later!), so all the creation/drawing/destruction is just using that array of pointers – each block, as you may recall, has it’s own Draw() and Destroy() functions, so it is just a matter of calling each’ block procedures Draw() and Destroy() of CTetrisFigure class.

Well, that’s about it for start! Now, let’s see something on the screen!

int InitGL(GLvoid) 
{
  // Skip OpenGL Initialization routines
  gTetrisGame.Create();
  
  CTetrisFigure *figure = new CTetrisFigure;
  figure->Create(4);
  
  int num_blocks_x = WINDOW_WIDTH / (BLOCK_SIZE + BLOCK_SPACING);
  int num_blocks_y = WINDOW_HEIGHT / (BLOCK_SIZE + BLOCK_SPACING);
  
  figure->GetBlock(0)->SetPosX(num_blocks_x / 2);
  figure->GetBlock(0)->SetPosY(num_blocks_y - 2);
  
  figure->GetBlock(1)->SetPosX((num_blocks_x / 2) + 1);
  figure->GetBlock(1)->SetPosY(num_blocks_y - 2);
  
  figure->GetBlock(2)->SetPosX((num_blocks_x / 2) + 1);
  figure->GetBlock(2)->SetPosY(num_blocks_y - 1);
  
  figure->GetBlock(3)->SetPosX(num_blocks_x / 2);
  figure->GetBlock(3)->SetPosY(num_blocks_y - 1);
  
  gTetrisGame.MapFigure(figure, true);
  
  return TRUE;	// Initialization Went OK
}

Now, let’s take a look on the screen and be proud of ourselves!

In Tutorial 2 we will learn how to move and rotate the figure. Cyas there!