diff --git a/Pacman.pro b/Pacman.pro index b915c09..9a399d0 100644 --- a/Pacman.pro +++ b/Pacman.pro @@ -2,18 +2,33 @@ QT += core gui greaterThan(QT_MAJOR_VERSION, 4): QT += widgets -CONFIG += c++17 +CONFIG += c++11 +CONFIG += c++14 # 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 += \ + pacmanarea/dragitem/coindragitem.cpp \ + pacmanarea/dragitem/dragitemfabric.cpp \ + pacmanarea/dragitem/walldragitem.cpp \ + pacmanarea/pacman/pacmanitem.cpp \ + pacmanarea\dragitem\abstractdragitem.cpp \ + pacmanarea\droppablearea\droppablearea.cpp \ main.cpp \ - mainwindow.cpp + mainwindow.cpp \ + pacmanarea\pacmanarea.cpp HEADERS += \ - mainwindow.h + pacmanarea/dragitem/coindragitem.h \ + pacmanarea/dragitem/dragitemfabric.h \ + pacmanarea/dragitem/walldragitem.h \ + pacmanarea/pacman/pacmanitem.h \ + pacmanarea\dragitem\abstractdragitem.h \ + pacmanarea\droppablearea\droppablearea.h \ + mainwindow.h \ + pacmanarea\pacmanarea.h FORMS += \ mainwindow.ui diff --git a/gamewindow.cpp b/gamewindow.cpp new file mode 100644 index 0000000..64b7ee4 --- /dev/null +++ b/gamewindow.cpp @@ -0,0 +1,23 @@ +#include "gamewindow.h" + +GameWindow::GameWindow(QVector> boxArea, QWidget *parent) : QWidget (parent) { + boxArea_ = boxArea; + initializeGame(); + QTimer* timer = new QTimer(this); + connect(timer, &QTimer::timeout, this, &GameWindow::updateGame); + timer->start(500); +} + +void GameWindow::paintEvent(QPaintEvent* event) { + Q_UNUSED(event); + QPainter painter(this); + drawGameArea(&painter); + pacman_->paint(&painter, nullptr, nullptr); +} + +void GameWindow::updateGame() { + movePacman(); + checkCollision(); + update(); +} + diff --git a/gamewindow.h b/gamewindow.h new file mode 100644 index 0000000..14da35f --- /dev/null +++ b/gamewindow.h @@ -0,0 +1,26 @@ +#ifndef GAMEWINDOW_H +#define GAMEWINDOW_H + +#include +#include +#include +#include +#include "pacmanarea/pacman/pacmanitem.h" + +class GameWindow : public QWidget +{ + Q_OBJECT +public: + explicit GameWindow(QVector> boxArea, QWidget *parent = nullptr); +protected: + void updateGame(); + void paintEvent(QPaintEvent* event); + +signals: + +private: + QVector> boxArea_; + PacManItem* pacman_; +}; + +#endif // GAMEWINDOW_H diff --git a/main.cpp b/main.cpp index e9562cc..fd3e533 100644 --- a/main.cpp +++ b/main.cpp @@ -4,8 +4,8 @@ int main(int argc, char *argv[]) { - QApplication a(argc, argv); - MainWindow w; - w.show(); - return a.exec(); + QApplication a(argc, argv); + MainWindow w; + w.show(); + return a.exec(); } diff --git a/mainwindow.cpp b/mainwindow.cpp index 7e184b2..a71939f 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -3,13 +3,23 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) - , ui(new Ui::MainWindow) + , ui(new Ui::MainWindow) { - ui->setupUi(this); + ui->setupUi(this); + pacman_ = new PacmanArea(); + ui->sceneLayout->addWidget(pacman_); + + connect(ui->startBtn, &QPushButton::clicked, pacman_, &PacmanArea::startGame); + connect(ui->startBtn, &QPushButton::clicked, this, &MainWindow::setFocuse); + connect(ui->stopBtn, &QPushButton::clicked, pacman_, &PacmanArea::stopGame); +} + +void MainWindow::setFocuse() { + pacman_->setFocus(); } MainWindow::~MainWindow() { - delete ui; + delete ui; } diff --git a/mainwindow.h b/mainwindow.h index dbe42ab..6a5fe3f 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -2,6 +2,7 @@ #define MAINWINDOW_H #include +#include "./pacmanarea/pacmanarea.h" QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } @@ -9,13 +10,17 @@ QT_END_NAMESPACE class MainWindow : public QMainWindow { - Q_OBJECT + Q_OBJECT - public: - MainWindow(QWidget *parent = nullptr); - ~MainWindow(); +public: + MainWindow(QWidget *parent = nullptr); + ~MainWindow(); - private: - Ui::MainWindow *ui; +public slots: + void setFocuse(); + +private: + Ui::MainWindow *ui; + PacmanArea * pacman_; }; #endif // MAINWINDOW_H diff --git a/mainwindow.ui b/mainwindow.ui index b232854..e788f1c 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -6,15 +6,115 @@ 0 0 - 800 - 600 + 588 + 567 MainWindow - - + + QWidget { + background-color: #fff; +} +QLabel { + color: #464d55; + font-weight: 600; +} +QLabel#heading { + color: #0f1925; + font-size: 18px; + margin-bottom: 10px; +} + +QLabel#subheading { + color: #0f1925; + font-size: 12px; + font-weight: normal; + margin-bottom: 10px; +} +QLineEdit { + border-radius: 8px; + border: 1px solid #e0e4e7; + padding: 5px 15px; +} + +QLineEdit:focus { + border: 1px solid #d0e3ff; +} + +QLineEdit::placeholder { + color: #767e89; +} +QPushButton { + background-color: #0d6efd; + color: #fff; + font-weight: 600; + border-radius: 8px; + border: 1px solid #0d6efd; + padding: 20px 15px; + margin: 10px; + outline: 0px; +} +QPushButton:hover, +QPushButton:focus { + background-color: #0b5ed7; + border: 3px solid #9ac3fe; +} + + + + + + + + + + QLayout::SetMinimumSize + + + + + Закончить игру + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + + + Начать игру + + + + + + + + + + + 0 + 0 + 588 + 21 + + + diff --git a/pacmanarea/dragitem/abstractdragitem.cpp b/pacmanarea/dragitem/abstractdragitem.cpp new file mode 100644 index 0000000..49862b7 --- /dev/null +++ b/pacmanarea/dragitem/abstractdragitem.cpp @@ -0,0 +1,32 @@ +#include "abstractdragitem.h" +#include + +AbstractDragItem::AbstractDragItem(){}; + +AbstractDragItem::AbstractDragItem(qreal x, qreal y, qreal boxSize, QString name, QColor color) { + setBrush(color); + setFlag(QGraphicsItem::ItemIsMovable); + this->name_ = name; +} + +void AbstractDragItem::mousePressEvent(QGraphicsSceneMouseEvent* event) { + if (event->button() == Qt::LeftButton) { + QMimeData* mimeData = new QMimeData; + mimeData->setText(name_); + + QDrag* drag = new QDrag(this); + drag->setMimeData(mimeData); + + drag->exec(Qt::MoveAction); + } + + QGraphicsRectItem::mousePressEvent(event); +} + +QString AbstractDragItem::getName() { + return name_; +}; + +QPair AbstractDragItem::getSize() { + return QPair{ width_, height_ }; +} diff --git a/pacmanarea/dragitem/abstractdragitem.h b/pacmanarea/dragitem/abstractdragitem.h new file mode 100644 index 0000000..8742c60 --- /dev/null +++ b/pacmanarea/dragitem/abstractdragitem.h @@ -0,0 +1,33 @@ +#ifndef ABSTRACTDRAGITEM_H +#define ABSTRACTDRAGITEM_H + +#include +#include +#include +#include +#include +#include +#include +#include + +class AbstractDragItem : public QObject, public QGraphicsRectItem { + Q_OBJECT +public: + AbstractDragItem(); + AbstractDragItem(qreal x, qreal y, qreal boxSize, QString name, QColor color); + void mousePressEvent(QGraphicsSceneMouseEvent* event) override; + QPair getSize(); + QString getName(); + +public slots: + virtual void touch() = 0; + +protected: + int width_ = 1; + int height_ = 1; + +private: + QString name_; +}; + +#endif // ABSTRACTDRAGITEM_H diff --git a/pacmanarea/dragitem/coindragitem.cpp b/pacmanarea/dragitem/coindragitem.cpp new file mode 100644 index 0000000..4ee0614 --- /dev/null +++ b/pacmanarea/dragitem/coindragitem.cpp @@ -0,0 +1,24 @@ +#include "coindragitem.h" + +CoinDragItem::CoinDragItem(qreal x, qreal y, qreal boxSize) : + AbstractDragItem::AbstractDragItem(x, y, boxSize, DragItemFabric::getNameByType(DragItemFabric::COIN), Qt::yellow) +{ + setRect(x, y, boxSize * WIDTH_, boxSize * HEIGHT_); + AbstractDragItem::WIDTH_ = WIDTH_; + AbstractDragItem::HEIGHT_ = HEIGHT_; +} + +void CoinDragItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) { + Q_UNUSED(option); + Q_UNUSED(widget); + + painter->setBrush(Qt::yellow); + painter->setRenderHint(QPainter::Antialiasing, true); + + QRectF rect = boundingRect(); + painter->drawEllipse(rect); +} + +void CoinDragItem::touch(){ + delete this; +}; diff --git a/pacmanarea/dragitem/coindragitem.h b/pacmanarea/dragitem/coindragitem.h new file mode 100644 index 0000000..6fbef4b --- /dev/null +++ b/pacmanarea/dragitem/coindragitem.h @@ -0,0 +1,20 @@ +#ifndef COINDRAGITEM_H +#define COINDRAGITEM_H + +#include "abstractdragitem.h" +#include "dragitemfabric.h" + +class CoinDragItem : public AbstractDragItem{ +public: + CoinDragItem(qreal x, qreal y, qreal boxSize); + +public slots: + void touch() override; + void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = nullptr) override; + +private: + int width_ = 1; + int height_ = 1; +}; + +#endif // COINDRAGITEM_H diff --git a/pacmanarea/dragitem/dragitemfabric.cpp b/pacmanarea/dragitem/dragitemfabric.cpp new file mode 100644 index 0000000..3a8ae1f --- /dev/null +++ b/pacmanarea/dragitem/dragitemfabric.cpp @@ -0,0 +1,76 @@ +#include "dragitemfabric.h" + +QString DragItemFabric::getNameByType(DragItemType type) { + switch(type) { + case VWALL: + return "VWALL"; + case HWALL: + return "HWALL"; + case COIN: + return "COIN"; + default: + throw std::runtime_error(QString("invalid DragItemType: %1").arg(type).toStdString()); + } +}; + +DragItemFabric::DragItemType DragItemFabric::getTypeByName(QString name) { + if (name == "VWALL") { + return VWALL; + } else if (name == "HWALL") { + return HWALL; + } else if (name == "COIN") { + return COIN; + } + throw std::runtime_error(QString("invalid name: %1 for get DragItemType").arg(name).toStdString()); +}; + +int DragItemFabric::getNumByType(DragItemType type) { + switch(type) { + case VWALL: + return 1; + case HWALL: + return 2; + case COIN: + return 3; + default: + return 0; + } +}; + +DragItemFabric::DragItemType DragItemFabric::getTypeByNum(int value) { + switch(value) { + case 1: + return VWALL; + case 2: + return HWALL; + case 3: + return COIN; + default: + throw std::runtime_error(QString("invalid value: %1 for get DragItemType").arg(value).toStdString()); + } +}; + +AbstractDragItem* DragItemFabric::getVerticalWall(qreal x, qreal y, qreal boxSize) { + return new WallDragItem(x, y, boxSize, WallDragItem::VERTICAL); +}; + +AbstractDragItem* DragItemFabric::getCoin(qreal x, qreal y, qreal boxSize) { + return new CoinDragItem(x, y, boxSize); +}; + +AbstractDragItem* DragItemFabric::getHorisontalWall(qreal x, qreal y, qreal boxSize) { + return new WallDragItem(x, y, boxSize, WallDragItem::HORISONTAL); +}; + +AbstractDragItem* DragItemFabric::getItemByType(DragItemType type, qreal x, qreal y, qreal boxSize) { + switch(type) { + case VWALL: + return getVerticalWall(x, y, boxSize); + case HWALL: + return getHorisontalWall(x, y, boxSize); + case COIN: + return getCoin(x, y, boxSize); + default: + throw std::runtime_error(QString("invalid DragItemType: %1 for get Item").arg(type).toStdString()); + } +}; diff --git a/pacmanarea/dragitem/dragitemfabric.h b/pacmanarea/dragitem/dragitemfabric.h new file mode 100644 index 0000000..0f55cb7 --- /dev/null +++ b/pacmanarea/dragitem/dragitemfabric.h @@ -0,0 +1,22 @@ +#ifndef DRAGITEMFABRIC_H +#define DRAGITEMFABRIC_H + +#include "abstractdragitem.h" +#include "coindragitem.h" +#include "walldragitem.h" + +class DragItemFabric { +public: + enum DragItemType { VWALL, HWALL, COIN }; +public: + static QString getNameByType(DragItemType type); + static DragItemType getTypeByName(QString name); + static int getNumByType(DragItemType type); + static DragItemType getTypeByNum(int name); + static AbstractDragItem* getVerticalWall(qreal x, qreal y, qreal boxSize); + static AbstractDragItem* getCoin(qreal x, qreal y, qreal boxSize); + static AbstractDragItem* getHorisontalWall(qreal x, qreal y, qreal boxSize); + static AbstractDragItem* getItemByType(DragItemType type, qreal x, qreal y, qreal boxSize); +}; + +#endif // DRAGITEMFABRIC_H diff --git a/pacmanarea/dragitem/walldragitem.cpp b/pacmanarea/dragitem/walldragitem.cpp new file mode 100644 index 0000000..07d6676 --- /dev/null +++ b/pacmanarea/dragitem/walldragitem.cpp @@ -0,0 +1,21 @@ +#include "walldragitem.h" + +WallDragItem::WallDragItem(qreal x, qreal y, qreal boxSize, kWallType type) : + AbstractDragItem::AbstractDragItem( + x, + y, + boxSize, + (type == kWallType::VERTICAL ? DragItemFabric::getNameByType(DragItemFabric::VWALL) : DragItemFabric::getNameByType(DragItemFabric::HWALL)), + Qt::blue + ){ + if (type == kWallType::HORISONTAL){ + qreal temporaryVariable = width_; + WIDTH_ = height_; + HEIGHT_ = temporaryVariable; + } + setRect(x, y, boxSize * width_, boxSize * height_); + AbstractDragItem::WIDTH_ = width_; + AbstractDragItem::HEIGHT_ = height_; +} + +void WallDragItem::touch(){}; diff --git a/pacmanarea/dragitem/walldragitem.h b/pacmanarea/dragitem/walldragitem.h new file mode 100644 index 0000000..e9b946e --- /dev/null +++ b/pacmanarea/dragitem/walldragitem.h @@ -0,0 +1,21 @@ +#ifndef WALLDRAGITEM_H +#define WALLDRAGITEM_H + +#include "abstractdragitem.h" +#include "dragitemfabric.h" + +class WallDragItem : public AbstractDragItem { +public: + enum kWallType { VERTICAL, HORISONTAL }; +public: + WallDragItem(qreal x, qreal y, qreal boxSize, WallType type); + +public slots: + void touch(); + +private: + int width_ = 1; + int height_ = 3; +}; + +#endif // WALLDRAGITEM_H diff --git a/pacmanarea/droppablearea/droppablearea.cpp b/pacmanarea/droppablearea/droppablearea.cpp new file mode 100644 index 0000000..9b1eecb --- /dev/null +++ b/pacmanarea/droppablearea/droppablearea.cpp @@ -0,0 +1,221 @@ +#include "droppablearea.h" +#include +#include + + +DroppableArea::DroppableArea(int x, int y, qreal width, qreal height) { + setRect(x, y, width, height); + startPos_ = {x, y}; + setAcceptDrops(true); + boxArea_ = QVector>(width / BOX_SIZE_, QVector(height / BOX_SIZE_, 0)); + pacman_ = PacManItem::instance(); + gameTimer_ = new QTimer(); + pacmanPos_ = QPoint(-1, -1); + + connect(gameTimer_, &QTimer::timeout, this, &DroppableArea::updateGame); +} + +void DroppableArea::initGame() { + if (pacmanPos_.x() == -1) { // выводит true + QMessageBox::information(nullptr, "Ошибка", "Pacman не пристуствует на поле"); + return; + } + setAcceptDrops(false); + gameTimer_->start(500); +} + +void DroppableArea::closeGame() { + setAcceptDrops(true); + gameTimer_->stop(); +} + +void DroppableArea::updateGame() { + QPoint nextCoord = getNextCoord(pacmanPos_); + int x = nextCoord.x(); + int y = nextCoord.y(); + if(x >= boxArea_.size() || y >= boxArea_[0].size() || x < 0 || y < 0) { + pacman_->setDark(); + } else { + AbstractDragItem* neighbour = getNeighbour(nextCoord); + + if(neighbour == nullptr){ + updateCoord(pacmanPos_, nextCoord); + pacman_->setGreen(); + } else { + updatePacmanByNeighbour(DragItemFabric::getTypeByName(neighbour->getName()), nextCoord); + updateBoxAreaByNeighbour(DragItemFabric::getTypeByName(neighbour->getName()), neighbour); + neighbour->touch(); + } + } + scene()->removeItem(pacman_); + scene()->addItem(pacman_); +} + +void DroppableArea::updateCoord(QPoint coord, QPoint nextCoord){ + int x = nextCoord.x(); + int y = nextCoord.y(); + + boxArea_[coord.x()][coord.y()] = 0; + boxArea_[x][y] = PacManItem::value(); + pacmanPos_.setX(x); + pacmanPos_.setY(y); + pacman_->setCoord(x * BOX_SIZE_ + startPos_.x(), y * BOX_SIZE_ + startPos_.y()); + qDebug() << pacmanPos_; +}; + +void DroppableArea::updatePacmanByNeighbour(DragItemFabric::DragItemType type, QPoint nextCoord){ + switch(type){ + case DragItemFabric::COIN: + updateCoord(pacmanPos_, nextCoord); + emit updateScore(); + break; + case DragItemFabric::VWALL: + case DragItemFabric::HWALL: + pacman_->setDark(); + break; + } +}; + +void DroppableArea::updateBoxAreaByNeighbour(DragItemFabric::DragItemType type, AbstractDragItem* neighbour){ + switch(type){ + case DragItemFabric::COIN: + while (coordToItemsMap_.values().contains(neighbour)) { + auto point = itemsToCoordMap_.find(neighbour).value(); + boxArea_[point.first][point.second] = 0; + coordToItemsMap_.remove(point); + itemsToCoordMap_.remove(neighbour, point); + } + scene()->removeItem(neighbour); + break; + case DragItemFabric::VWALL: + case DragItemFabric::HWALL: + break; + } +}; + +AbstractDragItem* DroppableArea::getNeighbour(QPoint coord){ + if (coordToItemsMap_.contains({coord.x(), coord.y()}) ) + return coordToItemsMap_.find({coord.x(), coord.y()}).value(); + else return nullptr; +}; + +QPoint DroppableArea::getNextCoord(QPoint coord){ + switch(pacman_->direction()){ + case PacManItem::DOWN: + return {pacmanPos_.x(), pacmanPos_.y() + 1}; + case PacManItem::UP: + return {pacmanPos_.x(), pacmanPos_.y() - 1}; + case PacManItem::LEFT: + return {pacmanPos_.x() - 1, pacmanPos_.y()}; + case PacManItem::RIGHT: + return {pacmanPos_.x() + 1, pacmanPos_.y()}; + } +}; + + +void DroppableArea::dragEnterEvent(QGraphicsSceneDragDropEvent* event) { + if (event->mimeData()->hasText()) { + auto coord = getBoxCoord(event); + int x = coord.x(); + int y = coord.y(); + if(x < boxArea_.size() && y < boxArea_[0].size() && x > 0 && y > 0){ + if (event->mimeData()->text() == PacManItem::name()) { + boxArea_[x][y] = 0; + event->setAccepted(true); + return; + } + if(!coordToItemsMap_.contains({x, y})) { + pacman_->setRadius(BOX_SIZE_); + event->setAccepted(false); + return; + } + AbstractDragItem* temp = coordToItemsMap_.find({x, y}).value(); + while (coordToItemsMap_.values().contains(temp)) { + auto point = itemsToCoordMap_.find(temp).value(); + boxArea_[point.first][point.second] = 0; + coordToItemsMap_.remove(point); + itemsToCoordMap_.remove(temp, point); + } + currentDropItem_ = temp; + } + event->setAccepted(true); + } else { + event->setAccepted(false); + } +} + +void DroppableArea::dragMoveEvent(QGraphicsSceneDragDropEvent* event) { + auto coord = getBoxCoord(event); + int x = coord.x(); + int y = coord.y(); + if (event->mimeData()->text() == PacManItem::name()) { + if(x > boxArea_.size() - 1 || y > boxArea_[0].size() - 1 || x < 0 || y < 0 ) { + return; + } + if(x < boxArea_.size() && y < boxArea_[0].size() && !canMove(x, y)){ + return; + } + pacman_->setCoord(x * BOX_SIZE_ + startPos_.x(), y * BOX_SIZE_ + startPos_.y()); + scene()->removeItem(pacman_); + scene()->addItem(pacman_); + return; + } + if(currentDropItem_ != nullptr){ + auto size = currentDropItem_->getSize(); + if(x > boxArea_.size() - size.first || y > boxArea_[0].size() - size.second || x < 0 || y < 0 ) { + return; + } + if(x < boxArea_.size() && y < boxArea_[0].size() && !canMove(x, y, size)){ + return; + } + scene()->removeItem(currentDropItem_); + } + auto type = DragItemFabric::getTypeByName(event->mimeData()->text()); + currentDropItem_ = DragItemFabric::getItemByType(type, x * BOX_SIZE_ + startPos_.x(), y * BOX_SIZE_ + startPos_.y(), BOX_SIZE_); + scene()->addItem(currentDropItem_); + currentPos_ = {x, y}; +} + +void DroppableArea::dropEvent(QGraphicsSceneDragDropEvent* event) { + if (event->mimeData()->hasText()) { + if (event->mimeData()->text() == PacManItem::name()) { + auto coord = getBoxCoord(event); + boxArea_[coord.x()][coord.y()] = PacManItem::value(); + pacmanPos_.setX(coord.x()); + pacmanPos_.setY(coord.y()); + qDebug() << pacmanPos_; + return; + } + auto type = DragItemFabric::getTypeByName(event->mimeData()->text()); + int x = currentPos_.x(); + int y = currentPos_.y(); + auto size = currentDropItem_->getSize(); + AbstractDragItem* temp = currentDropItem_; + items_.append(temp); + for (int i = 0; i < size.first; i++) { + for(int j = 0; j < size.second; j++) { + boxArea_[x + i][y + j] = DragItemFabric::getNumByType(type); + coordToItemsMap_.insert({x + i, y + j}, temp); + itemsToCoordMap_.insertMulti(temp, {x + i, y + j}); + } + } + currentDropItem_ = nullptr; + } +} + +bool DroppableArea::canMove(int x, int y, QPair size) { + for (int i = 0; i < size.first; i++) { + for(int j = 0; j < size.second; j++) { + if(boxArea_[x + i][y + j]){ + return false; + } + } + } + return true; +} + +QPoint DroppableArea::getBoxCoord(QGraphicsSceneDragDropEvent* event) { + qreal x = event->scenePos().x() - event->mimeData()->text().toDouble() - startPos_.x(); + qreal y = event->scenePos().y() - event->mimeData()->text().toDouble() - startPos_.y(); + return { qFloor(x / BOX_SIZE_), qFloor(y / BOX_SIZE_) }; +} diff --git a/pacmanarea/droppablearea/droppablearea.h b/pacmanarea/droppablearea/droppablearea.h new file mode 100644 index 0000000..c9c4e89 --- /dev/null +++ b/pacmanarea/droppablearea/droppablearea.h @@ -0,0 +1,58 @@ +#ifndef DROPPABLEAREA_H +#define DROPPABLEAREA_H + +#include +#include +#include +#include +#include +#include +#include +#include "../dragitem/dragitemfabric.h" +#include "../pacman/pacmanitem.h" +#include +#include + + +class DroppableArea : public QObject, public QGraphicsRectItem { + Q_OBJECT +public: + DroppableArea(int x, int y, qreal width, qreal height); + void dragEnterEvent(QGraphicsSceneDragDropEvent* event) override; + void dragMoveEvent(QGraphicsSceneDragDropEvent* event) override; + void dropEvent(QGraphicsSceneDragDropEvent* event) override; + +public slots: + void initGame(); + void closeGame(); + void updateGame(); + +signals: + void updateScore(); + +private: + QPoint getBoxCoord(QGraphicsSceneDragDropEvent* event); + bool canMove(int x, int y, QPair size = {1, 1}); + AbstractDragItem* getNeighbour(QPoint coord); + QPoint getNextCoord(QPoint coord); + void updateCoord(QPoint coord, QPoint nextCoord); + void updatePacmanByNeighbour(DragItemFabric::DragItemType type, QPoint nextCoord); + void updateBoxAreaByNeighbour(DragItemFabric::DragItemType type, AbstractDragItem* neighbour); + +private: + qreal BOX_SIZE_ = 20; + PacManItem* pacman_; + QPoint startPos_; + QPoint currentPos_; + QPoint pacmanPos_; + AbstractDragItem* currentDropItem_ = nullptr; + QVector items_; + QMap, AbstractDragItem*> coordToItemsMap_; + QMultiMap> itemsToCoordMap_; + QVector> boxArea_; + + QTimer* gameTimer_; + +}; + +#endif // DROPPABLEAREA_H diff --git a/pacmanarea/pacman/pacmanitem.cpp b/pacmanarea/pacman/pacmanitem.cpp new file mode 100644 index 0000000..db6cb0a --- /dev/null +++ b/pacmanarea/pacman/pacmanitem.cpp @@ -0,0 +1,101 @@ +#include "pacmanitem.h" +#include + +PacManItem* PacManItem::instance_ = nullptr; +QString PacManItem::name_ = "Pacman"; +PacManItem::Direction PacManItem::direction_ = RIGHT; +int PacManItem::value_ = 10; + +PacManItem::PacManItem(int x, int y, int radius) : radius_(radius), angle_(45), pie_(270), x_(x), y_(y) { + setGreen(); +}; + +QRectF PacManItem::boundingRect() const{ + return QRectF(x_, y_, 2 * radius_, 2 * radius_); +} + +PacManItem* PacManItem::instance(int x, int y, int radius) { + if (!instance_) { + instance_ = new PacManItem(x, y, radius); + } + return instance_; +} + +QString PacManItem::name() { + return name_; +} + +PacManItem::Direction PacManItem::direction() { + return direction_; +} + +int PacManItem::value() { + return value_; +} + +void PacManItem::setCoord(int x, int y) { + x_= x; + y_ = y; + update(); +} + +QPoint PacManItem::getCoord(){return {x_, y_};}; + +void PacManItem::setRadius(int radius) { + radius_ = radius; + update(); +} + +void PacManItem::setGreen(){ color_ = Qt::green; }; +void PacManItem::setDark(){ color_ = Qt::darkGreen; }; + +void PacManItem::mousePressEvent(QGraphicsSceneMouseEvent* event) { + if (event->button() == Qt::LeftButton) { + QMimeData* mimeData = new QMimeData; + mimeData->setText(name_); + + QDrag* drag = new QDrag(this); + drag->setMimeData(mimeData); + + drag->exec(Qt::MoveAction); + } + + QGraphicsItem::mousePressEvent(event); +} + +void PacManItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) { + Q_UNUSED(option); + Q_UNUSED(widget); + + painter->setBrush(color_); + painter->setRenderHint(QPainter::Antialiasing, true); + + QRectF rect(x_, y_, 2 * radius_, 2 * radius_); + painter->drawPie(rect, angle_ * 16, pie_ * 16); +} + +void PacManItem::keyPressEvent(QKeyEvent* event) { + switch (event->key()) { + case Qt::Key_Left: + angle_ = 225; + pie_ = 270; + direction_ = LEFT; + break; + case Qt::Key_Right: + angle_ = 45; + pie_ = 270; + direction_ = RIGHT; + break; + case Qt::Key_Up: + angle_ = 135; + pie_ = 270; + direction_ = UP; + break; + case Qt::Key_Down: + angle_ = 315; + pie_ = 270; + direction_ = DOWN; + break; + } + update(); +} diff --git a/pacmanarea/pacman/pacmanitem.h b/pacmanarea/pacman/pacmanitem.h new file mode 100644 index 0000000..70c8fee --- /dev/null +++ b/pacmanarea/pacman/pacmanitem.h @@ -0,0 +1,50 @@ +#ifndef PACMANITEM_H +#define PACMANITEM_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class PacManItem :public QObject, public QGraphicsItem { + Q_OBJECT +public: + enum Direction {UP, DOWN, LEFT, RIGHT}; +public: + static PacManItem* instance(int x = 0, int y = 0, int radius = 0); + static QString name(); + static int value(); + static Direction direction(); + QRectF boundingRect() const override; + void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = nullptr) override; + void mousePressEvent(QGraphicsSceneMouseEvent* event) override; + void setCoord(int x, int y); + QPoint getCoord(); + void setGreen(); + void setDark(); + void setRadius(int radius); + +public slots: + void keyPressEvent(QKeyEvent* event) override; + +private: + PacManItem(int x, int y, int radius); + int radius_; + int angle_; + int pie_; + int x_; + int y_; + QColor color_; + static QString name_; + static int value_; + static PacManItem* instance_; + static Direction direction_; +}; + +#endif // PACMANITEM_H diff --git a/pacmanarea/pacmanarea.cpp b/pacmanarea/pacmanarea.cpp new file mode 100644 index 0000000..c00862c --- /dev/null +++ b/pacmanarea/pacmanarea.cpp @@ -0,0 +1,73 @@ +#include "pacmanarea.h" + +PacmanArea::PacmanArea(QWidget* parent) : QGraphicsView(parent) { + + scene_ = new QGraphicsScene(this); + + AbstractDragItem * vwall = DragItemFabric::getVerticalWall( + DEMO_BOX_SIZE_, + DEMO_BOX_SIZE_, + DEMO_BOX_SIZE_ + ); + AbstractDragItem * hwall = DragItemFabric::getHorisontalWall( + DEMO_BOX_SIZE_ * PRINT_ITEM_STEP, + DEMO_BOX_SIZE_, + DEMO_BOX_SIZE_ + ); + AbstractDragItem * coin = DragItemFabric::getCoin( + DEMO_BOX_SIZE_ * PRINT_ITEM_STEP * 2, + DEMO_BOX_SIZE_, + DEMO_BOX_SIZE_ + ); + PacManItem* pacMan = PacManItem::instance( + DEMO_BOX_SIZE_ * PRINT_ITEM_STEP * 3, + DEMO_BOX_SIZE_, + DEMO_BOX_SIZE_/2 + ); + + scoreRect_ = std::make_unique(); + scoreRect_.get()->setPos( + DEMO_BOX_SIZE_ * PRINT_ITEM_STEP * 4, + DEMO_BOX_SIZE_ + ); + scoreRect_->setFont(QFont("Helvetica", 30, 5)); + + scene_->addItem(scoreRect_.get()); + updateScore(); + scene_->addItem(vwall); + scene_->addItem(hwall); + scene_->addItem(coin); + scene_->addItem(pacMan); + + droppableArea_ = new DroppableArea( + 0, + ITEMS_FIELD_BOX_HEIGHT_COUNT_ * DEMO_BOX_SIZE_, + AREA_BOX_COUNT_ * DEMO_BOX_SIZE_, + AREA_BOX_COUNT_ * DEMO_BOX_SIZE_ + ); + + scene_->addItem(droppableArea_); + + setScene(scene_); + setRenderHint(QPainter::Antialiasing, true); + setRenderHint(QPainter::SmoothPixmapTransform, true); + + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + + setFixedSize(AREA_BOX_COUNT_ * DEMO_BOX_SIZE_, (AREA_BOX_COUNT_ + ITEMS_FIELD_BOX_HEIGHT_COUNT_) * DEMO_BOX_SIZE_); + + connect(this, &PacmanArea::startGame, droppableArea_, &DroppableArea::initGame); + connect(this, &PacmanArea::stopGame, droppableArea_, &DroppableArea::closeGame); + connect(droppableArea_, &DroppableArea::updateScore, this, &PacmanArea::updateScore); +} + +void PacmanArea::updateScore() { + scoreRect_.get()->setPlainText(QString("Очки: %1").arg(score_++)); + scene_->removeItem(scoreRect_.get()); + scene_->addItem(scoreRect_.get()); +} + +void PacmanArea::keyPressEvent(QKeyEvent* event) { + PacManItem::instance()->keyPressEvent(event); +}; diff --git a/pacmanarea/pacmanarea.h b/pacmanarea/pacmanarea.h new file mode 100644 index 0000000..82a4b73 --- /dev/null +++ b/pacmanarea/pacmanarea.h @@ -0,0 +1,34 @@ +#ifndef PACMANAREA_H +#define PACMANAREA_H + +#include +#include +#include +#include "./droppablearea/droppablearea.h" + +class PacmanArea : public QGraphicsView { + Q_OBJECT +public: + PacmanArea(QWidget* parent = nullptr); + void keyPressEvent(QKeyEvent* event); + +public slots: + void updateScore(); + +signals: + void startGame(); + void stopGame(); + +private: + QGraphicsScene* scene_; + DroppableArea* droppableArea_; + const int kDemoBoxSize = 20; + const int kAreaBoxCount = 30; + const int ItemsFieldBoxHeightCount = 5; + const int PrintItemStep = 5; + + int score_ = 0; + std::unique_ptr scoreRect_; +}; + +#endif // PACMANAREA_H