diff --git a/CMakeLists.txt b/CMakeLists.txt index 22c2308..24d0d56 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,7 +33,10 @@ set(GAME_OBJECTS GameObjects/Entities/Mobs/skeleton.cpp GameObjects/Entities/Mobs/cobra.cpp GameObjects/Entities/Mobs/hedgehog.cpp - GameObjects/Entities/Mobs/dwarf.cpp GameObjects/Entities/Projectiles/linear_autoguided_projectile.cpp GameObjects/Entities/Projectiles/linear_autoguided_projectile.h GameObjects/Entities/Projectiles/linear_test_projectile.cpp GameObjects/Entities/Projectiles/linear_test_projectile.h) + GameObjects/Entities/Mobs/dwarf.cpp + GameObjects/explosion.cpp + GameObjects/Entities/Projectiles/linear_autoguided_projectile.cpp + GameObjects/Entities/Projectiles/linear_test_projectile.cpp) set(UTILITIES Utilities/damage.cpp @@ -53,7 +56,9 @@ set(UI UI/linear_menu.cpp UI/linear_layout.cpp UI/button.cpp - UI/padding_box.cpp UI/pixmap_object.cpp UI/pixmap_object.h) + UI/padding_box.cpp + UI/pixmap_object.cpp + UI/pixmap_object.h) add_executable(Game ${RESOURCES} diff --git a/Controller/controller.cpp b/Controller/controller.cpp index 35b1ed8..176f6e3 100644 --- a/Controller/controller.cpp +++ b/Controller/controller.cpp @@ -12,6 +12,7 @@ #include "GameObjects/Entities/Mobs/hedgehog.h" #include "GameObjects/Entities/Mobs/cobra.h" #include "GameObjects/Entities/Mobs/dwarf.h" +#include "GameObjects/explosion.h" #include "constants.h" #include "UI/button.h" #include "UI/linear_menu.h" @@ -52,120 +53,16 @@ Level* Controller::GetLevel() const { void Controller::SetupScene() { { // temporary code - LinearMenu* main_menu = new LinearMenu(); - main_menu->SetTexturedBoxPixmaps(PixmapLoader::kMenu2TexturedBoxPixmaps); - main_menu->SetSpacing(30); - - TextButton* test_button = new TextButton(); - test_button->SetText("Test button"); - QFont button_font = test_button->GetTextDocument()->defaultFont(); - button_font.setPixelSize(30); - test_button->GetTextDocument()->setDefaultFont(button_font); - - connect(test_button, &TextButton::Clicked, - [this, test_button, main_menu](){ - static int i = 0; - i++; - scene_->addItem(new TestMob({200.0 + 10 * i, 200})); - test_button->setScale(1.5); - test_button->SetIcon(PixmapLoader::Pixmaps::FireTotem::kIdle.at(0)); - test_button->SetSpacing(test_button->Spacing() + 5); - test_button->SetPadding(test_button->Padding() + 3); - main_menu->setPos( - scene_->sceneRect().topRight() - - main_menu->boundingRect().topRight() + - QPointF{-5, 5}); - main_menu->RecalculatePositions(); - }); - - LinearLayout* layout = new LinearLayout(); - layout->SetSpacing(10); - layout->AddItem(new TextButton({0, 0}, "Menu button 1")); - layout->AddItem(new TextButton({0, 0}, "Menu button 2")); - TextButton* close_button = new TextButton({0, 0}, "Quit"); - layout->AddItem(close_button); - connect(close_button, &TextButton::Clicked, [](){ QApplication::exit(); }); - - LinearMenu* menu = new LinearMenu(); - menu->AddItem(new PaddingBox(new TextButton({0, 0}, "Menu button 1"), 10)); - menu->AddItem(new PaddingBox(new TextButton({0, 0}, "Menu button 2"), 10)); - menu->SetSpacing(5); - menu->SetPadding(20); - menu->setScale(1.2); - menu->SetTexturedBoxPixmaps(PixmapLoader::kMenuTexturedBoxPixmaps); - menu->SetType(LinearLayout::Type::Vertical); - - main_menu->AddItem(layout); - main_menu->AddItem(menu); - main_menu->AddItem(test_button); - main_menu->SetType(LinearLayout::Type::Vertical); - main_menu->setScale(0.3); - - //{ - // LinearLayout* test_hor_layout = new LinearLayout(); - // test_hor_layout->AddItem(new TextButton({0, 0}, "test 1")); - // test_hor_layout->AddItem(new TextButton({0, 0}, "test 2")); - // test_hor_layout->SetType(LinearLayout::Type::Horizontal); - // test_hor_layout->SetSpacing(20); - // test_hor_layout->setPos(200, 200); - // - // LinearLayout* test_ver_layout = new LinearLayout(); - // test_ver_layout->AddItem(new TextButton({0, 0}, "test 1")); - // test_ver_layout->AddItem(new TextButton({0, 0}, "test 2")); - // test_ver_layout->SetType(LinearLayout::Type::Vertical); - // test_ver_layout->SetSpacing(20); - // test_ver_layout->setPos(200, 300); - // - // scene_->addItem(test_hor_layout); - // scene_->addItem(test_ver_layout); - //} - //{ - // LinearMenu* test_hor_menu = new LinearMenu(); - // test_hor_menu->AddItem(new TextButton({0, 0}, "test 1")); - // test_hor_menu->AddItem(new TextButton({0, 0}, "test 2")); - // test_hor_menu->SetType(LinearLayout::Type::Horizontal); - // test_hor_menu->SetTexturedBoxPixmaps( - // PixmapLoader::kMenu2TexturedBoxPixmaps); - // test_hor_menu->SetPadding(50); - // test_hor_menu->SetSpacing(20); - // test_hor_menu->setPos(-200, 100); - // - // LinearMenu* test_ver_menu = new LinearMenu(); - // test_ver_menu->AddItem(new TextButton({0, 0}, "test 1")); - // test_ver_menu->AddItem(new TextButton({0, 0}, "test 2")); - // test_ver_menu->SetType(LinearLayout::Type::Vertical); - // test_ver_menu->SetTexturedBoxPixmaps( - // PixmapLoader::kMenu2TexturedBoxPixmaps); - // test_ver_menu->SetPadding(50); - // test_ver_menu->SetSpacing(20); - // test_ver_menu->setPos(-600, 100); - // - // scene_->addItem(test_hor_menu); - // scene_->addItem(test_ver_menu); - //} - //{ - // TextButton* text_button = new TextButton({0, 0}, "Button"); - // PaddingBox* padding_box = new PaddingBox(text_button, 20); - // padding_box->setPos(0, 0); - // - // scene_->addItem(padding_box); - //} - //{ - // TextButton* text_button = new TextButton({-300, 0}, "Button"); - // - // connect(text_button, &TextButton::Clicked, [text_button]() { - // text_button->SetText( - // text_button->GetTextDocument()->toPlainText() + " Button"); - // }); - // - // scene_->addItem(text_button); - //} - - scene_->addItem(main_menu); - main_menu->setPos( - scene_->sceneRect().topRight() - - main_menu->boundingRect().topRight() * main_menu->scale() + - QPointF{-5, 5}); + TextButton* quit_button = new TextButton({0, 0}, "Quit"); + auto quit_button_font = quit_button->GetTextDocument()->defaultFont(); + quit_button_font.setPixelSize(20); + quit_button->GetTextDocument()->setDefaultFont(quit_button_font); + quit_button->setPos( + scene_->sceneRect().topRight() + - quit_button->boundingRect().topRight() + - VectorF(5, -5)); + connect(quit_button, &TextButton::Clicked, [](){ QApplication::exit(); }); + scene_->addItem(quit_button); } // temporary code end level_->AddObjectsToScene(scene_); diff --git a/GameObjects/Entities/Projectiles/autoguided_projectile.h b/GameObjects/Entities/Projectiles/autoguided_projectile.h index 5f19191..8ef9847 100644 --- a/GameObjects/Entities/Projectiles/autoguided_projectile.h +++ b/GameObjects/Entities/Projectiles/autoguided_projectile.h @@ -34,8 +34,8 @@ class AutoguidedProjectile : public Projectile { Entity* target_; VectorF speed_; + Damage damage_; qreal max_speed_; qreal acceleration_; qreal enemy_find_distance_; - Damage damage_; }; diff --git a/GameObjects/Entities/Towers/test_tower.cpp b/GameObjects/Entities/Towers/test_tower.cpp index 3360f96..04b6222 100644 --- a/GameObjects/Entities/Towers/test_tower.cpp +++ b/GameObjects/Entities/Towers/test_tower.cpp @@ -2,8 +2,8 @@ #include -#include "GameObjects/Entities/Projectiles/test_projectile.h" #include "GameObjects/Entities/Projectiles/linear_test_projectile.h" +#include "GameObjects/Entities/Projectiles/test_projectile.h" #include "GameObjects/Entities/Mobs/Basis/mob.h" #include "Utilities/Resources/pixmap_loader.h" #include "constants.h" @@ -42,7 +42,7 @@ void TestTower::Tick(Time delta) { if (mob->GetHealth() <= 0) { continue; } - scene()->addItem(new LinearTestProjectile(scenePos(), mob)); + scene()->addItem(new TestProjectile(scenePos(), mob)); attack_timer_.Start(Entities::TestTower::kAttackCooldown); break; } diff --git a/GameObjects/explosion.cpp b/GameObjects/explosion.cpp new file mode 100644 index 0000000..24dd66d --- /dev/null +++ b/GameObjects/explosion.cpp @@ -0,0 +1,59 @@ +#include "explosion.h" + +#include "GameObjects/Entities/Mobs/Basis/mob.h" +#include "Utilities/Resources/pixmap_loader.h" +#include "constants.h" + +Explosion::Explosion(const VectorF& coordinates, qreal radius, Damage damage) + : radius_(radius), + damage_(damage), + animation_(new Animation( + PixmapLoader::Pixmaps::Explosion::kExplosion, + Explosions::kTimeBetweenFrames)) { + setPos(coordinates); + setZValue(Explosions::kZValue); +} + +QRectF Explosion::boundingRect() const { + QRectF result = animation_->Frame()->rect(); + qreal scale = result.width() / (radius_ * 2); + result = QRectF(0, 0, result.width() / scale, result.height() / scale); + result.translate(-result.width() / 2, -result.height() / 2); + return result; +} + +void Explosion::paint(QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget) { + QRectF rect = boundingRect(); + QPixmap* pixmap = animation_->Frame(); + painter->drawPixmap(rect, *pixmap, pixmap->rect()); +} + +void Explosion::Tick(Time delta) { + animation_->Tick(delta); + + if (animation_->WasEndedDuringPreviousUpdate()) { + deleteLater(); + } +} + +void Explosion::DamageMobs() { + for (auto mob : scene()->Mobs()) { + if (VectorF(scenePos() - mob->scenePos()).length() < radius_) { + mob->ApplyDamage(damage_); + } + } +} + +QVariant Explosion::itemChange(QGraphicsItem::GraphicsItemChange change, + const QVariant& value) { + if (change == GraphicsItemChange::ItemSceneHasChanged) { + DamageMobs(); + } + return QGraphicsItem::itemChange(change, value); +} + +Explosion::~Explosion() { + delete animation_; +} diff --git a/GameObjects/explosion.h b/GameObjects/explosion.h new file mode 100644 index 0000000..a335a66 --- /dev/null +++ b/GameObjects/explosion.h @@ -0,0 +1,32 @@ +#pragma once + +#include "GameObjects/Interface/graphics_object.h" +#include "GameObjects/Interface/tickable.h" +#include "constants.h" +#include "Utilities/animation.h" + +class Explosion : public GraphicsObject, public Tickable { + public: + Explosion( + const VectorF& coordinates, + qreal radius = Explosions::kDefaultRadius, + Damage damage = Explosions::kDefaultDamage); + + QRectF boundingRect() const override; + void paint(QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget) override; + void Tick(Time delta) override; + + virtual ~Explosion(); + + QVariant itemChange(QGraphicsItem::GraphicsItemChange change, + const QVariant& value) override; + + private: + void DamageMobs(); + + Animation* animation_; + qreal radius_; + Damage damage_; +}; diff --git a/Resources/resources.qrc b/Resources/resources.qrc index 7d522c8..7153579 100644 --- a/Resources/resources.qrc +++ b/Resources/resources.qrc @@ -23,6 +23,8 @@ Levels/Level1/map.png Levels/Level1/level.json + images/explosion.png + GUI/Textured boxes/Default/top_left_corner.png diff --git a/Utilities/Resources/pixmap_loader.cpp b/Utilities/Resources/pixmap_loader.cpp index ebb034f..417d6ba 100644 --- a/Utilities/Resources/pixmap_loader.cpp +++ b/Utilities/Resources/pixmap_loader.cpp @@ -33,6 +33,8 @@ std::vector P::Hedgehog::kDeath; QPixmap* P::Dwarf::kAnimations; std::vector P::Dwarf::kWalk; std::vector P::Dwarf::kDeath; +QPixmap* P::Explosion::kAnimations; +std::vector P::Explosion::kExplosion; // ----------------------------------------------------------------------------- @@ -60,6 +62,7 @@ void PixmapLoader::LoadPixmaps() { LoadCobraAnimations(); LoadHedgehogAnimations(); LoadDwarfAnimations(); + LoadExplosionAnimation(); LoadUI(); } @@ -265,6 +268,27 @@ void PixmapLoader::LoadDwarfAnimations() { death_animation_row * frame_height); } +void PixmapLoader::LoadExplosionAnimation() { + // file size - 384x48 + // 1 frame rows, 8 frame columns + const int animation_frames_count = 8; + const int frame_width = 384 / animation_frames_count; + const int frame_height = 48 / 1; + // row and column start from 0 + const int animation_row = 0; + const int animation_column = 0; + + P::Explosion::kAnimations = new QPixmap(":images/explosion.png"); + + P::Explosion::kExplosion = CreateHorizontalFramesVector( + P::Explosion::kAnimations, + frame_width, + frame_height, + animation_frames_count, + animation_column * frame_width, + animation_row * frame_height); +} + void PixmapLoader::LoadUI() { LoadDefaultTextureBox(); LoadMenuTextureBox(); diff --git a/Utilities/Resources/pixmap_loader.h b/Utilities/Resources/pixmap_loader.h index 846afb4..02228d4 100644 --- a/Utilities/Resources/pixmap_loader.h +++ b/Utilities/Resources/pixmap_loader.h @@ -34,27 +34,29 @@ class PixmapLoader { static std::vector kWalk; static std::vector kDeath; }; - class Cobra { public: static QPixmap* kAnimations; static std::vector kWalk; static std::vector kDeath; }; - class Hedgehog { public: static QPixmap* kAnimations; static std::vector kWalk; static std::vector kDeath; }; - class Dwarf { public: static QPixmap* kAnimations; static std::vector kWalk; static std::vector kDeath; }; + class Explosion { + public: + static QPixmap* kAnimations; + static std::vector kExplosion; + }; }; static TexturedBoxPixmaps kMenuTexturedBoxPixmaps; @@ -78,6 +80,7 @@ class PixmapLoader { static void LoadCobraAnimations(); static void LoadHedgehogAnimations(); static void LoadDwarfAnimations(); + static void LoadExplosionAnimation(); static void LoadUI(); static void LoadDefaultTextureBox(); diff --git a/constants.cpp b/constants.cpp index 4f80771..0b1c527 100644 --- a/constants.cpp +++ b/constants.cpp @@ -24,6 +24,13 @@ namespace LevelData { extern const int kLevelsCount = 1; } +namespace Explosions { +const qreal kDefaultRadius = 70.0; +const Damage kDefaultDamage = Damage(50); +const Time kTimeBetweenFrames = 50_ms; +const qreal kZValue = 2000; +} + namespace Entities { const int kCircleAttackAreaApproximationPointsCount = 10; const QString kTestMobId = "TestMob"; diff --git a/constants.h b/constants.h index 88e98cb..613f92a 100644 --- a/constants.h +++ b/constants.h @@ -25,6 +25,13 @@ namespace LevelData { extern const int kLevelsCount; } +namespace Explosions { +extern const qreal kDefaultRadius; +extern const Damage kDefaultDamage; +extern const Time kTimeBetweenFrames; +extern const qreal kZValue; +} + namespace Entities { extern const int kCircleAttackAreaApproximationPointsCount; extern const QString kTestMobId;