← index
Qt.Projects/source/desktop/games/PuzzleDrop/main_window.cpp
Source: Qt.Projects/source/desktop/games/PuzzleDrop/main_window.cpp
#include "main_window.hpp"
#include "high_scores.hpp"
#include<QPainter>
#include<QMessageBox>
#include<cstdlib>
#include<ctime>
#include<QTextStream>

using puzzle::BlockType;

GameWindow::GameWindow() : grid(1280/BLOCK_WIDTH, 720/BLOCK_HEIGHT) {
    scores_window = new HighScores(this);
    setWindowTitle("PuzzleDrop");
    setWindowIcon(QPixmap(":/img/green3.png").scaled(32, 32));
    setFixedSize(1280, 745);
    blocks[0] = QImage(":/img/red1.png");
    blocks[1] = QImage(":/img/red2.png");
    blocks[2] = QImage(":/img/red3.png");
    blocks[3] = QImage(":/img/green1.png");
    blocks[4] = QImage(":/img/green2.png");
    blocks[5] = QImage(":/img/green3.png");
    blocks[6] = QImage(":/img/blue1.png");
    blocks[7] = QImage(":/img/blue2.png");
    blocks[8] = QImage(":/img/blue3.png");
    background[0] = loadAndScale(":/img/level1.png");
    background[1] = loadAndScale(":/img/level2.png");
    background[2] = loadAndScale(":/img/level3.png");
    background[3] = loadAndScale(":/img/level4.png");
    background[4] = loadAndScale(":/img/level5.png");
    background[5] = loadAndScale(":/img/level6.png");
    background[6] = loadAndScale(":/img/level7.png");
    background[7] = loadAndScale(":/img/level8.png");
    file_menu = menuBar()->addMenu(tr("&File"));
    options_menu = menuBar()->addMenu(tr("&Options"));
    help_menu = menuBar()->addMenu(tr("&Help"));
    file_menu_new = new QAction(tr("&New Game"), this);
    file_menu->addAction(file_menu_new);
    file_menu_scores = new QAction(tr("High Scores"), this);
    file_menu->addAction(file_menu_scores);
    diff_menu = options_menu->addMenu(tr("Difficulty"));
    diff_easy = new QAction(tr("Easy"), this);
    diff_med = new QAction(tr("Medium"), this);
    diff_hard = new QAction(tr("Hard"), this);
    diff_easy->setCheckable(true);
    diff_easy->setChecked(true);
    diff_med->setCheckable(true);
    diff_med->setChecked(false);
    diff_hard->setCheckable(true);
    diff_hard->setChecked(false);
    diff_menu->addAction(diff_easy);
    diff_menu->addAction(diff_med);
    diff_menu->addAction(diff_hard);
    connect(diff_easy, SIGNAL(triggered()), this, SLOT(setEasy()));
    connect(diff_med, SIGNAL(triggered()), this, SLOT(setMedium()));
    connect(diff_hard, SIGNAL(triggered()), this, SLOT(setHard()));
    difficulty_level = 0;
    game_started = false;
    help_about = new QAction(tr("&About"), this);
    connect(help_about, SIGNAL(triggered()), this, SLOT(showAbout()));
    help_howto = new QAction(tr("&How to Play"), this);
    connect(help_howto, SIGNAL(triggered()), this, SLOT(showHowTo()));
    help_menu->addAction(help_howto);
    help_menu->addAction(help_about);
    connect(file_menu_new, SIGNAL(triggered()), this, SLOT(newGame()));
    connect(file_menu_scores, SIGNAL(triggered()), this, SLOT(openScores()));
    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(update()));
    background_proc = new QTimer(this);
    connect(background_proc, SIGNAL(timeout()), this, SLOT(proc()));
    first_game = true;
}

QImage GameWindow::loadAndScale(QString filename) {
    QImage img = QImage(filename);
    return img.scaled(1280, 745);
}


void GameWindow::paintEvent(QPaintEvent *e) {
    Q_UNUSED(e);
    QPainter paint(this);
    int offset_y = 25;
    paint.drawImage(0, 0, background[grid.level()-1]);
    for(int x = 0; x < grid.getWidth(); ++x) {
        for(int y = 0; y < grid.getHeight(); ++y) {
            puzzle::Block *b = grid.grid(x,y);
            if(b != 0 && b->getType() == puzzle::BlockType::BLOCK_NULL) {
                paint.fillRect(QRect(x*BLOCK_WIDTH+1, offset_y+(y*BLOCK_HEIGHT+1), BLOCK_WIDTH-1, BLOCK_HEIGHT-1), QBrush("#000000"));
            }
             else {
                int image = static_cast<int>(b->getType())-2;
                if(b->getType() == BlockType::BLOCK_CLEAR || b->getType() == BlockType::MATCH)
                    image = (rand()%9);
                paint.drawImage(x*BLOCK_WIDTH, offset_y+(y*BLOCK_HEIGHT), blocks[image]);
            }
        }
    }  
    puzzle::Piece &p = grid.getPiece();
    int b1 = static_cast<int>(p.blocks[0].getType())-2;
    int b2 = static_cast<int>(p.blocks[1].getType())-2;
    int b3 = static_cast<int>(p.blocks[2].getType())-2;
    if(p.blocks[0] == BlockType::MATCH)
        b1 = rand()%9;
    if(p.blocks[1] == BlockType::MATCH)
        b2 = rand()%9;
    if(p.blocks[2] == BlockType::MATCH)
        b3 = rand()%9;
    paint.drawImage(p.blocks[0].getX()*BLOCK_WIDTH, offset_y+(p.blocks[0].getY()*BLOCK_HEIGHT), blocks[b1]);
    paint.drawImage(p.blocks[1].getX()*BLOCK_WIDTH, offset_y+(p.blocks[1].getY()*BLOCK_HEIGHT), blocks[b2]);
    paint.drawImage(p.blocks[2].getX()*BLOCK_WIDTH, offset_y+(p.blocks[2].getY()*BLOCK_HEIGHT), blocks[b3]);
    if(game_started == false) {
        QFont font = paint.font();
        QPen pen = paint.pen();
        pen.setColor(QColor(QRgb(0xFFFFFF)));
        font.setPixelSize(70);
        font.setBold(true);
        paint.setFont(font);
        paint.setPen(pen);
        paint.drawText(425, offset_y+150, "Puzzle Drop");
        paint.drawText(235, offset_y+250, "Click New Game in Menu");
    } 
    if(game_started == true || first_game == false) {
        QFont font = paint.font();
        QPen pen = paint.pen();
        pen.setColor(QColor(QRgb(0xFFFFFF)));
        font.setPixelSize(25);
        font.setBold(true);
        paint.setFont(font);
        paint.setPen(pen);
        QString text;
        QTextStream stream(&text);
        stream << "Level: " << grid.level() << " Lines: " << grid.currentLines();
        paint.drawText(25, offset_y+60, text);
    }
}

void GameWindow::keyPressEvent(QKeyEvent *ke) {
    if(ke->key() == Qt::Key_Escape)
        exit(0);
    if(game_started == false)
        return;
    if(grid.gameOver() == true) {
        game_started = false;
        gameOver();
        repaint();
        return;
    }
    switch(ke->key()) {
        case Qt::Key_Left:
            grid.keyLeft();
            repaint();
            break;
        case Qt::Key_Right:
            grid.keyRight();
            repaint();
            break;
        case Qt::Key_Down:
            grid.keyDown();
            repaint();
            break;
        case Qt::Key_A:
            grid.keyShiftUp();
            repaint();
            break;
        case Qt::Key_S:
            grid.keyShiftDown();
            repaint();
            break;
        case Qt::Key_Z:
            grid.keyRotateLeft();
            repaint();
            break;
        case Qt::Key_X:
            grid.keyRotateRight();
            repaint();
            break;
    }
}

void GameWindow::gameOver() {
    background_proc->stop();
    timer->stop();
    game_started = false;
    first_game = false;
    diff_menu->setEnabled(true);
    QString name;
    if(scores_window->inputName(name)) {
        scores_window->addScore(name, grid.currentLines());
        scores_window->show();
    }
}
  

void GameWindow::update() {
    grid.keyDown();
    repaint();
    if(grid.gameOver() == true) {
        game_started = false;
        gameOver();
        repaint();
    }
}

void GameWindow::proc() {
    grid.procBlocks();
    grid.procMoveDown();
    repaint();  
}
  

void GameWindow::newGame() {
     int interval = 1000;
    if(difficulty_level == 1)
        interval = 750;
    else if(difficulty_level == 2)
        interval = 500;
    grid.clearGrid();
    game_started = true;
    timer->setInterval(interval);
    background_proc->setInterval(10);
    timer->start();
    background_proc->start();
    diff_menu->setEnabled(false);
}

void GameWindow::openScores() {
    scores_window->show();
}

void GameWindow::setEasy() {
    diff_easy->setChecked(true);
    diff_med->setChecked(false);
    diff_hard->setChecked(false);
    difficulty_level = 0;
}

void GameWindow::setMedium() {
    diff_easy->setChecked(false);
    diff_med->setChecked(true);
    diff_hard->setChecked(false);
    difficulty_level = 1;
}

void GameWindow::setHard() {
    diff_easy->setChecked(false);
    diff_med->setChecked(false);
    diff_hard->setChecked(true);
    difficulty_level = 2;
}

void GameWindow::showAbout() {
    QMessageBox box;
    QString info;
    QTextStream stream(&info);
    stream << tr("Puzzle Drop ") << PUZZLEDROP_VERSION << "\n" << tr("(C) 2022 LostSideDead Software\n Programmed by Jared Bruni\n");
    box.setText(info);
    QPixmap pix = QPixmap(":/img/red3.png");
    box.setIconPixmap(pix.scaled(QSize(64, 64)));
    box.setWindowIcon(QPixmap(":/img/red1.png").scaled(32, 32));
    box.setWindowTitle(tr("About Puzzle Drop"));
    box.exec();
}

void GameWindow::showHowTo() {
    QMessageBox box;
    box.setText(tr("You play by moving the blocks left and right with the arrow keys. You press A and S to shift the blocks, Z and X to rotate them Line up the pattern of the same color 1 2 3, or 3 2 1 Either horizontal, vertical, or diagonal line. There is a wildcard block that flashes different colors, it will match any block. Clear as many lines as you can."));
    QPixmap pix = QPixmap(":/img/blue3.png");
    box.setIconPixmap(pix.scaled(QSize(64, 64)));
    box.setWindowIcon(QPixmap(":/img/red1.png").scaled(32, 32));
    box.setWindowTitle(tr("How to Play"));
    box.exec();
}