Revision: 48037
Updated Code
at June 22, 2011 19:36 by offs
Updated Code
#include "gl.h"
#include <time.h>
#include "Draw.h"
#include "Text.h"
#include "Game.h"
const unsigned char ESC = 27;
const unsigned char SPACE = 32;
const unsigned MIN_SPEED = 1;
const unsigned MAX_SPEED = 9;
const unsigned BASE_SCORE = 100;
const unsigned NEXT_LEVEL_LINES_LIMIT = 10;
Game::Game()
: _lines(0)
, _score(0)
, _speed(MIN_SPEED)
, _lose(false)
, _paused(false)
, _nextFigIndex(rand() % VARIOUS_BLOCKS)
, _nextRotIndex(rand() % ROTATIONS)
{
srand(time(NULL));
_well = WellPtr(new Well(this));
_block = BlockPtr(new Block(_well));
_StartNextBlock();
}
#pragma warning (disable : 4100) //to suppress unused warning int x, int y needed by GLUT API
void Game::KeyPressed(int specialKey, unsigned char key, int x, int y)
{
switch (specialKey)
{
case GLUT_KEY_UP :
case GLUT_KEY_DOWN :
case GLUT_KEY_LEFT :
case GLUT_KEY_RIGHT : _InGameKey(specialKey, 0); break;
}
switch (key)
{
case SPACE : _InGameKey(0, key); break;
case '+' : _SpeedUp(); break;
case '-' : _SpeedDown(); break;
case 'p' :
case 'P' : _Pause(); break;
case 'r' :
case 'R' : _Restart(); break;
case ESC : _Stop(); break;
}
}
#pragma warning (default : 4100)
void Game::_InGameKey(int specialKey, unsigned char key)
{
if (!_paused && !_lose)
{
switch (specialKey)
{
case GLUT_KEY_UP : _block->Rotate(); break;
case GLUT_KEY_DOWN : _block->MoveDown(); break;
case GLUT_KEY_LEFT : _block->MoveLeft(); break;
case GLUT_KEY_RIGHT : _block->MoveRight(); break;
}
switch (key)
{
case SPACE : _block->FallDown();
Update(); break;
}
}
}
void Game::Draw()
{
unsigned x0 = 50, y0 = 50, x0new = 0, y0new = 0;
glClear(GL_COLOR_BUFFER_BIT);
_DrawWell(x0, y0, x0new, y0new);
_DrawStatus(x0new, y0);
glutSwapBuffers();
}
void Game::_DrawStatus(unsigned x0, unsigned y0)
{
DrawText(x0, y0 + 20, GLUT_BITMAP_HELVETICA_12, FormatText("Lines: %i", _lines).c_str());
DrawText(x0, y0 + 40, GLUT_BITMAP_HELVETICA_12, FormatText("Score: %i", _score).c_str());
DrawText(x0, y0 + 60, GLUT_BITMAP_HELVETICA_12, FormatText("Speed: %i", _speed).c_str());
DrawText(x0, y0 + 420, GLUT_BITMAP_HELVETICA_18, " Next");
_DrawNext(x0, y0 + 460);
if (_lose)
{
DrawText(x0, y0 + 240, GLUT_BITMAP_HELVETICA_18, " Game over." );
DrawText(x0, y0 + 220, GLUT_BITMAP_HELVETICA_18, "Press R to restart.");
}
else if (_paused)
{
DrawText(x0, y0 + 240, GLUT_BITMAP_HELVETICA_18, " Game paused." );
DrawText(x0, y0 + 220, GLUT_BITMAP_HELVETICA_18, "Press P to continue.");
}
}
void Game::_DrawNext(unsigned x0, unsigned y0)
{
for (unsigned cell = 0; cell != FIGURE_COMPLEXITY; ++cell)
{
unsigned x = x0 + _blocks[_nextFigIndex][_nextRotIndex][2*cell]*_well->CellSize();
unsigned y = y0 + _blocks[_nextFigIndex][_nextRotIndex][2*cell + 1]*_well->CellSize();
DrawRect(x, y, x + _well->CellSize(), y + _well->CellSize(), Color[_nextColor - 1]);
}
}
void Game::_DrawWell( unsigned x0, unsigned y0, unsigned& x0new, unsigned& y0new )
{
unsigned rectX1 = x0, rectX2 = rectX1 + _well->CellSize();
unsigned rectY1 = y0, rectY2 = rectY1 + _well->CellSize();
DrawGrid(x0, y0, _well->Width(), _well->RedLine(), _well->CellSize());
DrawBorder(x0, y0, _well->Width() * _well->CellSize(), _well->Height() * _well->CellSize());
for (unsigned width = 0; width != _well->Width(); ++width)
{
rectY1 = y0;
rectY2 = rectY1 + _well->CellSize();
for (unsigned height = 0; height != _well->Height(); ++height)
{
DrawRect(rectX1, rectY1, rectX2, rectY2, Color[(_well->Cell(width, height) & COLOR_MASK) - 1]);
rectY1 = rectY2;
rectY2 += _well->CellSize();
}
rectX1 = rectX2;
rectX2 += _well->CellSize();
}
x0new = rectX2;
y0new = rectY2;
}
void Game::ReportLinesRemoval(unsigned lines)
{
_lines += lines;
_score += lines * BASE_SCORE;
while (lines--)
_score += lines * (BASE_SCORE >> lines);
}
void Game::_StartNextBlock()
{
_block->Update(_nextFigIndex, _nextRotIndex);
_nextFigIndex = rand() % VARIOUS_BLOCKS;
_nextRotIndex = rand() % ROTATIONS;
_nextColor = _nextFigIndex + 1;
_block->PutOnTop();
}
void Game::Update()
{
if (!_paused && !_block->MoveDown())
{
_block->CheckLines();
if (!_lose)
{
if (_lines >= NEXT_LEVEL_LINES_LIMIT)
{
_SpeedUp();
_lines = 0;
}
_StartNextBlock();
}
}
}
void Game::_Restart()
{
_lose = false;
_paused = false;
_lines = 0;
_score = 0;
_well->Clear();
_StartNextBlock();
}
void Game::_Pause()
{
_paused = !_paused;
}
void Game::_Stop()
{
exit(0);
}
void Game::ReportLoseState()
{
_lose = true;
}
unsigned Game::UpdateInterval()
{
return (MAX_SPEED - _speed + 1)*100;
}
void Game::_SpeedUp()
{
if (_speed < MAX_SPEED) ++_speed;
}
void Game::_SpeedDown()
{
if (_speed > MIN_SPEED) --_speed;
}
Revision: 48036
Initial Code
Initial URL
Initial Description
Initial Title
Initial Tags
Initial Language
at June 22, 2011 09:22 by offs
Initial Code
#include "gl.h"
#include <time.h>
#include "Draw.h"
#include "Text.h"
#include "Game.h"
const unsigned char ESC = 27;
const unsigned char SPACE = 32;
const unsigned MIN_SPEED = 1;
const unsigned MAX_SPEED = 9;
const unsigned BASE_SCORE = 100;
const unsigned NEXT_LEVEL_LINES_LIMIT = 10;
Game::Game()
: _lines(0)
, _score(0)
, _speed(MIN_SPEED)
, _lose(false)
, _paused(false)
, _nextFigIndex(rand() % VARIOUS_BLOCKS)
, _nextRotIndex(rand() % ROTATIONS)
{
srand(time(NULL));
_well = WellPtr(new Well(this));
_block = std::tr1::shared_ptr<Block>(new Block(_well));
_StartNextBlock();
}
#pragma warning (disable : 4100) //to suppress unused warning int x, int y needed by GLUT API
void Game::KeyPressed(int specialKey, unsigned char key, int x, int y)
{
switch (specialKey)
{
case GLUT_KEY_UP :
case GLUT_KEY_DOWN :
case GLUT_KEY_LEFT :
case GLUT_KEY_RIGHT : _InGameKey(specialKey, 0); break;
}
switch (key)
{
case SPACE : _InGameKey(0, key); break;
case '+' : _SpeedUp(); break;
case '-' : _SpeedDown(); break;
case 'p' :
case 'P' : _Pause(); break;
case 'r' :
case 'R' : _Restart(); break;
case ESC : _Stop(); break;
}
}
#pragma warning (default : 4100)
void Game::_InGameKey(int specialKey, unsigned char key)
{
if (!_paused && !_lose)
{
switch (specialKey)
{
case GLUT_KEY_UP : _block->Rotate(); break;
case GLUT_KEY_DOWN : _block->MoveDown(); break;
case GLUT_KEY_LEFT : _block->MoveLeft(); break;
case GLUT_KEY_RIGHT : _block->MoveRight(); break;
}
switch (key)
{
case SPACE : _block->FallDown();
Update(); break;
}
}
}
void Game::Draw()
{
unsigned x0 = 50, y0 = 50, x0new = 0, y0new = 0;
glClear(GL_COLOR_BUFFER_BIT);
_DrawCan(x0, y0, x0new, y0new);
_DrawStatus(x0new, y0);
glutSwapBuffers();
}
void Game::_DrawStatus(unsigned x0, unsigned y0)
{
DrawText(x0, y0 + 20, GLUT_BITMAP_HELVETICA_12, FormatText("Lines: %i", _lines).c_str());
DrawText(x0, y0 + 40, GLUT_BITMAP_HELVETICA_12, FormatText("Score: %i", _score).c_str());
DrawText(x0, y0 + 60, GLUT_BITMAP_HELVETICA_12, FormatText("Speed: %i", _speed).c_str());
DrawText(x0, y0 + 420, GLUT_BITMAP_HELVETICA_18, " Next");
_DrawNext(x0, y0 + 460);
if (_lose)
{
DrawText(x0, y0 + 240, GLUT_BITMAP_HELVETICA_18, " Game over." );
DrawText(x0, y0 + 220, GLUT_BITMAP_HELVETICA_18, "Press R to restart.");
}
else if (_paused)
{
DrawText(x0, y0 + 240, GLUT_BITMAP_HELVETICA_18, " Game paused." );
DrawText(x0, y0 + 220, GLUT_BITMAP_HELVETICA_18, "Press P to continue.");
}
}
void Game::_DrawNext(unsigned x0, unsigned y0)
{
for (unsigned cell = 0; cell != FIGURE_COMPLEXITY; ++cell)
{
unsigned x = x0 + _blocks[_nextFigIndex][_nextRotIndex][2*cell]*_well->CellSize();
unsigned y = y0 + _blocks[_nextFigIndex][_nextRotIndex][2*cell + 1]*_well->CellSize();
DrawRect(x, y, x + _well->CellSize(), y + _well->CellSize(), Color[_nextColor - 1]);
}
}
void Game::_DrawCan(unsigned x0, unsigned y0, unsigned& x0new, unsigned& y0new)
{
unsigned rectX1 = x0, rectX2 = rectX1 + _well->CellSize();
unsigned rectY1 = y0, rectY2 = rectY1 + _well->CellSize();
DrawGrid(x0, y0, _well->Width(), _well->RedLine(), _well->CellSize());
DrawBorder(x0, y0, _well->Width() * _well->CellSize(), _well->Height() * _well->CellSize());
for (unsigned width = 0; width != _well->Width(); ++width)
{
rectY1 = y0;
rectY2 = rectY1 + _well->CellSize();
for (unsigned height = 0; height != _well->Height(); ++height)
{
DrawRect(rectX1, rectY1, rectX2, rectY2, Color[(_well->Cell(width, height) & COLOR_MASK) - 1]);
rectY1 = rectY2;
rectY2 += _well->CellSize();
}
rectX1 = rectX2;
rectX2 += _well->CellSize();
}
x0new = rectX2;
y0new = rectY2;
}
void Game::ReportLinesRemoval(unsigned lines)
{
_lines += lines;
_score += lines * BASE_SCORE;
while (lines--)
_score += lines * (BASE_SCORE >> lines);
}
void Game::_StartNextBlock()
{
_block->Update(_nextFigIndex, _nextRotIndex);
_nextFigIndex = rand() % VARIOUS_BLOCKS;
_nextRotIndex = rand() % ROTATIONS;
_nextColor = _nextFigIndex + 1;
_block->PutOnTop();
}
void Game::Update()
{
if (!_paused && !_block->MoveDown())
{
_block->CheckLines();
if (!_lose)
{
if (_lines >= NEXT_LEVEL_LINES_LIMIT)
{
_SpeedUp();
_lines = 0;
}
_StartNextBlock();
}
}
}
void Game::_Restart()
{
_lose = false;
_paused = false;
_lines = 0;
_score = 0;
_well->Clear();
_StartNextBlock();
}
void Game::_Pause()
{
_paused = !_paused;
}
void Game::_Stop()
{
exit(0);
}
void Game::ReportLoseState()
{
_lose = true;
}
unsigned Game::UpdateInterval()
{
return (MAX_SPEED - _speed + 1)*100;
}
void Game::_SpeedUp()
{
if (_speed < MAX_SPEED) ++_speed;
}
void Game::_SpeedDown()
{
if (_speed > MIN_SPEED) --_speed;
}
Initial URL
Initial Description
КуÑок ÑамопиÑного тетриÑа. C++/openGL.
Initial Title
Tetris main logic
Initial Tags
Initial Language
C++