From 8402f4a449a1edf28e7e9b18a02602d8462fee7e Mon Sep 17 00:00:00 2001 From: EndrII Date: Fri, 25 Jun 2021 14:38:44 +0300 Subject: [PATCH 1/7] ref #63 added support extensions clasess --- src/Core/CMakeLists.txt | 1 + src/Core/Crawl/clasteritem.cpp | 2 +- src/Core/Crawl/guiobject.h | 2 +- src/Core/Crawl/iplayer.cpp | 6 +- src/Core/Crawl/iplayer.h | 9 ++- src/Core/Crawl/irender.h | 26 +++++++ src/Core/Crawl/iworld.cpp | 2 +- src/Core/Crawl/singleclasterworlditem.cpp | 10 ++- src/Core/Crawl/singleclasterworlditem.h | 8 ++- src/Core/Crawl/snake.cpp | 64 +++++++++++++++++ src/Core/Crawl/snake.h | 53 ++++++++++++++ src/Core/Crawl/snakeitem.cpp | 36 ++++++++++ src/Core/Crawl/snakeitem.h | 38 ++++++++++ .../Concept.md} | 65 ++++++++++++++--- src/Core/{Crawl => Extensions}/claster.cpp | 9 +-- src/Core/{Crawl => Extensions}/claster.h | 18 ++--- src/Core/Extensions/movableobject.cpp | 69 +++++++++++++++++++ .../{Crawl => Extensions}/movableobject.h | 21 ++++-- src/CrawlTestLvl | 2 +- tests/units/clasterstest.cpp | 6 +- 20 files changed, 404 insertions(+), 43 deletions(-) create mode 100644 src/Core/Crawl/snake.cpp create mode 100644 src/Core/Crawl/snake.h create mode 100644 src/Core/Crawl/snakeitem.cpp create mode 100644 src/Core/Crawl/snakeitem.h rename src/Core/{Crawl/movableobject.cpp => Extensions/Concept.md} (54%) rename src/Core/{Crawl => Extensions}/claster.cpp (80%) rename src/Core/{Crawl => Extensions}/claster.h (76%) create mode 100644 src/Core/Extensions/movableobject.cpp rename src/Core/{Crawl => Extensions}/movableobject.h (86%) diff --git a/src/Core/CMakeLists.txt b/src/Core/CMakeLists.txt index ff3f813..d02e49a 100644 --- a/src/Core/CMakeLists.txt +++ b/src/Core/CMakeLists.txt @@ -12,6 +12,7 @@ add_definitions(-DCRAWL_LIBRARY) file(GLOB SOURCE_CPP "*Crawl/*.cpp" + "*Extensions/*.cpp" "private/*.cpp" "*.qrc" "Crawl/*.qrc" diff --git a/src/Core/Crawl/clasteritem.cpp b/src/Core/Crawl/clasteritem.cpp index 6294640..50b4dd1 100644 --- a/src/Core/Crawl/clasteritem.cpp +++ b/src/Core/Crawl/clasteritem.cpp @@ -5,7 +5,7 @@ //# of this license document, but changing it is not allowed. //# -#include "claster.h" +#include "Extensions/claster.h" #include "clasteritem.h" ClasterItem::ClasterItem(const QString &name, diff --git a/src/Core/Crawl/guiobject.h b/src/Core/Crawl/guiobject.h index 2e4f8a7..58a7ee6 100644 --- a/src/Core/Crawl/guiobject.h +++ b/src/Core/Crawl/guiobject.h @@ -20,7 +20,7 @@ /** * @brief The GuiObject class This base model for gui objects. */ -class CRAWL_EXPORT GuiObject: public QObject, public IRender { +class CRAWL_EXPORT GuiObject: public QObject, virtual public IRender { Q_OBJECT Q_PROPERTY(QString color READ color WRITE setColor NOTIFY colorChanged) Q_PROPERTY(int guiId READ guiId NOTIFY guiIdChanged) diff --git a/src/Core/Crawl/iplayer.cpp b/src/Core/Crawl/iplayer.cpp index a9ee4dc..f37e676 100644 --- a/src/Core/Crawl/iplayer.cpp +++ b/src/Core/Crawl/iplayer.cpp @@ -11,7 +11,7 @@ IPlayer::IPlayer(const QString &name, const QString &viewTempalte, QObject *ptr): - MovableObject(name, viewTempalte, ptr) { + IWorldItem(name, viewTempalte, ptr) { } @@ -41,6 +41,10 @@ void IPlayer::fine(int value) { _currentPoints -= value; } +void IPlayer::render(unsigned int tbfMsec) { + MovableObject::render(tbfMsec); +} + float IPlayer::speed() const { return _speed; } diff --git a/src/Core/Crawl/iplayer.h b/src/Core/Crawl/iplayer.h index 94de13c..47f7266 100644 --- a/src/Core/Crawl/iplayer.h +++ b/src/Core/Crawl/iplayer.h @@ -10,14 +10,15 @@ #include "gameresult.h" #include "global.h" -#include "movableobject.h" +#include "iworlditem.h" +#include "Extensions/movableobject.h" class IControl; /** * @brief The IPlayer class This is base class of the player functions. */ -class CRAWL_EXPORT IPlayer: public MovableObject { +class CRAWL_EXPORT IPlayer: public IWorldItem, protected MovableObject { Q_OBJECT public: IPlayer(const QString& name, @@ -92,6 +93,8 @@ protected: */ void fine(int value); + void render(unsigned int tbfMsec) override; + protected slots: /** * @brief onTap This method invoked when user tap on screen. @@ -99,11 +102,13 @@ protected slots: */ virtual void onTap() = 0; + private: bool _fDead = false; int _currentPoints = 0; float _speed = 0; const IControl * _currentControl = nullptr; + }; #endif // IPLAYER_H diff --git a/src/Core/Crawl/irender.h b/src/Core/Crawl/irender.h index 7c996f4..c112095 100644 --- a/src/Core/Crawl/irender.h +++ b/src/Core/Crawl/irender.h @@ -9,10 +9,16 @@ #define IRENDER_H #include "global.h" +#include "quasarapp.h" /** * @brief The IRender class This interface provide render functionality for all objects. * @note Override the render method. + * @note The IRender Interface suppor extension concept + * + * ### Extension concept + * You can create child class of the IRender class and override the render method. But the render method will works with another class object using dynamic_cast of this pointer. + * */ class CRAWL_EXPORT IRender { public: @@ -24,6 +30,26 @@ public: * @param tbf This is time betwin frame in milesecunds. */ virtual void render(unsigned int tbfMsec) = 0; + + /** + * @brief checkminimumRequariedType This method check + * @return This object casted to Requared type this objct. + * + * **Example of use**: + * + * ```cpp + * auto _this = checkminimumRequariedType(); + * ``` + */ + template + Requared* checkminimumRequariedType() { + + Requared* result = dynamic_cast(this); + + debug_assert(result, "This render function not support this class"); + + return result; + }; }; #endif // IRENDER_H diff --git a/src/Core/Crawl/iworld.cpp b/src/Core/Crawl/iworld.cpp index 43ff9f1..e05734e 100644 --- a/src/Core/Crawl/iworld.cpp +++ b/src/Core/Crawl/iworld.cpp @@ -5,7 +5,7 @@ //# of this license document, but changing it is not allowed. //# -#include "claster.h" +#include "Extensions/claster.h" #include "iai.h" #include "iworld.h" #include "iworlditem.h" diff --git a/src/Core/Crawl/singleclasterworlditem.cpp b/src/Core/Crawl/singleclasterworlditem.cpp index 6bada5e..46769fb 100644 --- a/src/Core/Crawl/singleclasterworlditem.cpp +++ b/src/Core/Crawl/singleclasterworlditem.cpp @@ -6,7 +6,7 @@ //# -#include "claster.h" +#include "Extensions/claster.h" #include "singleclasterworlditem.h" #include "quasarapp.h" @@ -26,3 +26,11 @@ void SingleClasterWorldItem::setClaster(Claster *claster) { ClasterItem::setClaster(claster); } + +Claster *SingleClasterWorldItem::parentClaster() const { + if (parentClastersCount() <= 0 ) { + return nullptr; + } + + return *ClasterItem::parentClasters().begin(); +} diff --git a/src/Core/Crawl/singleclasterworlditem.h b/src/Core/Crawl/singleclasterworlditem.h index 875cef9..cd9969f 100644 --- a/src/Core/Crawl/singleclasterworlditem.h +++ b/src/Core/Crawl/singleclasterworlditem.h @@ -24,7 +24,7 @@ public: SingleClasterWorldItem(const QString& name, const QString& viewTempalte = DEFAULT_VIEW_TEMPLATE, QObject *ptr = nullptr); -private: +protected: /** * @brief setClaster invoked when object added to new claster. @@ -33,6 +33,12 @@ private: */ void setClaster(Claster *claster) override; + /** + * @brief parentClaster This method is wraper of the ClasterItem::parentClasters method. + * @return pointer to the parent claster object. + */ + Claster* parentClaster() const; + friend class Claster; }; diff --git a/src/Core/Crawl/snake.cpp b/src/Core/Crawl/snake.cpp new file mode 100644 index 0000000..51a4747 --- /dev/null +++ b/src/Core/Crawl/snake.cpp @@ -0,0 +1,64 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "clasteritem.h" +#include "snake.h" +#include "snakeitem.h" +#include +#include + +Snake::Snake(const QString &name, const QString &viewTempalte, QObject *ptr): + IPlayer (name, viewTempalte, ptr) { + +} + +void Snake::render(unsigned int tbfMsec) { + IPlayer::render(tbfMsec); +} + +void Snake::add(ClasterItem *object) { + if (auto snakeItem = dynamic_cast(object)) { + snakeItem->setPrev(_lastSnakeItem->guiId()); + _lastSnakeItem = static_cast(snakeItem); + + Claster::add(object); + return ; + } + + QuasarAppUtils::Params::log("Failed to add item to Snake." + " You need to use the SnakeItem child class as a argument", + QuasarAppUtils::Error); +} + +void Snake::remove(ClasterItem *object) { + + if (_lastSnakeItem == object) { + _lastSnakeItem = getItem(static_cast(_lastSnakeItem)->prev()); + } + + return Claster::remove(object); +} + +void Snake::remove(int id) { + if (_lastSnakeItem->guiId() == id) { + _lastSnakeItem = getItem(static_cast(_lastSnakeItem)->prev()); + } + + return Claster::remove(id); +} + +void Snake::onTap() { + +} + +float Snake::lengthBetwinItems() const{ + return _lengthBetwinItems; +} + +void Snake::setLengthBetwinItems(float newLengthBetwinItems) { + _lengthBetwinItems = newLengthBetwinItems; +} diff --git a/src/Core/Crawl/snake.h b/src/Core/Crawl/snake.h new file mode 100644 index 0000000..cd4cfd5 --- /dev/null +++ b/src/Core/Crawl/snake.h @@ -0,0 +1,53 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef SNAKE_H +#define SNAKE_H + +#include "iplayer.h" +#include "Extensions/claster.h" + +/** + * @brief The Snake class This class implement render mehod for snake object. + */ +class CRAWL_EXPORT Snake : public IPlayer, public Claster +{ + Q_OBJECT +public: + Snake(const QString& name, + const QString& viewTempalte = DEFAULT_VIEW_TEMPLATE, + QObject *ptr = nullptr); + + void render(unsigned int tbfMsec) override; + + void add(ClasterItem *object) override; + void remove(ClasterItem *object) override; + void remove(int id) override; + + // IPlayer interface + /** + * @brief lengthBetwinItems This method return length betwin snake items; + * @return length betwin snake items + */ + float lengthBetwinItems() const; + + /** + * @brief setLengthBetwinItems This method sets length betwin snake items. + * @param newLengthBetwinItems This is new value of the length betwin snake items. + */ + void setLengthBetwinItems(float newLengthBetwinItems); + +protected slots: + void onTap() override; + +private: + float _lengthBetwinItems = 0; + const IWorldItem* _lastSnakeItem = nullptr; + +}; + +#endif // SNAKE_H diff --git a/src/Core/Crawl/snakeitem.cpp b/src/Core/Crawl/snakeitem.cpp new file mode 100644 index 0000000..8a06b2f --- /dev/null +++ b/src/Core/Crawl/snakeitem.cpp @@ -0,0 +1,36 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "snake.h" +#include "snakeitem.h" + +SnakeItem::SnakeItem(const QString itemName): SingleClasterWorldItem(itemName) { + +} + +void SnakeItem::setPrev(int newPrev) { + _prev = newPrev; +} + +void SnakeItem::render(unsigned int tbfMsec) { + auto prev = getItem(_prev); + auto ratationVector = (prev->position() - position()); + + if (auto claster = static_cast(parentClaster())) { + if (ratationVector.length() < claster->lengthBetwinItems()) { + setMovableVector({0,0,0}); + } else { + setMovableVector(ratationVector *= claster->speed()); + } + } + + MovableObject::render(tbfMsec); +} + +int SnakeItem::prev() const { + return _prev; +} diff --git a/src/Core/Crawl/snakeitem.h b/src/Core/Crawl/snakeitem.h new file mode 100644 index 0000000..8bba9f8 --- /dev/null +++ b/src/Core/Crawl/snakeitem.h @@ -0,0 +1,38 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +#ifndef SNAKEITEM_H +#define SNAKEITEM_H + +#include "singleclasterworlditem.h" +#include "Extensions/movableobject.h" + +class CRAWL_EXPORT SnakeItem: public SingleClasterWorldItem, protected MovableObject +{ + Q_OBJECT +public: + SnakeItem(const QString itemName = "SnakeItem"); + + /** + * @brief setPrev This method sets id of the previous snake item. + * @param newPrev this is new value of the id of previous snake item. + */ + void setPrev(int newPrev); + void render(unsigned int tbfMsec) override; + + /** + * @brief prev This method return prev object of snake + * @return id of the prev objects of the snake + */ + int prev() const; + +private: + int _prev = -1; +}; + +#endif // SNAKEITEM_H diff --git a/src/Core/Crawl/movableobject.cpp b/src/Core/Extensions/Concept.md similarity index 54% rename from src/Core/Crawl/movableobject.cpp rename to src/Core/Extensions/Concept.md index 38340e8..b0d08ac 100644 --- a/src/Core/Crawl/movableobject.cpp +++ b/src/Core/Extensions/Concept.md @@ -1,21 +1,68 @@ -#include "movableobject.h" -#include +# Extension concept -MovableObject::MovableObject(const QString &name, - const QString &viewTempalte, - QObject *ptr): - IWorldItem(name, viewTempalte, ptr) { +The extension it is separate module class with custom function. + +## How to use + +1. Create own child class from IRender interface. +2. Override the IRender::render method of base interface +3. Check compatibility betwin this type and requred type using the IRender::checkminimumRequariedType method. +4. In the render method using dynamic_cast operator get neede interface of class object. +5. Implement needed functions for object. + + +## Example: + +Movable object header: + +```cpp + +class CRAWL_EXPORT MovableObject: public virtual IRender +{ + +public: + MovableObject(); + + void render(unsigned int tbfMsec) override; + + const QVector3D &movableVector() const; + + void setMovableVector(const QVector3D &newMovableVector); + + float angularVelocity() const; + + void setAngularVelocity(float newAngularVelocity); + + float breakingForce() const; + + void setBreakingForce(float newBreakingForce); + +private: + QVector3D _movableVector; + QVector3D _currentMovableVector; + + float _angularVelocity = 0; + float _breakingForce = 0; +}; +``` + +Movable object source: + +```cpp +MovableObject::MovableObject() +{ } void MovableObject::render(unsigned int tbfMsec) { + auto _this = checkminimumRequariedType(); // get object center position - QVector3D currentPosition = position(); + QVector3D currentPosition = _this->position(); // move object to vector currentPosition += (_currentMovableVector * (tbfMsec / 1000.0)); - setposition(currentPosition); + _this->setposition(currentPosition); // calc temp vector betvin user moveble vector and real moveble vector QVector3D tempVector = _movableVector - _currentMovableVector ; @@ -59,3 +106,5 @@ float MovableObject::breakingForce() const { void MovableObject::setBreakingForce(float newBreakingForce) { _breakingForce = newBreakingForce; } + +``` diff --git a/src/Core/Crawl/claster.cpp b/src/Core/Extensions/claster.cpp similarity index 80% rename from src/Core/Crawl/claster.cpp rename to src/Core/Extensions/claster.cpp index 5f37fa2..75ede55 100644 --- a/src/Core/Crawl/claster.cpp +++ b/src/Core/Extensions/claster.cpp @@ -6,14 +6,9 @@ //# #include "claster.h" -#include "singleclasterworlditem.h" +#include "Crawl/singleclasterworlditem.h" -Claster::Claster(const QString &name, - const QString &viewTempalte, - QObject *ptr): - IWorldItem(name, viewTempalte, ptr) { - -} +Claster::Claster() {} Claster::~Claster() { for (auto child : qAsConst(_objects)) { diff --git a/src/Core/Crawl/claster.h b/src/Core/Extensions/claster.h similarity index 76% rename from src/Core/Crawl/claster.h rename to src/Core/Extensions/claster.h index d341d24..dcfac7d 100644 --- a/src/Core/Crawl/claster.h +++ b/src/Core/Extensions/claster.h @@ -15,34 +15,33 @@ class ClasterItem; /** * @brief The Claster class are object with support multiple objects render. * For example snake with 20 points of the snake blocks. + * @note The claster object is extansion for the IWorldItems objects. */ -class CRAWL_EXPORT Claster: public IWorldItem +class CRAWL_EXPORT Claster { - Q_OBJECT public: - Claster(const QString& name, - const QString& viewTempalte = DEFAULT_VIEW_TEMPLATE, - QObject *ptr = nullptr); + Claster(); - ~Claster(); + virtual ~Claster(); /** * @brief add This method added new object to claster. * @param object This is model of added object + * @note if you want you can override this methods for extend functionality of this class. */ - void add(ClasterItem* object); + virtual void add(ClasterItem* object); /** * @brief remove This method remove object from claster * @param object poiter of removed object */ - void remove(ClasterItem* object); + virtual void remove(ClasterItem* object); /** * @brief remove some as a Claster::remove(IWorldItem* object) but by id. * @param id of the remved object. */ - void remove(int id); + virtual void remove(int id); /** * @brief objects This method return list of collected objects. @@ -52,6 +51,7 @@ public: private: QHash _objects; + }; #endif // CLASTER_H diff --git a/src/Core/Extensions/movableobject.cpp b/src/Core/Extensions/movableobject.cpp new file mode 100644 index 0000000..c5ee4d9 --- /dev/null +++ b/src/Core/Extensions/movableobject.cpp @@ -0,0 +1,69 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +#include "movableobject.h" + +#include + +MovableObject::MovableObject() { + +} + +void MovableObject::render(unsigned int tbfMsec) { + + + if (auto _this = checkminimumRequariedType()) { + // get object center position + QVector3D currentPosition = _this->position(); + + // move object to vector + currentPosition += (_currentMovableVector * (tbfMsec / 1000.0)); + _this->setposition(currentPosition); + + // calc temp vector betvin user moveble vector and real moveble vector + QVector3D tempVector = _movableVector - _currentMovableVector ; + + // calc change on this iteration for new moveble vector + float delta = std::min(_angularVelocity * (tbfMsec / 1000.0), static_cast(tempVector.length())); + + // resize temp vector for calc changes of the movableVector + tempVector = tempVector.normalized() * delta; + + // recalc new currentMovable vector (applay changes) + _currentMovableVector += tempVector; + + float newMovableVectorLength = std::max(_movableVector.length() - (_breakingForce * (tbfMsec / 1000.0)), 0.0); + + // update movable vector + _movableVector = _movableVector.normalized() * newMovableVectorLength; + } +} + +const QVector3D &MovableObject::movableVector() const { + return _movableVector; +} + +void MovableObject::setMovableVector(const QVector3D &newMovableVector) { + _movableVector = newMovableVector; +} + +float MovableObject::angularVelocity() const { + return _angularVelocity; +} + +void MovableObject::setAngularVelocity(float newAngularVelocity) { + _angularVelocity = newAngularVelocity; +} + +float MovableObject::breakingForce() const { + return _breakingForce; +} + +void MovableObject::setBreakingForce(float newBreakingForce) { + _breakingForce = newBreakingForce; +} diff --git a/src/Core/Crawl/movableobject.h b/src/Core/Extensions/movableobject.h similarity index 86% rename from src/Core/Crawl/movableobject.h rename to src/Core/Extensions/movableobject.h index 5b4e834..4d070fc 100644 --- a/src/Core/Crawl/movableobject.h +++ b/src/Core/Extensions/movableobject.h @@ -1,7 +1,17 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + #ifndef MOVABLEOBJECT_H #define MOVABLEOBJECT_H -#include "iworlditem.h" +#include "Crawl/irender.h" + +#include /** * @brief The MovableObject class contains functions for moving object on the world. @@ -12,13 +22,11 @@ * * **Angular velocity** This property sets spead of the angle moving. * * **Braking force** This property are delta decriment the Power of the movable vector on time. */ -class CRAWL_EXPORT MovableObject: public IWorldItem +class CRAWL_EXPORT MovableObject: public virtual IRender { - Q_OBJECT + public: - MovableObject(const QString& name, - const QString& viewTempalte = DEFAULT_VIEW_TEMPLATE, - QObject *ptr = nullptr); + MovableObject(); /** * @brief render This impplementation of the render method add simulation of the physics in the vacuum space. @@ -72,7 +80,6 @@ private: float _angularVelocity = 0; float _breakingForce = 0; - }; #endif // MOVABLEOBJECT_H diff --git a/src/CrawlTestLvl b/src/CrawlTestLvl index 46878c1..931c937 160000 --- a/src/CrawlTestLvl +++ b/src/CrawlTestLvl @@ -1 +1 @@ -Subproject commit 46878c18cae14eed67a2b105dc993ff2d670a3bc +Subproject commit 931c937cb076766714e74a8241db8ebb78d6633d diff --git a/tests/units/clasterstest.cpp b/tests/units/clasterstest.cpp index 78151f4..7a39ad5 100644 --- a/tests/units/clasterstest.cpp +++ b/tests/units/clasterstest.cpp @@ -7,16 +7,16 @@ #include "clasterstest.h" #include -#include +#include #include #include #include // Test claster object. -class TestClasterObject: public Claster { +class TestClasterObject: public IWorldItem, public Claster { public: - TestClasterObject(): Claster("TestClaster"){}; + TestClasterObject(): IWorldItem("TestClaster"){}; protected: void onIntersects(const IWorldItem *) {}; }; From 95a1d6d631be7350d6d690722172337cc713d04b Mon Sep 17 00:00:00 2001 From: EndrII Date: Fri, 25 Jun 2021 14:38:44 +0300 Subject: [PATCH 2/7] ref #63 added support extensions clasess --- src/Core/CMakeLists.txt | 1 + src/Core/Crawl/clasteritem.cpp | 2 +- src/Core/Crawl/guiobject.h | 2 +- src/Core/Crawl/iplayer.cpp | 6 +- src/Core/Crawl/iplayer.h | 9 ++- src/Core/Crawl/irender.h | 26 +++++++ src/Core/Crawl/iworld.cpp | 2 +- src/Core/Crawl/singleclasterworlditem.cpp | 10 ++- src/Core/Crawl/singleclasterworlditem.h | 8 ++- src/Core/Crawl/snake.cpp | 64 +++++++++++++++++ src/Core/Crawl/snake.h | 53 ++++++++++++++ src/Core/Crawl/snakeitem.cpp | 36 ++++++++++ src/Core/Crawl/snakeitem.h | 38 ++++++++++ .../Concept.md} | 65 ++++++++++++++--- src/Core/{Crawl => Extensions}/claster.cpp | 9 +-- src/Core/{Crawl => Extensions}/claster.h | 18 ++--- src/Core/Extensions/movableobject.cpp | 69 +++++++++++++++++++ .../{Crawl => Extensions}/movableobject.h | 21 ++++-- src/CrawlTestLvl | 2 +- tests/units/clasterstest.cpp | 6 +- 20 files changed, 404 insertions(+), 43 deletions(-) create mode 100644 src/Core/Crawl/snake.cpp create mode 100644 src/Core/Crawl/snake.h create mode 100644 src/Core/Crawl/snakeitem.cpp create mode 100644 src/Core/Crawl/snakeitem.h rename src/Core/{Crawl/movableobject.cpp => Extensions/Concept.md} (54%) rename src/Core/{Crawl => Extensions}/claster.cpp (80%) rename src/Core/{Crawl => Extensions}/claster.h (76%) create mode 100644 src/Core/Extensions/movableobject.cpp rename src/Core/{Crawl => Extensions}/movableobject.h (86%) diff --git a/src/Core/CMakeLists.txt b/src/Core/CMakeLists.txt index ff3f813..d02e49a 100644 --- a/src/Core/CMakeLists.txt +++ b/src/Core/CMakeLists.txt @@ -12,6 +12,7 @@ add_definitions(-DCRAWL_LIBRARY) file(GLOB SOURCE_CPP "*Crawl/*.cpp" + "*Extensions/*.cpp" "private/*.cpp" "*.qrc" "Crawl/*.qrc" diff --git a/src/Core/Crawl/clasteritem.cpp b/src/Core/Crawl/clasteritem.cpp index 6294640..50b4dd1 100644 --- a/src/Core/Crawl/clasteritem.cpp +++ b/src/Core/Crawl/clasteritem.cpp @@ -5,7 +5,7 @@ //# of this license document, but changing it is not allowed. //# -#include "claster.h" +#include "Extensions/claster.h" #include "clasteritem.h" ClasterItem::ClasterItem(const QString &name, diff --git a/src/Core/Crawl/guiobject.h b/src/Core/Crawl/guiobject.h index fe88eb6..25d7127 100644 --- a/src/Core/Crawl/guiobject.h +++ b/src/Core/Crawl/guiobject.h @@ -52,7 +52,7 @@ * } * ``` */ -class CRAWL_EXPORT GuiObject: public QObject, public IRender { +class CRAWL_EXPORT GuiObject: public QObject, virtual public IRender { Q_OBJECT Q_PROPERTY(QString color READ color WRITE setColor NOTIFY colorChanged) Q_PROPERTY(int guiId READ guiId NOTIFY guiIdChanged) diff --git a/src/Core/Crawl/iplayer.cpp b/src/Core/Crawl/iplayer.cpp index a9ee4dc..f37e676 100644 --- a/src/Core/Crawl/iplayer.cpp +++ b/src/Core/Crawl/iplayer.cpp @@ -11,7 +11,7 @@ IPlayer::IPlayer(const QString &name, const QString &viewTempalte, QObject *ptr): - MovableObject(name, viewTempalte, ptr) { + IWorldItem(name, viewTempalte, ptr) { } @@ -41,6 +41,10 @@ void IPlayer::fine(int value) { _currentPoints -= value; } +void IPlayer::render(unsigned int tbfMsec) { + MovableObject::render(tbfMsec); +} + float IPlayer::speed() const { return _speed; } diff --git a/src/Core/Crawl/iplayer.h b/src/Core/Crawl/iplayer.h index 94de13c..47f7266 100644 --- a/src/Core/Crawl/iplayer.h +++ b/src/Core/Crawl/iplayer.h @@ -10,14 +10,15 @@ #include "gameresult.h" #include "global.h" -#include "movableobject.h" +#include "iworlditem.h" +#include "Extensions/movableobject.h" class IControl; /** * @brief The IPlayer class This is base class of the player functions. */ -class CRAWL_EXPORT IPlayer: public MovableObject { +class CRAWL_EXPORT IPlayer: public IWorldItem, protected MovableObject { Q_OBJECT public: IPlayer(const QString& name, @@ -92,6 +93,8 @@ protected: */ void fine(int value); + void render(unsigned int tbfMsec) override; + protected slots: /** * @brief onTap This method invoked when user tap on screen. @@ -99,11 +102,13 @@ protected slots: */ virtual void onTap() = 0; + private: bool _fDead = false; int _currentPoints = 0; float _speed = 0; const IControl * _currentControl = nullptr; + }; #endif // IPLAYER_H diff --git a/src/Core/Crawl/irender.h b/src/Core/Crawl/irender.h index 7c996f4..c112095 100644 --- a/src/Core/Crawl/irender.h +++ b/src/Core/Crawl/irender.h @@ -9,10 +9,16 @@ #define IRENDER_H #include "global.h" +#include "quasarapp.h" /** * @brief The IRender class This interface provide render functionality for all objects. * @note Override the render method. + * @note The IRender Interface suppor extension concept + * + * ### Extension concept + * You can create child class of the IRender class and override the render method. But the render method will works with another class object using dynamic_cast of this pointer. + * */ class CRAWL_EXPORT IRender { public: @@ -24,6 +30,26 @@ public: * @param tbf This is time betwin frame in milesecunds. */ virtual void render(unsigned int tbfMsec) = 0; + + /** + * @brief checkminimumRequariedType This method check + * @return This object casted to Requared type this objct. + * + * **Example of use**: + * + * ```cpp + * auto _this = checkminimumRequariedType(); + * ``` + */ + template + Requared* checkminimumRequariedType() { + + Requared* result = dynamic_cast(this); + + debug_assert(result, "This render function not support this class"); + + return result; + }; }; #endif // IRENDER_H diff --git a/src/Core/Crawl/iworld.cpp b/src/Core/Crawl/iworld.cpp index 43ff9f1..e05734e 100644 --- a/src/Core/Crawl/iworld.cpp +++ b/src/Core/Crawl/iworld.cpp @@ -5,7 +5,7 @@ //# of this license document, but changing it is not allowed. //# -#include "claster.h" +#include "Extensions/claster.h" #include "iai.h" #include "iworld.h" #include "iworlditem.h" diff --git a/src/Core/Crawl/singleclasterworlditem.cpp b/src/Core/Crawl/singleclasterworlditem.cpp index 6bada5e..46769fb 100644 --- a/src/Core/Crawl/singleclasterworlditem.cpp +++ b/src/Core/Crawl/singleclasterworlditem.cpp @@ -6,7 +6,7 @@ //# -#include "claster.h" +#include "Extensions/claster.h" #include "singleclasterworlditem.h" #include "quasarapp.h" @@ -26,3 +26,11 @@ void SingleClasterWorldItem::setClaster(Claster *claster) { ClasterItem::setClaster(claster); } + +Claster *SingleClasterWorldItem::parentClaster() const { + if (parentClastersCount() <= 0 ) { + return nullptr; + } + + return *ClasterItem::parentClasters().begin(); +} diff --git a/src/Core/Crawl/singleclasterworlditem.h b/src/Core/Crawl/singleclasterworlditem.h index 875cef9..cd9969f 100644 --- a/src/Core/Crawl/singleclasterworlditem.h +++ b/src/Core/Crawl/singleclasterworlditem.h @@ -24,7 +24,7 @@ public: SingleClasterWorldItem(const QString& name, const QString& viewTempalte = DEFAULT_VIEW_TEMPLATE, QObject *ptr = nullptr); -private: +protected: /** * @brief setClaster invoked when object added to new claster. @@ -33,6 +33,12 @@ private: */ void setClaster(Claster *claster) override; + /** + * @brief parentClaster This method is wraper of the ClasterItem::parentClasters method. + * @return pointer to the parent claster object. + */ + Claster* parentClaster() const; + friend class Claster; }; diff --git a/src/Core/Crawl/snake.cpp b/src/Core/Crawl/snake.cpp new file mode 100644 index 0000000..51a4747 --- /dev/null +++ b/src/Core/Crawl/snake.cpp @@ -0,0 +1,64 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "clasteritem.h" +#include "snake.h" +#include "snakeitem.h" +#include +#include + +Snake::Snake(const QString &name, const QString &viewTempalte, QObject *ptr): + IPlayer (name, viewTempalte, ptr) { + +} + +void Snake::render(unsigned int tbfMsec) { + IPlayer::render(tbfMsec); +} + +void Snake::add(ClasterItem *object) { + if (auto snakeItem = dynamic_cast(object)) { + snakeItem->setPrev(_lastSnakeItem->guiId()); + _lastSnakeItem = static_cast(snakeItem); + + Claster::add(object); + return ; + } + + QuasarAppUtils::Params::log("Failed to add item to Snake." + " You need to use the SnakeItem child class as a argument", + QuasarAppUtils::Error); +} + +void Snake::remove(ClasterItem *object) { + + if (_lastSnakeItem == object) { + _lastSnakeItem = getItem(static_cast(_lastSnakeItem)->prev()); + } + + return Claster::remove(object); +} + +void Snake::remove(int id) { + if (_lastSnakeItem->guiId() == id) { + _lastSnakeItem = getItem(static_cast(_lastSnakeItem)->prev()); + } + + return Claster::remove(id); +} + +void Snake::onTap() { + +} + +float Snake::lengthBetwinItems() const{ + return _lengthBetwinItems; +} + +void Snake::setLengthBetwinItems(float newLengthBetwinItems) { + _lengthBetwinItems = newLengthBetwinItems; +} diff --git a/src/Core/Crawl/snake.h b/src/Core/Crawl/snake.h new file mode 100644 index 0000000..cd4cfd5 --- /dev/null +++ b/src/Core/Crawl/snake.h @@ -0,0 +1,53 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef SNAKE_H +#define SNAKE_H + +#include "iplayer.h" +#include "Extensions/claster.h" + +/** + * @brief The Snake class This class implement render mehod for snake object. + */ +class CRAWL_EXPORT Snake : public IPlayer, public Claster +{ + Q_OBJECT +public: + Snake(const QString& name, + const QString& viewTempalte = DEFAULT_VIEW_TEMPLATE, + QObject *ptr = nullptr); + + void render(unsigned int tbfMsec) override; + + void add(ClasterItem *object) override; + void remove(ClasterItem *object) override; + void remove(int id) override; + + // IPlayer interface + /** + * @brief lengthBetwinItems This method return length betwin snake items; + * @return length betwin snake items + */ + float lengthBetwinItems() const; + + /** + * @brief setLengthBetwinItems This method sets length betwin snake items. + * @param newLengthBetwinItems This is new value of the length betwin snake items. + */ + void setLengthBetwinItems(float newLengthBetwinItems); + +protected slots: + void onTap() override; + +private: + float _lengthBetwinItems = 0; + const IWorldItem* _lastSnakeItem = nullptr; + +}; + +#endif // SNAKE_H diff --git a/src/Core/Crawl/snakeitem.cpp b/src/Core/Crawl/snakeitem.cpp new file mode 100644 index 0000000..8a06b2f --- /dev/null +++ b/src/Core/Crawl/snakeitem.cpp @@ -0,0 +1,36 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "snake.h" +#include "snakeitem.h" + +SnakeItem::SnakeItem(const QString itemName): SingleClasterWorldItem(itemName) { + +} + +void SnakeItem::setPrev(int newPrev) { + _prev = newPrev; +} + +void SnakeItem::render(unsigned int tbfMsec) { + auto prev = getItem(_prev); + auto ratationVector = (prev->position() - position()); + + if (auto claster = static_cast(parentClaster())) { + if (ratationVector.length() < claster->lengthBetwinItems()) { + setMovableVector({0,0,0}); + } else { + setMovableVector(ratationVector *= claster->speed()); + } + } + + MovableObject::render(tbfMsec); +} + +int SnakeItem::prev() const { + return _prev; +} diff --git a/src/Core/Crawl/snakeitem.h b/src/Core/Crawl/snakeitem.h new file mode 100644 index 0000000..8bba9f8 --- /dev/null +++ b/src/Core/Crawl/snakeitem.h @@ -0,0 +1,38 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +#ifndef SNAKEITEM_H +#define SNAKEITEM_H + +#include "singleclasterworlditem.h" +#include "Extensions/movableobject.h" + +class CRAWL_EXPORT SnakeItem: public SingleClasterWorldItem, protected MovableObject +{ + Q_OBJECT +public: + SnakeItem(const QString itemName = "SnakeItem"); + + /** + * @brief setPrev This method sets id of the previous snake item. + * @param newPrev this is new value of the id of previous snake item. + */ + void setPrev(int newPrev); + void render(unsigned int tbfMsec) override; + + /** + * @brief prev This method return prev object of snake + * @return id of the prev objects of the snake + */ + int prev() const; + +private: + int _prev = -1; +}; + +#endif // SNAKEITEM_H diff --git a/src/Core/Crawl/movableobject.cpp b/src/Core/Extensions/Concept.md similarity index 54% rename from src/Core/Crawl/movableobject.cpp rename to src/Core/Extensions/Concept.md index 38340e8..b0d08ac 100644 --- a/src/Core/Crawl/movableobject.cpp +++ b/src/Core/Extensions/Concept.md @@ -1,21 +1,68 @@ -#include "movableobject.h" -#include +# Extension concept -MovableObject::MovableObject(const QString &name, - const QString &viewTempalte, - QObject *ptr): - IWorldItem(name, viewTempalte, ptr) { +The extension it is separate module class with custom function. + +## How to use + +1. Create own child class from IRender interface. +2. Override the IRender::render method of base interface +3. Check compatibility betwin this type and requred type using the IRender::checkminimumRequariedType method. +4. In the render method using dynamic_cast operator get neede interface of class object. +5. Implement needed functions for object. + + +## Example: + +Movable object header: + +```cpp + +class CRAWL_EXPORT MovableObject: public virtual IRender +{ + +public: + MovableObject(); + + void render(unsigned int tbfMsec) override; + + const QVector3D &movableVector() const; + + void setMovableVector(const QVector3D &newMovableVector); + + float angularVelocity() const; + + void setAngularVelocity(float newAngularVelocity); + + float breakingForce() const; + + void setBreakingForce(float newBreakingForce); + +private: + QVector3D _movableVector; + QVector3D _currentMovableVector; + + float _angularVelocity = 0; + float _breakingForce = 0; +}; +``` + +Movable object source: + +```cpp +MovableObject::MovableObject() +{ } void MovableObject::render(unsigned int tbfMsec) { + auto _this = checkminimumRequariedType(); // get object center position - QVector3D currentPosition = position(); + QVector3D currentPosition = _this->position(); // move object to vector currentPosition += (_currentMovableVector * (tbfMsec / 1000.0)); - setposition(currentPosition); + _this->setposition(currentPosition); // calc temp vector betvin user moveble vector and real moveble vector QVector3D tempVector = _movableVector - _currentMovableVector ; @@ -59,3 +106,5 @@ float MovableObject::breakingForce() const { void MovableObject::setBreakingForce(float newBreakingForce) { _breakingForce = newBreakingForce; } + +``` diff --git a/src/Core/Crawl/claster.cpp b/src/Core/Extensions/claster.cpp similarity index 80% rename from src/Core/Crawl/claster.cpp rename to src/Core/Extensions/claster.cpp index 5f37fa2..75ede55 100644 --- a/src/Core/Crawl/claster.cpp +++ b/src/Core/Extensions/claster.cpp @@ -6,14 +6,9 @@ //# #include "claster.h" -#include "singleclasterworlditem.h" +#include "Crawl/singleclasterworlditem.h" -Claster::Claster(const QString &name, - const QString &viewTempalte, - QObject *ptr): - IWorldItem(name, viewTempalte, ptr) { - -} +Claster::Claster() {} Claster::~Claster() { for (auto child : qAsConst(_objects)) { diff --git a/src/Core/Crawl/claster.h b/src/Core/Extensions/claster.h similarity index 76% rename from src/Core/Crawl/claster.h rename to src/Core/Extensions/claster.h index d341d24..dcfac7d 100644 --- a/src/Core/Crawl/claster.h +++ b/src/Core/Extensions/claster.h @@ -15,34 +15,33 @@ class ClasterItem; /** * @brief The Claster class are object with support multiple objects render. * For example snake with 20 points of the snake blocks. + * @note The claster object is extansion for the IWorldItems objects. */ -class CRAWL_EXPORT Claster: public IWorldItem +class CRAWL_EXPORT Claster { - Q_OBJECT public: - Claster(const QString& name, - const QString& viewTempalte = DEFAULT_VIEW_TEMPLATE, - QObject *ptr = nullptr); + Claster(); - ~Claster(); + virtual ~Claster(); /** * @brief add This method added new object to claster. * @param object This is model of added object + * @note if you want you can override this methods for extend functionality of this class. */ - void add(ClasterItem* object); + virtual void add(ClasterItem* object); /** * @brief remove This method remove object from claster * @param object poiter of removed object */ - void remove(ClasterItem* object); + virtual void remove(ClasterItem* object); /** * @brief remove some as a Claster::remove(IWorldItem* object) but by id. * @param id of the remved object. */ - void remove(int id); + virtual void remove(int id); /** * @brief objects This method return list of collected objects. @@ -52,6 +51,7 @@ public: private: QHash _objects; + }; #endif // CLASTER_H diff --git a/src/Core/Extensions/movableobject.cpp b/src/Core/Extensions/movableobject.cpp new file mode 100644 index 0000000..c5ee4d9 --- /dev/null +++ b/src/Core/Extensions/movableobject.cpp @@ -0,0 +1,69 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +#include "movableobject.h" + +#include + +MovableObject::MovableObject() { + +} + +void MovableObject::render(unsigned int tbfMsec) { + + + if (auto _this = checkminimumRequariedType()) { + // get object center position + QVector3D currentPosition = _this->position(); + + // move object to vector + currentPosition += (_currentMovableVector * (tbfMsec / 1000.0)); + _this->setposition(currentPosition); + + // calc temp vector betvin user moveble vector and real moveble vector + QVector3D tempVector = _movableVector - _currentMovableVector ; + + // calc change on this iteration for new moveble vector + float delta = std::min(_angularVelocity * (tbfMsec / 1000.0), static_cast(tempVector.length())); + + // resize temp vector for calc changes of the movableVector + tempVector = tempVector.normalized() * delta; + + // recalc new currentMovable vector (applay changes) + _currentMovableVector += tempVector; + + float newMovableVectorLength = std::max(_movableVector.length() - (_breakingForce * (tbfMsec / 1000.0)), 0.0); + + // update movable vector + _movableVector = _movableVector.normalized() * newMovableVectorLength; + } +} + +const QVector3D &MovableObject::movableVector() const { + return _movableVector; +} + +void MovableObject::setMovableVector(const QVector3D &newMovableVector) { + _movableVector = newMovableVector; +} + +float MovableObject::angularVelocity() const { + return _angularVelocity; +} + +void MovableObject::setAngularVelocity(float newAngularVelocity) { + _angularVelocity = newAngularVelocity; +} + +float MovableObject::breakingForce() const { + return _breakingForce; +} + +void MovableObject::setBreakingForce(float newBreakingForce) { + _breakingForce = newBreakingForce; +} diff --git a/src/Core/Crawl/movableobject.h b/src/Core/Extensions/movableobject.h similarity index 86% rename from src/Core/Crawl/movableobject.h rename to src/Core/Extensions/movableobject.h index 5b4e834..4d070fc 100644 --- a/src/Core/Crawl/movableobject.h +++ b/src/Core/Extensions/movableobject.h @@ -1,7 +1,17 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + #ifndef MOVABLEOBJECT_H #define MOVABLEOBJECT_H -#include "iworlditem.h" +#include "Crawl/irender.h" + +#include /** * @brief The MovableObject class contains functions for moving object on the world. @@ -12,13 +22,11 @@ * * **Angular velocity** This property sets spead of the angle moving. * * **Braking force** This property are delta decriment the Power of the movable vector on time. */ -class CRAWL_EXPORT MovableObject: public IWorldItem +class CRAWL_EXPORT MovableObject: public virtual IRender { - Q_OBJECT + public: - MovableObject(const QString& name, - const QString& viewTempalte = DEFAULT_VIEW_TEMPLATE, - QObject *ptr = nullptr); + MovableObject(); /** * @brief render This impplementation of the render method add simulation of the physics in the vacuum space. @@ -72,7 +80,6 @@ private: float _angularVelocity = 0; float _breakingForce = 0; - }; #endif // MOVABLEOBJECT_H diff --git a/src/CrawlTestLvl b/src/CrawlTestLvl index 46878c1..931c937 160000 --- a/src/CrawlTestLvl +++ b/src/CrawlTestLvl @@ -1 +1 @@ -Subproject commit 46878c18cae14eed67a2b105dc993ff2d670a3bc +Subproject commit 931c937cb076766714e74a8241db8ebb78d6633d diff --git a/tests/units/clasterstest.cpp b/tests/units/clasterstest.cpp index 78151f4..7a39ad5 100644 --- a/tests/units/clasterstest.cpp +++ b/tests/units/clasterstest.cpp @@ -7,16 +7,16 @@ #include "clasterstest.h" #include -#include +#include #include #include #include // Test claster object. -class TestClasterObject: public Claster { +class TestClasterObject: public IWorldItem, public Claster { public: - TestClasterObject(): Claster("TestClaster"){}; + TestClasterObject(): IWorldItem("TestClaster"){}; protected: void onIntersects(const IWorldItem *) {}; }; From d5afbd889b8aaa276ac57cf2f3368377e686bff6 Mon Sep 17 00:00:00 2001 From: EndrII Date: Mon, 28 Jun 2021 18:16:27 +0300 Subject: [PATCH 3/7] added bas snake class --- src/Core/Crawl/guiobject.cpp | 1 + src/Core/Crawl/irender.h | 5 ++ src/Core/Crawl/iworld.cpp | 16 ++++-- src/Core/Crawl/iworld.h | 12 ++-- src/Core/Crawl/iworlditem.cpp | 2 + src/Core/Crawl/iworlditem.h | 2 +- src/Core/Crawl/snake.cpp | 80 ++++++++++++++++++++++++++- src/Core/Crawl/snake.h | 55 +++++++++++++++++- src/Core/CrawlModule/GraphicItem.qml | 17 ++---- src/Core/CrawlModule/Scene.qml | 6 +- src/Core/Extensions/movableobject.cpp | 61 +++++++++++--------- src/Core/Extensions/movableobject.h | 22 +++++++- src/Core/private/engine.cpp | 4 +- src/CrawlTestLvl | 2 +- 14 files changed, 222 insertions(+), 63 deletions(-) diff --git a/src/Core/Crawl/guiobject.cpp b/src/Core/Crawl/guiobject.cpp index a80bf63..2ab3e22 100644 --- a/src/Core/Crawl/guiobject.cpp +++ b/src/Core/Crawl/guiobject.cpp @@ -14,6 +14,7 @@ GuiObject::GuiObject(const QString &name, const QString &viewTempalte, QObject * _viewTemplate = viewTempalte; _className = name; generateId(); + setRatation({1,1,0,0}); } QString GuiObject::color() const { diff --git a/src/Core/Crawl/irender.h b/src/Core/Crawl/irender.h index c112095..e468370 100644 --- a/src/Core/Crawl/irender.h +++ b/src/Core/Crawl/irender.h @@ -31,6 +31,11 @@ public: */ virtual void render(unsigned int tbfMsec) = 0; + /** + * @brief init This method should be invoked after create object. + */ + virtual void init() = 0; + /** * @brief checkminimumRequariedType This method check * @return This object casted to Requared type this objct. diff --git a/src/Core/Crawl/iworld.cpp b/src/Core/Crawl/iworld.cpp index e05734e..6962b17 100644 --- a/src/Core/Crawl/iworld.cpp +++ b/src/Core/Crawl/iworld.cpp @@ -24,9 +24,11 @@ IWorld::IWorld() { } IWorld::~IWorld() { - deinit(); + reset(); } +void IWorld::init() {prepare();} + IControl *IWorld::initUserInterface() const { return new DefaultControl; } @@ -97,7 +99,7 @@ void IWorld::setPlayer(QObject *newPlayer) { } _player = newPlayerObject; - addAtomicItem(_player); + addItem(_player); emit playerChanged(); } @@ -129,7 +131,7 @@ IWorldItem *IWorld::getItem(int id) const { return _items.value(id, nullptr); } -bool IWorld::init() { +bool IWorld::prepare() { if (isInit()) return true; @@ -144,12 +146,12 @@ bool IWorld::init() { if (!isInit()) { QuasarAppUtils::Params::log("Failed to init world implementation."); - deinit(); + reset(); return false; } if (!_worldRules->size()) { - deinit(); + reset(); return false; } @@ -173,6 +175,8 @@ void IWorld::addItem(IWorldItem *obj, QList *addedObjectsList) { if (!obj) return; + obj->init(); + // Work wih claster if (auto claster = dynamic_cast(obj)) { for (auto item : claster->objects()) { @@ -218,7 +222,7 @@ void IWorld::removeItem(int id, QList *removedObjectsList) { } -void IWorld::deinit() { +void IWorld::reset() { if (_player) { delete _player; _player = nullptr; diff --git a/src/Core/Crawl/iworld.h b/src/Core/Crawl/iworld.h index be5126c..9c49231 100644 --- a/src/Core/Crawl/iworld.h +++ b/src/Core/Crawl/iworld.h @@ -51,7 +51,9 @@ class CRAWL_EXPORT IWorld : public QObject, public IRender public: IWorld(); - virtual ~IWorld(); + ~IWorld() override; + + void init() override; /** * @brief initPlayer The implementation of This interface must be return playerObject. @@ -354,12 +356,12 @@ private slots: private: /** - * @brief init This method initialize world object. + * @brief prepare This method initialize world object. * @note If object alredy initalize then this method do nothing. - * @return + * @return true if world initialized successful */ - bool init(); - void deinit(); + bool prepare(); + void reset(); void worldChanged(const WorldObjects& objects); void clearItems(); diff --git a/src/Core/Crawl/iworlditem.cpp b/src/Core/Crawl/iworlditem.cpp index 9db8175..4475555 100644 --- a/src/Core/Crawl/iworlditem.cpp +++ b/src/Core/Crawl/iworlditem.cpp @@ -42,6 +42,8 @@ void IWorldItem::render(unsigned int) { } } +void IWorldItem::init() {} + void IWorldItem::initOnWorld(const IWorld *world, const IWorldItem * player) { _world = world; _playerObject = player; diff --git a/src/Core/Crawl/iworlditem.h b/src/Core/Crawl/iworlditem.h index 5f42158..3459237 100644 --- a/src/Core/Crawl/iworlditem.h +++ b/src/Core/Crawl/iworlditem.h @@ -31,6 +31,7 @@ public: * @note new position = playerPosition + scaneSize; */ void render(unsigned int tbfMsec) override; + void init() override; protected: @@ -60,7 +61,6 @@ private: const IWorld* _world = nullptr; const IWorldItem *_playerObject = nullptr; friend class IWorld; - }; #endif // IWORLDITEM_H diff --git a/src/Core/Crawl/snake.cpp b/src/Core/Crawl/snake.cpp index 51a4747..15355e9 100644 --- a/src/Core/Crawl/snake.cpp +++ b/src/Core/Crawl/snake.cpp @@ -14,6 +14,14 @@ Snake::Snake(const QString &name, const QString &viewTempalte, QObject *ptr): IPlayer (name, viewTempalte, ptr) { + _vectors = new QVector3D[2]; + _vectors[0] = QVector3D(50,50,0); // left tap + _vectors[1] = QVector3D(50,-50,0); // right tap + +} + +Snake::~Snake( ){ + delete [] _vectors; } void Snake::render(unsigned int tbfMsec) { @@ -22,7 +30,13 @@ void Snake::render(unsigned int tbfMsec) { void Snake::add(ClasterItem *object) { if (auto snakeItem = dynamic_cast(object)) { - snakeItem->setPrev(_lastSnakeItem->guiId()); + + if (_lastSnakeItem) { + snakeItem->setPrev(_lastSnakeItem->guiId()); + } else { + snakeItem->setPrev(guiId()); + } + _lastSnakeItem = static_cast(snakeItem); Claster::add(object); @@ -51,8 +65,70 @@ void Snake::remove(int id) { return Claster::remove(id); } -void Snake::onTap() { +void Snake::init() { + generateBody(); +} +void Snake::onTap() { + setMovableVector(_vectors[_clickIndex++ % 2]); +} + +void Snake::generateBody() { + + auto scaleIt = _scales.begin(); + + for(int i = 0; i < _bodyCount; ++i) { + if (!_factory) { + QuasarAppUtils::Params::log("Please use the registerBodyitem method" + " before invoke parent constructor.", + QuasarAppUtils::Error); + return; + } + + auto item = _factory(); + + float scale = 1; + if (scaleIt != _scales.end()) { + float position = static_cast(i) / _bodyCount; + float from = 0, fromKey = 0; + float to = 0, toKey = 0; + while (position > scaleIt.value() && scaleIt != _scales.end()) { + scaleIt++; + + if (scaleIt != _scales.end()) { + from = (scaleIt - 1).value(); + to = scaleIt.value(); + fromKey = (scaleIt - 1).key(); + toKey = scaleIt.key(); + } + } + + scale = ((position - fromKey) * toKey / (to - from)) + from; + + scaleIt.value(); + + } + + item->setSize(item->size() * scale); + + add(item); + } +} + +int Snake::bodyCount() const { + return _bodyCount; +} + +void Snake::setBodyCount(int newBodyCount) { + _bodyCount = newBodyCount; +} + +const QMap &Snake::scales() const { + return _scales; +} + +void Snake::setScales(const QMap &newScales) { + _scales = newScales; } float Snake::lengthBetwinItems() const{ diff --git a/src/Core/Crawl/snake.h b/src/Core/Crawl/snake.h index cd4cfd5..77de7af 100644 --- a/src/Core/Crawl/snake.h +++ b/src/Core/Crawl/snake.h @@ -21,12 +21,15 @@ public: Snake(const QString& name, const QString& viewTempalte = DEFAULT_VIEW_TEMPLATE, QObject *ptr = nullptr); + ~Snake() override; void render(unsigned int tbfMsec) override; void add(ClasterItem *object) override; void remove(ClasterItem *object) override; void remove(int id) override; + void init() override; + // IPlayer interface /** @@ -41,12 +44,62 @@ public: */ void setLengthBetwinItems(float newLengthBetwinItems); + template + /** + * @brief registerBodyitem This method register snake body item type. The body items will be generated in the generateBody method. The size of body companents calc from the Snake::scales property. + */ + void registerBodyitem() { + _factory = [](){ + return new Type; + }; + } + + /** + * @brief scales This method return the map of the snake body scales. + * The key of map are position of snake Body and the value are scale factor of current body item. + * The default scales map of snake are: + * ``` + * 0.1 - 0.7 + * 0.6 - 1 + * 1 - 0.1 + * ``` + * @return scales map of snake body. + */ + const QMap &scales() const; + + /** + * @brief setScales This method sets new scales map for snake body. + * @param newScales This is new value of the scales map. + */ + void setScales(const QMap &newScales); + + /** + * @brief bodyCount This method return count of the body items of this snake. + * @return count of body items of the snake. + */ + int bodyCount() const; + + /** + * @brief setBodyCount This method sets new size of snake. + * @param newBodyCount this is new value of the body count. + * @note Use This method in the constructor of your child snake class. + */ + void setBodyCount(int newBodyCount); + protected slots: void onTap() override; private: - float _lengthBetwinItems = 0; + void generateBody(); + + QMap _scales; + std::function _factory = nullptr; + + float _lengthBetwinItems = 10; + int _bodyCount = 10; const IWorldItem* _lastSnakeItem = nullptr; + unsigned int _clickIndex = 0; + QVector3D* _vectors; }; diff --git a/src/Core/CrawlModule/GraphicItem.qml b/src/Core/CrawlModule/GraphicItem.qml index d4c7459..ae839dd 100644 --- a/src/Core/CrawlModule/GraphicItem.qml +++ b/src/Core/CrawlModule/GraphicItem.qml @@ -13,7 +13,10 @@ Model { property var model: null property int guiId: (model) ? model.guiId : -1; - property bool fMapColor: model && (model.baseColorMap.length || model.emissiveMap.length || model.roughnessMap.length || model.normalMap.length) + property bool fMapColor: model && (model.baseColorMap.length || + model.emissiveMap.length || + model.roughnessMap.length || + model.normalMap.length) DefaultMaterial { id: defaultMaterial @@ -38,15 +41,3 @@ Model { position: (model) ? model.position: Qt.vector3d(0,0,0); } - -//Model { -// source: "#Cube"; -// property var model: null -// property int guiId: (model) ? model.guiId : -1; -// materials: [ -// DefaultMaterial { -// id: defaultMaterial -// diffuseColor: "#ff1111" -// } -// ] -//} diff --git a/src/Core/CrawlModule/Scene.qml b/src/Core/CrawlModule/Scene.qml index 6c1d6a0..fdafa5f 100644 --- a/src/Core/CrawlModule/Scene.qml +++ b/src/Core/CrawlModule/Scene.qml @@ -23,10 +23,6 @@ View3D { : Qt.vector3d(0,0,100) - onPositionChanged: { - console.log(position) - } - rotation: (privateRoot.world)? privateRoot.world.cameraRatation: Qt.quaternion(0,0,0,0) } @@ -82,7 +78,7 @@ View3D { obj.model = model.getGameObject(cppObjId); arrayObjects.push(obj) } else { - console.log("wrong viewTemplate in model"); + console.log("wrong viewTemplate in model " + temp.errorString()); } } diff --git a/src/Core/Extensions/movableobject.cpp b/src/Core/Extensions/movableobject.cpp index c5ee4d9..26de9cb 100644 --- a/src/Core/Extensions/movableobject.cpp +++ b/src/Core/Extensions/movableobject.cpp @@ -7,7 +7,7 @@ #include "movableobject.h" - +#include #include MovableObject::MovableObject() { @@ -16,31 +16,9 @@ MovableObject::MovableObject() { void MovableObject::render(unsigned int tbfMsec) { - if (auto _this = checkminimumRequariedType()) { - // get object center position - QVector3D currentPosition = _this->position(); - - // move object to vector - currentPosition += (_currentMovableVector * (tbfMsec / 1000.0)); - _this->setposition(currentPosition); - - // calc temp vector betvin user moveble vector and real moveble vector - QVector3D tempVector = _movableVector - _currentMovableVector ; - - // calc change on this iteration for new moveble vector - float delta = std::min(_angularVelocity * (tbfMsec / 1000.0), static_cast(tempVector.length())); - - // resize temp vector for calc changes of the movableVector - tempVector = tempVector.normalized() * delta; - - // recalc new currentMovable vector (applay changes) - _currentMovableVector += tempVector; - - float newMovableVectorLength = std::max(_movableVector.length() - (_breakingForce * (tbfMsec / 1000.0)), 0.0); - - // update movable vector - _movableVector = _movableVector.normalized() * newMovableVectorLength; + renderPosition(_this, tbfMsec); + renderRatation(_this, tbfMsec); } } @@ -67,3 +45,36 @@ float MovableObject::breakingForce() const { void MovableObject::setBreakingForce(float newBreakingForce) { _breakingForce = newBreakingForce; } + +void MovableObject::renderRatation(GuiObject *object, unsigned int) { + if (_currentMovableVector.length() > 0) { + object->setRatation(QQuaternion::rotationTo({1.0f, 0.0, 0.0}, _currentMovableVector)); + } +} + +void MovableObject::renderPosition(GuiObject *object, unsigned int tbfMsec) { + // get object center position + QVector3D currentPosition = object->position(); + + // move object to vector + currentPosition += (_currentMovableVector * (tbfMsec / 1000.0)); + object->setposition(currentPosition); + + // calc temp vector betvin user moveble vector and real moveble vector + QVector3D tempVector = _movableVector - _currentMovableVector ; + + // calc change on this iteration for new moveble vector + float delta = std::min(_angularVelocity * (tbfMsec / 1000.0), static_cast(tempVector.length())); + + // resize temp vector for calc changes of the movableVector + tempVector = tempVector.normalized() * delta; + + // recalc new currentMovable vector (applay changes) + _currentMovableVector += tempVector; + + float newMovableVectorLength = std::max(_movableVector.length() - (_breakingForce * (tbfMsec / 1000.0)), 0.0); + + // update movable vector + _movableVector = _movableVector.normalized() * newMovableVectorLength; + +} diff --git a/src/Core/Extensions/movableobject.h b/src/Core/Extensions/movableobject.h index 4d070fc..8948e2a 100644 --- a/src/Core/Extensions/movableobject.h +++ b/src/Core/Extensions/movableobject.h @@ -10,9 +10,10 @@ #define MOVABLEOBJECT_H #include "Crawl/irender.h" - #include +class GuiObject; + /** * @brief The MovableObject class contains functions for moving object on the world. * All moving separate to next properties: @@ -45,7 +46,8 @@ public: /** * @brief setMovableVector This method sets new value of the mvable vector. - * @param newMovableVector - this is a new value ofthe movable vector + * @param newMovableVector this is a new value ofthe movable vector + * @note The movable vector will be changed in time if you set the MovableObject::breakingForce propertye to non 0 value. */ void setMovableVector(const QVector3D &newMovableVector); @@ -74,6 +76,22 @@ public: */ void setBreakingForce(float newBreakingForce); +protected: + + /** + * @brief renderRatation This method recalc raration for an @a object. The Default implementation converts movableVector to ratation of an @a object. + * @param object This is provessing object. Usually @a an object is casted pointer of this to GuiObject type. + * @param tbfMsec This is time betwin frames argument. soame as in the IRender::render function. + */ + virtual void renderRatation(GuiObject* object, unsigned int tbfMsec); + + /** + * @brief renderRatation This method recalc position for an @a object. The Default implementation move the current movable vector to setts movable vector. For example if you invoke the MovableObject::setMovableVector method then object change current movable vector with spead MovableObject::angularVelocity. If you sets + * @param object This is provessing object. Usually @a an object is casted pointer of this to GuiObject type. + * @param tbfMsec This is time betwin frames argument. soame as in the IRender::render function. + */ + virtual void renderPosition(GuiObject* object, unsigned int tbfMsec); + private: QVector3D _movableVector; QVector3D _currentMovableVector; diff --git a/src/Core/private/engine.cpp b/src/Core/private/engine.cpp index c73c9f4..a9987f6 100644 --- a/src/Core/private/engine.cpp +++ b/src/Core/private/engine.cpp @@ -40,12 +40,12 @@ void Engine::setWorld(IWorld *world) { return ; if (_currentWorld) { - _currentWorld->deinit(); + _currentWorld->reset(); } _currentWorld = world; - if (!_currentWorld->init()) { + if (!_currentWorld->prepare()) { QuasarAppUtils::Params::log("Failed to init world. World name: " + _currentWorld->name(), QuasarAppUtils::Error); diff --git a/src/CrawlTestLvl b/src/CrawlTestLvl index 931c937..b0804c7 160000 --- a/src/CrawlTestLvl +++ b/src/CrawlTestLvl @@ -1 +1 @@ -Subproject commit 931c937cb076766714e74a8241db8ebb78d6633d +Subproject commit b0804c7c9c6ef2214e37d26869179923faa3ac41 From 04ceb5fc134746a2719731419fd84dc3dd724b14 Mon Sep 17 00:00:00 2001 From: EndrII Date: Tue, 29 Jun 2021 20:24:57 +0300 Subject: [PATCH 4/7] ref #63 "fix movable objects of snake " --- src/Core/Crawl/iplayer.cpp | 22 -------- src/Core/Crawl/iplayer.h | 30 +---------- src/Core/Crawl/iworld.cpp | 73 ++++++++++++++++----------- src/Core/Crawl/iworld.h | 42 ++++++++++----- src/Core/Crawl/snake.cpp | 49 +++++++++++++----- src/Core/Crawl/snake.h | 27 +++++++--- src/Core/Crawl/snakeitem.cpp | 23 +++++---- src/Core/Crawl/snakeitem.h | 12 ++--- src/Core/CrawlModule/Scene.qml | 16 +----- src/Core/Extensions/movableobject.cpp | 11 +++- src/Core/Extensions/movableobject.h | 6 +++ src/Core/private/engine.cpp | 40 +++++++-------- src/Core/private/engine.h | 9 +--- src/CrawlTestLvl | 2 +- 14 files changed, 187 insertions(+), 175 deletions(-) diff --git a/src/Core/Crawl/iplayer.cpp b/src/Core/Crawl/iplayer.cpp index f37e676..a7b7752 100644 --- a/src/Core/Crawl/iplayer.cpp +++ b/src/Core/Crawl/iplayer.cpp @@ -27,16 +27,6 @@ void IPlayer::reward(int value) { _currentPoints += value; } -float IPlayer::speedUp(float increment) { - setSpeed(_speed + increment); - return _speed; -} - -float IPlayer::setSpeedDown(float decrement) { - setSpeed(_speed - decrement); - return _speed; -} - void IPlayer::fine(int value) { _currentPoints -= value; } @@ -45,18 +35,6 @@ void IPlayer::render(unsigned int tbfMsec) { MovableObject::render(tbfMsec); } -float IPlayer::speed() const { - return _speed; -} - -void IPlayer::setSpeed(float newSpead) { - _speed = newSpead; - - if (_speed < 0) { - _speed = 0; - } -} - void IPlayer::setControl(const IControl *control) { diff --git a/src/Core/Crawl/iplayer.h b/src/Core/Crawl/iplayer.h index 47f7266..61f8b3c 100644 --- a/src/Core/Crawl/iplayer.h +++ b/src/Core/Crawl/iplayer.h @@ -18,7 +18,7 @@ class IControl; /** * @brief The IPlayer class This is base class of the player functions. */ -class CRAWL_EXPORT IPlayer: public IWorldItem, protected MovableObject { +class CRAWL_EXPORT IPlayer: public IWorldItem, public MovableObject { Q_OBJECT public: IPlayer(const QString& name, @@ -37,18 +37,6 @@ public: */ bool isDead() const; - /** - * @brief speed This method return current speed of the snake. - * @return current speed - */ - float speed() const; - - /** - * @brief setSpeed This method sets new value for player spead. - * @param newSpead This is a new value of a snake speed. - */ - void setSpeed(float newSpead); - /** * @brief setControl This method should be connect player object with control object. * @param control This is control object. @@ -71,21 +59,6 @@ protected: */ void reward(int value); - /** - * @brief speedUp This method increment snake speed. - * @param increment This is value that will added to a snake speed. - * @return new snake speed. - */ - float speedUp(float increment); - - /** - * @brief setSpeedDown This method decrement snake speed. - * @param decrement This is value that will take away from a snake speed. - * @return new snake speed. - * @note return 0 if a snake speed less than a decrement value. - */ - float setSpeedDown(float decrement); - /** * @brief fine This method remove reward for player. * @param value This is fine amount; @@ -106,7 +79,6 @@ protected slots: private: bool _fDead = false; int _currentPoints = 0; - float _speed = 0; const IControl * _currentControl = nullptr; }; diff --git a/src/Core/Crawl/iworld.cpp b/src/Core/Crawl/iworld.cpp index 6962b17..8286d56 100644 --- a/src/Core/Crawl/iworld.cpp +++ b/src/Core/Crawl/iworld.cpp @@ -46,11 +46,13 @@ void IWorld::render(unsigned int tbfMsec) { } } + _ItemsMutex.unlock(); + + if (_player->isDead()) { emit sigGameFinished(_player->getCurrentStatus()); } - _ItemsMutex.unlock(); int waitTime = 1000 / _targetFps - tbfMsec; if (waitTime > 0) @@ -67,7 +69,6 @@ void IWorld::initPlayerControl(IControl *control) { bool IWorld::start() { _player->setposition({0,0,0}); - _player->setSpeed(0); setWorldStatus(WorldStatus::Game); _backgroundAI->stopAI(); @@ -94,9 +95,8 @@ void IWorld::setPlayer(QObject *newPlayer) { return; } - if (_player) { - removeIAtomicItem(_player->guiId()); - } + if (_player) + removeItem(_player->guiId()); _player = newPlayerObject; addItem(_player); @@ -138,7 +138,7 @@ bool IWorld::prepare() { _worldRules = initWorldRules(); - _hdrMap = initHdrBackGround(); + setHdr(initHdrBackGround()); setPlayer(initPlayer()); _player->initOnWorld(this, _player); _userInterface = initUserInterface(); @@ -176,20 +176,25 @@ void IWorld::addItem(IWorldItem *obj, QList *addedObjectsList) { return; obj->init(); + Diff diff; // Work wih claster if (auto claster = dynamic_cast(obj)) { for (auto item : claster->objects()) { addAtomicItem(item); - if (item && addedObjectsList) { - addedObjectsList->push_back(item->guiId()); + if (item) { + diff.addedIds.push_back(item->guiId()); } } } addAtomicItem(obj); + diff.addedIds.push_back(obj->guiId()); + if (addedObjectsList) - addedObjectsList->push_back(obj->guiId()); + *addedObjectsList = diff.addedIds; + + emit sigOBjctsListChanged(diff); } @@ -200,26 +205,31 @@ void IWorld::removeItem(int id, QList *removedObjectsList) { if (!obj) return; + Diff diff; + // Work wih claster if (auto claster = dynamic_cast(obj)) { - auto copyOfObjectsList = claster->objects(); + const auto copyOfObjectsList = claster->objects(); for (auto item : copyOfObjectsList) { if (!item || !item->parentClastersCount()) continue; int id = item->guiId(); - removeIAtomicItem(item); + removeAtomicItem(item); if (removedObjectsList) - removedObjectsList->push_back(id); + diff.removeIds.push_back(id); } } - addAtomicItem(obj); - if (removedObjectsList) - removedObjectsList->push_back(obj->guiId()); + removeAtomicItem(obj); + diff.removeIds.push_back(id); + if (removedObjectsList) + *removedObjectsList = diff.removeIds; + + emit sigOBjctsListChanged(diff); } void IWorld::reset() { @@ -244,7 +254,7 @@ void IWorld::reset() { } clearItems(); - _hdrMap = ""; + setHdr(""); } @@ -261,7 +271,7 @@ void IWorld::addAtomicItem(IWorldItem* obj) { obj->initOnWorld(this, _player); } -bool IWorld::removeIAtomicItem(int id) { +bool IWorld::removeAtomicItem(int id) { QMutexLocker lock(&_ItemsMutex); auto obj = _items.value(id); @@ -278,7 +288,7 @@ bool IWorld::removeIAtomicItem(int id) { return true; } -bool IWorld::removeIAtomicItem(IWorldItem *obj) { +bool IWorld::removeAtomicItem(IWorldItem *obj) { if (!obj) { return false; } @@ -307,6 +317,14 @@ void IWorld::setTargetFps(int newTargetFps) { _targetFps = newTargetFps; } +void IWorld::setHdr(const QString &hdr) { + if (hdr == _hdrMap) + return; + + _hdrMap = hdr; + emit hdrChanged(); +} + const QQuaternion &IWorld::cameraRatation() const { return _cameraRatation; } @@ -346,33 +364,26 @@ const QVector3D &IWorld::cameraReleativePosition() const { return _cameraReleativePosition; } -const QString &IWorld::hdrMap() const { - return _hdrMap; -} +void IWorld::worldChanged(WorldObjects objects) { -void IWorld::worldChanged(const WorldObjects &objects) { + objects[_player->className()] = 1; - Diff diff; for (auto it = objects.begin(); it != objects.end(); ++it) { int count = it.value() - _itemsGroup.count(it.key()); if (count > 0) { for ( int i = 0; i < count; ++i ) { - addItem(generate(it.key()), &diff.addedIds); + addItem(generate(it.key())); } } else { for (; count < 0; ++count ) { - removeAnyItemFromGroup(it.key(), &diff.removeIds); + removeAnyItemFromGroup(it.key()); } } } - - if (diff.addedIds.size() || diff.removeIds.size()) - emit sigOBjctsListChanged(diff); } - int IWorld::wordlStatus() const { return _worldStatus; } @@ -385,3 +396,7 @@ void IWorld::setWorldStatus(int newWorldStatus) { emit worldStatusChanged(); } + +const QString &IWorld::hdr() const { + return _hdrMap; +} diff --git a/src/Core/Crawl/iworld.h b/src/Core/Crawl/iworld.h index 9c49231..a5dd534 100644 --- a/src/Core/Crawl/iworld.h +++ b/src/Core/Crawl/iworld.h @@ -46,6 +46,7 @@ class CRAWL_EXPORT IWorld : public QObject, public IRender Q_PROPERTY(QVector3D cameraReleativePosition READ cameraReleativePosition NOTIFY cameraReleativePositionChanged) Q_PROPERTY(QQuaternion cameraRatation READ cameraRatation NOTIFY cameraRatationChanged) Q_PROPERTY(QObject * player READ player WRITE setPlayer NOTIFY playerChanged) + Q_PROPERTY(QString hdr READ hdr NOTIFY hdrChanged) Q_PROPERTY(int worldStatus READ wordlStatus WRITE setWorldStatus NOTIFY worldStatusChanged) @@ -167,12 +168,6 @@ public: */ IWorldItem *getItem(int id) const; - /** - * @brief hdrMap This method return path to hdr map of world. - * @return - */ - const QString &hdrMap() const; - /** * @brief cameraReleativePosition return a releative of player camera position. * @return @@ -221,6 +216,12 @@ public: */ QObject *player() const; + /** + * @brief hdr This method return path to hdr map of the lvl. + * @return path to hdr map of this lvl. + */ + const QString &hdr() const; + signals: /** * @brief sigGameFinished This signal emit when game are finished @@ -260,6 +261,11 @@ signals: */ void playerChanged(); + /** + * @brief hdrChanged This signal emited when the hdr map are changed. + */ + void hdrChanged(); + protected: /** @@ -313,6 +319,12 @@ protected: */ void setTargetFps(int newTargetFps); + /** + * @brief setHdr This method sets new path to hdr map of this lvl. + * @param hdr path to hdr map. + */ + void setHdr(const QString& hdr); + template /** @@ -363,7 +375,13 @@ private: bool prepare(); void reset(); - void worldChanged(const WorldObjects& objects); + /** + * @brief worldChanged This method generate diff for the qml + * @param objects This is list of object on lvl + * @note This method addd player object to this list. + */ + void worldChanged(WorldObjects objects); + void clearItems(); /** @@ -389,18 +407,18 @@ private: void addAtomicItem(IWorldItem *obj); /** - * @brief removeIAtomictem This method remove object with @a id. This method work with atomic objects only. If you rty remove claster objects then it will be ramoved witohout child objects. + * @brief removeAtomicItem This method remove object with @a id. This method work with atomic objects only. If you rty remove claster objects then it will be ramoved witohout child objects. * @param id This is id of removed objects. * @return return true if object remove successul */ - bool removeIAtomicItem(int id); + bool removeAtomicItem(int id); /** - * @brief removeIAtomicItem This method remove object @a obj. This method work with atomic objects only. If you rty remove claster objects then it will be ramoved witohout child objects. + * @brief removeAtomicItem This method remove object @a obj. This method work with atomic objects only. If you rty remove claster objects then it will be ramoved witohout child objects. * @param obj This is id of removed objects. * @return return true if object remove successul */ - bool removeIAtomicItem(IWorldItem *obj); + bool removeAtomicItem(IWorldItem *obj); /** * @brief removeAnyItemFromGroup This method remove any object from group and return id of removed object. If The objec are claster then this method remove all child objects. @@ -413,6 +431,7 @@ private: QHash _items; QMultiHash _itemsGroup; + QMultiHash _lastItemsGroup; mutable QMutex _ItemsMutex; @@ -434,7 +453,6 @@ private: // testing friend class ClastersTest; - }; #endif // IWORLD_H diff --git a/src/Core/Crawl/snake.cpp b/src/Core/Crawl/snake.cpp index 15355e9..9ac0996 100644 --- a/src/Core/Crawl/snake.cpp +++ b/src/Core/Crawl/snake.cpp @@ -10,14 +10,24 @@ #include "snakeitem.h" #include #include +#include Snake::Snake(const QString &name, const QString &viewTempalte, QObject *ptr): IPlayer (name, viewTempalte, ptr) { _vectors = new QVector3D[2]; - _vectors[0] = QVector3D(50,50,0); // left tap - _vectors[1] = QVector3D(50,-50,0); // right tap + setAngularVelocity(100); + setSpeed(100); + setLengthBetwinItems(1); + setBodyCount(50); + setSpeed(100); + + _clickIndex = 0; + + setScales({{0, 0.8}, + {0.4, 1.2}, + {1, 0.5}}); } Snake::~Snake( ){ @@ -32,11 +42,13 @@ void Snake::add(ClasterItem *object) { if (auto snakeItem = dynamic_cast(object)) { if (_lastSnakeItem) { - snakeItem->setPrev(_lastSnakeItem->guiId()); + snakeItem->setPrev(_lastSnakeItem); } else { - snakeItem->setPrev(guiId()); + snakeItem->setPrev(this); } + snakeItem->setBreakingForce(breakingForce()); + _lastSnakeItem = static_cast(snakeItem); Claster::add(object); @@ -51,7 +63,7 @@ void Snake::add(ClasterItem *object) { void Snake::remove(ClasterItem *object) { if (_lastSnakeItem == object) { - _lastSnakeItem = getItem(static_cast(_lastSnakeItem)->prev()); + _lastSnakeItem = static_cast(_lastSnakeItem)->prev(); } return Claster::remove(object); @@ -59,7 +71,7 @@ void Snake::remove(ClasterItem *object) { void Snake::remove(int id) { if (_lastSnakeItem->guiId() == id) { - _lastSnakeItem = getItem(static_cast(_lastSnakeItem)->prev()); + _lastSnakeItem = static_cast(_lastSnakeItem)->prev(); } return Claster::remove(id); @@ -77,6 +89,9 @@ void Snake::generateBody() { auto scaleIt = _scales.begin(); + float from = 0, fromKey = 0; + float to = scaleIt.value(), toKey = scaleIt.key(); + for(int i = 0; i < _bodyCount; ++i) { if (!_factory) { QuasarAppUtils::Params::log("Please use the registerBodyitem method" @@ -90,23 +105,18 @@ void Snake::generateBody() { float scale = 1; if (scaleIt != _scales.end()) { float position = static_cast(i) / _bodyCount; - float from = 0, fromKey = 0; - float to = 0, toKey = 0; - while (position > scaleIt.value() && scaleIt != _scales.end()) { + while (position >= scaleIt.key() && scaleIt != _scales.end()) { scaleIt++; if (scaleIt != _scales.end()) { - from = (scaleIt - 1).value(); + from = to; to = scaleIt.value(); - fromKey = (scaleIt - 1).key(); + fromKey = toKey; toKey = scaleIt.key(); } } scale = ((position - fromKey) * toKey / (to - from)) + from; - - scaleIt.value(); - } item->setSize(item->size() * scale); @@ -115,6 +125,17 @@ void Snake::generateBody() { } } +float Snake::speed() const { + return _speed; +} + +void Snake::setSpeed(float newSpeed) { + _speed = newSpeed; + float asixPos = std::sqrt(std::pow(_speed, 2.0) / 2); + _vectors[0] = QVector3D(asixPos, asixPos,0); // left tap + _vectors[1] = QVector3D(asixPos,-asixPos,0); // right tap +} + int Snake::bodyCount() const { return _bodyCount; } diff --git a/src/Core/Crawl/snake.h b/src/Core/Crawl/snake.h index 77de7af..3823c53 100644 --- a/src/Core/Crawl/snake.h +++ b/src/Core/Crawl/snake.h @@ -11,6 +11,8 @@ #include "iplayer.h" #include "Extensions/claster.h" +class SnakeItem; + /** * @brief The Snake class This class implement render mehod for snake object. */ @@ -59,9 +61,9 @@ public: * The key of map are position of snake Body and the value are scale factor of current body item. * The default scales map of snake are: * ``` - * 0.1 - 0.7 - * 0.6 - 1 - * 1 - 0.1 + * 0.0 - 0.8 + * 0.6 - 1.2 + * 1 - 0.5 * ``` * @return scales map of snake body. */ @@ -86,6 +88,18 @@ public: */ void setBodyCount(int newBodyCount); + /** + * @brief speed This method return current speed snake speed. + * @return snake speed + */ + float speed() const; + + /** + * @brief setSpeed This method sets new current speed of the snake. + * @param newSpeed new value of the snake speed. + */ + void setSpeed(float newSpeed); + protected slots: void onTap() override; @@ -95,11 +109,12 @@ private: QMap _scales; std::function _factory = nullptr; - float _lengthBetwinItems = 10; - int _bodyCount = 10; + float _lengthBetwinItems; + int _bodyCount; const IWorldItem* _lastSnakeItem = nullptr; - unsigned int _clickIndex = 0; + unsigned int _clickIndex; QVector3D* _vectors; + float _speed; }; diff --git a/src/Core/Crawl/snakeitem.cpp b/src/Core/Crawl/snakeitem.cpp index 8a06b2f..cc458cf 100644 --- a/src/Core/Crawl/snakeitem.cpp +++ b/src/Core/Crawl/snakeitem.cpp @@ -9,28 +9,31 @@ #include "snakeitem.h" SnakeItem::SnakeItem(const QString itemName): SingleClasterWorldItem(itemName) { + setAngularVelocity(-1); } -void SnakeItem::setPrev(int newPrev) { - _prev = newPrev; +void SnakeItem::setPrev(const IWorldItem * newPrev) { + _prevObject = newPrev; } void SnakeItem::render(unsigned int tbfMsec) { - auto prev = getItem(_prev); - auto ratationVector = (prev->position() - position()); + + if (!_prevObject) { + return; + } + + auto ratationVector = (_prevObject->position() - position()); if (auto claster = static_cast(parentClaster())) { - if (ratationVector.length() < claster->lengthBetwinItems()) { - setMovableVector({0,0,0}); - } else { - setMovableVector(ratationVector *= claster->speed()); + if (ratationVector.length() > claster->lengthBetwinItems()) { + setMovableVector(ratationVector.normalized() * claster->currentMovableVector().length()); } } MovableObject::render(tbfMsec); } -int SnakeItem::prev() const { - return _prev; +const IWorldItem * SnakeItem::prev() const { + return _prevObject; } diff --git a/src/Core/Crawl/snakeitem.h b/src/Core/Crawl/snakeitem.h index 8bba9f8..23c20ff 100644 --- a/src/Core/Crawl/snakeitem.h +++ b/src/Core/Crawl/snakeitem.h @@ -12,7 +12,7 @@ #include "singleclasterworlditem.h" #include "Extensions/movableobject.h" -class CRAWL_EXPORT SnakeItem: public SingleClasterWorldItem, protected MovableObject +class CRAWL_EXPORT SnakeItem: public SingleClasterWorldItem, public MovableObject { Q_OBJECT public: @@ -20,19 +20,19 @@ public: /** * @brief setPrev This method sets id of the previous snake item. - * @param newPrev this is new value of the id of previous snake item. + * @param newPrev this is new value of the previous snake item. */ - void setPrev(int newPrev); + void setPrev(const IWorldItem * newPrev); void render(unsigned int tbfMsec) override; /** * @brief prev This method return prev object of snake - * @return id of the prev objects of the snake + * @return the prev objects of the snake */ - int prev() const; + const IWorldItem * prev() const; private: - int _prev = -1; + const IWorldItem *_prevObject = nullptr; }; #endif // SNAKEITEM_H diff --git a/src/Core/CrawlModule/Scene.qml b/src/Core/CrawlModule/Scene.qml index fdafa5f..4ea123a 100644 --- a/src/Core/CrawlModule/Scene.qml +++ b/src/Core/CrawlModule/Scene.qml @@ -38,7 +38,7 @@ View3D { id: background backgroundMode: SceneEnvironment.SkyBox lightProbe: Texture { - source: (model)? model.hdr: "" + source: (privateRoot.world)? privateRoot.world.hdr: "" } } @@ -47,7 +47,6 @@ View3D { property var arrayObjects: [] property var world: (model)? model.world: null - property int oldPlayerId: -1 property var gameMenuModel: (model)? model.menu: null property var player: (world)? world.player: null @@ -121,19 +120,6 @@ View3D { Connections { target: privateRoot; - function onPlayerChanged() { - - if (!privateRoot.player) - return - - if (privateRoot.oldPlayerId >= 0) { - privateRoot.remove(privateRoot.oldPlayerId); - } - - privateRoot.add(privateRoot.player.guiId); - privateRoot.oldPlayerId = privateRoot.player.guiId - } - function onGameMenuModelChanged() { if (!privateRoot.gameMenuModel) { return; diff --git a/src/Core/Extensions/movableobject.cpp b/src/Core/Extensions/movableobject.cpp index 26de9cb..087b8ec 100644 --- a/src/Core/Extensions/movableobject.cpp +++ b/src/Core/Extensions/movableobject.cpp @@ -64,7 +64,12 @@ void MovableObject::renderPosition(GuiObject *object, unsigned int tbfMsec) { QVector3D tempVector = _movableVector - _currentMovableVector ; // calc change on this iteration for new moveble vector - float delta = std::min(_angularVelocity * (tbfMsec / 1000.0), static_cast(tempVector.length())); + float delta = 0.0; + if (_angularVelocity <= 0) { + delta = tempVector.length(); + } else { + delta = std::min(_angularVelocity * (tbfMsec / 1000.0), static_cast(tempVector.length())); + } // resize temp vector for calc changes of the movableVector tempVector = tempVector.normalized() * delta; @@ -78,3 +83,7 @@ void MovableObject::renderPosition(GuiObject *object, unsigned int tbfMsec) { _movableVector = _movableVector.normalized() * newMovableVectorLength; } + +const QVector3D &MovableObject::currentMovableVector() const { + return _currentMovableVector; +} diff --git a/src/Core/Extensions/movableobject.h b/src/Core/Extensions/movableobject.h index 8948e2a..6cb5a85 100644 --- a/src/Core/Extensions/movableobject.h +++ b/src/Core/Extensions/movableobject.h @@ -76,6 +76,12 @@ public: */ void setBreakingForce(float newBreakingForce); + /** + * @brief currentMovableVector This method return current movable vector. + * @return current movable vector. + */ + const QVector3D ¤tMovableVector() const; + protected: /** diff --git a/src/Core/private/engine.cpp b/src/Core/private/engine.cpp index a9987f6..5171f71 100644 --- a/src/Core/private/engine.cpp +++ b/src/Core/private/engine.cpp @@ -44,33 +44,13 @@ void Engine::setWorld(IWorld *world) { } _currentWorld = world; - - if (!_currentWorld->prepare()) { - QuasarAppUtils::Params::log("Failed to init world. World name: " + _currentWorld->name(), - QuasarAppUtils::Error); - - _currentWorld = nullptr; - return; - } - - if (!_currentWorld->userInterface()->init()) { - return; - } - - setMenu(_currentWorld->userInterface()); - emit worldChanged(); + prepareNewWorld(); + startRenderLoop(); } -QString Engine::hdr() const { - if (!_currentWorld) - return ""; - - return _currentWorld->hdrMap(); -} - void Engine::setScane(QObject *newScane) { if (_scane == newScane) return; @@ -149,6 +129,22 @@ void Engine::setPrepareLvlProgress(int newPrepareLvlProgress) { emit prepareLvlProgressChanged(); } +void Engine::prepareNewWorld() { + if (!_currentWorld->prepare()) { + QuasarAppUtils::Params::log("Failed to init world. World name: " + _currentWorld->name(), + QuasarAppUtils::Error); + + _currentWorld = nullptr; + return; + } + + if (!_currentWorld->userInterface()->init()) { + return; + } + + setMenu(_currentWorld->userInterface()); +} + void Engine::renderLoop() { if (!_currentWorld) diff --git a/src/Core/private/engine.h b/src/Core/private/engine.h index 3c1b5b3..173365e 100644 --- a/src/Core/private/engine.h +++ b/src/Core/private/engine.h @@ -21,7 +21,6 @@ class IWorld; class Engine : public QObject { Q_OBJECT - Q_PROPERTY(QString hdr READ hdr NOTIFY worldChanged) Q_PROPERTY(QObject* player READ player NOTIFY playerChanged) Q_PROPERTY(QObject* world READ world NOTIFY worldChanged) @@ -51,12 +50,6 @@ public: */ void setWorld(IWorld *world); - /** - * @brief hdr This method should return hdr map of the lvl - * @return path to hdr map. - */ - QString hdr() const; - /** * @brief setScane This method sets new scane object. The scane object are * @param newScane are Qt Quick 3d node object form qml. @@ -139,7 +132,7 @@ signals: private: void setPrepareLvlProgress(int newPrepareLvlProgress); - + void prepareNewWorld(); void renderLoop(); diff --git a/src/CrawlTestLvl b/src/CrawlTestLvl index b0804c7..0f022f4 160000 --- a/src/CrawlTestLvl +++ b/src/CrawlTestLvl @@ -1 +1 @@ -Subproject commit b0804c7c9c6ef2214e37d26869179923faa3ac41 +Subproject commit 0f022f42093a1e5311cbcd13c9ed40b54163c251 From 8ccd31cbef46899572700fe0633e843f76bcae78 Mon Sep 17 00:00:00 2001 From: EndrII Date: Wed, 30 Jun 2021 12:15:57 +0300 Subject: [PATCH 5/7] ref #63 snake object are done --- src/Core/Crawl/iworld.cpp | 39 ++++++++++++++++++------ src/Core/Crawl/iworld.h | 20 ++++++++++++ src/Core/Crawl/iworlditem.cpp | 14 ++++++--- src/Core/Crawl/snakeitem.cpp | 6 +++- src/Core/private/defaultbackgroundai.cpp | 4 ++- src/Core/private/engine.cpp | 21 ++++++++----- src/Core/private/engine.h | 2 +- src/CrawlTestLvl | 2 +- 8 files changed, 81 insertions(+), 27 deletions(-) diff --git a/src/Core/Crawl/iworld.cpp b/src/Core/Crawl/iworld.cpp index 8286d56..c2acae0 100644 --- a/src/Core/Crawl/iworld.cpp +++ b/src/Core/Crawl/iworld.cpp @@ -35,6 +35,11 @@ IControl *IWorld::initUserInterface() const { void IWorld::render(unsigned int tbfMsec) { + if (!_running) { + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + return; + } + _ItemsMutex.lock(); for (auto i = _items.begin(); i != _items.end(); ++i) { @@ -77,6 +82,8 @@ bool IWorld::start() { worldChanged(*_worldRules->begin()); setTargetFps(60); + setRunning(true); + return true; } @@ -109,15 +116,7 @@ IWorldItem *IWorld::generate(const QString &objectType) const { } bool IWorld::stop() { - start(); - - setWorldStatus(WorldStatus::Background); - _player->setControl(dynamic_cast(_backgroundAI)); - - _backgroundAI->startAI(); - - setTargetFps(30); - + setRunning(false); return true; } @@ -233,6 +232,7 @@ void IWorld::removeItem(int id, QList *removedObjectsList) { } void IWorld::reset() { + if (_player) { delete _player; _player = nullptr; @@ -309,6 +309,14 @@ void IWorld::removeAnyItemFromGroup(const QString &group, removeItem(anyObjectId, removedObjectsList); } +bool IWorld::running() const { + return _running; +} + +void IWorld::setRunning(bool newRunning) { + _running = newRunning; +} + int IWorld::targetFps() const { return _targetFps; } @@ -357,7 +365,7 @@ void IWorld::setCameraReleativePosition(const QVector3D &newCameraReleativePosit } void IWorld::handleStop() { - stop(); + runAsBackGround(); } const QVector3D &IWorld::cameraReleativePosition() const { @@ -400,3 +408,14 @@ void IWorld::setWorldStatus(int newWorldStatus) { const QString &IWorld::hdr() const { return _hdrMap; } + +void IWorld::runAsBackGround() { + start(); + + setWorldStatus(WorldStatus::Background); + _player->setControl(dynamic_cast(_backgroundAI)); + + _backgroundAI->startAI(); + + setTargetFps(30); +} diff --git a/src/Core/Crawl/iworld.h b/src/Core/Crawl/iworld.h index a5dd534..2eb1dfd 100644 --- a/src/Core/Crawl/iworld.h +++ b/src/Core/Crawl/iworld.h @@ -222,6 +222,12 @@ public: */ const QString &hdr() const; + /** + * @brief runAsBackGround This method run this world as a backgroud. + * The player start new game and sets new control from the backgroundAI method. + */ + void runAsBackGround(); + signals: /** * @brief sigGameFinished This signal emit when game are finished @@ -375,6 +381,19 @@ private: bool prepare(); void reset(); + + /** + * @brief running This varibale check in render function if the running is true then render loop are working correctly + * @return + */ + bool running() const; + + /** + * @brief setRunning + * @param newRunning + */ + void setRunning(bool newRunning); + /** * @brief worldChanged This method generate diff for the qml * @param objects This is list of object on lvl @@ -447,6 +466,7 @@ private: QHash> _registeredTypes; int _targetFps = 60; + bool _running = false; // engine friend class Engine; diff --git a/src/Core/Crawl/iworlditem.cpp b/src/Core/Crawl/iworlditem.cpp index 4475555..a0a49d7 100644 --- a/src/Core/Crawl/iworlditem.cpp +++ b/src/Core/Crawl/iworlditem.cpp @@ -31,12 +31,16 @@ const IWorldItem *IWorldItem::getPlayer() const { } void IWorldItem::render(unsigned int) { - if (_playerObject->position().x() - position().x() > - _world->cameraReleativePosition().z() * 2) { - setX(_playerObject->position().x() + _world->cameraReleativePosition().z() * 4); + if (_playerObject->position().x() - _world->cameraReleativePosition().z() > + position().x()) { - float dY = rand() % static_cast(_world->cameraReleativePosition().z() * 2 - - _world->cameraReleativePosition().z()); + float dX = _world->cameraReleativePosition().z() * 2 + + (rand() % static_cast(_world->cameraReleativePosition().z())); + + setX(_playerObject->position().x() + dX); + + float dY = (rand() % static_cast(_world->cameraReleativePosition().z() * 4) + - _world->cameraReleativePosition().z() * 2); setY(_playerObject->position().y() + dY); } diff --git a/src/Core/Crawl/snakeitem.cpp b/src/Core/Crawl/snakeitem.cpp index cc458cf..a94d1a8 100644 --- a/src/Core/Crawl/snakeitem.cpp +++ b/src/Core/Crawl/snakeitem.cpp @@ -26,7 +26,11 @@ void SnakeItem::render(unsigned int tbfMsec) { auto ratationVector = (_prevObject->position() - position()); if (auto claster = static_cast(parentClaster())) { - if (ratationVector.length() > claster->lengthBetwinItems()) { + float ratationLength = ratationVector.length(); + + if (ratationLength > claster->lengthBetwinItems() * 10) { + setposition(_prevObject->position()); + } else if (ratationLength > claster->lengthBetwinItems()) { setMovableVector(ratationVector.normalized() * claster->currentMovableVector().length()); } } diff --git a/src/Core/private/defaultbackgroundai.cpp b/src/Core/private/defaultbackgroundai.cpp index 32b57da..9c7e998 100644 --- a/src/Core/private/defaultbackgroundai.cpp +++ b/src/Core/private/defaultbackgroundai.cpp @@ -11,6 +11,8 @@ DefaultBackgroundAI::DefaultBackgroundAI() { _timer = new QTimer(); _timer->setInterval(1000); + + connect(_timer, &QTimer::timeout, this, &DefaultBackgroundAI::handleTimerTriger); } DefaultBackgroundAI::~DefaultBackgroundAI() { @@ -27,7 +29,7 @@ void DefaultBackgroundAI::stopAI() { } void DefaultBackgroundAI::handleTimerTriger() { - _timer->setInterval(rand() % 1000 + 10); + _timer->setInterval(rand() % 2000 + 200); emit userTap(); } diff --git a/src/Core/private/engine.cpp b/src/Core/private/engine.cpp index 5171f71..cdbc819 100644 --- a/src/Core/private/engine.cpp +++ b/src/Core/private/engine.cpp @@ -46,9 +46,16 @@ void Engine::setWorld(IWorld *world) { _currentWorld = world; emit worldChanged(); - prepareNewWorld(); + if (!prepareNewWorld()) { + QuasarAppUtils::Params::log("Failed to init world. World name: " + _currentWorld->name(), + QuasarAppUtils::Error); + + _currentWorld = nullptr; + return; + } startRenderLoop(); + _currentWorld->runAsBackGround(); } void Engine::setScane(QObject *newScane) { @@ -129,20 +136,18 @@ void Engine::setPrepareLvlProgress(int newPrepareLvlProgress) { emit prepareLvlProgressChanged(); } -void Engine::prepareNewWorld() { +bool Engine::prepareNewWorld() { if (!_currentWorld->prepare()) { - QuasarAppUtils::Params::log("Failed to init world. World name: " + _currentWorld->name(), - QuasarAppUtils::Error); - - _currentWorld = nullptr; - return; + return false; } if (!_currentWorld->userInterface()->init()) { - return; + return false; } setMenu(_currentWorld->userInterface()); + + return true; } void Engine::renderLoop() { diff --git a/src/Core/private/engine.h b/src/Core/private/engine.h index 173365e..b4cc171 100644 --- a/src/Core/private/engine.h +++ b/src/Core/private/engine.h @@ -132,7 +132,7 @@ signals: private: void setPrepareLvlProgress(int newPrepareLvlProgress); - void prepareNewWorld(); + bool prepareNewWorld(); void renderLoop(); diff --git a/src/CrawlTestLvl b/src/CrawlTestLvl index 0f022f4..9f06054 160000 --- a/src/CrawlTestLvl +++ b/src/CrawlTestLvl @@ -1 +1 @@ -Subproject commit 0f022f42093a1e5311cbcd13c9ed40b54163c251 +Subproject commit 9f06054ae836016881dc132d336c5da5bb3dca6c From 4bebdc5933ab9a79c7f96dc777fbeaa007a72493 Mon Sep 17 00:00:00 2001 From: EndrII Date: Wed, 30 Jun 2021 22:20:12 +0300 Subject: [PATCH 6/7] update submodule --- src/CrawlTestLvl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CrawlTestLvl b/src/CrawlTestLvl index 9f06054..b08e823 160000 --- a/src/CrawlTestLvl +++ b/src/CrawlTestLvl @@ -1 +1 @@ -Subproject commit 9f06054ae836016881dc132d336c5da5bb3dca6c +Subproject commit b08e8238fba0c28aed2c65e3a1fb317e61422d23 From 31d4b8cdac2e9a15857d0c5fc9e1db50852fed24 Mon Sep 17 00:00:00 2001 From: EndrII Date: Wed, 30 Jun 2021 22:45:17 +0300 Subject: [PATCH 7/7] ref #63 fix tests --- src/Core/Crawl/iworld.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core/Crawl/iworld.cpp b/src/Core/Crawl/iworld.cpp index c2acae0..09c8d7d 100644 --- a/src/Core/Crawl/iworld.cpp +++ b/src/Core/Crawl/iworld.cpp @@ -210,7 +210,7 @@ void IWorld::removeItem(int id, QList *removedObjectsList) { if (auto claster = dynamic_cast(obj)) { const auto copyOfObjectsList = claster->objects(); for (auto item : copyOfObjectsList) { - if (!item || !item->parentClastersCount()) + if (!item || item->parentClastersCount() > 1) continue; int id = item->guiId();