4
1
mirror of https://github.com/QuasarApp/Snake.git synced 2025-05-11 08:59:46 +00:00

ref added support extensions clasess

This commit is contained in:
Andrei Yankovich 2021-06-25 14:38:44 +03:00
parent dbab1e081a
commit 8402f4a449
20 changed files with 404 additions and 43 deletions

@ -12,6 +12,7 @@ add_definitions(-DCRAWL_LIBRARY)
file(GLOB SOURCE_CPP
"*Crawl/*.cpp"
"*Extensions/*.cpp"
"private/*.cpp"
"*.qrc"
"Crawl/*.qrc"

@ -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,

@ -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)

@ -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;
}

@ -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

@ -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<RequaredType>();
* ```
*/
template<class Requared>
Requared* checkminimumRequariedType() {
Requared* result = dynamic_cast<Requared*>(this);
debug_assert(result, "This render function not support this class");
return result;
};
};
#endif // IRENDER_H

@ -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"

@ -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();
}

@ -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;
};

64
src/Core/Crawl/snake.cpp Normal file

@ -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 <QQuaternion>
#include <quasarapp.h>
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<SnakeItem*>(object)) {
snakeItem->setPrev(_lastSnakeItem->guiId());
_lastSnakeItem = static_cast<IWorldItem*>(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<const SnakeItem*>(_lastSnakeItem)->prev());
}
return Claster::remove(object);
}
void Snake::remove(int id) {
if (_lastSnakeItem->guiId() == id) {
_lastSnakeItem = getItem(static_cast<const SnakeItem*>(_lastSnakeItem)->prev());
}
return Claster::remove(id);
}
void Snake::onTap() {
}
float Snake::lengthBetwinItems() const{
return _lengthBetwinItems;
}
void Snake::setLengthBetwinItems(float newLengthBetwinItems) {
_lengthBetwinItems = newLengthBetwinItems;
}

53
src/Core/Crawl/snake.h Normal file

@ -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

@ -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<Snake*>(parentClaster())) {
if (ratationVector.length() < claster->lengthBetwinItems()) {
setMovableVector({0,0,0});
} else {
setMovableVector(ratationVector *= claster->speed());
}
}
MovableObject::render(tbfMsec);
}
int SnakeItem::prev() const {
return _prev;
}

@ -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

@ -1,21 +1,68 @@
#include "movableobject.h"
#include <QDebug>
# 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<IWorldItem>();
// 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;
}
```

@ -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)) {

@ -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<int, ClasterItem*> _objects;
};
#endif // CLASTER_H

@ -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 <Crawl/guiobject.h>
MovableObject::MovableObject() {
}
void MovableObject::render(unsigned int tbfMsec) {
if (auto _this = checkminimumRequariedType<GuiObject>()) {
// 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<double>(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;
}

@ -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 <QVector3D>
/**
* @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

@ -1 +1 @@
Subproject commit 46878c18cae14eed67a2b105dc993ff2d670a3bc
Subproject commit 931c937cb076766714e74a8241db8ebb78d6633d

@ -7,16 +7,16 @@
#include "clasterstest.h"
#include <QtTest>
#include <Crawl/claster.h>
#include <Extensions/claster.h>
#include <Crawl/clasteritem.h>
#include <Crawl/singleclasterworlditem.h>
#include <Crawl/iworld.h>
// 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 *) {};
};