Upgrade of the tower done, add visual projectile shoot by tower

# To do:
- Dasagne
- Easter egg
- I'm a teapot
This commit is contained in:
2024-05-02 10:40:18 +02:00
parent dbb88d99c7
commit ecf144d78c
11 changed files with 241 additions and 34 deletions

View File

@@ -35,6 +35,8 @@ add_executable(Poulpes_de_l_espace_La_derniere_ligne_de_defense ${sourceCode}
src/Tower.cpp
src/Tower.h
src/PlayerDeadException.cpp
src/PlayerDeadException.h)
src/PlayerDeadException.h
src/Projectile.cpp
src/Projectile.h)
target_link_libraries(Poulpes_de_l_espace_La_derniere_ligne_de_defense PRIVATE Qt6::Widgets Qt6::Sql)

View File

@@ -176,4 +176,11 @@ void Enemy::setPosition(int x, int y) {
this->x = x;
this->y = y;
graphics->setPos(x * 50, y * 50);
}
QPointF Enemy::getPosition() {
if(this == nullptr) {
return QPointF(0, 0);
}
return QPointF(x, y);
}

View File

@@ -6,6 +6,7 @@
#define POULPES_DE_L_ESPACE_LA_DERNIERE_LIGNE_DE_DEFENSE_ENEMY_H
#include <QGraphicsPixmapItem>
#include <QTimer>
#include <QPointF>
#include "Mob.h"
#include "Map.h"
#include "Game.h"
@@ -33,6 +34,7 @@ public:
void initializeEnemy(int health, int shield, int damage, int regenerationRate, int speed, std::string avatarPath,
int x, int y, int coinDrop, int weight, int id);
void setPosition(int x, int y);
QPointF getPosition();
private slots:
void onMoveTimerTimeout();

View File

@@ -5,7 +5,6 @@
#include "Game.h"
#include "Player.h"
#include <QGraphicsView>
#include <iostream>
#include <QDebug>
Game::Game(Menu* menu) : menu(menu)
@@ -279,19 +278,113 @@ 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) {
for (auto* tower : towers) {
if (tower->getGraphics()->pos() == QPointF(gridX * 50, gridY * 50)) {
upgradeTower(tower, event);
}
}
}
for (auto& tileList : gameMap.getTiles()) {
for (auto* tile : tileList) {
if (tile->gridX() == gridX && tile->gridY() == gridY && tile->getType() == Tile::Other) {
tile->setType(Tile::Tower);
}
}
}
}
void Game::upgradeTower(Tower* tower, QMouseEvent* event) {
// Create a menu to upgrade the tower
QMenu upgradeMenu;
// Check if the user has enough gold to upgrade the tower
if(userGold < 50) {
QAction* notEnoughGold = upgradeMenu.addAction("Not enough gold to upgrade");
QAction* selectedAction = upgradeMenu.exec(event->globalPosition().toPoint());
}
else {
if(tower->getDamageUpgrades() == 5 && tower->getFireRateUpgrades() == 5) {
QAction* maxUpgrades = upgradeMenu.addAction("Tower is fully upgraded");
QAction* selectedAction = upgradeMenu.exec(event->globalPosition().toPoint());
}
else if(tower->getDamageUpgrades() == 5){
QAction* upgradeFireRate = upgradeMenu.addAction("Upgrade Fire Rate - 50 gold");
QAction* selectedAction = upgradeMenu.exec(event->globalPosition().toPoint());
if(selectedAction == upgradeFireRate) {
userGold -= 50;
tower->upgradeFireRate();
}
}
else if(tower->getFireRateUpgrades() == 5){
QAction* upgradeDamage = upgradeMenu.addAction("Upgrade Damage - 50 gold");
QAction* selectedAction = upgradeMenu.exec(event->globalPosition().toPoint());
if(selectedAction == upgradeDamage) {
userGold -= 50;
tower->upgradeDamage();
}
}
else{
QAction* upgradeDamage = upgradeMenu.addAction("Upgrade Damage - 50 gold");
QAction* upgradeFireRate = upgradeMenu.addAction("Upgrade Fire Rate - 50 gold");
// Display the menu and wait for the user to select an action
QAction* selectedAction = upgradeMenu.exec(event->globalPosition().toPoint());
// Perform the selected upgrade
if (selectedAction == upgradeDamage && userGold >= 50) {
userGold -= 50;
tower->upgradeDamage();
} else if (selectedAction == upgradeFireRate && userGold >= 50) {
userGold -= 50;
tower->upgradeFireRate();
}
}
}
}
void Game::placeTower(int gridX, int gridY, QMouseEvent* event) {
// Clear the previous actions
towerMenu.clear();
QAction* laserTower = nullptr;
QAction* balisticTower = nullptr;
QAction* distorsionTower = nullptr;
if(userGold < 50) {
QAction* notEnoughGold = towerMenu.addAction("Not enough gold to place a tower");
QAction* selectedAction = towerMenu.exec(event->globalPosition().toPoint());
return;
}
else if(userGold < 75){
laserTower = towerMenu.addAction("Laser Tower - 50 gold");
balisticTower = towerMenu.addAction("Balistic Tower - 100 gold Not enough gold");
distorsionTower = towerMenu.addAction("Distorsion Tower - 75 gold Not enough gold");
}
else if(userGold < 100){
laserTower = towerMenu.addAction("Laser Tower - 50 gold");
balisticTower = towerMenu.addAction("Balistic Tower - 100 gold Not enough gold");
distorsionTower = towerMenu.addAction("Distorsion Tower - 75 gold");
}
else {
laserTower = towerMenu.addAction("Laser Tower - 50 gold");
balisticTower = towerMenu.addAction("Balistic Tower - 100 gold");
distorsionTower = towerMenu.addAction("Distorsion Tower - 75 gold");
}
// Display the menu and wait for the user to select an action
if(event == nullptr || towerMenu.actions().isEmpty()) {
return;
}
// Create a menu to select the tower type
QMenu towerMenu;
QAction* laserTower = towerMenu.addAction("Laser Tower - 50 gold");
QAction* balisticTower = towerMenu.addAction("Balistic Tower - 100 gold");
QAction* distorsionTower = towerMenu.addAction("Distorsion Tower - 75 gold");
// Display the menu and wait for the user to select an action
QAction* selectedAction = towerMenu.exec(event->globalPosition().toPoint());
// Check if selectedAction is nullptr before using it
if (selectedAction == nullptr) {
return;
}
// Create the selected tower and add it to the list of towers
if (selectedAction == laserTower && userGold >= 50) {
userGold -= 50;
@@ -335,5 +428,6 @@ void Game::clearTowers() {
}
delete tower;
}
towers.clear(); // Clear the list of towers after deleting them
// Clear the list of towers after deleting them
towers.clear();
}

View File

@@ -12,6 +12,7 @@
#include <QVector>
#include <QSqlQuery>
#include <QProcessEnvironment>
#include <QMenu>
#include "Map.h"
#include "Player.h"
#include "Enemy.h"
@@ -46,6 +47,8 @@ public:
void placeTower(QMouseEvent* event);
void endRound() const;
void clearTowers();
void upgradeTower(Tower* tower, QMouseEvent* event);
void placeTower(int gridX, int gridY, QMouseEvent* event);
private:
QTimer gameTimer;
@@ -61,6 +64,7 @@ private:
Menu* menu;
QVector<Tower*> towers;
bool isWaveSpawning;
QMenu towerMenu;
protected:
void keyPressEvent(QKeyEvent* event) override;

View File

@@ -109,4 +109,8 @@ Tile* Map::getTile(int x, int y) {
return tiles[y][x];
}
return nullptr;
}
QVector<QVector<Tile*>> Map::getTiles() {
return tiles;
}

View File

@@ -18,6 +18,7 @@ public:
int getWidth();
int getHeight();
Tile* getTile(int x, int y);
QVector<QVector<Tile*>> getTiles();
private:
QVector<QVector<Tile*>> tiles;

45
src/Projectile.cpp Normal file
View File

@@ -0,0 +1,45 @@
//
// Created by breizhhardware on 02/05/24.
//
#include "Projectile.h"
Projectile::Projectile(QPointF start, QPointF end) : start(start * 50), end(end * 50) {
setRect(0, 0, 5, 5);
setBrush(Qt::red);
setPos(start *50 );
setZValue(3);
// Create a timer to move the projectile every 50ms
QTimer* timer = new QTimer();
connect(timer, &QTimer::timeout, this, &Projectile::move);
timer->start(50);
}
void Projectile::move() {
// Check if the projectile has reached an enemy
QList<QGraphicsItem *> colliding_items = collidingItems();
for (int i = 0, n = colliding_items.size(); i < n; ++i) {
Enemy *enemy = dynamic_cast<Enemy *>(colliding_items[i]);
if (enemy) {
// Update the end position to the current position of the enemy
end = enemy->getPosition() * 50;
// Remove the projectile
scene()->removeItem(this);
delete this;
return;
}
}
// Move the projectile towards the end point
QLineF line(pos(), end);
if (line.length() > 5) {
line.setLength(line.length() - 5);
setPos(line.p2());
} else {
// If the projectile has reached the end point, delete it
scene()->removeItem(this);
delete this;
}
}

29
src/Projectile.h Normal file
View File

@@ -0,0 +1,29 @@
//
// Created by breizhhardware on 02/05/24.
//
#ifndef POULPES_DE_L_ESPACE_LA_DERNIERE_LIGNE_DE_DEFENSE_PROJECTILE_H
#define POULPES_DE_L_ESPACE_LA_DERNIERE_LIGNE_DE_DEFENSE_PROJECTILE_H
#include <QGraphicsRectItem>
#include <QTimer>
#include <QGraphicsScene>
#include <QLineF>
#include <QObject>
#include "Enemy.h"
class Projectile : public QObject, public QGraphicsRectItem
{
Q_OBJECT
public:
Projectile(QPointF start, QPointF end);
public slots:
void move();
private:
QPointF start;
QPointF end;
};
#endif //POULPES_DE_L_ESPACE_LA_DERNIERE_LIGNE_DE_DEFENSE_PROJECTILE_H

View File

@@ -6,7 +6,7 @@
#include "Tower.h"
Tower::Tower(int damage, int fireRate, int range, int level, int cost, QPointF position,
Tower::Tower(int damage, double fireRate, int range, int level, int cost, QPointF position,
std::string avatarPath, Game& game) : game(game) {
this->damage = damage;
this->fireRate = fireRate;
@@ -51,9 +51,35 @@ void Tower::fire() {
return;
}
Enemy* target = getClosestEnemyInRange(enemies);
qDebug() << "Firing at enemy";
qDebug() << "Target: " << target;
auto* projectile = new Projectile(position, target->getPosition());
qDebug() << "Projectile created";
game.scene()->addItem(projectile);
fireAtClosest(target);
}
void Tower::upgradeDamage(){
if(damageUpgrades < 5){
damage *= 1.25;
damageUpgrades++;
}
else{
return;
}
}
void Tower::upgradeFireRate() {
if(fireRateUpgrades < 5){
fireRate *= 0.9;
fireTimer->setInterval(fireRate * 1000);
fireRateUpgrades++;
}
else{
return;
}
}
LaserTower::LaserTower(QPointF position, Game& game) : Tower(50, 1, 10, 1, 50, position,
"../ressources/Laser_Tower.png", game) {
QPixmap pixmap(QString::fromStdString(avatarPath));
@@ -75,12 +101,6 @@ QGraphicsPixmapItem* Tower::getGraphics() {
return graphics;
}
void LaserTower::upgrade() {
damage += 5;
level += 1;
cost += 50;
}
BalisticTower::BalisticTower(QPointF position, Game& game) : Tower(150, 2, 6, 1, 100, position,
"../ressources/Balistic_Tower.png", game) {
QPixmap pixmap(QString::fromStdString(avatarPath));
@@ -98,12 +118,6 @@ BalisticTower::BalisticTower(QPointF position, Game& game) : Tower(150, 2, 6, 1,
}
}
void BalisticTower::upgrade() {
damage += 10;
level += 1;
cost += 100;
}
DistorionTower::DistorionTower(QPointF position, Game& game) : Tower(100, 1, 7, 1, 75, position,
"../ressources/Distortion_Tower.png", game) {
QPixmap pixmap(QString::fromStdString(avatarPath));
@@ -121,8 +135,10 @@ DistorionTower::DistorionTower(QPointF position, Game& game) : Tower(100, 1, 7,
}
}
void DistorionTower::upgrade() {
damage += 5;
level += 1;
cost += 75;
int Tower::getDamageUpgrades() const {
return damageUpgrades;
}
int Tower::getFireRateUpgrades() const {
return fireRateUpgrades;
}

View File

@@ -11,6 +11,7 @@
#include <QTimer>
#include "Enemy.h"
#include "Game.h"
#include "Projectile.h"
class Enemy;
@@ -21,7 +22,7 @@ class Tower : public QObject
QOBJECT_H
protected:
int damage;
int fireRate;
double fireRate;
int range;
int level;
int cost;
@@ -29,15 +30,20 @@ protected:
std::string avatarPath;
QGraphicsPixmapItem* graphics{};
QTimer* fireTimer;
int damageUpgrades = 0;
int fireRateUpgrades = 0;
public:
Tower(int damage, int fireRate, int range, int level, int cost, QPointF position, std::string avatarPath, Game& game);
virtual void upgrade() = 0;
Tower(int damage, double fireRate, int range, int level, int cost, QPointF position, std::string avatarPath, Game& game);
virtual ~Tower() = default;
QGraphicsPixmapItem* getGraphics();
void fireAtClosest(Enemy* target = nullptr) const;
Enemy* getClosestEnemyInRange(const QVector<Enemy*>& enemies);
Game& game;
void upgradeDamage();
void upgradeFireRate();
int getDamageUpgrades() const;
int getFireRateUpgrades() const;
public slots:
void fire();
@@ -46,19 +52,16 @@ public slots:
class LaserTower : public Tower {
public:
explicit LaserTower(QPointF position, Game& game);
void upgrade() override;
};
class BalisticTower : public Tower {
public:
explicit BalisticTower(QPointF position, Game& game);
void upgrade() override;
};
class DistorionTower : public Tower {
public:
explicit DistorionTower(QPointF position, Game& game);
void upgrade() override;
};