Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 36 additions & 24 deletions Pacman.pro
Original file line number Diff line number Diff line change
@@ -1,24 +1,36 @@
QT += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++17

# 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 += \
main.cpp \
mainwindow.cpp

HEADERS += \
mainwindow.h

FORMS += \
mainwindow.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
QT += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++17

# 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 += \
dragitem.cpp \
itemsfactory.cpp \
itemswidget.cpp \
main.cpp \
mainwindow.cpp \
pacmangame.cpp \
pacmanitem.cpp \
scene.cpp

HEADERS += \
dragitem.h \
itemsfactory.h \
itemswidget.h \
mainwindow.h \
pacmangame.h \
pacmanitem.h \
scene.h

FORMS += \
mainwindow.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
52 changes: 26 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
# Игра Pac-Man
## Pac-Man
- Сделать реализацию движения (4 стороны) на кнопки. При нажатии меняется только направление. Пакман движется сам.
- Пакман может быть абсолютно любой формы, кроме прямоугольника и квадрата, главное правильно переопределить `boundingRect` и `shape` для сложных фигур
## Сцена
- Перед началом игры должна быть возможность создать уровень самому, перетащив все стены, монетки и пакмана с помощью drag and drop механизма.
- Пакман должен быть только один, тогда как монеток и стен можно разместить сколько угодно или какое-то заданное число, не меньше 10.
## Стены
- Стены могут быть просто прямоугольниками, которые можно вращать на сцене, чтобы создавать вертикальные и горизонтальные
## Монетки
- При соприкосновении с пакманом монетка исчезает со сцены
- Форма – любая отличная от прямоугольника и квадрата.
## Минимальный интерфейс
- Представление графической сцены (`QGraphicsView`)
- Набор фигур для Drag and Drop
- Кнопка “Начать игру”
- Кнопка “Стоп”
- Меню “Справка” с описанием горячих клавиш и особыми правилами (если такие имеются).
- Счетчик собранных момент
## Геймплей
- Если пакман сталкивается со стеной, то до момента пока он не отойдет от нее, его цвет должен меняться на другой.
- Монетки при сборе должны исчезать со сцены и добавляться в счетчик.
- Игра оканчивается при сборе всех монеток или по кнопке “Стоп”.
- Если собраны все монетки, выводится поздравительное сообщение.
- Когда игра началась, нельзя добавить новые фигуры или менять положение текущих (кроме перемещения самого пакмана).
- Все столкновения на сцене обрабатываются с помощью методов `QGraphicsScene::collidingItems`, `QGraphicsItem::collidingItems` и т.д.
# Игра Pac-Man
## Pac-Man
- Сделать реализацию движения (4 стороны) на кнопки. При нажатии меняется только направление. Пакман движется сам.
- Пакман может быть абсолютно любой формы, кроме прямоугольника и квадрата, главное правильно переопределить `boundingRect` и `shape` для сложных фигур
## Сцена
- Перед началом игры должна быть возможность создать уровень самому, перетащив все стены, монетки и пакмана с помощью drag and drop механизма.
- Пакман должен быть только один, тогда как монеток и стен можно разместить сколько угодно или какое-то заданное число, не меньше 10.
## Стены
- Стены могут быть просто прямоугольниками, которые можно вращать на сцене, чтобы создавать вертикальные и горизонтальные
## Монетки
- При соприкосновении с пакманом монетка исчезает со сцены
- Форма – любая отличная от прямоугольника и квадрата.
## Минимальный интерфейс
- Представление графической сцены (`QGraphicsView`)
- Набор фигур для Drag and Drop
- Кнопка “Начать игру”
- Кнопка “Стоп”
- Меню “Справка” с описанием горячих клавиш и особыми правилами (если такие имеются).
- Счетчик собранных момент
## Геймплей
- Если пакман сталкивается со стеной, то до момента пока он не отойдет от нее, его цвет должен меняться на другой.
- Монетки при сборе должны исчезать со сцены и добавляться в счетчик.
- Игра оканчивается при сборе всех монеток или по кнопке “Стоп”.
- Если собраны все монетки, выводится поздравительное сообщение.
- Когда игра началась, нельзя добавить новые фигуры или менять положение текущих (кроме перемещения самого пакмана).
- Все столкновения на сцене обрабатываются с помощью методов `QGraphicsScene::collidingItems`, `QGraphicsItem::collidingItems` и т.д.
31 changes: 31 additions & 0 deletions dragitem.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include "dragitem.h"

#include <QPainter>
#include <QRect>

DragItem::DragItem(ItemsFactory::ItemsType type, QWidget *parent)
: QWidget{parent}, QListWidgetItem() {
graphicsItem_ = ItemsFactory::Create(type);
type_ = type;

QRect geometry = graphicsItem_->boundingRect().toRect();
setGeometry(geometry);

int additionalHeight = 20;
setSizeHint(QSize(geometry.width(), geometry.height() + additionalHeight));
}

void DragItem::paintEvent(QPaintEvent *event) {
Q_UNUSED(event)

QPainter painter(this);
painter.setPen(graphicsItem_->pen());
painter.setBrush(graphicsItem_->brush());

QStyleOptionGraphicsItem itemOption;
graphicsItem_->paint(&painter, &itemOption, nullptr);
}

PacmanItem *DragItem::GetGraphicsItem() const { return graphicsItem_; }

ItemsFactory::ItemsType DragItem::GetType() const { return type_; }
30 changes: 30 additions & 0 deletions dragitem.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#ifndef DRAGITEM_H
#define DRAGITEM_H

#include <itemsfactory.h>

#include <QGraphicsItem>
#include <QListWidget>
#include <QWidget>

class DragItem : public QWidget, public QListWidgetItem {
Q_OBJECT
public:
explicit DragItem(ItemsFactory::ItemsType type, QWidget *parent = nullptr);

protected:
void paintEvent(QPaintEvent *event);

public:
PacmanItem *GetGraphicsItem() const;
ItemsFactory::ItemsType GetType() const;

public:
static const inline QString kMimeFormat = "application/x-dnditemdata";

private:
PacmanItem *graphicsItem_;
ItemsFactory::ItemsType type_;
};

#endif // DRAGITEM_H
48 changes: 48 additions & 0 deletions itemsfactory.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#include "itemsfactory.h"

ItemsFactory::ItemsFactory() {}

// Крайне примитивная реализация фабричного метода для выделения одного места,
// ответственного за создание фигур
PacmanItem *ItemsFactory::Create(ItemsType type) {
QPainterPath figurePath;

QPen pen(Qt::black, 1);
QBrush brush(GetColorByItemType(type), Qt::SolidPattern);


switch (type) {
case ItemsType::kWall:
figurePath.addRect(0, 0, 70, 20);
break;

case ItemsType::kCoin:
figurePath.addEllipse(0, 0, 20, 20);
break;

case ItemsType::kPlayer:
figurePath.addEllipse(0, 0, 40, 40);
break;

default:
figurePath.addRect(0, 0, 70, 20);
}

return new PacmanItem(figurePath, pen, brush);
}

QColor ItemsFactory::GetColorByItemType(ItemsType type) {
switch (type) {
case ItemsType::kWall:
return Qt::gray;

case ItemsType::kPlayer:
return Qt::red;

case ItemsType::kCoin:
return Qt::yellow;

default:
return Qt::black;
}
}
24 changes: 24 additions & 0 deletions itemsfactory.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#ifndef ITEMSFACTORY_H
#define ITEMSFACTORY_H

#include <QObject>
#include <QRectF>
#include <QPainter>

#include "pacmanitem.h"

class ItemsFactory : public QObject {
public:
enum ItemsType { kWall = 0, kPlayer = 1, kCoin = 2 };
Q_ENUM(ItemsType)

private:
ItemsFactory();

public:
static PacmanItem* Create(ItemsType type);
static QColor GetColorByItemType(ItemsType type);
};


#endif // ITEMSFACTORY_H
57 changes: 57 additions & 0 deletions itemswidget.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#include "itemswidget.h"

#include <QByteArray>
#include <QDataStream>
#include <QDrag>
#include <QMimeData>
#include <QMouseEvent>
#include <QPainter>

ItemsWidget::ItemsWidget(QWidget *parent) : QListWidget(parent) {
setSelectionMode(SingleSelection);
setDragEnabled(true);
}

void ItemsWidget::mousePressEvent(QMouseEvent *event) {
dragStartPosition_ = event->pos();
dragableItem_ = dynamic_cast<DragItem *>(itemAt(dragStartPosition_));

QListWidget::mousePressEvent(event);
}

void ItemsWidget::mouseMoveEvent(QMouseEvent *event) {
if ((event->buttons() == Qt::LeftButton) == false ||
dragableItem_ == nullptr) {
return;
}

// Записываем в mime тип (спец. тип для переноса данных)
// необходимую для нас информацию - тип фигуры
QByteArray itemData;
QDataStream dataStream(&itemData, QIODevice::WriteOnly);
dataStream << dragableItem_->GetType();

QMimeData *mimeData = new QMimeData;
mimeData->setData(dragableItem_->kMimeFormat, itemData);

QDrag *drag = new QDrag(this);
drag->setMimeData(mimeData);
drag->setPixmap(GetPreview());

drag->exec(Qt::CopyAction | Qt::MoveAction);
}

// Отрисовываем перетаскиваемый предмет рядом с мышкой
QPixmap ItemsWidget::GetPreview() const {
auto *item = dragableItem_->GetGraphicsItem();

QPixmap pixmap(item->boundingRect().size().toSize());
pixmap.fill(Qt::transparent);

QPainter painter(&pixmap);
painter.setPen(item->pen());
painter.setBrush(item->brush());
painter.drawPath(item->shape());

return pixmap;
}
25 changes: 25 additions & 0 deletions itemswidget.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#ifndef ITEMSWIDGET_H
#define ITEMSWIDGET_H

#include <dragitem.h>

#include <QListWidget>

class ItemsWidget : public QListWidget {
Q_OBJECT
public:
explicit ItemsWidget(QWidget *parent = nullptr);

protected:
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);

private:
QPixmap GetPreview() const;

private:
QPoint dragStartPosition_;
DragItem *dragableItem_;
};

#endif // ITEMSWIDGET_H
22 changes: 11 additions & 11 deletions main.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
Loading