4
1
mirror of https://github.com/QuasarApp/Snake.git synced 2025-05-07 23:19:43 +00:00

update core library

This commit is contained in:
Andrei Yankovich 2021-08-12 23:27:20 +03:00
parent eb5d8cd796
commit 8979ba73ce
33 changed files with 457 additions and 286 deletions

@ -39,10 +39,6 @@
</context>
<context>
<name>MainMenu</name>
<message>
<source>Play game</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>My Settings</source>
<translation type="unfinished"></translation>
@ -51,6 +47,10 @@
<source>Exit</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Select level</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PreviewControl</name>

@ -39,10 +39,6 @@
</context>
<context>
<name>MainMenu</name>
<message>
<source>Play game</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>My Settings</source>
<translation type="unfinished"></translation>
@ -51,6 +47,10 @@
<source>Exit</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Select level</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PreviewControl</name>

@ -39,10 +39,6 @@
</context>
<context>
<name>MainMenu</name>
<message>
<source>Play game</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>My Settings</source>
<translation type="unfinished"></translation>
@ -51,6 +47,10 @@
<source>Exit</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Select level</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PreviewControl</name>

@ -39,10 +39,6 @@
</context>
<context>
<name>MainMenu</name>
<message>
<source>Play game</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>My Settings</source>
<translation type="unfinished"></translation>
@ -51,6 +47,10 @@
<source>Exit</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Select level</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PreviewControl</name>

@ -39,10 +39,6 @@
</context>
<context>
<name>MainMenu</name>
<message>
<source>Play game</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>My Settings</source>
<translation type="unfinished"></translation>
@ -51,6 +47,10 @@
<source>Exit</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Select level</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PreviewControl</name>

@ -39,10 +39,6 @@
</context>
<context>
<name>MainMenu</name>
<message>
<source>Play game</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>My Settings</source>
<translation type="unfinished"></translation>
@ -51,6 +47,10 @@
<source>Exit</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Select level</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PreviewControl</name>

@ -39,10 +39,6 @@
</context>
<context>
<name>MainMenu</name>
<message>
<source>Play game</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>My Settings</source>
<translation type="unfinished"></translation>
@ -51,6 +47,10 @@
<source>Exit</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Select level</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PreviewControl</name>

@ -39,10 +39,6 @@
</context>
<context>
<name>MainMenu</name>
<message>
<source>Play game</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>My Settings</source>
<translation type="unfinished"></translation>
@ -51,6 +47,10 @@
<source>Exit</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Select level</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PreviewControl</name>

@ -39,10 +39,6 @@
</context>
<context>
<name>MainMenu</name>
<message>
<source>Play game</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>My Settings</source>
<translation type="unfinished"></translation>
@ -51,6 +47,10 @@
<source>Exit</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Select level</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PreviewControl</name>

@ -39,10 +39,6 @@
</context>
<context>
<name>MainMenu</name>
<message>
<source>Play game</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>My Settings</source>
<translation type="unfinished"></translation>
@ -51,6 +47,10 @@
<source>Exit</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Select level</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PreviewControl</name>

@ -24,7 +24,6 @@
<file>CrawlCoreAssets/particles/smokeSprite.png</file>
<file>CrawlModule/particles/Fire.qml</file>
<file>CrawlModule/particles/Wint.qml</file>
<file>CrawlModule/PreviewScane.qml</file>
<file>CrawlModule/PreviewControl.qml</file>
</qresource>
</RCC>

@ -23,6 +23,7 @@
#include "pluginloader.h"
#include <viewsolutions.h>
#include "worldstatus.h"
#include "user.h"
namespace CRAWL {
@ -36,18 +37,27 @@ QByteArray ClientApp::initTheme() {
}
}
ILevel *ClientApp::getLastLevel() {
for (const auto &data : qAsConst(_availableLvls)) {
if (data.model && data.model->world() && _engine->currentUser() &&
_engine->currentUser()->isUnlocked(data.model->world()->itemId())) {
return data.model;
}
}
return nullptr;
}
ClientApp::ClientApp() {
_engine = new Engine();
_menu = new MainMenuModel();
_store = new Store();
connect(_menu, &MainMenuModel::sigNewGame, this, &ClientApp::start);
connect(_menu, &MainMenuModel::sigLevelChanged, this, &ClientApp::changeLevel);
}
ClientApp::~ClientApp() {
delete _menu;
delete _engine;
delete _store;
for (auto it = _availableLvls.begin(); it != _availableLvls.end(); ++it) {
delete it.value().viewModel;
@ -57,26 +67,17 @@ ClientApp::~ClientApp() {
_availableLvls.clear();
}
IWorld *ClientApp::getLastWorld() {
for (const auto &data : qAsConst(_availableLvls)) {
if (data.viewModel && data.viewModel->unlocked()) {
return data.model;
}
}
return nullptr;
}
void ClientApp::initStore(Store *store) {
QMultiHash<int, const IItem *> storeItems;
for (const auto &data : qAsConst(_availableLvls)) {
storeItems.unite(data.model->childItemsRecursive());
if (data.model && data.model->world())
storeItems.unite(data.model->world()->childItemsRecursive());
}
store->init(storeItems);
}
void ClientApp::start(const QString &lvl) {
void ClientApp::changeLevel(int lvl) {
WordlData data = _availableLvls.value(lvl);
if (!data.model) {
@ -91,8 +92,7 @@ void ClientApp::start(const QString &lvl) {
return;
}
_engine->setWorld(data.model);
_engine->start();
_engine->setLevel(data.model);
}
bool ClientApp::init(QQmlApplicationEngine *engine) {
@ -133,19 +133,19 @@ bool ClientApp::init(QQmlApplicationEngine *engine) {
if (engine->rootObjects().isEmpty())
return false;
_engine->setWorld(getLastWorld());
_engine->setLevel(getLastLevel());
_engine->setQmlEngine(engine);
initStore(_store);
initStore(_engine->store());
return true;
}
void ClientApp::addLvl(IWorld *levelWordl) {
void ClientApp::addLvl(ILevel *levelWordl) {
WordlData data;
data.model = levelWordl;
data.viewModel = new WorldViewData(data.model);
_availableLvls.insert(data.model->itemName(), data);
data.viewModel = new WorldViewData(data.model->world());
_availableLvls.insert(data.model->world()->itemId(), data);
_menu->addWorldViewModel(data.viewModel);
}

@ -27,7 +27,6 @@ class MainMenuModel;
class IControl;
class Store;
/**
* @brief The WordlData struct simple structure that contains information about world.
*/
@ -68,25 +67,25 @@ public:
private:
QByteArray initTheme();
IWorld* getLastWorld();
ILevel *getLastLevel();
void initStore(Store* store);
/**
* @brief addLvl This method should be add level to game.
* @param levelWordl This is world instance
*/
void addLvl(IWorld* levelWordl);
void addLvl(ILevel* levelWordl);
/**
* @brief start This method star new game in @a lvl
* @brief changeLevel This method star new game in @a lvl
* @param lvl This is lvl name
*/
void start(const QString& lvl);
void changeLevel(int lvl);
QHash<QString, WordlData> _availableLvls;
QHash<int, WordlData> _availableLvls;
MainMenuModel *_menu = nullptr;
Engine *_engine = nullptr;
Store *_store = nullptr;
};
}

@ -7,7 +7,7 @@
#include "iitem.h"
#include "ilevel.h"
#include "iworld.h"
#include "ipreviewscaneworld.h"
namespace CRAWL {
@ -20,7 +20,7 @@ IWorld *ILevel::world() {
return _world;
}
IWorld *ILevel::previewScane() {
IPreviewScaneWorld *ILevel::previewScane() {
return _previewScane;
}
@ -33,7 +33,7 @@ void ILevel::setWorld(IWorld *newWorld) {
_world = newWorld;
}
void ILevel::setPreviewScane(IWorld *newPreviewScane) {
void ILevel::setPreviewScane(IPreviewScaneWorld *newPreviewScane) {
_previewScane = newPreviewScane;
}

@ -15,6 +15,7 @@ namespace CRAWL {
class IWorld;
class IItem;
class IPreviewScaneWorld;
/**
* @brief The ILevel class This interface make the world instance object.
@ -39,7 +40,7 @@ public:
* @return pointer to the model of the preview scane.
* @see ILevel::setPreviewScane
*/
IWorld* previewScane();
IPreviewScaneWorld* previewScane();
/**
* @brief reset This method unload all loaded data from level.
@ -61,12 +62,12 @@ protected:
* @note The @a newPreviewScane item will be distroued with the parent object.
* @see ILevel::previewScane
*/
void setPreviewScane(IWorld *newPreviewScane);
void setPreviewScane(IPreviewScaneWorld *newPreviewScane);
private:
IWorld* _world = nullptr;
IWorld* _previewScane = nullptr;
IPreviewScaneWorld* _previewScane = nullptr;
};
}

@ -89,6 +89,10 @@ void IPreviewScaneWorld::handleSelect(int item, bool isSelected) {
}
}
const StartData &IPreviewScaneWorld::configuration() const {
return _configuration;
}
void IPreviewScaneWorld::initControl(IControl *control) {
auto controlObject = dynamic_cast<PreviewControl*>(control);

@ -17,6 +17,7 @@ namespace CRAWL {
*/
class CRAWL_EXPORT IPreviewScaneWorld: public IWorld
{
Q_OBJECT
public:
/**
* @brief IPreviewScaneWorld This is main constructo of the preview world model.
@ -38,6 +39,8 @@ public:
bool start(const StartData &config) override;
bool stop() override;
const StartData &configuration() const;
signals:
/**
* @brief sigPrepareIsFinished This signal emited when user finished prepare to game.

@ -67,6 +67,10 @@ void IWorld::render(unsigned int tbfMsec) {
_ItemsMutex.unlock();
for (int id: toRemove) {
if (id == static_cast<IWorldItem *>(player())->guiId()) {
playerIsDead(static_cast<PlayableObject*>(player()));
}
removeItem(id);
}
@ -97,6 +101,7 @@ bool IWorld::start(const StartData& config) {
setTargetFps(60);
setRunning(true);
_eventServer->start();
setVisible(true);
return true;
}
@ -134,6 +139,7 @@ IWorldItem *IWorld::generate(const QString &objectType) const {
bool IWorld::stop() {
setRunning(false);
setVisible(false);
_eventServer->stop();
return true;
}
@ -149,7 +155,7 @@ IWorldItem *IWorld::getItem(int id) const {
}
void IWorld::clearItems() {
stop();
IWorld::stop();
while (_items.cbegin() != _items.cend()) {
removeItem(*_items.cbegin());
@ -307,6 +313,19 @@ const WorldRule *IWorld::worldRules() {
return _worldRules;
}
void IWorld::setVisible(bool visible) {
if (_visible == visible) {
return;
}
_visible = visible;
emit visibleChanged();
}
void IWorld::playerIsDead(PlayableObject *) const {
emit sigGameFinished();
}
bool IWorld::running() const {
return _running;
}
@ -390,7 +409,7 @@ void IWorld::setCameraReleativePosition(const QVector3D &newCameraReleativePosit
}
void IWorld::handleStop() {
runAsBackGround();
stop();
}
const QVector3D &IWorld::cameraReleativePosition() const {
@ -467,4 +486,9 @@ void IWorld::setMenu(QObject *newMenu) {
emit menuChanged();
}
bool IWorld::visible() const
{
return _visible;
}
}

@ -71,8 +71,9 @@ class CRAWL_EXPORT IWorld : public QObject, public IRender, public IItem
* @see IWorld::getMenu
* @see IWorld::userInterface
*/
Q_PROPERTY(QObject * menu READ menu WRITE setMenu NOTIFY menuChanged)
Q_PROPERTY(QObject * menu READ getMenu WRITE setMenu NOTIFY menuChanged)
Q_PROPERTY(QString hdr READ hdr NOTIFY hdrChanged)
Q_PROPERTY(bool visible READ visible NOTIFY visibleChanged)
Q_PROPERTY(int worldStatus READ wordlStatus WRITE setWorldStatus NOTIFY worldStatusChanged)
@ -248,12 +249,17 @@ public:
*/
void reset();
/**
* @brief visible This metohd retunr current value of the visible object.
* @return true if view is visible else false.
*/
bool visible() const;
signals:
/**
* @brief sigGameFinished This signal emit when game are finished
* @brief result This is player statistics after finished level,
*/
void sigGameFinished(GameResult result);
void sigGameFinished() const;
/**
* @brief sigOBjctsListChanged This signal emited when lvel status are changed.
@ -304,6 +310,11 @@ signals:
*/
void menuChanged();
/**
* @brief visibleChanged This signal emited when visible of the view changed.
*/
void visibleChanged();
protected:
/**
@ -420,6 +431,16 @@ protected:
*/
const WorldRule *worldRules();
/**
* @brief setVisible This method sets visible propertye for the qml view.
* @param visible This is new value of a property
*/
void setVisible(bool visible);
/**
* @brief playerIsDead This method will be invoked when player object get signal dead.
*/
virtual void playerIsDead(PlayableObject*) const;
protected slots:
virtual void onIntersects(const IWorldItem * trigger, QList<const IWorldItem *> list);
@ -524,6 +545,7 @@ private:
int _targetFps = 60;
bool _running = false;
bool _visible = true;
// testing
friend ClastersTest;

@ -18,11 +18,19 @@ ApplicationWindow {
height: 720;
title: qsTr("Crawl");
property var model: engine
Metrix {id: metrix}
Scene {
id: scane;
model: engine;
model: (model)? model.world : null;
anchors.fill: parent;
}
Scene {
id: nest;
model: (model)? model.world : null;
anchors.fill: parent;
}

@ -38,7 +38,7 @@ Item {
MainMenuButton {
id: play
text: qsTr("Play game")
text: qsTr("Select level")
onClicked: {
selectLvl.open()

@ -1,135 +0,0 @@
import QtQuick
import QtQuick3D
import QtQuick.Controls.Material
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick3D.Particles3D
View3D {
id: scene;
property var model: null;
renderMode: View3D.Offscreen
PerspectiveCamera {
id: camera
position: Qt.vector3d(0,0, 100)
}
SceneEnvironment {
id: defautlBackground
backgroundMode: SceneEnvironment.Color
clearColor: "#777777"
}
environment: /*(privateRoot.world)? background:*/ defautlBackground
ParticleSystem3D {
id: privateRoot
property var arrayObjects: []
property var world: (model)? model.world: null
property var gameMenuModel: (model)? model.menu: null
property var player: (world)? world.player: null
property var releativeCameraPosition: (world)? world.cameraReleativePosition: null
function add (cppObjId) {
if (!model) {
console.log("create object fail")
return;
}
const objModel = model.getGameObject(cppObjId);
if (!objModel) {
console.log("object model not found");
return;
}
var viewTemplate = objModel.viewTemplate;
var temp = Qt.createComponent(viewTemplate)
if (temp.status === Component.Ready) {
var obj = temp.createObject(privateRoot)
obj.model = objModel;
arrayObjects.push(obj)
} else {
console.log("wrong viewTemplate in model " + temp.errorString());
}
}
function remove(id) {
if (typeof id !== "number" || id < 0) {
console.log("id not found");
return;
}
for (var i = 0; i < arrayObjects.length; ++i) {
if (id === arrayObjects[i].guiId) {
arrayObjects[i].destroy();
arrayObjects.splice(i,1);
}
}
}
Connections {
target: privateRoot.world;
function onSigOBjctsListChanged(diff) {
if (!diff) {
console.log("diff not found");
return;
}
let tempDifRem = [];
tempDifRem = diff.getRemoveIds();
let tempDifAdd = [];
tempDifAdd = diff.getAddedIds();
for (let i = 0; i < tempDifAdd.length; ++i) {
privateRoot.add(tempDifAdd[i]);
}
for (let j = 0; j < tempDifRem.length; ++j) {
privateRoot.remove(tempDifRem[j]);
}
}
}
Connections {
target: privateRoot;
function onGameMenuModelChanged() {
if (!privateRoot.gameMenuModel) {
return;
}
const comp = Qt.createComponent(privateRoot.gameMenuModel.view);
if (comp.status === Component.Ready) {
if (privateRoot.gameMenu) {
privateRoot.gameMenu.destroy()
}
privateRoot.gameMenu = comp.createObject(scene);
if (privateRoot.gameMenu === null) {
// Error Handling
console.log("Error creating object");
}
privateRoot.gameMenu.model = privateRoot.gameMenuModel;
} else if (comp.status === Component.Error) {
// Error Handling
console.log("Error loading component: " + privateRoot.gameMenuModel.view, comp.errorString());
}
}
function onShowMenuChanged() {
if (privateRoot.gameMenu) {
privateRoot.gameMenu.visible = !showMenu
}
}
}
}
}

@ -11,10 +11,12 @@ import engine.worldstatus
View3D {
id: scene;
property var model: null;
property var worldModel: null;
property alias showMenu: privateRoot.showMenu
renderMode: View3D.Offscreen
visible: worldModel && worldModel.visible
Label {
text: scane.renderStats.fps
x: 200
@ -44,18 +46,16 @@ View3D {
ParticleSystem3D {
id: privateRoot
property var arrayObjects: []
property var world: (model)? model.world: null
property var gameMenuModel: (world)? world.menu: null
property var player: (world)? world.player: null
property var releativeCameraPosition: (world)? world.cameraReleativePosition: null
property var progress: (model)? model.prepareLvlProgress: null
property var gameMenuModel: (worldModel)? worldModel.menu: null
property var player: (worldModel)? worldModel.player: null
property var releativeCameraPosition: (worldModel)? worldModel.cameraReleativePosition: null
property var gameMenu: null
property bool showMenu: (world)? WorldStatus.Game !== world.worldStatus : false;
property bool showMenu: (worldModel)? WorldStatus.Game !== worldModel.worldStatus : false;
function add (cppObjId) {
if (!model) {
if (!worldModel) {
console.log("create object fail")
return;
}
@ -95,7 +95,7 @@ View3D {
}
Connections {
target: privateRoot.world;
target: worldModel;
function onSigOBjctsListChanged(diff) {
if (!diff) {
console.log("diff not found");

@ -9,9 +9,11 @@
#include <QQmlComponent>
#include <Crawl/guiobject.h>
#include <Crawl/ipreviewscaneworld.h>
#include "Crawl/iworld.h"
#include <QThread>
#include <quasarapp.h>
#include <storeviewmodel.h>
#include "Crawl/icontrol.h"
#include "QDateTime"
#include "QtConcurrent"
@ -20,10 +22,14 @@
namespace CRAWL {
Engine::Engine(QObject *parent): QObject(parent) {
_store = new Store();
_storeView = new StoreViewModel;
}
Engine::~Engine() {
stopRenderLoop();
delete _storeView;
}
QObject *Engine::scane() {
@ -48,15 +54,19 @@ void Engine::setLevel(ILevel *world) {
_currentLevel = world;
emit worldChanged();
if (_currentLevel && _currentLevel->world() && !_currentLevel->world()->)) {
if (!_currentLevel) {
if (_currentLevel->world()) {
QuasarAppUtils::Params::log("Failed to init world. World name: " + _currentLevel->world()->itemName(),
QuasarAppUtils::Error);
} else {
QuasarAppUtils::Params::log("Failed to init world. The World object is null! ",
QuasarAppUtils::Error);
}
QuasarAppUtils::Params::log("Failed to init world. The World object is null! ",
QuasarAppUtils::Error);
_currentLevel = nullptr;
return;
}
if (_currentLevel->world()) {
QuasarAppUtils::Params::log("Failed to init world. World name: " +
_currentLevel->world()->itemName(),
QuasarAppUtils::Error);
_currentLevel = nullptr;
return;
@ -64,6 +74,12 @@ void Engine::setLevel(ILevel *world) {
startRenderLoop();
_currentLevel->world()->runAsBackGround();
connect(_currentLevel->previewScane(), &IPreviewScaneWorld::sigPrepareIsFinished,
this, &Engine::start);
connect(_currentLevel->world(), &IPreviewScaneWorld::sigGameFinished,
this, &Engine::stop);
}
void Engine::setScane(QObject *newScane) {
@ -81,28 +97,41 @@ QObject *Engine::player() const {
}
QObject *Engine::world() const {
if (!_currentLevel)
return nullptr;
return _currentLevel->world();
}
int Engine::prepareLvlProgress() const {
return _prepareLvlProgress;
void Engine::start(const StartData& config) const {
if (!_currentLevel)
return;
if (!_currentLevel->previewScane()->stop()) {
return;
}
_currentLevel->world()->start(config);
}
bool Engine::start() const {
void Engine::stop() const {
if (!_currentLevel)
return false;
return;
if (!_currentLevel->isInit())
return false;
return _currentWorld->start();
if (!_currentLevel->world()->stop()) {
return;
}
_currentLevel->previewScane()->start(_currentLevel->previewScane()->configuration());
}
QObject *Engine::getGameObject(int id) const {
if (!_currentWorld)
if (!_currentLevel)
return nullptr;
return _currentWorld->getItem(id);
return _currentLevel->world()->getItem(id);
}
void Engine::startRenderLoop() {
@ -122,17 +151,9 @@ bool Engine::isRendering() const {
return _renderLoopFuture.isRunning();
}
void Engine::setPrepareLvlProgress(int newPrepareLvlProgress) {
if (_prepareLvlProgress == newPrepareLvlProgress) {
return;
}
_prepareLvlProgress = newPrepareLvlProgress;
emit prepareLvlProgressChanged();
}
void Engine::renderLoop() {
if (!_currentWorld)
if (!_currentLevel)
return;
while (_renderLoop) {
@ -144,11 +165,33 @@ void Engine::renderLoop() {
continue;
}
_currentWorld->render(currentTime - _oldTimeRender);
_currentLevel->world()->render(currentTime - _oldTimeRender);
_oldTimeRender = currentTime;
}
}
Store *Engine::store() const {
return _store;
}
QObject *Engine::nest() const {
if (!_currentLevel)
return nullptr;
return _currentLevel->previewScane();
}
User *Engine::currentUser() const {
return _currentUser;
}
QObject *Engine::storeView() const {
return _storeView;
}
void Engine::initStore(const QMultiHash<int, const IItem *> &availabelItems) {
_store->init(availabelItems);
_storeView->init(_store, _currentUser);
}
}

@ -18,6 +18,9 @@ namespace CRAWL {
class IWorld;
class Store;
class StartData;
class User;
class StoreViewModel;
/**
* @brief The Engine class
@ -27,9 +30,10 @@ class Engine : public QObject {
Q_OBJECT
Q_PROPERTY(QObject* player READ player NOTIFY playerChanged)
Q_PROPERTY(QObject* world READ world NOTIFY worldChanged)
Q_PROPERTY(QObject* nest READ nest NOTIFY worldChanged)
Q_PROPERTY(QObject* storeView READ storeView NOTIFY storeViewChanged)
Q_PROPERTY(QObject* scane READ scane WRITE setScane NOTIFY scaneChanged)
Q_PROPERTY(int _prepareLvlProgress READ prepareLvlProgress WRITE setPrepareLvlProgress NOTIFY prepareLvlProgressChanged)
public:
Engine(QObject * parent = nullptr);
@ -77,18 +81,6 @@ public:
*/
QObject* world() const;
/**
* @brief prepareLvlProgress This method return rurrent progress of the loading lvl.
* @return current progress of loading new level on the world. progress range is 0 - 100
*/
int prepareLvlProgress() const;
/**
* @brief start This method run current lvl
* @return true if lvl started successful.
*/
bool start() const;
/**
* @brief getGameObject This method using in qml for getting main model of the gui objects.
* @param id This is id of the gui object.
@ -112,27 +104,68 @@ public:
*/
bool isRendering() const;
/**
* @brief currentUser This method return pointer too current user.
* @return pointer too current user.
*/
User *currentUser() const;
/**
* @brief storeView This method return pointer to store view model
* @return pointer to store view model
*/
QObject *storeView() const;
/**
* @brief initStore This method is wrapper of the Store::init method.
* @param availabelItems This is list of available items.
*/
void initStore(const QMultiHash<int, const IItem *> &availabelItems);
/**
* @brief store This pointer return pointer to store.
* @return pointer to store.
*/
Store *store() const;
/**
* @brief nest This method return pointer to the nest model.
* @return pointer to the nest model.
*/
QObject *nest() const ;
signals:
void scaneChanged();
void playerChanged();
void worldChanged();
void storeViewChanged();
void prepareLvlProgressChanged();
private slots:
/**
* @brief start This method run current lvl ( move prepared data from the nest to game world)
* @param config This is confuguration that created new game world.
* @return true if lvl started successful.
*/
void start(const StartData &config) const;
/**
* @brief stop This slots invoked when world finished own session.
*/
void stop() const;
private:
void setPrepareLvlProgress(int newPrepareLvlProgress);
void renderLoop();
QObject *_scane = nullptr;
QQmlEngine *_engine = nullptr;
// IWorld* _currentWorld = nullptr;
ILevel* _currentLevel = nullptr;
int _prepareLvlProgress;
quint64 _oldTimeRender = 0;
User *_currentUser = nullptr;
StoreViewModel *_storeView = nullptr;
Store *_store = nullptr;
QFuture<void> _renderLoopFuture;
bool _renderLoop = false;
};

@ -37,8 +37,8 @@ void MainMenuModel::setAvailableLvls(const QList<QObject*> &newData) {
_availableLvlsModel->setSource(newData);
}
void MainMenuModel::newGame(const QString &lvl) {
emit sigNewGame(lvl);
void MainMenuModel::changeLevel(int lvl) {
emit sigLevelChanged(lvl);
}
}

@ -36,12 +36,12 @@ public:
QObject* availableLvlsModel() const;
void addWorldViewModel(QObject *);
void setAvailableLvls(const QList<QObject *> &newData);
Q_INVOKABLE void newGame(const QString& lvl);
Q_INVOKABLE void changeLevel(int lvl);
signals:
void userSettingsModelChanged(QObject* userSettingsModel);
void sigNewGame(const QString& lvl);
void sigLevelChanged(int lvl);
void availableLvlsModelChanged();
private:

@ -43,4 +43,12 @@ bool Store::init(const QMultiHash<int, const IItem *> &availabelItems) {
const IItem *Store::getItemById(int id) const {
return _store.value(id, nullptr);
}
int Store::size() const {
return _store.size();
}
QList<int> Store::keysList() const {
return QList<int>{_store.keyBegin(), _store.keyEnd()};
}
}

@ -45,6 +45,18 @@ public:
*/
const IItem* getItemById(int id) const;
/**
* @brief size This method return count of the available items in store.
* @return count of the available items.
*/
int size() const;
/**
* @brief keysList This method return a list of available keys
* @return a list of available keys
*/
QList<int> keysList() const;
private:
QMultiHash<int, const IItem*> _store;
};

@ -0,0 +1,93 @@
#include "storeviewmodel.h"
#include "store.h"
#include "user.h"
#include <Crawl/iitem.h>
namespace CRAWL {
StoreViewModel::StoreViewModel() {
}
QModelIndex StoreViewModel::index(int row, int column, const QModelIndex &parent) const {
return QAbstractListModel::index(row, column, parent);
}
int StoreViewModel::rowCount(const QModelIndex &) const {
return _keys.size();
}
int StoreViewModel::columnCount(const QModelIndex &) const {
return 1;
}
QVariant StoreViewModel::data(const QModelIndex &index, int role) const {
if (!_store)
return {};
if (index.row() >= rowCount()) {
return {};
}
int id = _keys.at(index.row());
const IItem* item = _store->getItemById(id);
if (!item)
return {};
switch (role) {
case ItemId: return id;
case ItemName: return item->itemName();
case ItemImage: return item->image();
case ItemDescription: return item->description();
case ItemWasBuy: return _currentUser && _currentUser->isUnlocked(id);
default:
return {};
}
}
QHash<int, QByteArray> StoreViewModel::roleNames() const {
QHash<int, QByteArray> roles;
roles[ItemId] = "itemId";
roles[ItemName] = "itemName";
roles[ItemDescription] = "itemDescription";
roles[ItemImage] = "itemImage";
roles[ItemWasBuy] = "itemWasBuy";
return roles;
}
void StoreViewModel::init(const Store * store, const User* user) {
setUser(user);
int diff = store->size() - _keys.size();
if (diff > 0) {
beginInsertRows({}, _keys.size(), store->size() - 1);
_store = store;
_keys = store->keysList();
endInsertRows();
} else if (diff == 0) {
emit dataChanged(index(0,0), index(rowCount() - 1, columnCount() - 1));
} else {
beginRemoveRows({}, store->size(), _keys.size() - 1);
_store = store;
_keys = store->keysList();
endRemoveRows();
}
}
void StoreViewModel::setUser(const User *user) {
_currentUser = user;
emit dataChanged(index(0,0), index(rowCount() - 1, columnCount() - 1), {ItemWasBuy});
}
}

@ -0,0 +1,62 @@
//#
//# 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 STOREVIEWMODEL_H
#define STOREVIEWMODEL_H
#include <QAbstractListModel>
namespace CRAWL {
class Store;
class User;
/**
* @brief The StoreViewModel class This is view model of the store. The object of this class should be initialized it he Store class.
*/
class StoreViewModel: public QAbstractListModel
{
Q_OBJECT
public:
StoreViewModel();
QModelIndex index(int row, int column, const QModelIndex &parent = {}) const override;
int rowCount(const QModelIndex &parent = {}) const override;
int columnCount(const QModelIndex &parent = {}) const override;
QVariant data(const QModelIndex &index, int role) const override;
QHash<int, QByteArray> roleNames() const override;
/**
* @brief init This method initialize data of the view model.
* @param _store This is poiter to store that contains all inforamtion about store items.
* @param user This is new pointer to current user.
* @see StoreViewModel::setUser
*/
void init(const Store * store, const User* user);
/**
* @brief setUser This method update user pointer
* @param user This is new pointer to current user.
*/
void setUser(const User* user);
private:
enum StoreRoles {
ItemId,
ItemName,
ItemImage,
ItemDescription,
ItemWasBuy
};
const Store *_store = nullptr;
QList<int> _keys;
const User* _currentUser = nullptr;
};
}
#endif // STOREVIEWMODEL_H

@ -9,10 +9,9 @@
#include "abslvlworld.h"
AbstractLevel::AbstractLevel() {
}
CRAWL::IWorld *AbstractLevel::world() {
initAbstractLvlResources();
return new AbstractLvl::AbsLvlWorld();
setWorld(new AbstractLvl::AbsLvlWorld());
setPreviewScane(new AbstractLvl::AbsLvlWorld());
}

@ -19,10 +19,6 @@ inline void initAbstractLvlResources() { Q_INIT_RESOURCE(abstractLevel);
class CRAWL_ABSTRACT_LEVEL_EXPORT AbstractLevel: public CRAWL::ILevel {
public:
AbstractLevel();
// ILevel interface
public:
CRAWL::IWorld *world() override;
};
#endif // ABSTRACTLEVEL_H