mirror of
https://github.com/QuasarApp/Snake.git
synced 2025-04-26 17:54:42 +00:00
commit
8606beb60e
@ -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,
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
@ -11,7 +11,7 @@
|
||||
IPlayer::IPlayer(const QString &name,
|
||||
const QString &viewTempalte,
|
||||
QObject *ptr):
|
||||
MovableObject(name, viewTempalte, ptr) {
|
||||
IWorldItem(name, viewTempalte, ptr) {
|
||||
|
||||
}
|
||||
|
||||
@ -27,30 +27,12 @@ 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;
|
||||
}
|
||||
|
||||
float IPlayer::speed() const {
|
||||
return _speed;
|
||||
}
|
||||
|
||||
void IPlayer::setSpeed(float newSpead) {
|
||||
_speed = newSpead;
|
||||
|
||||
if (_speed < 0) {
|
||||
_speed = 0;
|
||||
}
|
||||
void IPlayer::render(unsigned int tbfMsec) {
|
||||
MovableObject::render(tbfMsec);
|
||||
}
|
||||
|
||||
void IPlayer::setControl(const IControl *control) {
|
||||
|
@ -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, public MovableObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
IPlayer(const QString& name,
|
||||
@ -36,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.
|
||||
@ -70,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;
|
||||
@ -92,6 +66,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 +75,12 @@ 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,31 @@ public:
|
||||
* @param tbf This is time betwin frame in milesecunds.
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* **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"
|
||||
@ -24,15 +24,22 @@ IWorld::IWorld() {
|
||||
}
|
||||
|
||||
IWorld::~IWorld() {
|
||||
deinit();
|
||||
reset();
|
||||
}
|
||||
|
||||
void IWorld::init() {prepare();}
|
||||
|
||||
IControl *IWorld::initUserInterface() const {
|
||||
return new DefaultControl;
|
||||
}
|
||||
|
||||
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) {
|
||||
@ -44,11 +51,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)
|
||||
@ -65,7 +74,6 @@ void IWorld::initPlayerControl(IControl *control) {
|
||||
|
||||
bool IWorld::start() {
|
||||
_player->setposition({0,0,0});
|
||||
_player->setSpeed(0);
|
||||
|
||||
setWorldStatus(WorldStatus::Game);
|
||||
_backgroundAI->stopAI();
|
||||
@ -74,6 +82,8 @@ bool IWorld::start() {
|
||||
|
||||
worldChanged(*_worldRules->begin());
|
||||
setTargetFps(60);
|
||||
setRunning(true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -92,12 +102,11 @@ void IWorld::setPlayer(QObject *newPlayer) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_player) {
|
||||
removeIAtomicItem(_player->guiId());
|
||||
}
|
||||
if (_player)
|
||||
removeItem(_player->guiId());
|
||||
|
||||
_player = newPlayerObject;
|
||||
addAtomicItem(_player);
|
||||
addItem(_player);
|
||||
|
||||
emit playerChanged();
|
||||
}
|
||||
@ -107,15 +116,7 @@ IWorldItem *IWorld::generate(const QString &objectType) const {
|
||||
}
|
||||
|
||||
bool IWorld::stop() {
|
||||
start();
|
||||
|
||||
setWorldStatus(WorldStatus::Background);
|
||||
_player->setControl(dynamic_cast<IControl*>(_backgroundAI));
|
||||
|
||||
_backgroundAI->startAI();
|
||||
|
||||
setTargetFps(30);
|
||||
|
||||
setRunning(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -129,14 +130,14 @@ IWorldItem *IWorld::getItem(int id) const {
|
||||
return _items.value(id, nullptr);
|
||||
}
|
||||
|
||||
bool IWorld::init() {
|
||||
bool IWorld::prepare() {
|
||||
|
||||
if (isInit())
|
||||
return true;
|
||||
|
||||
_worldRules = initWorldRules();
|
||||
|
||||
_hdrMap = initHdrBackGround();
|
||||
setHdr(initHdrBackGround());
|
||||
setPlayer(initPlayer());
|
||||
_player->initOnWorld(this, _player);
|
||||
_userInterface = initUserInterface();
|
||||
@ -144,12 +145,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,19 +174,26 @@ void IWorld::addItem(IWorldItem *obj, QList<int> *addedObjectsList) {
|
||||
if (!obj)
|
||||
return;
|
||||
|
||||
obj->init();
|
||||
Diff diff;
|
||||
|
||||
// Work wih claster
|
||||
if (auto claster = dynamic_cast<Claster*>(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);
|
||||
|
||||
}
|
||||
|
||||
@ -196,29 +204,35 @@ void IWorld::removeItem(int id, QList<int> *removedObjectsList) {
|
||||
if (!obj)
|
||||
return;
|
||||
|
||||
Diff diff;
|
||||
|
||||
// Work wih claster
|
||||
if (auto claster = dynamic_cast<Claster*>(obj)) {
|
||||
auto copyOfObjectsList = claster->objects();
|
||||
const auto copyOfObjectsList = claster->objects();
|
||||
for (auto item : copyOfObjectsList) {
|
||||
if (!item || !item->parentClastersCount())
|
||||
if (!item || item->parentClastersCount() > 1)
|
||||
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::deinit() {
|
||||
void IWorld::reset() {
|
||||
|
||||
if (_player) {
|
||||
delete _player;
|
||||
_player = nullptr;
|
||||
@ -240,7 +254,7 @@ void IWorld::deinit() {
|
||||
}
|
||||
|
||||
clearItems();
|
||||
_hdrMap = "";
|
||||
setHdr("");
|
||||
|
||||
}
|
||||
|
||||
@ -257,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);
|
||||
@ -274,7 +288,7 @@ bool IWorld::removeIAtomicItem(int id) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IWorld::removeIAtomicItem(IWorldItem *obj) {
|
||||
bool IWorld::removeAtomicItem(IWorldItem *obj) {
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
@ -295,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;
|
||||
}
|
||||
@ -303,6 +325,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;
|
||||
}
|
||||
@ -335,40 +365,33 @@ void IWorld::setCameraReleativePosition(const QVector3D &newCameraReleativePosit
|
||||
}
|
||||
|
||||
void IWorld::handleStop() {
|
||||
stop();
|
||||
runAsBackGround();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@ -381,3 +404,18 @@ void IWorld::setWorldStatus(int newWorldStatus) {
|
||||
emit worldStatusChanged();
|
||||
}
|
||||
|
||||
|
||||
const QString &IWorld::hdr() const {
|
||||
return _hdrMap;
|
||||
}
|
||||
|
||||
void IWorld::runAsBackGround() {
|
||||
start();
|
||||
|
||||
setWorldStatus(WorldStatus::Background);
|
||||
_player->setControl(dynamic_cast<IControl*>(_backgroundAI));
|
||||
|
||||
_backgroundAI->startAI();
|
||||
|
||||
setTargetFps(30);
|
||||
}
|
||||
|
@ -46,12 +46,15 @@ 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)
|
||||
|
||||
public:
|
||||
IWorld();
|
||||
virtual ~IWorld();
|
||||
~IWorld() override;
|
||||
|
||||
void init() override;
|
||||
|
||||
/**
|
||||
* @brief initPlayer The implementation of This interface must be return playerObject.
|
||||
@ -165,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
|
||||
@ -219,6 +216,18 @@ 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;
|
||||
|
||||
/**
|
||||
* @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
|
||||
@ -258,6 +267,11 @@ signals:
|
||||
*/
|
||||
void playerChanged();
|
||||
|
||||
/**
|
||||
* @brief hdrChanged This signal emited when the hdr map are changed.
|
||||
*/
|
||||
void hdrChanged();
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
@ -311,6 +325,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<class Type>
|
||||
|
||||
/**
|
||||
@ -354,14 +374,33 @@ 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 true if world initialized successful
|
||||
*/
|
||||
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 init();
|
||||
void deinit();
|
||||
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
|
||||
* @note This method addd player object to this list.
|
||||
*/
|
||||
void worldChanged(WorldObjects objects);
|
||||
|
||||
void worldChanged(const WorldObjects& objects);
|
||||
void clearItems();
|
||||
|
||||
/**
|
||||
@ -387,18 +426,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.
|
||||
@ -411,6 +450,7 @@ private:
|
||||
|
||||
QHash<int, IWorldItem*> _items;
|
||||
QMultiHash<QString, int> _itemsGroup;
|
||||
QMultiHash<QString, int> _lastItemsGroup;
|
||||
|
||||
mutable QMutex _ItemsMutex;
|
||||
|
||||
@ -426,13 +466,13 @@ private:
|
||||
QHash<QString, std::function<IWorldItem*()>> _registeredTypes;
|
||||
|
||||
int _targetFps = 60;
|
||||
bool _running = false;
|
||||
|
||||
// engine
|
||||
friend class Engine;
|
||||
|
||||
// testing
|
||||
friend class ClastersTest;
|
||||
|
||||
};
|
||||
|
||||
#endif // IWORLD_H
|
||||
|
@ -31,17 +31,23 @@ 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<int>(_world->cameraReleativePosition().z() * 2
|
||||
- _world->cameraReleativePosition().z());
|
||||
float dX = _world->cameraReleativePosition().z() * 2 +
|
||||
(rand() % static_cast<int>(_world->cameraReleativePosition().z()));
|
||||
|
||||
setX(_playerObject->position().x() + dX);
|
||||
|
||||
float dY = (rand() % static_cast<int>(_world->cameraReleativePosition().z() * 4)
|
||||
- _world->cameraReleativePosition().z() * 2);
|
||||
|
||||
setY(_playerObject->position().y() + dY);
|
||||
}
|
||||
}
|
||||
|
||||
void IWorldItem::init() {}
|
||||
|
||||
void IWorldItem::initOnWorld(const IWorld *world, const IWorldItem * player) {
|
||||
_world = world;
|
||||
_playerObject = player;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
161
src/Core/Crawl/snake.cpp
Normal file
161
src/Core/Crawl/snake.cpp
Normal file
@ -0,0 +1,161 @@
|
||||
//#
|
||||
//# 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>
|
||||
#include <cmath>
|
||||
|
||||
Snake::Snake(const QString &name, const QString &viewTempalte, QObject *ptr):
|
||||
IPlayer (name, viewTempalte, ptr) {
|
||||
|
||||
_vectors = new QVector3D[2];
|
||||
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( ){
|
||||
delete [] _vectors;
|
||||
}
|
||||
|
||||
void Snake::render(unsigned int tbfMsec) {
|
||||
IPlayer::render(tbfMsec);
|
||||
}
|
||||
|
||||
void Snake::add(ClasterItem *object) {
|
||||
if (auto snakeItem = dynamic_cast<SnakeItem*>(object)) {
|
||||
|
||||
if (_lastSnakeItem) {
|
||||
snakeItem->setPrev(_lastSnakeItem);
|
||||
} else {
|
||||
snakeItem->setPrev(this);
|
||||
}
|
||||
|
||||
snakeItem->setBreakingForce(breakingForce());
|
||||
|
||||
_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 = static_cast<const SnakeItem*>(_lastSnakeItem)->prev();
|
||||
}
|
||||
|
||||
return Claster::remove(object);
|
||||
}
|
||||
|
||||
void Snake::remove(int id) {
|
||||
if (_lastSnakeItem->guiId() == id) {
|
||||
_lastSnakeItem = static_cast<const SnakeItem*>(_lastSnakeItem)->prev();
|
||||
}
|
||||
|
||||
return Claster::remove(id);
|
||||
}
|
||||
|
||||
void Snake::init() {
|
||||
generateBody();
|
||||
}
|
||||
|
||||
void Snake::onTap() {
|
||||
setMovableVector(_vectors[_clickIndex++ % 2]);
|
||||
}
|
||||
|
||||
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"
|
||||
" before invoke parent constructor.",
|
||||
QuasarAppUtils::Error);
|
||||
return;
|
||||
}
|
||||
|
||||
auto item = _factory();
|
||||
|
||||
float scale = 1;
|
||||
if (scaleIt != _scales.end()) {
|
||||
float position = static_cast<float>(i) / _bodyCount;
|
||||
while (position >= scaleIt.key() && scaleIt != _scales.end()) {
|
||||
scaleIt++;
|
||||
|
||||
if (scaleIt != _scales.end()) {
|
||||
from = to;
|
||||
to = scaleIt.value();
|
||||
fromKey = toKey;
|
||||
toKey = scaleIt.key();
|
||||
}
|
||||
}
|
||||
|
||||
scale = ((position - fromKey) * toKey / (to - from)) + from;
|
||||
}
|
||||
|
||||
item->setSize(item->size() * scale);
|
||||
|
||||
add(item);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void Snake::setBodyCount(int newBodyCount) {
|
||||
_bodyCount = newBodyCount;
|
||||
}
|
||||
|
||||
const QMap<float, float> &Snake::scales() const {
|
||||
return _scales;
|
||||
}
|
||||
|
||||
void Snake::setScales(const QMap<float, float> &newScales) {
|
||||
_scales = newScales;
|
||||
}
|
||||
|
||||
float Snake::lengthBetwinItems() const{
|
||||
return _lengthBetwinItems;
|
||||
}
|
||||
|
||||
void Snake::setLengthBetwinItems(float newLengthBetwinItems) {
|
||||
_lengthBetwinItems = newLengthBetwinItems;
|
||||
}
|
121
src/Core/Crawl/snake.h
Normal file
121
src/Core/Crawl/snake.h
Normal file
@ -0,0 +1,121 @@
|
||||
//#
|
||||
//# 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"
|
||||
|
||||
class SnakeItem;
|
||||
|
||||
/**
|
||||
* @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);
|
||||
~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
|
||||
/**
|
||||
* @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);
|
||||
|
||||
template<class Type>
|
||||
/**
|
||||
* @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.0 - 0.8
|
||||
* 0.6 - 1.2
|
||||
* 1 - 0.5
|
||||
* ```
|
||||
* @return scales map of snake body.
|
||||
*/
|
||||
const QMap<float, float> &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<float, float> &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);
|
||||
|
||||
/**
|
||||
* @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;
|
||||
|
||||
private:
|
||||
void generateBody();
|
||||
|
||||
QMap<float, float> _scales;
|
||||
std::function<ClasterItem*()> _factory = nullptr;
|
||||
|
||||
float _lengthBetwinItems;
|
||||
int _bodyCount;
|
||||
const IWorldItem* _lastSnakeItem = nullptr;
|
||||
unsigned int _clickIndex;
|
||||
QVector3D* _vectors;
|
||||
float _speed;
|
||||
|
||||
};
|
||||
|
||||
#endif // SNAKE_H
|
43
src/Core/Crawl/snakeitem.cpp
Normal file
43
src/Core/Crawl/snakeitem.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
//#
|
||||
//# 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) {
|
||||
setAngularVelocity(-1);
|
||||
|
||||
}
|
||||
|
||||
void SnakeItem::setPrev(const IWorldItem * newPrev) {
|
||||
_prevObject = newPrev;
|
||||
}
|
||||
|
||||
void SnakeItem::render(unsigned int tbfMsec) {
|
||||
|
||||
if (!_prevObject) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto ratationVector = (_prevObject->position() - position());
|
||||
|
||||
if (auto claster = static_cast<Snake*>(parentClaster())) {
|
||||
float ratationLength = ratationVector.length();
|
||||
|
||||
if (ratationLength > claster->lengthBetwinItems() * 10) {
|
||||
setposition(_prevObject->position());
|
||||
} else if (ratationLength > claster->lengthBetwinItems()) {
|
||||
setMovableVector(ratationVector.normalized() * claster->currentMovableVector().length());
|
||||
}
|
||||
}
|
||||
|
||||
MovableObject::render(tbfMsec);
|
||||
}
|
||||
|
||||
const IWorldItem * SnakeItem::prev() const {
|
||||
return _prevObject;
|
||||
}
|
38
src/Core/Crawl/snakeitem.h
Normal file
38
src/Core/Crawl/snakeitem.h
Normal file
@ -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, public 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 previous snake item.
|
||||
*/
|
||||
void setPrev(const IWorldItem * newPrev);
|
||||
void render(unsigned int tbfMsec) override;
|
||||
|
||||
/**
|
||||
* @brief prev This method return prev object of snake
|
||||
* @return the prev objects of the snake
|
||||
*/
|
||||
const IWorldItem * prev() const;
|
||||
|
||||
private:
|
||||
const IWorldItem *_prevObject = nullptr;
|
||||
};
|
||||
|
||||
#endif // SNAKEITEM_H
|
@ -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"
|
||||
// }
|
||||
// ]
|
||||
//}
|
||||
|
@ -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)
|
||||
|
||||
}
|
||||
@ -42,7 +38,7 @@ View3D {
|
||||
id: background
|
||||
backgroundMode: SceneEnvironment.SkyBox
|
||||
lightProbe: Texture {
|
||||
source: (model)? model.hdr: ""
|
||||
source: (privateRoot.world)? privateRoot.world.hdr: ""
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,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
|
||||
@ -82,7 +77,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());
|
||||
}
|
||||
}
|
||||
|
||||
@ -125,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;
|
||||
|
110
src/Core/Extensions/Concept.md
Normal file
110
src/Core/Extensions/Concept.md
Normal file
@ -0,0 +1,110 @@
|
||||
# Extension concept
|
||||
|
||||
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 = _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;
|
||||
}
|
||||
|
||||
```
|
@ -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
|
@ -1,39 +1,25 @@
|
||||
#include "movableobject.h"
|
||||
#include <QDebug>
|
||||
//#
|
||||
//# 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.
|
||||
//#
|
||||
|
||||
MovableObject::MovableObject(const QString &name,
|
||||
const QString &viewTempalte,
|
||||
QObject *ptr):
|
||||
IWorldItem(name, viewTempalte, ptr) {
|
||||
|
||||
#include "movableobject.h"
|
||||
#include <math.h>
|
||||
#include <Crawl/guiobject.h>
|
||||
|
||||
MovableObject::MovableObject() {
|
||||
|
||||
}
|
||||
|
||||
void MovableObject::render(unsigned int tbfMsec) {
|
||||
|
||||
// get object center position
|
||||
QVector3D currentPosition = position();
|
||||
|
||||
// move object to vector
|
||||
currentPosition += (_currentMovableVector * (tbfMsec / 1000.0));
|
||||
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;
|
||||
|
||||
if (auto _this = checkminimumRequariedType<GuiObject>()) {
|
||||
renderPosition(_this, tbfMsec);
|
||||
renderRatation(_this, tbfMsec);
|
||||
}
|
||||
}
|
||||
|
||||
const QVector3D &MovableObject::movableVector() const {
|
||||
@ -59,3 +45,45 @@ 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 = 0.0;
|
||||
if (_angularVelocity <= 0) {
|
||||
delta = tempVector.length();
|
||||
} else {
|
||||
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::currentMovableVector() const {
|
||||
return _currentMovableVector;
|
||||
}
|
@ -1,7 +1,18 @@
|
||||
//#
|
||||
//# 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>
|
||||
|
||||
class GuiObject;
|
||||
|
||||
/**
|
||||
* @brief The MovableObject class contains functions for moving object on the world.
|
||||
@ -12,13 +23,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.
|
||||
@ -37,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);
|
||||
|
||||
@ -66,13 +76,34 @@ public:
|
||||
*/
|
||||
void setBreakingForce(float newBreakingForce);
|
||||
|
||||
/**
|
||||
* @brief currentMovableVector This method return current movable vector.
|
||||
* @return current movable vector.
|
||||
*/
|
||||
const QVector3D ¤tMovableVector() const;
|
||||
|
||||
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;
|
||||
|
||||
float _angularVelocity = 0;
|
||||
float _breakingForce = 0;
|
||||
|
||||
};
|
||||
|
||||
#endif // MOVABLEOBJECT_H
|
@ -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();
|
||||
}
|
||||
|
@ -40,12 +40,13 @@ void Engine::setWorld(IWorld *world) {
|
||||
return ;
|
||||
|
||||
if (_currentWorld) {
|
||||
_currentWorld->deinit();
|
||||
_currentWorld->reset();
|
||||
}
|
||||
|
||||
_currentWorld = world;
|
||||
emit worldChanged();
|
||||
|
||||
if (!_currentWorld->init()) {
|
||||
if (!prepareNewWorld()) {
|
||||
QuasarAppUtils::Params::log("Failed to init world. World name: " + _currentWorld->name(),
|
||||
QuasarAppUtils::Error);
|
||||
|
||||
@ -53,22 +54,8 @@ void Engine::setWorld(IWorld *world) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_currentWorld->userInterface()->init()) {
|
||||
return;
|
||||
}
|
||||
|
||||
setMenu(_currentWorld->userInterface());
|
||||
|
||||
emit worldChanged();
|
||||
|
||||
startRenderLoop();
|
||||
}
|
||||
|
||||
QString Engine::hdr() const {
|
||||
if (!_currentWorld)
|
||||
return "";
|
||||
|
||||
return _currentWorld->hdrMap();
|
||||
_currentWorld->runAsBackGround();
|
||||
}
|
||||
|
||||
void Engine::setScane(QObject *newScane) {
|
||||
@ -149,6 +136,20 @@ void Engine::setPrepareLvlProgress(int newPrepareLvlProgress) {
|
||||
emit prepareLvlProgressChanged();
|
||||
}
|
||||
|
||||
bool Engine::prepareNewWorld() {
|
||||
if (!_currentWorld->prepare()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_currentWorld->userInterface()->init()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
setMenu(_currentWorld->userInterface());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Engine::renderLoop() {
|
||||
|
||||
if (!_currentWorld)
|
||||
|
@ -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);
|
||||
|
||||
bool prepareNewWorld();
|
||||
void renderLoop();
|
||||
|
||||
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 46878c18cae14eed67a2b105dc993ff2d670a3bc
|
||||
Subproject commit b08e8238fba0c28aed2c65e3a1fb317e61422d23
|
@ -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 *) {};
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user