mirror of
https://github.com/BreizhHardware/Poulpes-de-l-Espace-La-derniere-ligne-de-Defense.git
synced 2026-03-18 21:30:36 +01:00
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:
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
114
src/Game.cpp
114
src/Game.cpp
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -109,4 +109,8 @@ Tile* Map::getTile(int x, int y) {
|
||||
return tiles[y][x];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QVector<QVector<Tile*>> Map::getTiles() {
|
||||
return tiles;
|
||||
}
|
||||
@@ -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
45
src/Projectile.cpp
Normal 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
29
src/Projectile.h
Normal 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
|
||||
@@ -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;
|
||||
}
|
||||
15
src/Tower.h
15
src/Tower.h
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user