/ Published in: C++
КуÑок ÑамопиÑного тетриÑа. C++/openGL.
Expand |
Embed | Plain Text
Copy this code and paste it in your HTML
#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; }