Kindly hosted by
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!
|