diff --git a/TetrisTask.pro b/TetrisTask.pro index f4de819..4bb3e61 100644 --- a/TetrisTask.pro +++ b/TetrisTask.pro @@ -1,24 +1,34 @@ QT += core gui +QT += multimedia greaterThan(QT_MAJOR_VERSION, 4): QT += widgets CONFIG += c++17 +TARGET = TetrisTask +TEMPLATE = app + +DEFINES += QT_DEPRECATED_WARNINGS + # You can make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += \ - gamefield.cpp \ + game.cpp \ main.cpp \ - tetris.cpp + mainwindow.cpp \ HEADERS += \ - gamefield.h \ - tetris.h + block.h \ + game.h \ + gamecontroller.h \ + items.h \ + mainwindow.h \ FORMS += \ - tetris.ui + game.ui \ + mainwindow.ui \ # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin @@ -27,3 +37,6 @@ else: unix:!android: target.path = /opt/$${TARGET}/bin DISTFILES += \ README.md + +RESOURCES += \ + resources.qrc diff --git a/audio/tet.mp3 b/audio/tet.mp3 new file mode 100644 index 0000000..3bb904a Binary files /dev/null and b/audio/tet.mp3 differ diff --git a/block.h b/block.h new file mode 100644 index 0000000..1fcba17 --- /dev/null +++ b/block.h @@ -0,0 +1,146 @@ +#ifndef BLOCK_H +#define BLOCK_H + +#include "game.h" +#include "items.h" + +inline void block_cpy(int dblock[4][4],int sblock[4][4]) +{ + for(int i=0;i<4;i++){ + for(int j=0;j<4;j++){ + dblock[i][j]=sblock[i][j]; + } + } +} + +void Game::CopyCurrentBlockToCurrent() +{ + block_cpy(current_block_, next_block_); +} + +void Game::GetCurrentBlockBorder() +{ + GetBorder(current_block_, current_border_); +} + +void Game::CreateNextBlock() +{ + int block_id = rand() % 7; + CreateBlock(next_block_, block_id); +} + +void Game::GetBorder(int block[4][4],Border &border) +{ + //Calculate border of UP, DOWN, LEFT, RIGHT + for(int i=0;i<4;i++){ + for(int j=0;j<4;j++){ + if(block[i][j]==1){ + border.dbound=i; + break; + } + } + } + + for(int i=3;i>=0;i--){ + for(int j=0;j<4;j++){ + if(block[i][j]==1){ + border.ubound=i; + break; + } + } + } + + for(int j=0;j<4;j++){ + for(int i=0;i<4;i++){ + if(block[i][j]==1){ + border.rbound=j; + break; + } + } + } + + for(int j=3;j>=0;j--){ + for(int i=0;i<4;i++){ + if(block[i][j]==1){ + border.lbound=j; + break; + } + } + } +} + +void Game::DrawBackground(QPainter &painter) { + painter.setBrush(QBrush(Qt::white, Qt::SolidPattern)); + painter.drawRect(MARGIN, MARGIN, AREA_COL * BLOCK_SIZE, AREA_ROW * BLOCK_SIZE); +} + +void Game::DrawNextBlock(QPainter &painter) { + painter.setBrush(QBrush(Qt::blue, Qt::SolidPattern)); + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + if (next_block_[i][j] == 1) { + painter.drawRect(MARGIN * 3 + AREA_COL * BLOCK_SIZE + j * BLOCK_SIZE, + MARGIN + i * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE); + } + } + } +} + +void Game::DrawScore(QPainter &painter) { + QFontDatabase::addApplicationFont(":/src/font/pixel.ttf"); + painter.setPen(Qt::black); + painter.setFont(QFont(default_font_family, default_font_size)); + + painter.drawText(QRect(MARGIN * 3 + AREA_COL * BLOCK_SIZE, MARGIN * 2 + 4 * BLOCK_SIZE, + BLOCK_SIZE * 4, BLOCK_SIZE * 4), + Qt::AlignCenter, "SCORE: " + QString::number(score_)); +} + +void Game::DrawGameArea(QPainter &painter) { + for (int i = 0; i < AREA_ROW; i++) { + for (int j = 0; j < AREA_COL; j++) { + if (game_area_[i][j] == 1) { + DrawBlock(painter, Qt::red, j * BLOCK_SIZE + MARGIN, i * BLOCK_SIZE + MARGIN); + } else if (game_area_[i][j] == 2) { + DrawBlock(painter, Qt::green, j * BLOCK_SIZE + MARGIN, i * BLOCK_SIZE + MARGIN); + } + } + } +} + +void Game::DrawBlock(QPainter &painter, const QColor &color, int x, int y) { + painter.setBrush(QBrush(color, Qt::SolidPattern)); + painter.drawRect(x, y, BLOCK_SIZE, BLOCK_SIZE); +} + +void Game::CreateBlock(int block[4][4],int block_id) +{ + switch (block_id) + { + case 0: + block_cpy(block,item1); + break; + case 1: + block_cpy(block,item2); + break; + case 2: + block_cpy(block,item3); + break; + case 3: + block_cpy(block,item4); + break; + case 4: + block_cpy(block,item5); + break; + case 5: + block_cpy(block,item6); + break; + case 6: + block_cpy(block,item7); + break; + default: + break; + } +} + +#endif // BLOCK_H diff --git a/game.cpp b/game.cpp new file mode 100644 index 0000000..e203eb8 --- /dev/null +++ b/game.cpp @@ -0,0 +1,287 @@ +#include "game.h" +#include "block.h" +#include "ui_game.h" +#include "gamecontroller.h" +#include "mainwindow.h" + +Game::Game(QWidget *parent): + QWidget(parent), + ui(new Ui::Game) +{ + ui->setupUi(this); + startMusicPlayer(); + InitGame(); + StartGame(); +} + +Game::~Game() +{ + delete ui; +} + +inline GameState operator|(GameState a, GameState b) +{return static_cast(static_cast(a) | static_cast(b));} + +void Debug(Game *obj){ + int temp_block1[4][4]; + block_cpy(temp_block1, item7); + Border temp_border1; + obj->GetBorder(temp_block1,temp_border1); +} + +void Game::startMusicPlayer() { + music_player_ = new QMediaPlayer; + music_player_ ->setMedia(QUrl("qrc:/resources/audio/tet.mp3")); + music_player_ ->setVolume(50); + + connect(music_player_ , &QMediaPlayer::stateChanged, this, &Game::MusicStateChanged); + + toggleMusic(); +} + +void Game::toggleMusic() { + if (music_player_->state() == QMediaPlayer::PlayingState) { + music_player_->pause(); + } else { + music_player_->play(); + } +} + +void Game::MusicStateChanged(QMediaPlayer::State state) { + if (state == QMediaPlayer::StoppedState) { + QMediaPlayer* player = qobject_cast(sender()); + if (player) { + player->play(); + } + } +} + +void Game::InitGame() +{ + for(int i=0;ishow(); +} + +void Game::SetStartPositionForNewBlock() +{ + block_point start_point; + start_point.pos_x = AREA_COL / 2 - 2; + start_point.pos_y = -4; + block_position_ = start_point; +} + +void Game::ResetBlock() +{ + CopyCurrentBlockToCurrent(); + GetCurrentBlockBorder(); + + CreateNextBlock(); + SetStartPositionForNewBlock(); +} + +void Game::BlockMove(Direction dir) +{ + switch (dir) { + case UP: + MoveBlockUp(); + break; + case DOWN: + MoveBlockDown(); + break; + case LEFT: + MoveBlockLeft(); + break; + case RIGHT: + MoveBlockRight(); + break; + case SPACE: + MoveBlockSpace(); + break; + default: + break; + } + + + int i=AREA_ROW-1; + int line_count=0; + while(i>=1) + { + bool is_line_full=true; + for(int j=0;j=1;k--){ + for(int j=0;j= 0 && current_block_[i][j]==1){ + game_area_[y+i][x+j]=2; //x and y is reverse + } + } + } +} + +bool Game::IsCollide(int x,int y,Direction dir) +{ + int temp_block[4][4]; + block_cpy(temp_block,current_block_); + Border temp_border; + GetBorder(temp_block,temp_border); + + switch(dir) + { + case UP: + BlockRotate(temp_block); + GetBorder(temp_block,temp_border); //Recompute border atfer rotate. + break; + case DOWN: + y+=1; + break; + case LEFT: + x-=1; + break; + case RIGHT: + x+=1; + break; + default: + break; + } + + for(int i=temp_border.ubound;i<=temp_border.dbound;i++){ + for(int j=temp_border.lbound;j<=temp_border.rbound;j++){ + if(game_area_[y+i][x+j]==2 && temp_block[i][j]==1 + ||x+temp_border.lbound<0 + ||x+temp_border.rbound>AREA_COL-1){ + return true;} + } + } + + return false; +} + +void Game::paintEvent(QPaintEvent *event) { + QPainter painter(this); + + DrawBackground(painter); + DrawNextBlock(painter); + DrawScore(painter); + DrawGameArea(painter); +} + +void Game::timerEvent(QTimerEvent *event) +{ + if(event->timerId()==game_timer_ && game_state_ != Game_Over){ + BlockMove(DOWN); + } + if(event->timerId()==paint_timer_){ + update(); + } +} + +void Game::keyPressEvent(QKeyEvent *event) +{ + if( game_state_ == FreeRun){ + + switch(event->key()) + { + case Qt::Key_Up: + BlockMove(UP); + break; + case Qt::Key_Down: + BlockMove(DOWN); + break; + case Qt::Key_Left: + BlockMove(LEFT); + break; + case Qt::Key_Right: + BlockMove(RIGHT); + break; + case Qt::Key_Space: + BlockMove(SPACE); + break; + default: + break; + } + + } +} diff --git a/game.h b/game.h new file mode 100644 index 0000000..929a263 --- /dev/null +++ b/game.h @@ -0,0 +1,121 @@ +#ifndef GAME_H +#define GAME_H + +#include +#include +#include +#include +#include +#include +#include + +const int BLOCK_SIZE = 25; +const int MARGIN = 5 ; +const int AREA_ROW = 20; +const int AREA_COL = 12; +const int FONT_SIZE = 10; + +//direction +enum Direction +{ + UP, + DOWN, + LEFT, + RIGHT, + SPACE +}; + +struct Border +{ + int ubound; + int dbound; + int lbound; + int rbound; +}; + +struct block_point +{ + int pos_x; + int pos_y; +}; + +enum GameState +{ + FreeRun = 1, + Wait = 2, + Game_Over = 3 +}; + +namespace Ui { +class Game; +} + +class Game : public QWidget +{ + Q_OBJECT + +public: + void InitGame(); + void StartGame(); + void GameOver(); + + void ResetBlock(); + void BlockMove(Direction dir); + void BlockRotate(int block[4][4]); + void CreateBlock(int block[4][4],int block_id); + void GetBorder(int block[4][4],Border &border); + void ConvertStable(int x,int y); + void CopyCurrentBlockToCurrent(); + void GetCurrentBlockBorder(); + void SetStartPositionForNewBlock(); + void CreateNextBlock(); + void DrawBackground(QPainter &painter); + void DrawNextBlock(QPainter &painter); + void DrawScore(QPainter &painter); + void DrawGameArea(QPainter &painter); + void DrawBlock(QPainter &painter, const QColor &color, int x, int y); + void MusicStateChanged(QMediaPlayer::State state); + void MoveBlockUp(); + void MoveBlockRight(); + void MoveBlockLeft(); + void MoveBlockDown(); + void MoveBlockSpace(); + void handleGameOver(); + void toggleMusic(); + + bool IsCollide(int x,int y,Direction dir); + +public: + explicit Game(QWidget *parent = 0); + ~Game(); + + virtual void paintEvent(QPaintEvent *event); + virtual void timerEvent(QTimerEvent *event); + virtual void keyPressEvent(QKeyEvent *event); +private: + Ui::Game *ui; + +private: + GameState game_state_; + int game_area_[AREA_ROW][AREA_COL]; + block_point block_position_; + int current_block_[4][4]; + Border current_border_; + int next_block_[4][4]; + int score_; + int game_timer_; + int paint_timer_; + int speed_ms_; + int refresh_ms_; + + QMediaPlayer* music_player_; + + static const int font_size_title = 10; + static const int default_font_size = 10; + static const int small_font_size = 8; + const QString default_font_family = "Default"; + + void startMusicPlayer(); +}; + +#endif // GAME_H diff --git a/game.ui b/game.ui new file mode 100644 index 0000000..1bb64f0 --- /dev/null +++ b/game.ui @@ -0,0 +1,21 @@ + + + Game + + + + 0 + 0 + 500 + 560 + + + + Tetris - Game Window + + + + + + + diff --git a/gamecontroller.h b/gamecontroller.h new file mode 100644 index 0000000..78786c0 --- /dev/null +++ b/gamecontroller.h @@ -0,0 +1,131 @@ +#ifndef GAMECONTROLLER_H +#define GAMECONTROLLER_H + +#include "game.h" + +void Game::MoveBlockUp() { + if(IsCollide(block_position_.pos_x,block_position_.pos_y,UP)){ + return; + } + + BlockRotate(current_block_); + + for(int i=0;i<4;i++){ + for(int j=0;j<4;j++){ + if(block_position_.pos_y+i >=0 && game_area_[block_position_.pos_y+i][block_position_.pos_x+j] != 2){ + game_area_[block_position_.pos_y+i][block_position_.pos_x+j]=current_block_[i][j]; + } + } + } + GetBorder(current_block_,current_border_); +} + +void Game::MoveBlockDown() { + if(block_position_.pos_y+current_border_.dbound==AREA_ROW-1) + { + game_state_ = Wait; + + ConvertStable(block_position_.pos_x,block_position_.pos_y); + ResetBlock(); + + game_state_ = FreeRun; + + return; + } + if(IsCollide(block_position_.pos_x,block_position_.pos_y,DOWN)) + { + + game_state_ = Wait; + + ConvertStable(block_position_.pos_x,block_position_.pos_y); + ResetBlock(); + + game_state_ = FreeRun; + + return; + } + for(int j=current_border_.lbound;j<=current_border_.rbound;j++){ + if(block_position_.pos_y >=0){ + game_area_[block_position_.pos_y][block_position_.pos_x+j]=0; + } + } + block_position_.pos_y+=1; + for(int i=0;i<4;i++){ + for(int j=current_border_.lbound;j<=current_border_.rbound;j++){ + if(block_position_.pos_y+i<=AREA_ROW-1&&game_area_[block_position_.pos_y+i][block_position_.pos_x+j]!=2){ + if(block_position_.pos_y+i >=0){ + game_area_[block_position_.pos_y+i][block_position_.pos_x+j]=current_block_[i][j]; + } + } + } + } +} + +void Game::MoveBlockLeft() { + if(block_position_.pos_x+current_border_.lbound==0||IsCollide(block_position_.pos_x,block_position_.pos_y,LEFT)) + return; + for(int i=current_border_.ubound;i<=current_border_.dbound;i++){ + if(block_position_.pos_y+i >=0){ + game_area_[block_position_.pos_y+i][block_position_.pos_x+3]=0; + } + } + block_position_.pos_x-=1; + for(int i=current_border_.ubound;i<=current_border_.dbound;i++){ + for(int j=0;j<4;j++){ + if(block_position_.pos_x+j>=0&&game_area_[block_position_.pos_y+i][block_position_.pos_x+j]!=2){ + if(block_position_.pos_y+i >=0){ + game_area_[block_position_.pos_y+i][block_position_.pos_x+j]=current_block_[i][j]; + } + } + } + } +} + +void Game::MoveBlockRight() { + if(block_position_.pos_x+current_border_.rbound==AREA_COL-1||IsCollide(block_position_.pos_x,block_position_.pos_y,RIGHT)) + return; + for(int i=current_border_.ubound;i<=current_border_.dbound;i++){ + if(block_position_.pos_y+i >=0){ + game_area_[block_position_.pos_y+i][block_position_.pos_x]=0; + } + } + block_position_.pos_x+=1; + for(int i=current_border_.ubound;i<=current_border_.dbound;i++){ + for(int j=0;j<4;j++){ + if(block_position_.pos_x+j<=AREA_COL-1&&game_area_[block_position_.pos_y+i][block_position_.pos_x+j]!=2){ + if(block_position_.pos_y+i >=0){ + game_area_[block_position_.pos_y+i][block_position_.pos_x+j]=current_block_[i][j]; + } + } + } + } +} + +void Game::MoveBlockSpace() { + game_state_= Wait; + + while(block_position_.pos_y+current_border_.dbound=0){ + game_area_[block_position_.pos_y][block_position_.pos_x+j]=0; + } + } + block_position_.pos_y+=1; + for(int i=0;i<4;i++){ + for(int j=current_border_.lbound;j<=current_border_.rbound;j++){ + if(block_position_.pos_y+i<=AREA_ROW-1&&game_area_[block_position_.pos_y+i][block_position_.pos_x+j]!=2){ + if(block_position_.pos_y+i >=0){ + game_area_[block_position_.pos_y+i][block_position_.pos_x+j]=current_block_[i][j]; + } + } + } + } + } + ConvertStable(block_position_.pos_x,block_position_.pos_y); + ResetBlock(); + + game_state_ = FreeRun; +} + +#endif // GAMECONTROLLER_H diff --git a/gamefield.cpp b/gamefield.cpp deleted file mode 100644 index 6a5ce13..0000000 --- a/gamefield.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "gamefield.h" - -#include - -GameField::GameField(QWidget *parent) : QWidget{parent} { - connect(this, &GameField::InitialisationStarted, this, &GameField::SetCells, - Qt::QueuedConnection); - - emit InitialisationStarted(); -} - -uint GameField::GetRowsNumber() const { return rowsNumber_; } - -void GameField::SetRowsNumber(uint rowsNumber) { - if (rowsNumber_ == rowsNumber) return; - - rowsNumber_ = rowsNumber; - emit RowsNumberChanged(); -} - -uint GameField::GetColumnsNumber() const { return columnsNumber_; } - -void GameField::SetColumnNumber(uint columnsCount) { - if (columnsNumber_ == columnsCount) return; - - columnsNumber_ = columnsCount; - emit ColumnsNumberChanged(); -} - -void GameField::SetCells() { - qDebug() << rowsNumber_ << " " << columnsNumber_ << "|"; -} diff --git a/gamefield.h b/gamefield.h deleted file mode 100644 index e36baa8..0000000 --- a/gamefield.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef GAMEFIELD_H -#define GAMEFIELD_H - -#include - -class GameField : public QWidget { - Q_OBJECT - public: - explicit GameField(QWidget *parent = nullptr); - - Q_PROPERTY(uint rowsNumber READ GetRowsNumber WRITE SetRowsNumber NOTIFY - RowsNumberChanged FINAL) - Q_PROPERTY(uint columnsNumber READ GetColumnsNumber WRITE SetColumnNumber - NOTIFY ColumnsNumberChanged FINAL) - - signals: - void RowsNumberChanged(); - void ColumnsNumberChanged(); - void InitialisationStarted(); - - private slots: - void SetCells(); - - public: - uint GetRowsNumber() const; - void SetRowsNumber(uint newRowsNumber); - - uint GetColumnsNumber() const; - void SetColumnNumber(uint newColumnsCount); - - private: - uint rowsNumber_ = 0; - uint columnsNumber_ = 0; -}; - -#endif // GAMEFIELD_H diff --git a/items.h b/items.h new file mode 100644 index 0000000..853d935 --- /dev/null +++ b/items.h @@ -0,0 +1,54 @@ +#ifndef ITEMS_H +#define ITEMS_H + +int item1[4][4]= +{ + {0,1,1,0}, + {0,1,1,0}, + {0,0,0,0}, + {0,0,0,0} +}; +int item2[4][4]= +{ + {0,1,0,0}, + {0,1,0,0}, + {0,1,1,0}, + {0,0,0,0} +}; +int item3[4][4]= +{ + {0,0,1,0}, + {0,0,1,0}, + {0,1,1,0}, + {0,0,0,0} +}; +int item4[4][4]= +{ + {0,1,0,0}, + {0,1,1,0}, + {0,0,1,0}, + {0,0,0,0} +}; +int item5[4][4]= +{ + {0,0,1,0}, + {0,1,1,0}, + {0,1,0,0}, + {0,0,0,0} +}; +int item6[4][4]= +{ + {1,1,1,0}, + {0,1,0,0}, + {0,0,0,0}, + {0,0,0,0} +}; +int item7[4][4]= +{ + {0,0,1,0}, + {0,0,1,0}, + {0,0,1,0}, + {0,0,1,0} +}; + +#endif // ITEMS_H diff --git a/main.cpp b/main.cpp index f1c8bd9..b48f94e 100644 --- a/main.cpp +++ b/main.cpp @@ -1,10 +1,11 @@ +#include "mainwindow.h" #include -#include "tetris.h" +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindow w; + w.show(); -int main(int argc, char *argv[]) { - QApplication a(argc, argv); - Tetris w; - w.show(); - return a.exec(); + return a.exec(); } diff --git a/mainwindow.cpp b/mainwindow.cpp new file mode 100644 index 0000000..a08a9b0 --- /dev/null +++ b/mainwindow.cpp @@ -0,0 +1,26 @@ +#include "mainwindow.h" +#include "ui_mainwindow.h" + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::MainWindow) +{ + ui->setupUi(this); + loadUI(); +} + +MainWindow::~MainWindow() +{ + delete ui; +} + +void MainWindow::loadUI(){ + ui->play_button->setFont(QFont(default_font_family, font_size)); +} + +void MainWindow::on_play_button_clicked() +{ + this->close(); + Game *game = new Game(); + game->show(); +} diff --git a/mainwindow.h b/mainwindow.h new file mode 100644 index 0000000..528d20c --- /dev/null +++ b/mainwindow.h @@ -0,0 +1,35 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include +#include "game.h" + +namespace Ui { +class MainWindow; +} + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = 0); + ~MainWindow(); + +private slots: + void on_play_button_clicked(); + + void on_help_button_clicked(); + + void on_settings_button_clicked(); + +private: + Ui::MainWindow *ui; + static const int font_size_title = 25; + static const int font_size = 15; + const QString default_font_family = "Default"; + void loadUI(); +}; + +#endif // MAINWINDOW_H diff --git a/mainwindow.ui b/mainwindow.ui new file mode 100644 index 0000000..616da57 --- /dev/null +++ b/mainwindow.ui @@ -0,0 +1,38 @@ + + + MainWindow + + + + 0 + 0 + 500 + 550 + + + + Tetris - Home + + + + + + + + + 190 + 170 + 90 + 30 + + + + PLAY + + + + + + + + diff --git a/resources.qrc b/resources.qrc new file mode 100644 index 0000000..2e854a5 --- /dev/null +++ b/resources.qrc @@ -0,0 +1,5 @@ + + + audio/tet.mp3 + + diff --git a/tetris.cpp b/tetris.cpp deleted file mode 100644 index 50cf380..0000000 --- a/tetris.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "tetris.h" - -#include "ui_tetris.h" - -Tetris::Tetris(QWidget *parent) : QMainWindow(parent), ui(new Ui::Tetris) { - ui->setupUi(this); -} - -Tetris::~Tetris() { delete ui; } diff --git a/tetris.h b/tetris.h deleted file mode 100644 index 1245a26..0000000 --- a/tetris.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef TETRIS_H -#define TETRIS_H - -#include - -QT_BEGIN_NAMESPACE -namespace Ui { -class Tetris; -} -QT_END_NAMESPACE - -class Tetris : public QMainWindow { - Q_OBJECT - - public: - Tetris(QWidget *parent = nullptr); - ~Tetris(); - - private: - Ui::Tetris *ui; -}; -#endif // TETRIS_H diff --git a/tetris.ui b/tetris.ui deleted file mode 100644 index ae63379..0000000 --- a/tetris.ui +++ /dev/null @@ -1,46 +0,0 @@ - - - Tetris - - - - 0 - 0 - 800 - 600 - - - - Tetris - - - - 20 - - - 10 - - - - - - 0 - 0 - 800 - 21 - - - - - - - - GameField - QWidget -
gamefield.h
- 1 -
-
- - -