diff --git a/include/game/Towers.h b/include/game/Towers.h index 3671e6d..56eb6ac 100644 --- a/include/game/Towers.h +++ b/include/game/Towers.h @@ -10,6 +10,11 @@ namespace td { namespace game { +class World; +class Mob; + +typedef std::shared_ptr MobPtr; + enum class TowerType : std::uint8_t { Archer = 0, Ice, @@ -88,19 +93,21 @@ private: PlayerID m_Builder; protected: utils::Timer m_Timer; -public: // converting seconds to millis +public: Tower(TowerID id, TowerType type, std::uint16_t x, std::uint16_t y, PlayerID builder) : m_ID(id), m_Type(type), m_X(x), m_Y(y), m_Builder(builder), - m_Timer(getStats()->getDamageRate()) { + m_Timer(getStats()->getDamageRate() * 1000) { // converting seconds to millis } virtual TowerType getType() const = 0; virtual TowerSize getSize() const = 0; - virtual void tick(std::uint64_t delta) = 0; + virtual void tick(std::uint64_t delta, World* world) = 0; void upgrade(std::uint8_t level, TowerPath path) { m_Level.setLevel(level); m_Level.setPath(path); + m_Timer.setInterval(getStats()->getDamageRate() * 1000); // converting seconds to millis + m_Timer.reset(); } std::uint16_t getID() const { return m_ID; } @@ -109,6 +116,7 @@ public: // conve const TowerLevel& getLevel() const { return m_Level; } const TowerStats* getStats() const { return getTowerStats(m_Type, m_Level); } + bool isMobInRange(MobPtr mob); }; typedef std::shared_ptr TowerPtr; @@ -145,7 +153,7 @@ public: virtual TowerSize getSize() const { return TowerSize::Little; } virtual TowerType getType() const = 0; - virtual void tick(std::uint64_t delta) = 0; + virtual void tick(std::uint64_t delta, World* world) = 0; }; class ArcherTower : public LittleTower { @@ -153,7 +161,9 @@ public: ArcherTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, getType(), x, y, builder) {} virtual TowerType getType() const { return TowerType::Archer; } - virtual void tick(std::uint64_t delta); + virtual void tick(std::uint64_t delta, World* world); +private: + void shootArrow(MobPtr target); }; class IceTower : public LittleTower { @@ -161,7 +171,7 @@ public: IceTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, getType(), x, y, builder) {} virtual TowerType getType() const { return TowerType::Ice; } - virtual void tick(std::uint64_t delta); + virtual void tick(std::uint64_t delta, World* world); }; class MageTower : public LittleTower { @@ -169,7 +179,7 @@ public: MageTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, getType(), x, y, builder) {} virtual TowerType getType() const { return TowerType::Mage; } - virtual void tick(std::uint64_t delta); + virtual void tick(std::uint64_t delta, World* world); }; class PoisonTower : public LittleTower { @@ -177,7 +187,7 @@ public: PoisonTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, getType(), x, y, builder) {} virtual TowerType getType() const { return TowerType::Poison; } - virtual void tick(std::uint64_t delta); + virtual void tick(std::uint64_t delta, World* world); }; class QuakeTower : public LittleTower { @@ -185,7 +195,7 @@ public: QuakeTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, getType(), x, y, builder) {} virtual TowerType getType() const { return TowerType::Quake; } - virtual void tick(std::uint64_t delta); + virtual void tick(std::uint64_t delta, World* world); }; class ArtilleryTower : public LittleTower { @@ -193,7 +203,7 @@ public: ArtilleryTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, getType(), x, y, builder) {} virtual TowerType getType() const { return TowerType::Artillery; } - virtual void tick(std::uint64_t delta); + virtual void tick(std::uint64_t delta, World* world); }; class SorcererTower : public LittleTower { @@ -201,7 +211,7 @@ public: SorcererTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, getType(), x, y, builder) {} virtual TowerType getType() const { return TowerType::Sorcerer; } - virtual void tick(std::uint64_t delta); + virtual void tick(std::uint64_t delta, World* world); }; class ZeusTower : public LittleTower { @@ -209,7 +219,7 @@ public: ZeusTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, getType(), x, y, builder) {} virtual TowerType getType() const { return TowerType::Zeus; } - virtual void tick(std::uint64_t delta); + virtual void tick(std::uint64_t delta, World* world); }; // ---------- Big Towers ---------- @@ -221,7 +231,7 @@ public: virtual TowerSize getSize() const { return TowerSize::Big; } virtual TowerType getType() const = 0; - virtual void tick(std::uint64_t delta) = 0; + virtual void tick(std::uint64_t delta, World* world) = 0; }; class TurretTower : public BigTower { @@ -229,7 +239,7 @@ public: TurretTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : BigTower(id, getType(), x, y, builder) {} virtual TowerType getType() const { return TowerType::Turret; } - virtual void tick(std::uint64_t delta); + virtual void tick(std::uint64_t delta, World* world); }; class NecromancerTower : public BigTower { @@ -237,7 +247,7 @@ public: NecromancerTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : BigTower(id, getType(), x, y, builder) {} virtual TowerType getType() const { return TowerType::Necromancer; } - virtual void tick(std::uint64_t delta); + virtual void tick(std::uint64_t delta, World* world); }; class LeachTower : public BigTower { @@ -245,7 +255,7 @@ public: LeachTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : BigTower(id, getType(), x, y, builder) {} virtual TowerType getType() const { return TowerType::Leach; } - virtual void tick(std::uint64_t delta); + virtual void tick(std::uint64_t delta, World* world); }; } // namespace game diff --git a/include/game/World.h b/include/game/World.h index 5961e63..9addafc 100644 --- a/include/game/World.h +++ b/include/game/World.h @@ -184,6 +184,7 @@ public: const TowerList& getTowers() const { return m_Towers; }; private: void moveMobs(std::uint64_t delta); + void cleanDeadMobs(); }; } // namespace game diff --git a/include/game/server/Lobby.h b/include/game/server/Lobby.h index eab34e6..9ccd13a 100644 --- a/include/game/server/Lobby.h +++ b/include/game/server/Lobby.h @@ -15,7 +15,7 @@ private: bool m_GameStarted = false; std::uint64_t m_StartTimerTime = 0; std::vector m_Players; - utils::Timer m_Timer; + utils::AutoTimer m_Timer; public: Lobby(Server* server); diff --git a/include/game/server/ServerGame.h b/include/game/server/ServerGame.h index 8604c15..a573703 100644 --- a/include/game/server/ServerGame.h +++ b/include/game/server/ServerGame.h @@ -13,7 +13,7 @@ class ServerGame : public game::Game { private: Server* m_Server; ServerWorld m_ServerWorld; - utils::Timer m_GoldMineTimer{ 1000, std::bind(&ServerGame::updateGoldMines, this) }; + utils::AutoTimer m_GoldMineTimer{ 1000, std::bind(&ServerGame::updateGoldMines, this) }; public: ServerGame(Server* server); ~ServerGame() {} diff --git a/include/misc/Time.h b/include/misc/Time.h index 8c02c0c..55bbefa 100644 --- a/include/misc/Time.h +++ b/include/misc/Time.h @@ -12,7 +12,7 @@ std::uint64_t getTime(); typedef std::function TimerExecFunction; // utililty class to call function at regular period of time -class Timer { +class AutoTimer { private: std::uint64_t m_Interval; TimerExecFunction m_Function; @@ -20,9 +20,9 @@ private: std::uint64_t m_LastTime = getTime(); std::uint64_t m_InternalTime = 0; public: - Timer() : m_Interval(0), m_Function(nullptr) {} - Timer(std::uint64_t interval) : m_Interval(interval), m_Function(nullptr) {} - Timer(std::uint64_t interval, TimerExecFunction callback) : m_Interval(interval), m_Function(callback) {} + AutoTimer() : m_Interval(0), m_Function(nullptr) {} + AutoTimer(std::uint64_t interval) : m_Interval(interval), m_Function(nullptr) {} + AutoTimer(std::uint64_t interval, TimerExecFunction callback) : m_Interval(interval), m_Function(callback) {} void update(); void update(std::uint64_t delta); @@ -36,6 +36,23 @@ public: TimerExecFunction getCallbackFunction() const { return m_Function; } }; +// utililty class to call function at regular period of time +class Timer { +private: + std::uint64_t m_Interval; + + std::uint64_t m_InternalTime = 0; +public: + Timer() : m_Interval(0) {} + Timer(std::uint64_t interval) : m_Interval(interval) {} + + bool update(std::uint64_t delta); + + void reset(); + + void setInterval(std::uint64_t newInterval) { m_Interval = newInterval; } + std::uint64_t getInterval() const { return m_Interval; } +}; } // namespace utils } // namespace td diff --git a/src/game/Towers.cpp b/src/game/Towers.cpp index ad5136e..f661a64 100644 --- a/src/game/Towers.cpp +++ b/src/game/Towers.cpp @@ -6,6 +6,12 @@ namespace td { namespace game { +bool Tower::isMobInRange(MobPtr mob) { + if(!mob->isAlive()) + return false; + return (m_X - mob->getX()) * (m_X - mob->getX()) + (m_Y - mob->getY()) * (m_Y - mob->getY()) < (getStats()->getRange() * getStats()->getRange()); +} + const std::map, TowerStats> TowerConstants = { // // rate damage range {{TowerType::Archer, {1, TowerPath::Top}}, {2, 5, 10}}, @@ -161,7 +167,28 @@ TowerPtr createTower(TowerType type, TowerID id, std::int32_t x, std::int32_t y, void ArcherTower::tick(std::uint64_t delta, World* world) { + if (m_Timer.update(delta)) { + std::uint8_t arrowsShot = 0; + bool explosiveArrows = getLevel().getPath() == TowerPath::Bottom; + std::uint8_t arrows = explosiveArrows ? 2 : getLevel().getLevel(); + for (MobPtr mob : world->getMobList()) { + if (isMobInRange(mob)) { + shootArrow(mob); + arrowsShot++; + if(arrowsShot >= arrows) + break; + } + } + } +} +void ArcherTower::shootArrow(MobPtr target){ + bool explosiveArrows = getLevel().getPath() == TowerPath::Bottom; + if(explosiveArrows){ + + }else{ + target->damage(getStats()->getDamage()); + } } void IceTower::tick(std::uint64_t delta, World* world) { diff --git a/src/game/World.cpp b/src/game/World.cpp index a9e8f1e..2edcc1b 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -322,8 +322,9 @@ bool World::saveMap(const std::string& fileName) const { void World::tick(std::uint64_t delta) { moveMobs(delta); for(TowerPtr tower : m_Towers){ - tower->tick(delta); + tower->tick(delta, this); } + cleanDeadMobs(); } void World::spawnMobAt(MobID id, MobType type, std::uint8_t level, PlayerID sender, float x, float y, Direction dir) { @@ -447,6 +448,15 @@ bool World::CanPlaceBigTower(const glm::vec2& worldPos, PlayerID playerID) const return false; } +void World::cleanDeadMobs(){ + for(auto it = m_Mobs.begin(); it != m_Mobs.end(); it++){ + MobPtr mob = *it; + if(!mob->isAlive()){ + m_Mobs.erase(it); + } + } +} + Team& World::getRedTeam() { return m_Game->getRedTeam(); } diff --git a/src/misc/Time.cpp b/src/misc/Time.cpp index b2b0c4b..0b5f2a5 100644 --- a/src/misc/Time.cpp +++ b/src/misc/Time.cpp @@ -4,7 +4,7 @@ namespace td { namespace utils { -void Timer::update() { +void AutoTimer::update() { m_InternalTime += getTime() - m_LastTime; if (m_InternalTime >= m_Interval) { if (m_Function != nullptr) @@ -14,7 +14,7 @@ void Timer::update() { m_LastTime = getTime(); } -void Timer::update(std::uint64_t delta) { +void AutoTimer::update(std::uint64_t delta) { m_InternalTime += delta; if (m_InternalTime >= m_Interval) { if (m_Function != nullptr) @@ -24,11 +24,24 @@ void Timer::update(std::uint64_t delta) { m_LastTime = getTime(); } -void Timer::reset() { +void AutoTimer::reset() { m_InternalTime = 0; m_LastTime = getTime(); } +bool Timer::update(std::uint64_t delta){ + m_InternalTime += delta; + if (m_InternalTime >= m_Interval) { + m_InternalTime %= m_Interval; + return true; + } + return false; +} + +void Timer::reset(){ + m_InternalTime = 0; +} + std::uint64_t getTime() { return std::chrono::duration_cast(std::chrono::system_clock().now().time_since_epoch()).count(); }