From 652bb12e7bb77cab2d3cf8478e9dce2a0382234d Mon Sep 17 00:00:00 2001 From: Alexander Zhirov Date: Sat, 5 Feb 2022 12:05:21 +0300 Subject: [PATCH] lesson 8 --- SBomber/.settings/language.settings.xml | 4 +- SBomber/include/DestroyableGroundObject.h | 4 +- SBomber/include/House.h | 30 +- SBomber/include/SBomber.h | 4 +- SBomber/include/Tank.h | 13 + SBomber/main.cpp | 2 +- SBomber/src/SBomber.cpp | 676 ++++++++++++---------- 7 files changed, 427 insertions(+), 306 deletions(-) diff --git a/SBomber/.settings/language.settings.xml b/SBomber/.settings/language.settings.xml index f6236f6..4ec6580 100644 --- a/SBomber/.settings/language.settings.xml +++ b/SBomber/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + @@ -16,7 +16,7 @@ - + diff --git a/SBomber/include/DestroyableGroundObject.h b/SBomber/include/DestroyableGroundObject.h index fda59d0..6a90e73 100644 --- a/SBomber/include/DestroyableGroundObject.h +++ b/SBomber/include/DestroyableGroundObject.h @@ -12,6 +12,8 @@ public: virtual inline uint16_t GetScore() const = 0; + virtual DestroyableGroundObject* clone() const = 0; + protected: -}; \ No newline at end of file +}; diff --git a/SBomber/include/House.h b/SBomber/include/House.h index 02cec43..94a3a5a 100644 --- a/SBomber/include/House.h +++ b/SBomber/include/House.h @@ -3,16 +3,32 @@ #include "DestroyableGroundObject.h" #include -class House : public DestroyableGroundObject { +class House: public DestroyableGroundObject +{ public: - bool isInside(double x1, double x2) const override; + House() {} - inline uint16_t GetScore() const override { - return score; - } + House(const House &h) + { + x = h.x; + y = h.y; + width = h.width; + } - void Draw() const override; + bool isInside(double x1, double x2) const override; + + inline uint16_t GetScore() const override + { + return score; + } + + void Draw() const override; + + House* clone() const + { + return new House(*this); + } private: - const uint16_t score = 40; + const uint16_t score = 40; }; diff --git a/SBomber/include/SBomber.h b/SBomber/include/SBomber.h index 3ce1b9c..e3bd99f 100644 --- a/SBomber/include/SBomber.h +++ b/SBomber/include/SBomber.h @@ -42,6 +42,8 @@ private: void DropBomb(); + void AnimateScrolling(); + std::vector vecDynamicObj; std::vector vecStaticObj; @@ -50,4 +52,4 @@ private: uint64_t startTime, finishTime, passedTime; uint16_t bombsNumber, deltaTime, fps; int16_t score; -}; \ No newline at end of file +}; diff --git a/SBomber/include/Tank.h b/SBomber/include/Tank.h index 34b3d5c..f7c42c1 100644 --- a/SBomber/include/Tank.h +++ b/SBomber/include/Tank.h @@ -7,6 +7,14 @@ class Tank : public DestroyableGroundObject { public: + Tank() {} + + Tank(const Tank &t) + { + x = t.x; + y = t.y; + width = t.width; + } bool isInside(double x1, double x2) const override; @@ -14,6 +22,11 @@ public: void Draw() const override; + Tank* clone() const + { + return new Tank(*this); + } + private: const uint16_t score = 30; diff --git a/SBomber/main.cpp b/SBomber/main.cpp index aa0028a..2ccccee 100644 --- a/SBomber/main.cpp +++ b/SBomber/main.cpp @@ -54,7 +54,7 @@ int main(void) game.TimeFinish(); } while (!game.GetExitFlag()); - + game.AnimateScrolling(); MyTools::LoggerSingleton::getInstance().CloseLogFile(); return 0; diff --git a/SBomber/src/SBomber.cpp b/SBomber/src/SBomber.cpp index 40a93bf..4c5cb6d 100644 --- a/SBomber/src/SBomber.cpp +++ b/SBomber/src/SBomber.cpp @@ -1,4 +1,3 @@ - #include "MyTools.h" #include "SBomber.h" #include "Bomb.h" @@ -10,302 +9,391 @@ #include #include -SBomber::SBomber() - : exitFlag(false), startTime(0), finishTime(0), deltaTime(0), passedTime(0), - fps(0), bombsNumber(10), score(0) { - MyTools::LoggerSingleton::getInstance().WriteToLog(std::string(__func__) + " was invoked"); +extern int _kbhit(); - Plane* p = new Plane; - p->SetDirection(1, 0.1); - p->SetSpeed(4); - p->SetPos(5, 10); - vecDynamicObj.push_back(p); - - LevelGUI* pGUI = new LevelGUI; - pGUI->SetParam(passedTime, fps, bombsNumber, score); - const uint16_t maxX = ScreenSingleton::getInstance().GetMaxX(); - const uint16_t maxY = ScreenSingleton::getInstance().GetMaxY(); - const uint16_t offset = 3; - const uint16_t width = maxX - 7; - pGUI->SetPos(offset, offset); - pGUI->SetWidth(width); - pGUI->SetHeight(maxY - 4); - pGUI->SetFinishX(offset + width - 4); - vecStaticObj.push_back(pGUI); - - Ground* pGr = new Ground; - const uint16_t groundY = maxY - 5; - pGr->SetPos(offset + 1, groundY); - pGr->SetWidth(width - 2); - vecStaticObj.push_back(pGr); - - Tank* pTank = new Tank; - pTank->SetWidth(13); - pTank->SetPos(30, groundY - 1); - vecStaticObj.push_back(pTank); - - pTank = new Tank; - pTank->SetWidth(13); - pTank->SetPos(50, groundY - 1); - vecStaticObj.push_back(pTank); - - House* pHouse = new House; - pHouse->SetWidth(13); - pHouse->SetPos(80, groundY - 1); - vecStaticObj.push_back(pHouse); - - /* - Bomb* pBomb = new Bomb; - pBomb->SetDirection(0.3, 1); - pBomb->SetSpeed(2); - pBomb->SetPos(51, 5); - pBomb->SetSize(SMALL_CRATER_SIZE); - vecDynamicObj.push_back(pBomb); - */ -} - -SBomber::~SBomber() { - for (size_t i = 0; i < vecDynamicObj.size(); i++) { - if (vecDynamicObj[i] != nullptr) { - delete vecDynamicObj[i]; - } - } - - for (size_t i = 0; i < vecStaticObj.size(); i++) { - if (vecStaticObj[i] != nullptr) { - delete vecStaticObj[i]; - } - } -} - -void SBomber::MoveObjects() { - MyTools::LoggerSingleton::getInstance().WriteToLog(std::string(__func__) + " was invoked"); - - for (size_t i = 0; i < vecDynamicObj.size(); i++) { - if (vecDynamicObj[i] != nullptr) { - vecDynamicObj[i]->Move(deltaTime); - } - } -}; - -void SBomber::CheckObjects() { - MyTools::LoggerSingleton::getInstance().WriteToLog(std::string(__func__) + " was invoked"); - - CheckPlaneAndLevelGUI(); - CheckBombsAndGround(); -}; - -void SBomber::CheckPlaneAndLevelGUI() { - if (FindPlane()->GetX() > FindLevelGUI()->GetFinishX()) { - exitFlag = true; - } -} - -void SBomber::CheckBombsAndGround() { - std::vector vecBombs = FindAllBombs(); - Ground* pGround = FindGround(); - const double y = pGround->GetY(); - for (size_t i = 0; i < vecBombs.size(); i++) { - if (vecBombs[i]->GetY() >= y) { - pGround->AddCrater(vecBombs[i]->GetX()); - CheckDestoyableObjects(vecBombs[i]); - DeleteDynamicObj(vecBombs[i]); - } - } -} - -void SBomber::CheckDestoyableObjects(Bomb* pBomb) { - std::vector vecDestoyableObjects = - FindDestoyableGroundObjects(); - const double size = pBomb->GetWidth(); - const double size_2 = size / 2; - for (size_t i = 0; i < vecDestoyableObjects.size(); i++) { - const double x1 = pBomb->GetX() - size_2; - const double x2 = x1 + size; - if (vecDestoyableObjects[i]->isInside(x1, x2)) { - score += vecDestoyableObjects[i]->GetScore(); - DeleteStaticObj(vecDestoyableObjects[i]); - } - } -} - -void SBomber::DeleteDynamicObj(DynamicObject* pObj) { - auto it = vecDynamicObj.begin(); - for (; it != vecDynamicObj.end(); it++) { - if (*it == pObj) { - vecDynamicObj.erase(it); - break; - } - } -} - -void SBomber::DeleteStaticObj(GameObject* pObj) { - auto it = vecStaticObj.begin(); - for (; it != vecStaticObj.end(); it++) { - if (*it == pObj) { - vecStaticObj.erase(it); - break; - } - } -} - -std::vector SBomber::FindDestoyableGroundObjects() const { - std::vector vec; - Tank* pTank; - House* pHouse; - for (size_t i = 0; i < vecStaticObj.size(); i++) { - pTank = dynamic_cast(vecStaticObj[i]); - if (pTank != nullptr) { - vec.push_back(pTank); - continue; - } - - pHouse = dynamic_cast(vecStaticObj[i]); - if (pHouse != nullptr) { - vec.push_back(pHouse); - continue; - } - } - - return vec; -} - -Ground* SBomber::FindGround() const { - Ground* pGround; - - for (size_t i = 0; i < vecStaticObj.size(); i++) { - pGround = dynamic_cast(vecStaticObj[i]); - if (pGround != nullptr) { - return pGround; - } - } - - return nullptr; -} - -std::vector SBomber::FindAllBombs() const { - std::vector vecBombs; - - for (size_t i = 0; i < vecDynamicObj.size(); i++) { - Bomb* pBomb = dynamic_cast(vecDynamicObj[i]); - if (pBomb != nullptr) { - vecBombs.push_back(pBomb); - } - } - - return vecBombs; -} - -Plane* SBomber::FindPlane() const { - for (size_t i = 0; i < vecDynamicObj.size(); i++) { - Plane* p = dynamic_cast(vecDynamicObj[i]); - if (p != nullptr) { - return p; - } - } - - return nullptr; -} - -LevelGUI* SBomber::FindLevelGUI() const { - for (size_t i = 0; i < vecStaticObj.size(); i++) { - LevelGUI* p = dynamic_cast(vecStaticObj[i]); - if (p != nullptr) { - return p; - } - } - - return nullptr; -} - -void SBomber::ProcessKBHit() { - int c = getchar(); - - if (c == 224) { - c = getchar(); - } - - MyTools::LoggerSingleton::getInstance().WriteToLog(std::string(__func__) + " was invoked. key = ", c); - - switch (c) { - - case 27: // esc - exitFlag = true; - break; - - case 72: // up - FindPlane()->ChangePlaneY(-0.25); - break; - - case 80: // down - FindPlane()->ChangePlaneY(0.25); - break; - - case 'b': - DropBomb(); - break; - - case 'B': - DropBomb(); - break; - - default: - break; - } -} - -void SBomber::DrawFrame() { - MyTools::LoggerSingleton::getInstance().WriteToLog(std::string(__func__) + " was invoked"); - - for (size_t i = 0; i < vecDynamicObj.size(); i++) { - if (vecDynamicObj[i] != nullptr) { - vecDynamicObj[i]->Draw(); - } - } - - for (size_t i = 0; i < vecStaticObj.size(); i++) { - if (vecStaticObj[i] != nullptr) { - vecStaticObj[i]->Draw(); - } - } - - ScreenSingleton::getInstance().GotoXY(0, 0); - fps++; - - FindLevelGUI()->SetParam(passedTime, fps, bombsNumber, score); -} - -void SBomber::TimeStart() { - MyTools::LoggerSingleton::getInstance().WriteToLog(std::string(__func__) + " was invoked"); - startTime = std::chrono::duration_cast( - std::chrono::high_resolution_clock::now().time_since_epoch()).count(); -} - -void SBomber::TimeFinish() { - finishTime = std::chrono::duration_cast( - std::chrono::high_resolution_clock::now().time_since_epoch()).count(); - deltaTime = uint16_t(finishTime - startTime); - passedTime += deltaTime; - - MyTools::LoggerSingleton::getInstance().WriteToLog(std::string(__func__) + " deltaTime = ", (int)deltaTime); -} - -void SBomber::DropBomb() { - if (bombsNumber > 0) { +SBomber::SBomber() : exitFlag(false), startTime(0), finishTime(0), deltaTime(0), passedTime(0), fps(0), bombsNumber(10), score(0) +{ MyTools::LoggerSingleton::getInstance().WriteToLog(std::string(__func__) + " was invoked"); - Plane* pPlane = FindPlane(); - double x = pPlane->GetX() + 4; - double y = pPlane->GetY() + 2; + Plane *p = new Plane; + p->SetDirection(1, 0.1); + p->SetSpeed(4); + p->SetPos(5, 10); + vecDynamicObj.push_back(p); - Bomb* pBomb = new Bomb; - pBomb->SetDirection(0.3, 1); - pBomb->SetSpeed(2); - pBomb->SetPos(x, y); - pBomb->SetWidth(SMALL_CRATER_SIZE); + LevelGUI *pGUI = new LevelGUI; + pGUI->SetParam(passedTime, fps, bombsNumber, score); + const uint16_t maxX = ScreenSingleton::getInstance().GetMaxX(); + const uint16_t maxY = ScreenSingleton::getInstance().GetMaxY(); + const uint16_t offset = 3; + const uint16_t width = maxX - 7; + pGUI->SetPos(offset, offset); + pGUI->SetWidth(width); + pGUI->SetHeight(maxY - 4); + pGUI->SetFinishX(offset + width - 4); + vecStaticObj.push_back(pGUI); - vecDynamicObj.push_back(pBomb); - bombsNumber--; - score -= Bomb::BombCost; - } + Ground *pGr = new Ground; + const uint16_t groundY = maxY - 5; + pGr->SetPos(offset + 1, groundY); + pGr->SetWidth(width - 2); + vecStaticObj.push_back(pGr); + + Tank *pTank = new Tank; + pTank->SetWidth(13); + pTank->SetPos(30, groundY - 1); + vecStaticObj.push_back(pTank); + + pTank = new Tank; + pTank->SetWidth(13); + pTank->SetPos(50, groundY - 1); + vecStaticObj.push_back(pTank); + + House *pHouse = new House; + pHouse->SetWidth(13); + pHouse->SetPos(80, groundY - 1); + vecStaticObj.push_back(pHouse); + + /* + Bomb* pBomb = new Bomb; + pBomb->SetDirection(0.3, 1); + pBomb->SetSpeed(2); + pBomb->SetPos(51, 5); + pBomb->SetSize(SMALL_CRATER_SIZE); + vecDynamicObj.push_back(pBomb); + */ } + +SBomber::~SBomber() +{ + for (size_t i = 0; i < vecDynamicObj.size(); i++) + { + if (vecDynamicObj[i] != nullptr) + { + delete vecDynamicObj[i]; + } + } + + for (size_t i = 0; i < vecStaticObj.size(); i++) + { + if (vecStaticObj[i] != nullptr) + { + delete vecStaticObj[i]; + } + } +} + +void SBomber::MoveObjects() +{ + MyTools::LoggerSingleton::getInstance().WriteToLog(std::string(__func__) + " was invoked"); + + for (size_t i = 0; i < vecDynamicObj.size(); i++) + { + if (vecDynamicObj[i] != nullptr) + { + vecDynamicObj[i]->Move(deltaTime); + } + } +} +; + +void SBomber::CheckObjects() +{ + MyTools::LoggerSingleton::getInstance().WriteToLog(std::string(__func__) + " was invoked"); + + CheckPlaneAndLevelGUI(); + CheckBombsAndGround(); +} +; + +void SBomber::CheckPlaneAndLevelGUI() +{ + if (FindPlane()->GetX() > FindLevelGUI()->GetFinishX()) + { + exitFlag = true; + } +} + +void SBomber::CheckBombsAndGround() +{ + std::vector vecBombs = FindAllBombs(); + Ground *pGround = FindGround(); + const double y = pGround->GetY(); + for (size_t i = 0; i < vecBombs.size(); i++) + { + if (vecBombs[i]->GetY() >= y) + { + pGround->AddCrater(vecBombs[i]->GetX()); + CheckDestoyableObjects(vecBombs[i]); + DeleteDynamicObj(vecBombs[i]); + } + } +} + +void SBomber::CheckDestoyableObjects(Bomb *pBomb) +{ + std::vector vecDestoyableObjects = FindDestoyableGroundObjects(); + const double size = pBomb->GetWidth(); + const double size_2 = size / 2; + for (size_t i = 0; i < vecDestoyableObjects.size(); i++) + { + const double x1 = pBomb->GetX() - size_2; + const double x2 = x1 + size; + if (vecDestoyableObjects[i]->isInside(x1, x2)) + { + score += vecDestoyableObjects[i]->GetScore(); + DeleteStaticObj(vecDestoyableObjects[i]); + } + } +} + +void SBomber::DeleteDynamicObj(DynamicObject *pObj) +{ + auto it = vecDynamicObj.begin(); + for (; it != vecDynamicObj.end(); it++) + { + if (*it == pObj) + { + vecDynamicObj.erase(it); + break; + } + } +} + +void SBomber::DeleteStaticObj(GameObject *pObj) +{ + auto it = vecStaticObj.begin(); + for (; it != vecStaticObj.end(); it++) + { + if (*it == pObj) + { + vecStaticObj.erase(it); + break; + } + } +} + +std::vector SBomber::FindDestoyableGroundObjects() const +{ + std::vector vec; + Tank *pTank; + House *pHouse; + for (size_t i = 0; i < vecStaticObj.size(); i++) + { + pTank = dynamic_cast(vecStaticObj[i]); + if (pTank != nullptr) + { + vec.push_back(pTank); + continue; + } + + pHouse = dynamic_cast(vecStaticObj[i]); + if (pHouse != nullptr) + { + vec.push_back(pHouse); + continue; + } + } + + return vec; +} + +Ground* SBomber::FindGround() const +{ + Ground *pGround; + + for (size_t i = 0; i < vecStaticObj.size(); i++) + { + pGround = dynamic_cast(vecStaticObj[i]); + if (pGround != nullptr) + { + return pGround; + } + } + + return nullptr; +} + +std::vector SBomber::FindAllBombs() const +{ + std::vector vecBombs; + + for (size_t i = 0; i < vecDynamicObj.size(); i++) + { + Bomb *pBomb = dynamic_cast(vecDynamicObj[i]); + if (pBomb != nullptr) + { + vecBombs.push_back(pBomb); + } + } + + return vecBombs; +} + +Plane* SBomber::FindPlane() const +{ + for (size_t i = 0; i < vecDynamicObj.size(); i++) + { + Plane *p = dynamic_cast(vecDynamicObj[i]); + if (p != nullptr) + { + return p; + } + } + + return nullptr; +} + +LevelGUI* SBomber::FindLevelGUI() const +{ + for (size_t i = 0; i < vecStaticObj.size(); i++) + { + LevelGUI *p = dynamic_cast(vecStaticObj[i]); + if (p != nullptr) + { + return p; + } + } + + return nullptr; +} + +void SBomber::ProcessKBHit() +{ + int c = getchar(); + + if (c == 224) + { + c = getchar(); + } + + MyTools::LoggerSingleton::getInstance().WriteToLog(std::string(__func__) + " was invoked. key = ", c); + + switch (c) + { + + case 27: // esc + exitFlag = true; + break; + + case 72: // up + FindPlane()->ChangePlaneY(-0.25); + break; + + case 80: // down + FindPlane()->ChangePlaneY(0.25); + break; + + case 'b': + DropBomb(); + break; + + case 'B': + DropBomb(); + break; + + case 'd': + { + DestroyableGroundObject *clone = nullptr; + + std::vector vecDestoyableObjects = FindDestoyableGroundObjects(); + for (size_t i = 0; i < vecDestoyableObjects.size(); i++) + { + if (!clone) clone = vecDestoyableObjects[i]->clone(); + if (!vecDestoyableObjects[i]->isInside(clone->GetX(), clone->GetY())) + { + vecStaticObj.push_back(clone); + } + } + + break; + } + default: + break; + } +} + +void SBomber::DrawFrame() +{ + MyTools::LoggerSingleton::getInstance().WriteToLog(std::string(__func__) + " was invoked"); + + for (size_t i = 0; i < vecDynamicObj.size(); i++) + { + if (vecDynamicObj[i] != nullptr) + { + vecDynamicObj[i]->Draw(); + } + } + + for (size_t i = 0; i < vecStaticObj.size(); i++) + { + if (vecStaticObj[i] != nullptr) + { + vecStaticObj[i]->Draw(); + } + } + + ScreenSingleton::getInstance().GotoXY(0, 0); + fps++; + + FindLevelGUI()->SetParam(passedTime, fps, bombsNumber, score); +} + +void SBomber::TimeStart() +{ + MyTools::LoggerSingleton::getInstance().WriteToLog(std::string(__func__) + " was invoked"); + startTime = std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count(); +} + +void SBomber::TimeFinish() +{ + finishTime = std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count(); + deltaTime = uint16_t(finishTime - startTime); + passedTime += deltaTime; + + MyTools::LoggerSingleton::getInstance().WriteToLog(std::string(__func__) + " deltaTime = ", (int) deltaTime); +} + +void SBomber::DropBomb() +{ + if (bombsNumber > 0) + { + MyTools::LoggerSingleton::getInstance().WriteToLog(std::string(__func__) + " was invoked"); + + Plane *pPlane = FindPlane(); + double x = pPlane->GetX() + 4; + double y = pPlane->GetY() + 2; + + Bomb *pBomb = new Bomb; + pBomb->SetDirection(0.3, 1); + pBomb->SetSpeed(2); + pBomb->SetPos(x, y); + pBomb->SetWidth(SMALL_CRATER_SIZE); + + vecDynamicObj.push_back(pBomb); + bombsNumber--; + score -= Bomb::BombCost; + } +} + +void SBomber::AnimateScrolling() +{ + MyTools::LoggerSingleton::getInstance().WriteToLog(std::string(__FUNCTION__) + " was invoked"); + const size_t windowHeight = 10; // Размер окна для скроллинга + const size_t startX = MyTools::GetMaxX() / 2 - ScrollWidth / 2; + const size_t startY = MyTools::GetMaxY() / 2 - windowHeight / 2; + double curPos = 0; + do { + TimeStart(); + MyTools::ClrScr(); + + // вывод windowHeight строк из ppScroll используя смещение curPos + // ... + MyTools::GotoXY(0, 0); + TimeFinish(); + curPos += deltaTime * 0.0015; + + } while (!_kbhit() && int(curPos) <= (ScrollHeight - windowHeight)); + MyTools::ClrScr(); +} +