diff --git a/Pacman.pro b/Pacman.pro index b915c09..be9dd46 100644 --- a/Pacman.pro +++ b/Pacman.pro @@ -9,16 +9,35 @@ CONFIG += c++17 #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += \ + customgraphicsview.cpp \ + directions.cpp \ + gameelement.cpp \ + hostile.cpp \ main.cpp \ - mainwindow.cpp + mainwindow.cpp \ + player.cpp \ + redactor.cpp \ + startgame.cpp HEADERS += \ - mainwindow.h + customgraphicsview.h \ + directions.h \ + gameelement.h \ + hostile.h \ + mainwindow.h \ + player.h \ + redactor.h \ + startgame.h FORMS += \ - mainwindow.ui + mainwindow.ui \ + redactor.ui \ + startgame.ui # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target + +RESOURCES += \ + resource.qrc diff --git a/coin.png b/coin.png new file mode 100644 index 0000000..42f852f Binary files /dev/null and b/coin.png differ diff --git a/customgraphicsview.cpp b/customgraphicsview.cpp new file mode 100644 index 0000000..b245c5c --- /dev/null +++ b/customgraphicsview.cpp @@ -0,0 +1,76 @@ +#include "customgraphicsview.h" + +#include +#include + +CustomGraphicsView::CustomGraphicsView(QGraphicsScene *scene, QWidget *parent, int gridSize) + : QGraphicsView(scene, parent), cellSize_(gridSize) +{ + setMouseTracking(true); +} + +void CustomGraphicsView::mouseMoveEvent(QMouseEvent *event) +{ + if (isDrawing_) + { + int halfGridSize = cellSize_ / 2; + QPoint localMousePos = event->pos(); + center_ = this->mapToScene(localMousePos); + center_.setX(this->center_.x() - halfGridSize); + center_.setY(this->center_.y() - halfGridSize); + update(); + qDebug() << "cursor Coordinates: (" << center_.x() << ", " << center_.y() << ")"; + } +} + +void CustomGraphicsView::mouseReleaseEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton && isDrawing_) + { + isDrawing_ = false; + setCursorStyle(); + emit customMouseRelease(); + } +} + +void CustomGraphicsView::setCursorStyle() +{ + if (isDrawing_) + { + setCursor(Qt::CrossCursor); + } + else + { + setCursor(Qt::ArrowCursor); + } +} + +int CustomGraphicsView::getCenterX() const +{ + return center_.x(); +} + +int CustomGraphicsView::getCenterY() const +{ + return center_.y(); +} + +void CustomGraphicsView::setCenterX(int newX) +{ + center_.setX(newX); +} + +void CustomGraphicsView::setCenterY(int newY) +{ + center_.setY(newY); +} + +void CustomGraphicsView::setCenter(QPointF newCenter) +{ + center_ = newCenter; +} + +void CustomGraphicsView::setDrawing(bool isDrawing) +{ + isDrawing_ = isDrawing; +} diff --git a/customgraphicsview.h b/customgraphicsview.h new file mode 100644 index 0000000..f10b512 --- /dev/null +++ b/customgraphicsview.h @@ -0,0 +1,35 @@ +#ifndef CUSTOMGRAPHICSVIEW_H +#define CUSTOMGRAPHICSVIEW_H + +#include +#include + +class CustomGraphicsView : public QGraphicsView +{ + Q_OBJECT + +public: + CustomGraphicsView(QGraphicsScene *scene, QWidget *parent = nullptr, int gridSize = 64); + + void setCursorStyle(); + int getCenterX() const; + int getCenterY() const; + void setCenterX(int newX); + void setCenterY(int newY); + void setCenter(QPointF isDrawing); + void setDrawing(bool newDrawing); + +protected: + void mouseMoveEvent(QMouseEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override; + +private: + int cellSize_; + QPointF center_; + bool isDrawing_ = false; + +signals: + void customMouseRelease(); +}; + +#endif // CUSTOMGRAPHICSVIEW_H diff --git a/directions.cpp b/directions.cpp new file mode 100644 index 0000000..b703ecf --- /dev/null +++ b/directions.cpp @@ -0,0 +1,24 @@ +#include "directions.h" + +const std::string Directions::Left = "Left"; +const std::string Directions::Right = "Right"; +const std::string Directions::Up = "Up"; +const std::string Directions::Down = "Down"; + +Directions::Directions(const std::string& type) : directionsType_(type) {} + +std::string Directions::getType() const +{ + return directionsType_; +} + +std::ostream& operator<<(std::ostream& os, const Directions& direction) +{ + os << direction.getType(); + return os; +} + +bool operator==(const Directions& left, const Directions& right) +{ + return left.getType() == right.getType(); +} diff --git a/directions.h b/directions.h new file mode 100644 index 0000000..132bd15 --- /dev/null +++ b/directions.h @@ -0,0 +1,24 @@ +#ifndef DIRECTIONS_H +#define DIRECTIONS_H + +#include + +class Directions { +public: + static const std::string Left; + static const std::string Right; + static const std::string Up; + static const std::string Down; + + Directions(const std::string& type); + + std::string getType() const; + + friend std::ostream& operator<<(std::ostream& os, const Directions& direction); + friend bool operator==(const Directions& left, const Directions& right); + +private: + std::string directionsType_; +}; + +#endif // DIRECTIONS_H diff --git a/gameelement.cpp b/gameelement.cpp new file mode 100644 index 0000000..1168235 --- /dev/null +++ b/gameelement.cpp @@ -0,0 +1,8 @@ +#include "gameelement.h" + +GameElement::GameElement(ElementType type) : elementType_(type) {} + +GameElement::ElementType GameElement::getType() const +{ + return elementType_; +} diff --git a/gameelement.h b/gameelement.h new file mode 100644 index 0000000..a3c5f6c --- /dev/null +++ b/gameelement.h @@ -0,0 +1,22 @@ +#ifndef GAMEELEMENT_H +#define GAMEELEMENT_H + +class GameElement { +public: + enum ElementType { + Empty = 0, + Wall = 1, + Puckman = 2, + Hostile = 3, + Coin = 4 + }; + + GameElement(ElementType type); + + ElementType getType() const; + +private: + ElementType elementType_; +}; + +#endif // GAMEELEMENT_H diff --git a/hostile.cpp b/hostile.cpp new file mode 100644 index 0000000..e958975 --- /dev/null +++ b/hostile.cpp @@ -0,0 +1,196 @@ +#include "hostile.h" + +using namespace std; + +Hostile::Hostile(std::vector>& inputMatrix) : position_(0, 0) +{} + +Hostile::Hostile() : position_(0, 0) +{} + +bool Hostile::isCellValidForMovement(int x, int y) +{ + int rows = matrix_.size(); + int columns = matrix_[0].size(); + return x >= GameElement::Empty && x < columns && y >= GameElement::Empty && y < rows && matrix_[y][x] != GameElement::Wall && matrix_[y][x] != GameElement::Hostile; +} + +std::vector getMoveDirections(const Point& start, const Point& end) +{ + int dx = end.x - start.x; + int dy = end.y - start.y; + + std::vector directions; + + if (dx > 0) + { + directions.push_back(Directions(Directions::Right)); + } + else if (dx < 0) + { + directions.push_back(Directions(Directions::Left)); + } + + if (dy > 0) + { + directions.push_back(Directions(Directions::Down)); + } + else if (dy < 0) + { + directions.push_back(Directions(Directions::Up)); + } + + return directions; +} + +std::vector Hostile::getPath(const Point& end) +{ + int rows = matrix_.size(); + int columns = matrix_[0].size(); + + std::vector directions; + + vector> distance(rows, vector(columns, INT_MAX)); + vector> path(rows, vector(columns, Point(-1, -1))); + priority_queue, greater> priorityQueue; + + priorityQueue.push(Node(position_, 0)); + distance[position_.y][position_.x] = 0; + + int dx[] = {-1, 1, 0, 0}; + int dy[] = {0, 0, -1, 1}; + + while (!priorityQueue.empty()) + { + Node current = priorityQueue.top(); + priorityQueue.pop(); + + if (current.point.x == end.x && current.point.y == end.y) + { + + vector pathPoints; + Point currentPoint = end; + + while (!(currentPoint.x == position_.x && currentPoint.y == position_.y)) + { + pathPoints.push_back(currentPoint); + currentPoint = path[currentPoint.y][currentPoint.x]; + } + + reverse(pathPoints.begin(), pathPoints.end()); + + for (const Point& point : pathPoints) + { + int dx = point.x - currentPoint.x; + int dy = point.y - currentPoint.y; + + if (dx == -1) + { + directions.push_back(Directions(Directions::Left)); + } + else if (dx == 1) + { + directions.push_back(Directions(Directions::Right)); + } + else if (dy == -1) + { + directions.push_back(Directions(Directions::Up)); + } + else if (dy == 1) + { + directions.push_back(Directions(Directions::Down)); + } + + currentPoint = point; + } + cout << endl; + + return directions; + } + + int stepWeight = 1; + const int kDirections = 4; + + for (int i = 0; i < kDirections; ++i) + { + int nextX = current.point.x + dx[i]; + int nextY = current.point.y + dy[i]; + + if (isCellValidForMovement(nextX, nextY)) + { + int newDistance = current.distance + stepWeight; + + if (newDistance < distance[nextY][nextX]) + { + distance[nextY][nextX] = newDistance; + path[nextY][nextX] = current.point; + priorityQueue.push(Node(Point(nextX, nextY), newDistance)); + } + } + } + } + + return std::vector(); +} + +void Hostile::setPosition(Point& pos) +{ + position_ = pos; +} + +void Hostile::setMatrix(std::vector > &matrix) +{ + matrix_ = matrix; +} + +Point Hostile::getPosition() +{ + return position_; +} + +int Hostile::Primer() +{ + + vector> inputMatrix = + { + {0, 0, 0, 0, 0}, + {0, 1, 0, 1, 0}, + {0, 1, 0, 0, 1}, + {0, 1, 1, 0, 1}, + {1, 0, 0, 0, 0} + }; + + Hostile hostile(inputMatrix); + + Point start(4, 0); + Point end(0, 3); + + hostile.setPosition(start); + std::vector pathDirections = hostile.getPath(end); + + if (pathDirections.empty()) + { + cout << "No path found." << endl; + } + else + { + cout << "Shortest Path Directions: "; + for (Directions direction : pathDirections) + { + cout << direction << " "; + } + cout << endl; + } + + return 0; +} + +void Hostile::setPreviousElement(int element) +{ + previousElement_ = element; +} + +int Hostile::getPreviousElement() +{ + return previousElement_; +} diff --git a/hostile.h b/hostile.h new file mode 100644 index 0000000..b7c92cb --- /dev/null +++ b/hostile.h @@ -0,0 +1,57 @@ +#ifndef HOSTILE_H +#define HOSTILE_H + +#include +#include +#include +#include +#include +#include + +#include "directions.h" +#include "gameelement.h" + +struct Point +{ + int x, y; + + Point(int _x, int _y) : x(_x), y(_y) {} +}; + +class Hostile +{ +public: + Hostile(); + Hostile(std::vector>& inputMatrix); + + std::vector getPath(const Point& end); + int getPreviousElement(); + int Primer(); + void setPreviousElement(int element); + void setPosition(Point& pos); + void setMatrix(std::vector>& inputMatrix); + Point getPosition(); + +private: + struct Node + { + Point point; + int distance; + + Node(Point _point, int _distance) : point(_point), distance(_distance) {} + + bool operator>(const Node& other) const { + return distance > other.distance; + } + }; + + std::vector> matrix_; + + bool isCellValidForMovement(int x, int y); + + Point position_; + int previousElement_ = 0; + +}; + +#endif // HOSTILE_H diff --git a/hostile.png b/hostile.png new file mode 100644 index 0000000..6deb889 Binary files /dev/null and b/hostile.png differ diff --git a/main.cpp b/main.cpp index e9562cc..8faf187 100644 --- a/main.cpp +++ b/main.cpp @@ -1,3 +1,4 @@ +#include "startgame.h" #include "mainwindow.h" #include @@ -5,7 +6,7 @@ int main(int argc, char *argv[]) { QApplication a(argc, argv); - MainWindow w; + StartGame w; w.show(); return a.exec(); } diff --git a/mainwindow.cpp b/mainwindow.cpp index 7e184b2..98fab81 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -1,15 +1,453 @@ #include "mainwindow.h" #include "ui_mainwindow.h" +#include "hostile.h" +#include "startgame.h" -MainWindow::MainWindow(QWidget *parent) - : QMainWindow(parent) - , ui(new Ui::MainWindow) +#include +#include +#include +#include +#include +#include +#include + +MainWindow::MainWindow(QWidget *parent, int** gameGrid) + : QMainWindow(parent), ui(new Ui::MainWindow) +{ + ui->setupUi(this); + setFocusPolicy(Qt::StrongFocus); + setFocus(); + + hostiles_.reserve(kColumns_*kRows_); + + scene_ = new QGraphicsScene(this); + view_ = new QGraphicsView(scene_, this); + + int indentationColumns = 4; + int indentationRows = 4; + int uiWidth = (kColumns_ + indentationColumns) * cellSize_; + int uiHeight = (kRows_ + indentationRows) * cellSize_; + + this->setFixedSize(uiWidth, uiHeight); + setCentralWidget(view_); + + gameTimer_ = new QTimer(this); + gameTimer_->start(250); + connect(gameTimer_, SIGNAL(timeout()), this, SLOT(updateGameTime())); + + hostileRunTimer_ = new QTimer(this); + hostileRunTimer_->start(1000); + connect(hostileRunTimer_, SIGNAL(timeout()), this, SLOT(updateHostileRunTime())); + + if (gameGrid != nullptr) + { + counsCount_ = 0; + std::vector> matrix; + for (int i = 0; i < kRows_; ++i) + { + std::vector row; + for (int j = 0; j < kColumns_; ++j) + { + row.push_back(gameGrid[i][j]); + } + matrix.push_back(row); + } + for (const auto& row : matrix) { + for (const auto& element : row) { + std::cout << element << " "; + } + std::cout << std::endl; + } + } + Hostile newHostile; + Point hostilePosition(0, 0); + if (gameGrid != nullptr) + { + gameGrid_ = new int*[kRows_]; + for (int i = 0; i < kRows_; ++i) + { + gameGrid_[i] = new int[kColumns_]; + for (int j = 0; j < kColumns_; ++j) + { + gameGrid_[i][j] = gameGrid[i][j]; + if(gameGrid_[i][j] == GameElement::Hostile) + { + hostilePosition.x = j; + hostilePosition.y = i; + newHostile.setPosition(hostilePosition); + qDebug() << "Hostile Coordinates: (" << hostilePosition.x << ", " << hostilePosition.y << ")"; + hostiles_.push_back(newHostile); + } + if(gameGrid_[i][j] == GameElement::Coin) + { + counsCount_++; + } + if(gameGrid_[i][j] == GameElement::Puckman) + { + player_.setY(i); + player_.setX(j); + } + } + } + } + else + { + gameGrid_ = new int*[kRows_]; + for (int i = 0; i < kRows_; ++i) + { + gameGrid_[i] = new int[kColumns_]; + } + generateRandomGameGrid(); + } + + setupGameGrid(); +} + +void MainWindow::updateGameTime() +{ + gameTime_ += 0.5; + isKeyTime_ = true; + setupGameGrid(); + if(gameGrid_[player_.getY()][player_.getX()] == GameElement::Hostile) + { + gameOver(false); + } + if(counsCount_ == 0) + { + gameOver(true); + } +} + +void MainWindow::updateHostileRunTime() { - ui->setupUi(this); + moveHostile(); } MainWindow::~MainWindow() { - delete ui; + for (int i = 0; i < kRows_; ++i) + { + delete[] gameGrid_[i]; + } + delete[] gameGrid_; + + delete ui; +} + +void MainWindow::gameOver(bool isWin) +{ + disconnect(gameTimer_, SIGNAL(timeout()), this, SLOT(updateGameTime())); + disconnect(hostileRunTimer_, SIGNAL(timeout()), this, SLOT(updateHostileRunTime())); + if (isWin) + { + std::string stringGameOver = "You WIN!"; + const char* charArray = stringGameOver.c_str(); + QMessageBox::information(this, "WIN", charArray); + } + else + { + std::string stringGameOver = "Game Over, coins left: "; + std::string stringGameOver2 = std::to_string(counsCount_); + stringGameOver.append(stringGameOver2); + const char* charArray = stringGameOver.c_str(); + QMessageBox::information(this, "False", charArray); + } + close(); + handleGameOver(); } +void MainWindow::handleGameOver() +{ + StartGame *SG = new StartGame(); + SG->show(); +} + +void MainWindow::generateRandomGameGrid() +{ + + std::srand(std::time(0)); + + for (int i = 0; i < kRows_; ++i) + { + for (int j = 0; j < kColumns_; ++j) + { + gameGrid_[i][j] = 0; + } + } + + int randomRow = std::rand() % kRows_; + int randomColumn = std::rand() % kColumns_; + + gameGrid_[randomRow][randomColumn] = GameElement::Puckman; + player_.setX(randomColumn); + player_.setY(randomRow); + qDebug() << "Player Coordinates: (" << player_.getX() << ", " << player_.getY() << ")"; + + int element = GameElement::Wall; + int count = 5; + generateRandomElements(element,count); + + element = GameElement::Hostile; + count = 2; + generateRandomElements(element,count); + + element = GameElement::Coin; + generateRandomElements(element,counsCount_); + +} + +void MainWindow::generateRandomElements(int element, int count) +{ + Hostile newHostile; + Point hostilePosition(0,0); + if (element == GameElement::Hostile) + { + std::vector> matrix; + for (int i = 0; i < kRows_; ++i) + { + std::vector row; + for (int j = 0; j < kColumns_; ++j) + { + row.push_back(gameGrid_[i][j]); + } + matrix.push_back(row); + } + + for (const auto& row : matrix) + { + for (const auto& element : row) + { + std::cout << element << " "; + } + std::cout << std::endl; + } + newHostile.setMatrix(matrix); + } + for (int k = 0; k < count; ++k) + { + int randomRow = std::rand() % kRows_; + int randomColumn = std::rand() % kColumns_; + + while (gameGrid_[randomRow][randomColumn] != GameElement::Empty) + { + randomRow = std::rand() % kRows_; + randomColumn = std::rand() % kColumns_; + } + if(element == GameElement::Hostile) + { + hostilePosition.x = randomColumn; + hostilePosition.y = randomRow; + newHostile.setPosition(hostilePosition); + hostiles_.push_back(newHostile); + } + gameGrid_[randomRow][randomColumn] = element; + } +} + +void MainWindow::setupGameGrid() +{ + scene_->clear(); + QGraphicsPixmapItem* puckmanItem; + QGraphicsPixmapItem* hostileItem; + QGraphicsPixmapItem* coinItem; + QGraphicsTextItem* coinsLabel = scene_->addText("Coins: "+ QString::number(counsCount_)); + coinsLabel->setDefaultTextColor(Qt::black); + QFont font = coinsLabel->font(); + font.setPointSize(14); + coinsLabel->setFont(font); + coinsLabel->setPos(kColumns_ * cellSize_ + 10, 10); + for (int i = 0; i < kRows_; ++i) + { + for (int j = 0; j < kColumns_; ++j) + { + + switch (gameGrid_[i][j]) + { + case GameElement::Empty: + scene_->addRect(j * cellSize_, i * cellSize_, cellSize_, cellSize_, QPen(Qt::black), QBrush(Qt::white)); + break; + case GameElement::Wall: + scene_->addRect(j * cellSize_, i * cellSize_, cellSize_, cellSize_, QPen(Qt::black), QBrush(Qt::darkGray)); + break; + case GameElement::Puckman: + puckmanItem = scene_->addPixmap(QPixmap(":resource/puckman.png").scaled(cellSize_, cellSize_)); + puckmanItem->setX(j * cellSize_); + puckmanItem->setY(i * cellSize_); + break; + case GameElement::Hostile: + hostileItem = scene_->addPixmap(QPixmap(":resource/hostile.png").scaled(cellSize_, cellSize_)); + hostileItem->setX(j * cellSize_); + hostileItem->setY(i * cellSize_); + break; + case GameElement::Coin: + coinItem = scene_->addPixmap(QPixmap(":resource/coin.png").scaled(cellSize_, cellSize_)); + coinItem->setX(j * cellSize_); + coinItem->setY(i * cellSize_); + break; + } + } + } + + view_->setSceneRect(0, 0, kColumns_ * cellSize_, kRows_ * cellSize_); + + view_->update(); +} + +void MainWindow::moveHostile() +{ + if (hostiles_.empty()) + { + qDebug() << "No hostiles found."; + return; + } + std::vector> matrix; + for (int i = 0; i < kRows_; ++i) + { + std::vector row; + for (int j = 0; j < kColumns_; ++j) + { + row.push_back(gameGrid_[i][j]); + } + matrix.push_back(row); + } + + for (const auto& row : matrix) + { + for (const auto& element : row) + { + std::cout << element << " "; + } + std::cout << std::endl; + } + + std::vector direction; + Point playerPoint(player_.getX(), player_.getY()); + Point hostilePosition(0,0); + + for (Hostile& currentHostile : hostiles_) + { + currentHostile.setMatrix(matrix); + direction = currentHostile.getPath(playerPoint); + if (direction.empty()) + { + return; + } + if (direction[0] == Directions::Left) + { + hostilePosition = currentHostile.getPosition(); + gameGrid_[hostilePosition.y][hostilePosition.x] = currentHostile.getPreviousElement(); + currentHostile.setPreviousElement(gameGrid_[hostilePosition.y][hostilePosition.x - 1]); + hostilePosition.x = hostilePosition.x - 1; + gameGrid_[hostilePosition.y][hostilePosition.x] = GameElement::Hostile; + currentHostile.setPosition(hostilePosition); + } + if (direction[0] == Directions::Right) + { + hostilePosition = currentHostile.getPosition(); + gameGrid_[hostilePosition.y][hostilePosition.x] = currentHostile.getPreviousElement(); + currentHostile.setPreviousElement(gameGrid_[hostilePosition.y][hostilePosition.x + 1]); + hostilePosition.x = hostilePosition.x + 1; + gameGrid_[hostilePosition.y][hostilePosition.x] = GameElement::Hostile; + currentHostile.setPosition(hostilePosition); + } + if (direction[0] == Directions::Up) + { + + hostilePosition = currentHostile.getPosition(); + gameGrid_[hostilePosition.y][hostilePosition.x] = currentHostile.getPreviousElement(); + currentHostile.setPreviousElement(gameGrid_[hostilePosition.y - 1][hostilePosition.x]); + hostilePosition.y = hostilePosition.y - 1; + gameGrid_[hostilePosition.y][hostilePosition.x] = GameElement::Hostile; + qDebug() << "gameGrid_ Coordinates: (" << hostilePosition.x << ", " << hostilePosition.y << ")"; + currentHostile.setPosition(hostilePosition); + } + if (direction[0] == Directions::Down) + { + + hostilePosition = currentHostile.getPosition(); + gameGrid_[hostilePosition.y][hostilePosition.x] = currentHostile.getPreviousElement(); + currentHostile.setPreviousElement(gameGrid_[hostilePosition.y + 1][hostilePosition.x]); + hostilePosition.y = hostilePosition.y + 1; + gameGrid_[hostilePosition.y][hostilePosition.x] = GameElement::Hostile; + qDebug() << "gameGrid_ Coordinates: (" << hostilePosition.x << ", " << hostilePosition.y << ")"; + currentHostile.setPosition(hostilePosition); + } + } +} + +void MainWindow::keyPressEvent(QKeyEvent *event) +{ + if (isKeyTime_) + { + switch (event->key()) + { + case Qt::Key_W: + movePlayer(Directions::Up); + isKeyTime_ = false; + break; + case Qt::Key_S: + movePlayer(Directions::Down); + isKeyTime_ = false; + break; + case Qt::Key_A: + movePlayer(Directions::Left); + isKeyTime_ = false; + break; + case Qt::Key_D: + movePlayer(Directions::Right); + isKeyTime_ = false; + break; + default: + QMainWindow::keyPressEvent(event); + break; + } + } +} + +void MainWindow::movePlayer(Directions direction) +{ + int newX = player_.getX(); + int newY = player_.getY(); + + int direc = 4; + if (direction == Directions::Up) + { + direc = 1; + } + if (direction == Directions::Down) + { + direc = 2; + } + if (direction == Directions::Left) + { + direc = 3; + } + switch (direc) + { + case 1: + newY = std::max(0, newY - 1); + break; + case 2: + newY = std::min(kRows_ - 1, newY + 1); + break; + case 3: + newX = std::max(0, newX - 1); + break; + case 4: + newX = std::min(kColumns_ - 1, newX + 1); + break; + } + + if (gameGrid_[newY][newX] != GameElement::Wall) + { + gameGrid_[player_.getY()][player_.getX()] = GameElement::Empty; + if (gameGrid_[newY][newX] == GameElement::Coin) + { + counsCount_--; + } + gameGrid_[newY][newX] = GameElement::Puckman; + player_.setX(newX); + player_.setY(newY); + qDebug() << "Player Coordinates: (" << player_.getX() << ", " << player_.getY() << ")"; + } +} diff --git a/mainwindow.h b/mainwindow.h index dbe42ab..9369cdc 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -1,7 +1,15 @@ #ifndef MAINWINDOW_H #define MAINWINDOW_H +#include "player.h" +#include "hostile.h" +#include "gameelement.h" + +#include +#include #include +#include +#include QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } @@ -9,13 +17,45 @@ QT_END_NAMESPACE class MainWindow : public QMainWindow { - Q_OBJECT + Q_OBJECT + +public: + MainWindow(QWidget *parent = nullptr, int** gameGrid = nullptr); + ~MainWindow(); + + void generateRandomGameGrid(); + void setupGameGrid(); + +protected: + void keyPressEvent(QKeyEvent *event) override; - public: - MainWindow(QWidget *parent = nullptr); - ~MainWindow(); +private: + Ui::MainWindow *ui; + QTimer* gameTimer_; + QTimer* hostileRunTimer_; + float gameTime_; + const int kRows_ = 10; + const int kColumns_ = 10; + int **gameGrid_; + int cellSize_ = 64; + int counsCount_ = 5; + bool isKeyTime_ = true; + Player player_; + QGraphicsScene *scene_; + QGraphicsView *view_; + std::vector hostiles_; + + void movePlayer(Directions direction); + void moveHostile(); + void generateRandomElements(int element, int count); + void updateCoinsCount(); + void gameOver(bool isWin); + void handleGameOver(); + +private slots: + void updateGameTime(); + void updateHostileRunTime(); - private: - Ui::MainWindow *ui; }; + #endif // MAINWINDOW_H diff --git a/mainwindow.ui b/mainwindow.ui index b232854..74d8304 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -1,22 +1,36 @@ - MainWindow - - - - 0 - 0 - 800 - 600 - - - - MainWindow - - - - - - - +MainWindow + + + + 0 + 0 + 800 + 600 + + + + MainWindow + + + + + + + + + + + 0 + 0 + 800 + 21 + + + + + + + diff --git a/player.cpp b/player.cpp new file mode 100644 index 0000000..ac2be04 --- /dev/null +++ b/player.cpp @@ -0,0 +1,23 @@ +#include "player.h" + +Player::Player() : x_(0), y_(0) {} + +int Player::getX() const +{ + return x_; +} + +int Player::getY() const +{ + return y_; +} + +void Player::setX(int newX) +{ + x_ = newX; +} + +void Player::setY(int newY) +{ + y_ = newY; +} diff --git a/player.h b/player.h new file mode 100644 index 0000000..274a9b2 --- /dev/null +++ b/player.h @@ -0,0 +1,18 @@ +#ifndef PLAYER_H +#define PLAYER_H + +class Player { +public: + Player(); + + int getX() const; + int getY() const; + void setX(int newX); + void setY(int newY); + +private: + int x_; + int y_; +}; + +#endif // PLAYER_H diff --git a/puckman.png b/puckman.png new file mode 100644 index 0000000..5398c1c Binary files /dev/null and b/puckman.png differ diff --git a/redactor.cpp b/redactor.cpp new file mode 100644 index 0000000..e2573ad --- /dev/null +++ b/redactor.cpp @@ -0,0 +1,313 @@ +#include "redactor.h" +#include "ui_redactor.h" +#include "mainwindow.h" +#include "startgame.h" + +#include +#include +#include +#include +#include +#include +#include + +Redactor::Redactor(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::Redactor) +{ + ui->setupUi(this); + setFocusPolicy(Qt::StrongFocus); + + scene = new QGraphicsScene(this); + view = new CustomGraphicsView(scene, this, cellSize_); + + view->setMouseTracking(true); + view->hasMouseTracking(); + + connect(view, &CustomGraphicsView::customMouseRelease, this, &Redactor::handleCustomMouseRelease); + + int indentationColumns = 6; + int indentationRows = 1; + int uiWidth = (kColumns_ + indentationColumns) * cellSize_; + int uiHeight = (kRows_ + indentationRows) * cellSize_; + + this->setFixedSize(uiWidth, uiHeight); + setCentralWidget(view); + + gameGrid_ = new int*[kRows_]; + for (int i = 0; i < kRows_; ++i) + { + gameGrid_[i] = new int[kColumns_]; + } + for (int i = 0; i < kRows_; ++i) + { + for (int j = 0; j < kColumns_; ++j) + { + gameGrid_[i][j] = 0; + } + } + + myButton = new QPushButton("Начать игру", this); + myButton->setGeometry(10, 10, 100, 30); + connect(myButton, &QPushButton::clicked, this, &Redactor::handleButtonClick); + + setupGameGrid(); + + ui->setupUi(this); +} + +void Redactor::exitRedaction() +{ + close(); + openGame(); +} + +void Redactor::openGame() +{ + MainWindow *startGame = new MainWindow(nullptr, gameGrid_); + startGame->show(); +} + +void Redactor::handleButtonClick() +{ + if (counsCount_ <= 0) + { + std::string stringWarn = "couns count < 0"; + const char* charArray = stringWarn.c_str(); + QMessageBox::information(this, "False", charArray); + return; + } + exitRedaction(); +} + +Redactor::~Redactor() +{ + for (int i = 0; i < kRows_; ++i) + { + delete[] gameGrid_[i]; + } + delete[] gameGrid_; + delete ui; +} + +void Redactor::paintEvent(QPaintEvent *event) +{ + dragItem(); +} + +void Redactor::dragItem() +{ + if (dragItem_ != nullptr) + { + scene->removeItem(dragItem_); + delete dragItem_; + } + dragItem_ = new QGraphicsPixmapItem(); + if (dragElement_ == GameElement::Wall) + { + dragItem_ = scene->addPixmap(QPixmap(":resource/wall.png").scaled(cellSize_, cellSize_)); + } + if (dragElement_ == GameElement::Puckman) + { + dragItem_ = scene->addPixmap(QPixmap(":resource/puckman.png").scaled(cellSize_, cellSize_)); + } + if (dragElement_ == GameElement::Hostile) + { + dragItem_ = scene->addPixmap(QPixmap(":resource/hostile.png").scaled(cellSize_, cellSize_)); + } + if (dragElement_ == GameElement::Coin) + { + dragItem_ = scene->addPixmap(QPixmap(":resource/coin.png").scaled(cellSize_, cellSize_)); + } + dragItem_->setX(view->getCenterX()); + dragItem_->setY(view->getCenterY()); +} + +void Redactor::setupGameGrid() +{ + scene->clear(); + QGraphicsPixmapItem* puckmanItem; + QGraphicsPixmapItem* hostileItem; + QGraphicsPixmapItem* coinItem; + + for (int i = 0; i < kRows_; ++i) + { + for (int j = 0; j < kColumns_; ++j) + { + + switch (gameGrid_[i][j]) + { + case GameElement::Empty: + scene->addRect(j * cellSize_, i * cellSize_, cellSize_, cellSize_, QPen(Qt::black), QBrush(Qt::white)); + break; + case GameElement::Wall: + scene->addRect(j * cellSize_, i * cellSize_, cellSize_, cellSize_, QPen(Qt::black), QBrush(Qt::darkGray)); + break; + case GameElement::Puckman: + puckmanItem = scene->addPixmap(QPixmap(":resource/puckman.png").scaled(cellSize_, cellSize_)); + puckmanItem->setX(j * cellSize_); + puckmanItem->setY(i * cellSize_); + break; + case GameElement::Hostile: + hostileItem = scene->addPixmap(QPixmap(":resource/hostile.png").scaled(cellSize_, cellSize_)); + hostileItem->setX(j * cellSize_); + hostileItem->setY(i * cellSize_); + break; + case GameElement::Coin: + coinItem = scene->addPixmap(QPixmap(":resource/coin.png").scaled(cellSize_, cellSize_)); + coinItem->setX(j * cellSize_); + coinItem->setY(i * cellSize_); + break; + } + } + } + int extraColumns = kColumns_+2; + int Row = 2; + int nextRow = Row * cellSize_; + wallItem_ = scene->addPixmap(QPixmap(":resource/wall.png").scaled(cellSize_, cellSize_)); + wallItem_->setX((extraColumns) * cellSize_); + wallItem_->setY(nextRow); + qDebug() << "wallItem Coordinates: (" << wallItem_->x() << ", " << wallItem_->y() << ")"; + Row = 4; + nextRow = Row * cellSize_; + + puckmanItem_ = scene->addPixmap(QPixmap(":resource/puckman.png").scaled(cellSize_, cellSize_)); + puckmanItem_->setX((extraColumns) * cellSize_); + puckmanItem_->setY(nextRow); + qDebug() << "puckmanItem Coordinates: (" << puckmanItem_->x() << ", " << puckmanItem_->y() << ")"; + + Row = 6; + nextRow = Row * cellSize_; + + hostileItem_ = scene->addPixmap(QPixmap(":resource/hostile.png").scaled(cellSize_, cellSize_)); + hostileItem_->setX((extraColumns) * cellSize_); + hostileItem_->setY(nextRow); + qDebug() << "hostileItem Coordinates: (" << hostileItem_->x() << ", " << hostileItem_->y() << ")"; + + Row = 8; + nextRow = Row * cellSize_; + + coinItem_ = scene->addPixmap(QPixmap(":resource/coin.png").scaled(cellSize_, cellSize_)); + coinItem_->setX((extraColumns) * cellSize_); + coinItem_->setY(nextRow); + qDebug() << "coinItem Coordinates: (" << coinItem_->x() << ", " << coinItem_->y() << ")"; + + view->setSceneRect(0, 0, kColumns_ * cellSize_, kRows_ * cellSize_); + + view->update(); +} + +QPoint Redactor::getGridPoint() +{ + QPoint coordinateElementGrid(-1, -1); + int halfGridSize = cellSize_ / 2; + for (int i = 0; i < kRows_; ++i) + { + for (int j = 0; j < kColumns_; ++j) + { + if (view->getCenterX() > i * cellSize_ - halfGridSize && view->getCenterX()< i * cellSize_ + halfGridSize) + { + if (view->getCenterY() > j * cellSize_ - halfGridSize && view->getCenterY() < j * cellSize_ + halfGridSize) + { + coordinateElementGrid.setX(i); + coordinateElementGrid.setY(j); + qDebug() << "getGridPoint Coordinates: (" << coordinateElementGrid.x() << ", " << coordinateElementGrid.y() << ")"; + return(coordinateElementGrid); + } + } + } + } + qDebug() << "getGridPoint Coordinates: (" << coordinateElementGrid.x() << ", " << coordinateElementGrid.y() << ")"; + return coordinateElementGrid; +} + +int Redactor::getElement() +{ + QGraphicsItem* item = scene->itemAt(view->getCenterX(), view->getCenterY(), QTransform()); + if (view->getCenterX() < wallItem_->x() + cellSize_ && view->getCenterX() > wallItem_->x() - cellSize_) + { + if (view->getCenterY() < wallItem_->y() + cellSize_ && view->getCenterY() > wallItem_->y() - cellSize_) + { + qDebug() << "you drag item: (" << item << ")"; + return GameElement::Wall; + } + } + if (view->getCenterX() < puckmanItem_->x() + cellSize_ && view->getCenterX() > puckmanItem_->x() - cellSize_) + { + if (view->getCenterY() < puckmanItem_->y() + cellSize_ && view->getCenterY() > puckmanItem_->y() - cellSize_) + { + if (isStatePacmanElement_ == false) + { + qDebug() << "you drag item: (" << item << ")"; + return GameElement::Puckman; + } + } + } + if (view->getCenterX() < hostileItem_->x() + cellSize_ && view->getCenterX() > hostileItem_->x() - cellSize_) + { + if (view->getCenterY() < hostileItem_->y() + cellSize_ && view->getCenterY() > hostileItem_->y() - cellSize_) + { + qDebug() << "you drag item: (" << item << ")"; + return GameElement::Hostile; + } + } + if (view->getCenterX() < coinItem_->x() + cellSize_ && view->getCenterX() > coinItem_->x() - cellSize_) + { + if (view->getCenterY() < coinItem_->y() + cellSize_ && view->getCenterY() > coinItem_->y() - cellSize_) + { + qDebug() << "you drag item: (" << item << ")"; + return GameElement::Coin; + } + } + qDebug() << "you drag item: (" << item << ")"; + return 0; +} + +void Redactor::mousePressEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) + { + dragItem_ = new QGraphicsPixmapItem(); + view->setDrawing(true); + QPoint localMousePos = event->pos(); + view->setCenter(view->mapToScene(localMousePos)); + view->setCenterX(view->getCenterX()); + view->setCenterY(view->getCenterY()); + view->setCursorStyle(); + qDebug() << "cursor Coordinates: (" << view->getCenterX()<< ", " << view->getCenterY() << ")"; + dragElement_ = getElement(); + qDebug() << "you drag item: (" << getElement() << ")"; + + update(); + } + +} + +void Redactor::handleCustomMouseRelease() +{ + dragItem_ = new QGraphicsPixmapItem(); + QPoint cell = getGridPoint(); + if (cell.x() > 0 || cell.y() > 0) + { + if (gameGrid_[cell.y()][cell.x()] == GameElement::Puckman) + { + isStatePacmanElement_ = false; + } + if (gameGrid_[cell.y()][cell.x()] == GameElement::Coin) + { + counsCount_--; + } + gameGrid_[cell.y()][cell.x()] = dragElement_; + if (dragElement_ == GameElement::Puckman) + { + isStatePacmanElement_ = true; + } + if (dragElement_ == GameElement::Coin) + { + counsCount_++; + qDebug() << "counsCount = (" << counsCount_ << ")"; + } + } + update(); + setupGameGrid(); +} diff --git a/redactor.h b/redactor.h new file mode 100644 index 0000000..6f5ffa8 --- /dev/null +++ b/redactor.h @@ -0,0 +1,62 @@ +#ifndef REDACTOR_H +#define REDACTOR_H + +#include +#include +#include + +#include "mainwindow.h" +#include "customgraphicsview.h" + +namespace Ui +{ + class Redactor; +} + +class Redactor : public QMainWindow +{ + Q_OBJECT + +public: + Redactor(QWidget *parent = nullptr); + ~Redactor(); + +protected: + void paintEvent(QPaintEvent *event) override; + void mousePressEvent(QMouseEvent *event) override; + +private: + Ui::Redactor *ui; + MainWindow *MW; + int **gameGrid_; + const int kRows_ = 10; + const int kColumns_ = 10; + int cellSize_ = 64; + int counsCount_ = 0; + QGraphicsScene *scene; + CustomGraphicsView *view; + bool isDrawing_ = false; + QPointF center_; + int lineWidth_; + QColor lineColor_; + int dragElement_; + QGraphicsPixmapItem* wallItem_; + QGraphicsPixmapItem* puckmanItem_; + QGraphicsPixmapItem* hostileItem_; + QGraphicsPixmapItem* coinItem_; + QGraphicsPixmapItem* dragItem_ = nullptr; + bool isStatePacmanElement_ = false; + QPushButton *myButton; + + void setupGameGrid(); + void drawItems(QPainter *painter, const QPoint ¢er); + QPoint getGridPoint(); + void dragItem(); + void handleCustomMouseRelease(); + void handleButtonClick(); + void openGame(); + void exitRedaction(); + int getElement(); +}; + +#endif // REDACTOR_H diff --git a/redactor.ui b/redactor.ui new file mode 100644 index 0000000..55dbda6 --- /dev/null +++ b/redactor.ui @@ -0,0 +1,21 @@ + + + + + Redactor + + + + 0 + 0 + 400 + 300 + + + + Form + + + + + diff --git a/resource.qrc b/resource.qrc new file mode 100644 index 0000000..58ffa1e --- /dev/null +++ b/resource.qrc @@ -0,0 +1,8 @@ + + + puckman.png + hostile.png + coin.png + wall.png + + diff --git a/startgame.cpp b/startgame.cpp new file mode 100644 index 0000000..65cca1a --- /dev/null +++ b/startgame.cpp @@ -0,0 +1,36 @@ +#include "startgame.h" +#include "ui_startgame.h" +#include "mainwindow.h" +#include "redactor.h" + +StartGame::StartGame(QWidget *parent) : + QWidget(parent), + ui(new Ui::StartGame) +{ + ui->setupUi(this); + loadUI(); +} + +StartGame::~StartGame() +{ + delete ui; +} + +void StartGame::loadUI(){ + ui->play_button->setFont(QFont(kdefaultFontFamily_, kFontSize_)); + ui->redactor_button->setFont(QFont(kdefaultFontFamily_, kFontSize_)); +} + +void StartGame::on_play_button_clicked() +{ + this->close(); + MainWindow *game = new MainWindow(nullptr, nullptr); + game->show(); +} + +void StartGame::on_redactor_button_clicked() +{ + this->close(); + Redactor *game = new Redactor(); + game->show(); +} diff --git a/startgame.h b/startgame.h new file mode 100644 index 0000000..9973c2e --- /dev/null +++ b/startgame.h @@ -0,0 +1,31 @@ +#ifndef STARTGAME_H +#define STARTGAME_H + +#include + +namespace Ui +{ + class StartGame; +} + +class StartGame : public QWidget +{ + Q_OBJECT + +public: + explicit StartGame(QWidget *parent = nullptr); + ~StartGame(); + +private slots: + void on_play_button_clicked(); + void on_redactor_button_clicked(); + +private: + Ui::StartGame *ui; + static const int kFontSize_ = 15; + const QString kdefaultFontFamily_ = "Default"; + + void loadUI(); +}; + +#endif // STARTGAME_H diff --git a/startgame.ui b/startgame.ui new file mode 100644 index 0000000..9d8952b --- /dev/null +++ b/startgame.ui @@ -0,0 +1,69 @@ + + + StartGame + + + + 0 + 0 + 500 + 550 + + + + Pacman + + + + + + + + 0 + 0 + 470 + 370 + + + + + + + 0 + 0 + 500 + 450 + + + + + + 190 + 190 + 75 + 23 + + + + PLAY + + + + + + 180 + 260 + 101 + 21 + + + + REDACTOR + + + + + + + + diff --git a/wall.png b/wall.png new file mode 100644 index 0000000..b7e086d Binary files /dev/null and b/wall.png differ