diff --git a/Includes/CubbyTower/Commons/TowerData.hpp b/Includes/CubbyTower/Commons/TowerData.hpp index c531475..d34f9b8 100644 --- a/Includes/CubbyTower/Commons/TowerData.hpp +++ b/Includes/CubbyTower/Commons/TowerData.hpp @@ -14,6 +14,9 @@ constexpr static int ARROW_TOWER_LV1_PRICE = 100; //! The price of arrow tower at level 2. constexpr static int ARROW_TOWER_LV2_PRICE = 200; + +//! The price of collatz tower. +constexpr static int COLLATZ_TOWER_PRICE = 500; } // namespace CubbyTower #endif // CUBBYTOWER_TOWER_DATA_HPP \ No newline at end of file diff --git a/Includes/CubbyTower/Components/CollatzDamage.hpp b/Includes/CubbyTower/Components/CollatzDamage.hpp new file mode 100644 index 0000000..28e7eff --- /dev/null +++ b/Includes/CubbyTower/Components/CollatzDamage.hpp @@ -0,0 +1,23 @@ +// Copyright (c) 2021 CubbyTower Team +// Chris Ohk, Minkyu Lee, Minjune Yi +// We are making my contributions/submissions to this project solely in our +// personal capacity and are not conveying any rights to any intellectual +// property of any third parties. + +#ifndef CUBBYTOWER_COLLATZ_DAMAGE_HPP +#define CUBBYTOWER_COLLATZ_DAMAGE_HPP + +namespace CubbyTower +{ +//! +//! \brief Damage struct for Collatz tower. +//! +//! This struct stores the max damage of the tower. +//! +struct CollatzDamage +{ + int maxDamage; +}; +} // namespace CubbyTower + +#endif // CUBBYTOWER_COLLATZ_DAMAGE_HPP \ No newline at end of file diff --git a/Includes/CubbyTower/Helpers/ShootingHelpers.hpp b/Includes/CubbyTower/Helpers/ShootingHelpers.hpp index 2afb32b..f1e559e 100644 --- a/Includes/CubbyTower/Helpers/ShootingHelpers.hpp +++ b/Includes/CubbyTower/Helpers/ShootingHelpers.hpp @@ -24,6 +24,14 @@ namespace Shooting void CreateArrow(entt::registry& registry, const Position& from, const Position& to, int damage); +//! Creates an Collatz entity to shoot a target. +//! \param registry A registry that handles entities. +//! \param from The start position of the collatz for the collatz tower. +//! \param to The end position of the collatz for target. +//! \param collatzDamage The amount of collatz damage to give. +void CreateCollatz(entt::registry& registry, const Position& from, + const Position& to, CollatzDamage collatzDamage); + //! Gives a damage to a target. //! \param registry A registry that handles entities. //! \param target A target that takes a damage. diff --git a/Includes/CubbyTower/Helpers/TowerHelpers.hpp b/Includes/CubbyTower/Helpers/TowerHelpers.hpp index bce9a14..ab34583 100644 --- a/Includes/CubbyTower/Helpers/TowerHelpers.hpp +++ b/Includes/CubbyTower/Helpers/TowerHelpers.hpp @@ -48,6 +48,18 @@ void ShootArrowLv1(entt::registry& registry, entt::entity target, void ShootArrowLv2(entt::registry& registry, entt::entity target, entt::entity from); +//! Buys a collatz tower. +//! \param registry A registry that handles entities. +//! \param position The position to place a collatz tower. +void BuyCollatzTower(entt::registry& registry, const Position& position); + +// Shoots a collatz instance for collatz tower. +//! \param registry A registry that handles entities. +//! \param target A target entity to shoot. +//! \param from A tower entity that shoots collatz instance. +void ShootCollatz(entt::registry& registry, entt::entity target, + entt::entity from); + //! Finds a first target within a range. //! \param registry A registry that handles entities. //! \return a first target if it is within a range, entt::null otherwise. diff --git a/Sources/CubbyTower/Game.cpp b/Sources/CubbyTower/Game.cpp index a5bda5f..8224dce 100644 --- a/Sources/CubbyTower/Game.cpp +++ b/Sources/CubbyTower/Game.cpp @@ -137,6 +137,12 @@ void Initialize(entt::registry& registry) [](entt::registry& registry, entt::entity button) { Tower::CreatePlacer(registry, Tower::BuyArrowTower); }); + + UI::CreateTowerButton( + registry, "Collatz Tower", { -1, 15.5f }, COLLATZ_TOWER_PRICE, + [](entt::registry& registry, entt::entity button) { + Tower::CreatePlacer(registry, Tower::BuyCollatzTower); + }); } } diff --git a/Sources/CubbyTower/Helpers/ShootingHelpers.cpp b/Sources/CubbyTower/Helpers/ShootingHelpers.cpp index 4c8b021..7597f1f 100644 --- a/Sources/CubbyTower/Helpers/ShootingHelpers.cpp +++ b/Sources/CubbyTower/Helpers/ShootingHelpers.cpp @@ -5,6 +5,7 @@ // property of any third parties. #include +#include #include #include #include @@ -53,6 +54,48 @@ static void OnCollideArrow(entt::registry& registry, entt::entity entity) registry.emplace(fxEntity, color); } +static void OnCollideCollatz(entt::registry& registry, entt::entity entity) +{ + auto impactPoint = registry.get(entity); + auto color = registry.get(entity); + auto collatzDamage = registry.get(entity); + + registry.destroy(entity); + + registry.view().each( + [®istry, impactPoint, collatzDamage]( + entt::entity entity, [[maybe_unused]] const Health& health, + const Position& position) { + auto dx = position.x - impactPoint.x; + auto dy = position.y - impactPoint.y; + auto dist = dx * dx + dy * dy; + + if (dist < 0.5f) + { + int damage = collatzDamage.maxDamage; + + if (health.curAmount % 2 == 0) + { + damage = std::min(damage, health.curAmount / 2); + } + else + { + damage = -(health.curAmount * 2 + 1); + } + + GiveDamage(registry, entity, damage); + } + }); + + auto fxEntity = registry.create(); + registry.emplace(fxEntity, impactPoint); + registry.emplace(fxEntity, 0.4f); + registry.emplace(fxEntity, 0.5f); + registry.emplace(fxEntity, Shape::DrawCircle); + registry.emplace(fxEntity, 0.0f, 25.0f, 0.15f, 0.5f); + registry.emplace(fxEntity, color); +} + void CreateArrow(entt::registry& registry, const Position& from, const Position& to, int damage) { @@ -70,6 +113,23 @@ void CreateArrow(entt::registry& registry, const Position& from, registry.emplace(entity, damage); } +void CreateCollatz(entt::registry& registry, const Position& from, + const Position& to, CollatzDamage collatzDamage) +{ + const float dx = to.x - from.x; + const float dy = to.y - from.y; + const float len = std::sqrt(dx * dx + dy * dy); + + auto entity = registry.create(); + registry.emplace(entity, from); + registry.emplace(entity, from, to, 0.0f, len / 10.0f, + OnCollideCollatz); + registry.emplace(entity, Shape::DrawBox); + registry.emplace(entity, 0.15f, 0.15f); + registry.emplace(entity, Color{ 0.0f, 1.0f, 1.0f, 1.0f }); + registry.emplace(entity, collatzDamage); +} + void GiveDamage(entt::registry& registry, entt::entity& target, int damage) { if (!registry.all_of(target)) @@ -79,6 +139,7 @@ void GiveDamage(entt::registry& registry, entt::entity& target, int damage) auto& health = registry.get(target); health.curAmount -= damage; + health.curAmount = std::min(health.curAmount, health.maxAmount); if (health.curAmount <= 0) { @@ -92,4 +153,4 @@ void Kill(entt::registry& registry, entt::entity& target) registry.destroy(target); } -} // namespace CubbyTower::Shooting \ No newline at end of file +} // namespace CubbyTower::Shooting diff --git a/Sources/CubbyTower/Helpers/TowerHelpers.cpp b/Sources/CubbyTower/Helpers/TowerHelpers.cpp index c07e6bd..f1c4b5e 100644 --- a/Sources/CubbyTower/Helpers/TowerHelpers.cpp +++ b/Sources/CubbyTower/Helpers/TowerHelpers.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -91,6 +92,39 @@ void ShootArrowLv2(entt::registry& registry, entt::entity target, // Do nothing } +void BuyCollatzTower(entt::registry& registry, const Position& position) +{ + // Check the player can buy arrow tower + if (!Bank::Withdraw(registry, registry.view()[0], + COLLATZ_TOWER_PRICE)) + { + return; + } + + auto entity = registry.create(); + registry.emplace(entity); + registry.emplace(entity, position); + registry.emplace(entity, TOWER_SIZE, TOWER_SIZE); + registry.emplace(entity, TOWER_LEVEL1_COLOR); + registry.emplace(entity, "C", Color{ 0.0f, 0.0f, 0.0f, 0.0f }, + 0.5f); + registry.emplace(entity, Shape::DrawBox); + registry.emplace(entity, "Collatz Tower(WIP)"); + registry.emplace(entity, TargetMask{ GROUND | AIR }, + 210.0f / 60.0f, 1.0f, ShootCollatz); + registry.emplace(entity); + registry.emplace(entity, FindFirstTarget); +} + +void ShootCollatz(entt::registry& registry, entt::entity target, + entt::entity from) +{ + Shooting::CreateCollatz(registry, registry.get(from), + registry.get(target), + CollatzDamage{ 100 }); + Audio::PlaySound("arrow"); +} + entt::entity FindFirstTarget(entt::registry& registry) { return entt::null;