Refactor of the Tile and Map system, add zoom capability

# To do:
- Dasagne
- Better rules
This commit is contained in:
2024-05-23 13:12:39 +02:00
parent 8d71cbe5cf
commit fd169ae769
10 changed files with 127 additions and 74 deletions

View File

@@ -17,8 +17,11 @@ Game::Game(Menu* menu) : menu(menu)
// Set the FocusPolicy to StrongFocus to allow the QGraphicsView to receive key events
this->setFocusPolicy(Qt::StrongFocus);
// Create the Map object
gameMap = new Map(this);
// Create the player object
player = new Player(150, 0, 10, 10, 1, ":/ressources/player.png", 0, 0, gameMap, *this);
player = new Player(150, 0, 10, 10, 1, ":/ressources/player.png", 0, 0, *gameMap, *this);
// Create the text items for the health, gold and wave number
healthDisplay = new QGraphicsTextItem();
@@ -36,10 +39,10 @@ Game::Game(Menu* menu) : menu(menu)
waveDisplay->setDefaultTextColor(Qt::red);
// Add all the items to the scene
gameMap.addItem(healthDisplay);
gameMap.addItem(goldDisplay);
gameMap.addItem(waveDisplay);
gameMap.addItem(player->getGraphics());
gameMap->addItem(healthDisplay);
gameMap->addItem(goldDisplay);
gameMap->addItem(waveDisplay);
gameMap->addItem(player->getGraphics());
// Set the position of the text items
healthDisplay->setPos(0, 0);
@@ -47,7 +50,7 @@ Game::Game(Menu* menu) : menu(menu)
waveDisplay->setPos(0, 40);
// Set the scene of the QGraphicsView to the gameMap
this->setScene(&gameMap);
this->setScene(gameMap);
player->updatePreviousHealth();
}
@@ -58,7 +61,7 @@ void Game::start() {
player->heal(150 - preiousHealth);
// Create the map
gameMap.generateMap(25, 14);
gameMap->generateMap(25, 14, this);
// Set the user gold
userGold = 100;
@@ -67,14 +70,14 @@ void Game::start() {
waveNumber = 1;
// Get the start tile of the map
Tile* startTile = gameMap.getStartTile();
Tile* startTile = gameMap->getStartTile();
// Get start tile coordinates
x = startTile->gridX();
y = startTile->gridY();
// Set the player position to the end tile
Tile* endTile = gameMap.getEndTile();
Tile* endTile = gameMap->getEndTile();
int xEnd = endTile->gridX();
int yEnd = endTile->gridY();
@@ -111,6 +114,12 @@ void Game::keyPressEvent(QKeyEvent *event) {
case Qt::Key_Down:
player->setPosition(player->getX(), player->getY() + 1);
break;
case Qt::Key_Plus:
this->setTransform(this->transform().scale(1.1, 1.1));
break;
case Qt::Key_Minus:
this->setTransform(this->transform().scale(0.9, 0.9));
break;
default:
QGraphicsView::keyPressEvent(event);
}
@@ -141,21 +150,21 @@ void Game::spawnEnemies(int waveNumber) {
int enemyId = 0;
// Get the start tile
Tile* startTile = gameMap.getStartTile();
Tile* startTile = gameMap->getStartTile();
auto* spawnTimer = new QTimer();
connect(spawnTimer, &QTimer::timeout, [this, waveNumber, &enemyId, spawnTimer, startTile](){
if(totalWeight < targetWeight){
for (int i = Enemy::Idris; i >= Enemy::P52; i--) {
Enemy::Type type = static_cast<Enemy::Type>(i);
Enemy enemy(type, gameMap, enemyId, *this);
Enemy enemy(type, *gameMap, enemyId, *this);
if (totalWeight + enemy.getWeight() <= targetWeight) {
totalWeight += enemy.getWeight();
Enemy* newEnemy = new Enemy(type, gameMap, enemyId, *this);
Enemy* newEnemy = new Enemy(type, *gameMap, enemyId, *this);
// Set the enemy position to the start tile
newEnemy->setPosition(startTile->gridX(), startTile->gridY());
currentEnemies.push_back(newEnemy);
gameMap.addItem(currentEnemies.back()->getGraphics());
gameMap->addItem(currentEnemies.back()->getGraphics());
enemyId++;
break;
}
@@ -185,8 +194,8 @@ void Game::removeEnemy(Enemy* enemy) {
delete enemy;
return;
}
if (enemy->getGraphics()->scene() == &gameMap) {
gameMap.removeItem(enemy->getGraphics());
if (enemy->getGraphics()->scene() == gameMap) {
gameMap->removeItem(enemy->getGraphics());
}
auto it = std::find(currentEnemies.begin(), currentEnemies.end(), enemy);
if (it != currentEnemies.end()) {
@@ -202,16 +211,16 @@ void Game::gameOver() {
// Remove all the enemies from the game
while (!currentEnemies.empty()) {
Enemy* enemy = currentEnemies.back();
if (enemy->getGraphics()->scene() == &gameMap) {
gameMap.removeItem(enemy->getGraphics());
if (enemy->getGraphics()->scene() == gameMap) {
gameMap->removeItem(enemy->getGraphics());
}
currentEnemies.pop_back();
delete enemy; // Delete the enemy after it has been removed from currentEnemies
}
// Remove the player from the game
if (player->getGraphics()->scene() == &gameMap) {
gameMap.removeItem(player->getGraphics());
if (player->getGraphics()->scene() == gameMap) {
gameMap->removeItem(player->getGraphics());
}
delete player;
@@ -263,10 +272,11 @@ void Game::gameOver() {
void Game::resetGame() {
// Recreate the player
player = new Player(100, 0, 10, 10, 1, ":/ressources/player.png", 0, 0, gameMap, *this);
gameMap.addItem(player->getGraphics());
player = new Player(100, 0, 10, 10, 1, ":/ressources/player.png", 0, 0, *gameMap, *this);
gameMap->addItem(player->getGraphics());
}
void Game::placeTower(QMouseEvent* event) {
// Check if the click is a left click
if (event->button() != Qt::LeftButton) {
@@ -278,17 +288,17 @@ void Game::placeTower(QMouseEvent* event) {
int gridY = event->pos().y() / 50;
// Check if the Tile is a other tile
if (gameMap.getTile(gridX, gridY)->getType() == Tile::Other) {
if (gameMap->getTile(gridX, gridY)->getType() == Tile::Other) {
placeTower(gridX, gridY, event);
}
else if(gameMap.getTile(gridX, gridY)->getType() == Tile::Tower) {
else if(gameMap->getTile(gridX, gridY)->getType() == Tile::Tower) {
for (auto* tower : towers) {
if (tower->getGraphics()->pos() == QPointF(gridX * 50, gridY * 50)) {
upgradeTower(tower, event);
}
}
}
for (auto& tileList : gameMap.getTiles()) {
for (auto& tileList : gameMap->getTiles()) {
for (auto* tile : tileList) {
if (tile->gridX() == gridX && tile->gridY() == gridY && tile->getType() == Tile::Other) {
tile->setType(Tile::Tower);
@@ -346,7 +356,7 @@ void Game::upgradeTower(Tower* tower, QMouseEvent* event) {
}
void Game::placeTower(int gridX, int gridY, QMouseEvent* event) {
if (gridX < 0 || gridX >= gameMap.getWidth() || gridY < 0 || gridY >= gameMap.getHeight()) {
if (gridX < 0 || gridX >= gameMap->getWidth() || gridY < 0 || gridY >= gameMap->getHeight()) {
return;
}
// Clear the previous actions
@@ -386,7 +396,6 @@ void Game::placeTower(int gridX, int gridY, QMouseEvent* event) {
if (towerMenu.isEmpty()) {
qDebug() << "towerMenu is not valid";
} else {
qDebug() << "towerMenu is valid";
}
// Check the validity of each QAction
@@ -396,9 +405,6 @@ void Game::placeTower(int gridX, int gridY, QMouseEvent* event) {
}
}
// Print out the QPoint object
qDebug() << "QPoint: " << point;
// Call exec()
QAction* selectedAction = towerMenu.exec(point);
@@ -410,32 +416,28 @@ void Game::placeTower(int gridX, int gridY, QMouseEvent* event) {
// Create the selected tower and add it to the list of towers
if (selectedAction == laserTower && userGold >= 50) {
userGold -= 50;
Tile* tile = gameMap.getTile(gridX, gridY);
Tile* tile = gameMap->getTile(gridX, gridY);
tile->setType(Tile::Tower);
auto* tower = new LaserTower(QPointF(gridX, gridY), *this);
towers.push_back(tower);
gameMap.addItem(tower->getGraphics());
gameMap->addItem(tower->getGraphics());
} else if (selectedAction == balisticTower && userGold >= 100) {
userGold -= 100;
Tile* tile = gameMap.getTile(gridX, gridY);
Tile* tile = gameMap->getTile(gridX, gridY);
tile->setType(Tile::Tower);
auto* tower = new BalisticTower(QPointF(gridX, gridY), *this);
towers.push_back(tower);
gameMap.addItem(tower->getGraphics());
gameMap->addItem(tower->getGraphics());
} else if (selectedAction == distorsionTower && userGold >= 75) {
userGold -= 75;
Tile* tile = gameMap.getTile(gridX, gridY);
Tile* tile = gameMap->getTile(gridX, gridY);
tile->setType(Tile::Tower);
auto* tower = new DistorionTower(QPointF(gridX, gridY), *this);
towers.push_back(tower);
gameMap.addItem(tower->getGraphics());
gameMap->addItem(tower->getGraphics());
}
}
void Game::mousePressEvent(QMouseEvent* event) {
placeTower(event);
}
void Game::endRound() {
if(player->getHealth() == player->getPreviousHealth()) {
player->heal(5);
@@ -445,15 +447,40 @@ void Game::endRound() {
void Game::clearTowers() {
for (auto* tower : towers) {
if (tower->getGraphics() != nullptr && tower->getGraphics()->scene() == &gameMap) {
gameMap.removeItem(tower->getGraphics());
if (tower->getGraphics() != nullptr && tower->getGraphics()->scene() == gameMap) {
gameMap->removeItem(tower->getGraphics());
}
// Remove the rangeIndicator from the scene
if (tower->getRangeIndicator() != nullptr && tower->getRangeIndicator()->scene() == &gameMap) {
gameMap.removeItem(tower->getRangeIndicator());
if (tower->getRangeIndicator() != nullptr && tower->getRangeIndicator()->scene() == gameMap) {
gameMap->removeItem(tower->getRangeIndicator());
}
delete tower;
}
// Clear the list of towers after deleting them
towers.clear();
}
void Game::handleTileClick(int gridX, int gridY, QMouseEvent* event) {
Tile* tile = gameMap->getTile(gridX, gridY);
if(tile->getType() == Tile::Other) {
placeTower(gridX, gridY, event);
}
else if(tile->getType() == Tile::Tower) {
for (auto* tower : towers) {
if (tower->getGraphics()->pos() == QPointF(gridX * 50, gridY * 50)) {
upgradeTower(tower, event);
}
}
}
}
void Game::wheelEvent(QWheelEvent* event) {
// Check if the wheel event is a zoom in or zoom out
if(event->angleDelta().y() > 0) {
// Zoom in
this->setTransform(this->transform().scale(1.1, 1.1));
} else {
// Zoom out
this->setTransform(this->transform().scale(0.9, 0.9));
}
}

View File

@@ -29,13 +29,15 @@ class Menu;
class Tower;
class Map;
class Game : public QGraphicsView
{
Q_OBJECT
public:
Game(Menu* menu);
void start();
Map gameMap;
Map* gameMap;
void updateDisplay() const;
void spawnEnemies(int waveNumber);
int userGold;
@@ -50,6 +52,7 @@ public:
void clearTowers();
void upgradeTower(Tower* tower, QMouseEvent* event);
void placeTower(int gridX, int gridY, QMouseEvent* event);
void handleTileClick(int gridX, int gridY, QMouseEvent* event);
private:
QTimer gameTimer;
@@ -69,7 +72,7 @@ private:
protected:
void keyPressEvent(QKeyEvent* event) override;
void mousePressEvent(QMouseEvent* event) override;
void wheelEvent(QWheelEvent* event) override;
};

View File

@@ -34,11 +34,12 @@ Leaderboard::Leaderboard(QWidget *parent) : QGraphicsScene(parent) {
"color: #9EB1BD;" // Couleur du texte des en-têtes
"border: 1px solid #0A5688;" // Couleur des bordures des en-têtes
"}");
leaderboardTable->setFixedWidth(730);
leaderboardTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
// Access the corner widget
QWidget* cornerWidget = leaderboardTable->findChild<QWidget*>("qt_scrollarea_corner");
if (cornerWidget) {
// Apply the stylesheet to the corner widget
cornerWidget->setStyleSheet("background-color: #071A22;"); // Set the color to match your table's background color
cornerWidget->setStyleSheet("background-color: #071A22;");
}
QGraphicsProxyWidget* proxy = this->addWidget(leaderboardTable);
proxy->setPos(0, leaderboardLabel->boundingRect().height() + 50);

View File

@@ -11,6 +11,7 @@
#include <QGraphicsProxyWidget>
#include <QTableView>
#include <QtSql/QSqlTableModel>
#include <QHeaderView>
class Leaderboard : public QGraphicsScene
{

View File

@@ -6,7 +6,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
Menu* menu = new Menu(this);
this->setCentralWidget(menu);
this->setWindowTitle("Poulpes de l'espace: La dernière ligne de défense");
this->setFixedSize(1320, 760);
//this->setFixedSize(1320, 760);
helpMenu = menuBar()->addMenu(tr("&Help"));
QAction* actionHelp = new QAction(tr("&About"), this);

View File

@@ -8,7 +8,7 @@
Map::Map(QObject *parent) : QGraphicsScene(parent) {
}
void Map::generateMap(const int width, const int height) {
void Map::generateMap(const int width, const int height, Game* game) {
tiles = QVector<QVector<Tile*>>(height, QVector<Tile*>(width));
int x = 0, y = height - 1;
// Length of the path
@@ -20,10 +20,12 @@ void Map::generateMap(const int width, const int height) {
// Create a new Start tile
Tile* startTile = new Tile(Tile::Start);
startTile->setRect(x * 50, y * 50, 50, 50);
startTile->getGraphics()->setPos(x * 50, y * 50);
startTile->setGeometry(x * 50, y * 50, 50, 50);
tiles[y][x] = startTile;
addItem(startTile->getGraphics());
auto* startProxy = new QGraphicsProxyWidget();
startProxy->setContentsMargins(0, 0, 0, 0);
startProxy->setWidget(startTile);
addItem(startProxy);
length++;
while (length < pathLength){
@@ -43,29 +45,36 @@ void Map::generateMap(const int width, const int height) {
// Create a new Road tile
Tile* tile = new Tile(Tile::Road);
tile->setRect(x * 50, y * 50, 50, 50);
tile->getGraphics()->setPos(x * 50, y * 50);
tile->setGeometry(x * 50, y * 50, 50, 50);
tiles[y][x] = tile;
addItem(tile->getGraphics());
auto* roadProxy = new QGraphicsProxyWidget();
roadProxy->setContentsMargins(0, 0, 0, 0);
roadProxy->setWidget(tile);
addItem(roadProxy);
length++;
}
// Create a new End tile
Tile* endTile = new Tile(Tile::End);
endTile->setRect(x * 50, y * 50, 50, 50);
endTile->getGraphics()->setPos(x * 50, y * 50);
endTile->setGeometry(x * 50, y * 50, 50, 50);
tiles[y][x] = endTile;
addItem(endTile->getGraphics());
auto* endProxy = new QGraphicsProxyWidget();
endProxy->setContentsMargins(0, 0, 0, 0);
endProxy->setWidget(endTile);
addItem(endProxy);
// Fill the rest of the map with Other tiles
for (int i = 0; i < height; i++){
for (int j = 0; j < width; j++){
if (tiles[i][j] == nullptr){
Tile* tile = new Tile(Tile::Other);
tile->setRect(j * 50, i * 50, 50, 50);
tile->getGraphics()->setPos(j * 50, i * 50);
connect(tile, &Tile::tileClicked, game, &Game::handleTileClick);
tile->setGeometry(j * 50, i * 50, 50, 50);
tiles[i][j] = tile;
addItem(tile->getGraphics());
auto* proxy = new QGraphicsProxyWidget();
proxy->setContentsMargins(0, 0, 0, 0);
proxy->setWidget(tile);
addItem(proxy);
}
}
}

View File

@@ -5,13 +5,17 @@
#ifndef POULPES_DE_L_ESPACE_LA_DERNIERE_LIGNE_DE_DEFENSE_MAP_H
#define POULPES_DE_L_ESPACE_LA_DERNIERE_LIGNE_DE_DEFENSE_MAP_H
#include "Tile.h"
#include "Game.h"
#include <QGraphicsScene>
#include <QGraphicsProxyWidget>
class Game;
class Map : public QGraphicsScene
{
public:
Map(QObject* parent = nullptr);
void generateMap(int width, int height);
void generateMap(int width, int height, Game* game);
Tile* getEndTile();
Tile* getStartTile();
QGraphicsScene scene;

View File

@@ -62,7 +62,7 @@ void Menu::onPlayButtonClicked() {
game->start();
// Show the game
view->setScene(&game->gameMap);
view->setScene(game->gameMap);
view->setFocus(); // Set focus to the QGraphicsView
// Get a pointer to the MainWindow

View File

@@ -4,7 +4,7 @@
#include "Tile.h"
Tile::Tile(Tile::Type type, QGraphicsItem *parent) : QGraphicsRectItem(parent), type(type) {
Tile::Tile(Tile::Type type, QWidget *parent) : QPushButton(parent), type(type) {
setType(type);
}
@@ -16,11 +16,11 @@ Tile::Type Tile::getType() const {
}
int Tile::gridX() {
return rect().x() / 50;
return x() / 50;
}
int Tile::gridY() {
return rect().y() / 50;
return y() / 50;
}
bool Tile::isPath() {
@@ -53,14 +53,17 @@ void Tile::setType(Tile::Type type) {
if (pixmap.isNull()) {
return;
} else {
graphics = new QGraphicsPixmapItem();
QPixmap scaledPixmap = pixmap.scaled(50, 50, Qt::KeepAspectRatio, Qt::SmoothTransformation); // Scale the pixmap to 50x50 pixels
graphics->setPixmap(scaledPixmap);
graphics->setPos(x() * 50, y() * 50);
graphics->setZValue(1);
QIcon ButtonIcon(pixmap);
this->setIcon(ButtonIcon);
this->setIconSize(QSize(50, 50));
this->setStyleSheet("padding: 0px; border: 0px;");
}
}
QGraphicsPixmapItem* Tile::getGraphics() const {
return graphics;
}
void Tile::mousePressEvent(QMouseEvent* event) {
emit tileClicked(gridX(), gridY(), event);
}

View File

@@ -4,26 +4,31 @@
#ifndef POULPES_DE_L_ESPACE_LA_DERNIERE_LIGNE_DE_DEFENSE_TILE_H
#define POULPES_DE_L_ESPACE_LA_DERNIERE_LIGNE_DE_DEFENSE_TILE_H
#include <QGraphicsRectItem>
#include <QPushButton>
#include <QBrush>
#include <QGraphicsPixmapItem>
#include <QPixmap>
class Tile : public QGraphicsRectItem
class Tile : public QPushButton
{
Q_OBJECT
public:
enum Type { Road, Start, End, Tower, Other, Null };
Tile(Type type, QGraphicsItem* parent = nullptr);
Tile(Type type, QWidget* parent = nullptr);
Type getType() const;
int gridX();
int gridY();
bool isPath();
void setType(Type type);
QGraphicsPixmapItem* getGraphics() const;
void mousePressEvent(QMouseEvent* event) override;
private:
Type type;
QGraphicsPixmapItem* graphics;
signals:
void tileClicked(int gridX, int gridY, QMouseEvent* event);
};