Skip to content

Commit

Permalink
Add map downloader screen
Browse files Browse the repository at this point in the history
  • Loading branch information
DenisD3D committed Apr 1, 2024
1 parent 0a7cbb6 commit 3de500c
Show file tree
Hide file tree
Showing 10 changed files with 219 additions and 1 deletion.
6 changes: 5 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ find_package(Qt5 COMPONENTS
Gui
Widgets
Xml
Network
REQUIRED)

add_subdirectory(minizip-ng)
Expand All @@ -21,21 +22,24 @@ qt5_add_resources(RESOURCE_ADDED resources.qrc)
add_executable(SnakeQT ${RESOURCE_ADDED}
src/main.cpp
src/jeu.cpp
src/inmemoryzip.cpp
src/map.cpp
src/constants.hpp
src/inmemoryzip.cpp
src/network_manager.cpp
src/screens/snakewindow.cpp
src/screens/mainmenu.hpp
src/screens/gamescreen.cpp
src/screens/editorscreen.cpp
src/screens/snakewindow.cpp
src/screens/gamearea.cpp
src/screens/browsemapscreen.cpp
)

target_link_libraries(SnakeQT
Qt5::Core
Qt5::Gui
Qt5::Widgets
Qt5::Xml
Qt5::Network
minizip
)
Binary file added images/cloud.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions resources.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
<file>images/ground.png</file>
<file>images/wall.png</file>
<file>images/apple.png</file>
<file>images/cloud.png</file>
</qresource>
</RCC>
25 changes: 25 additions & 0 deletions src/network_manager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include "network_manager.hpp"

FileDownloader::FileDownloader(const QUrl &url, QObject *parent) : QObject(parent), m_WebCtrl(this) {
connect(&m_WebCtrl, SIGNAL(finished(QNetworkReply*)), this, SLOT(fileDownloaded(QNetworkReply*)));

const QNetworkRequest request(url);
m_WebCtrl.get(request);
}

FileDownloader::~FileDownloader() {
}

void FileDownloader::fileDownloaded(QNetworkReply *pReply) {
if (pReply->error() != QNetworkReply::NoError) {
qDebug() << "Network error: " << pReply->errorString();
} else {
m_DownloadedData = pReply->readAll();
emit downloaded();
}
pReply->deleteLater();
}

QByteArray FileDownloader::downloadedData() const {
return m_DownloadedData;
}
31 changes: 31 additions & 0 deletions src/network_manager.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#ifndef NETWORK_MANAGER_H
#define NETWORK_MANAGER_H

#include <QObject>
#include <QByteArray>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>

class FileDownloader final : public QObject {
Q_OBJECT

public:
explicit FileDownloader(const QUrl &url, QObject *parent = nullptr);

~FileDownloader() override;

QByteArray downloadedData() const;

signals:
void downloaded();

private slots:
void fileDownloaded(QNetworkReply *pReply);

private:
QNetworkAccessManager m_WebCtrl;
QByteArray m_DownloadedData;
};

#endif // NETWORK_MANAGER_H
94 changes: 94 additions & 0 deletions src/screens/browsemapscreen.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
#include "browsemapscreen.hpp"


/**
* Construct map browser screen.
*/
BrowseMapScreen::BrowseMapScreen(QWidget *parent): QWidget(parent) {
const auto layout = new QVBoxLayout(this);

const auto backButton = new QPushButton("Back", this);
mapList = new QListWidget(this);
loadButton = new QPushButton("Play", this);

layout->addWidget(backButton);
layout->addWidget(mapList);
layout->addWidget(loadButton);

connect(backButton, &QPushButton::clicked, this, &BrowseMapScreen::backClicked);
connect(loadButton, &QPushButton::clicked, this, &BrowseMapScreen::loadClicked);
connect(mapList, &QListWidget::itemSelectionChanged, this, &BrowseMapScreen::mapSelectionChanged);

// Load maps
QDirIterator it("maps", QDir::Files);
QPixmap transparentPixmap(24, 24);
transparentPixmap.fill(Qt::transparent);
const QIcon spacerIcon(transparentPixmap);
while (it.hasNext()) {
it.next();
const auto item = new QListWidgetItem(it.fileName());
item->setIcon(spacerIcon);
item->setData(Qt::UserRole, true);
mapList->addItem(item);
}

loadOnlineMaps();
}

void BrowseMapScreen::loadOnlineMaps() {
downloader = new FileDownloader(QUrl("https://snakeqt.denisd3d.fr/maps"), this);
connect(downloader, &FileDownloader::downloaded, this, &BrowseMapScreen::onlineMapListDownloaded);
}

void BrowseMapScreen::backClicked() {
emit back();
}

void BrowseMapScreen::loadClicked() {
if (mapList->currentItem() != nullptr) {
if (!mapList->currentItem()->data(Qt::UserRole).toBool()) {
auto mapName = mapList->currentItem()->text().replace(".skm", "");
downloader = new FileDownloader(QUrl("https://snakeqt.denisd3d.fr/maps/" + mapName),
this);
connect(downloader, &FileDownloader::downloaded, [this, mapName]() {
QFile file("maps/" + mapName + ".skm");
file.open(QIODevice::WriteOnly);
file.write(downloader->downloadedData());
file.close();
emit load("maps/" + mapName + ".skm");
});
} else {
emit load("maps/" + mapList->currentItem()->text());
}
}
}

void BrowseMapScreen::mapSelectionChanged() {
if (mapList->currentItem() != nullptr) {
loadButton->setText(mapList->currentItem()->data(Qt::UserRole).toBool() ? "Play" : "Download and Play");
}
}

void BrowseMapScreen::onlineMapListDownloaded() {
const QByteArray data = downloader->downloadedData();
const QJsonDocument doc = QJsonDocument::fromJson(data);
const QIcon cloudIcon(":/images/cloud.png");
QJsonArray array = doc.array();
for (const auto &value: array) {
QString mapName = value.toObject().value("id").toString();
bool found = false;
for (int i = 0; i < mapList->count(); i++) {
if (mapList->item(i)->text() == mapName) {
found = true;
break;
}
}

if (!found) {
const auto item = new QListWidgetItem(mapName);
item->setData(Qt::UserRole, false);
item->setIcon(cloudIcon);
mapList->addItem(item);
}
}
}
37 changes: 37 additions & 0 deletions src/screens/browsemapscreen.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#ifndef BROWSEMAPSCREEN_HPP
#define BROWSEMAPSCREEN_HPP

#include <QtCore/QtCore>
#include <QtWidgets/QtWidgets>

#include "../network_manager.hpp"

class BrowseMapScreen final : public QWidget {
Q_OBJECT
QListWidget *mapList;
QPushButton *loadButton;
FileDownloader *downloader;

void loadOnlineMaps();

void updateMapList();

public:
explicit BrowseMapScreen(QWidget *parent = nullptr);

public slots:
void backClicked();

void loadClicked();

void onlineMapListDownloaded();

void mapSelectionChanged();

signals:
void back();

void load(const QString &mapName);
};

#endif //BROWSEMAPSCREEN_HPP
5 changes: 5 additions & 0 deletions src/screens/mainmenu.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,24 @@ class MainMenu final : public QWidget {

const auto startButton = new QPushButton("Start Game", this);
startButton->setDisabled(true);
const auto browseMapButton = new QPushButton("Browse Map", this);
const auto exitButton = new QPushButton("Exit", this);

layout->addWidget(startButton);
layout->addWidget(browseMapButton);
layout->addWidget(exitButton);

connect(startButton, &QPushButton::clicked, this, &MainMenu::startGameClicked);
connect(browseMapButton, &QPushButton::clicked, this, &MainMenu::browseMapClicked);
connect(exitButton, &QPushButton::clicked, this, &MainMenu::exitClicked);
}

signals:
void startGameClicked();

void exitClicked();

void browseMapClicked();
};


Expand Down
17 changes: 17 additions & 0 deletions src/screens/snakewindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ SnakeWindow::SnakeWindow(QWidget *pParent, Qt::WindowFlags flags)
mainMenu = new MainMenu(this);

connect(mainMenu, &MainMenu::startGameClicked, this, &SnakeWindow::handleStartGameClicked);
connect(mainMenu, &MainMenu::browseMapClicked, this, &SnakeWindow::handleBrowseMapClicked);
connect(mainMenu, &MainMenu::exitClicked, this, &SnakeWindow::handleExitClicked);

stackedWidget->addWidget(mainMenu);
Expand Down Expand Up @@ -91,6 +92,22 @@ void SnakeWindow::handleStartGameClicked() {
stackedWidget->setCurrentWidget(gameScreen);
}

void SnakeWindow::handleBrowseMapClicked() {
browseMapScreen = new BrowseMapScreen(this);
stackedWidget->addWidget(browseMapScreen);
stackedWidget->setCurrentWidget(browseMapScreen);

connect(browseMapScreen, &BrowseMapScreen::back, this, [this] {
stackedWidget->setCurrentWidget(mainMenu);
});

connect(browseMapScreen, &BrowseMapScreen::load, this, [this](const QString &fileName) {
gameScreen = new GameScreen(this, fileName);
stackedWidget->addWidget(gameScreen);
stackedWidget->setCurrentWidget(gameScreen);
});
}

void SnakeWindow::handleExitClicked() {
// Exit the application when the "Exit" button is clicked
QApplication::quit();
Expand Down
4 changes: 4 additions & 0 deletions src/screens/snakewindow.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <QtCore/QtCore>
#include <QtWidgets/QtWidgets>

#include "browsemapscreen.hpp"
#include "editorscreen.hpp"
#include "mainmenu.hpp"
#include "gamescreen.hpp"
Expand All @@ -15,6 +16,7 @@ class SnakeWindow final : public QMainWindow {
QStackedWidget *stackedWidget;
MainMenu *mainMenu;
GameScreen *gameScreen{};
BrowseMapScreen *browseMapScreen{};
EditorScreen *editorScreen{};

public:
Expand All @@ -23,6 +25,8 @@ class SnakeWindow final : public QMainWindow {
public slots:
void handleStartGameClicked();

void handleBrowseMapClicked();

static void handleExitClicked();

void toggleFullScreen() {
Expand Down

0 comments on commit 3de500c

Please sign in to comment.