chore: Init

This commit is contained in:
NaiJi ✨ 2023-02-09 17:41:24 +04:00
commit 716544321a
87 changed files with 4442 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*.pro.user
*.autosave

120
QuestWizard.pro Normal file
View File

@ -0,0 +1,120 @@
#-------------------------------------------------
#
# Project created by QtCreator 2018-02-10T20:30:04
#
#-------------------------------------------------
VERSION = 0.0.1
CONFIG += c++17
QMAKE_CXXFLAGS = -Wall -Werror -Wextra -Wpedantic -Wconversion -std=c++17 -O2 -g
QT += core gui multimedia widgets quickwidgets
# Potato22 is the best vector artist, you can't change my mind.
# The icon is precious!
RC_FILE += add_ico.rc
TARGET = QuestWizard
TEMPLATE = app
DEFINES += QT_DEPRECATED_WARNINGS
SOURCES += main.cpp \
game.cpp \
features/qw_abstractdialoguemanager.cpp \
features/qw_dialoguefactory.cpp \
features/qw_textdialoguemanager.cpp \
features/qw_widgetdialoguemanager.cpp \
features/qw_eventfactory.cpp \
features/qw_inventorymanager.cpp \
features/qw_levelbuilder.cpp \
features/qw_soundplayer.cpp \
features/qw_statemachine.cpp \
qw_globalmetadata.cpp \
\
models/events/qw_abstractevent.cpp \
models/events/qw_abstractinventoryevent.cpp \
models/events/qw_abstractlevelevent.cpp \
models/events/qw_abstractsceneevent.cpp \
models/events/qw_abstractsoundevent.cpp \
models/events/qw_changelocationevent.cpp \
models/events/qw_changetriggerpropertiesevent.cpp \
models/events/qw_deletefrominventoryevent.cpp \
models/events/qw_endlevelevent.cpp \
models/events/qw_newgameevent.cpp \
models/events/qw_pickupitemevent.cpp \
models/events/qw_playmusicevent.cpp \
models/events/qw_playsoundevent.cpp \
models/events/qw_quitgameevent.cpp \
models/events/qw_startdialogueevent.cpp \
models/events/qw_addtriggerevent.cpp \
models/events/qw_removetriggerevent.cpp \
models/events/qw_switcheventsevent.cpp \
models/dialogues/qw_abstractgamedialogue.cpp \
models/dialogues/qw_textdialogue.cpp \
models/dialogues/qw_widgetdialogue.cpp \
models/qw_tagholder.cpp \
models/qw_trigger.cpp \
models/qw_location.cpp \
\
view/controls/pushbuttonsound.cpp \
view/controls/qw_abstractscenecontrol.cpp \
view/controls/scenedialoguepanel.cpp \
view/controls/sceneinventorypanel.cpp \
\
view/qw_scene.cpp \
view/qw_view.cpp
HEADERS += \
game.h \
features/qw_abstractdialoguemanager.h \
features/gamefeatures.h \
features/qw_dialoguefactory.h \
features/qw_textdialoguemanager.h \
features/qw_widgetdialoguemanager.h \
features/qw_eventfactory.h \
features/qw_inventorymanager.h \
features/qw_levelbuilder.h \
features/qw_soundplayer.h \
features/qw_statemachine.h \
qw_globalmetadata.h \
\
models/events/qw_abstractevent.h \
models/events/qw_abstractinventoryevent.h \
models/events/qw_abstractlevelevent.h \
models/events/qw_abstractsceneevent.h \
models/events/qw_abstractsoundevent.h \
models/events/qw_changelocationevent.h \
models/events/qw_changetriggerpropertiesevent.h \
models/events/qw_deletefrominventoryevent.h \
models/events/qw_endlevelevent.h \
models/events/qw_newgameevent.h \
models/events/qw_pickupitemevent.h \
models/events/qw_playmusicevent.h \
models/events/qw_playsoundevent.h \
models/events/qw_quitgameevent.h \
models/events/qw_startdialogueevent.h \
models/events/qw_addtriggerevent.h \
models/events/qw_removetriggerevent.h \
models/events/qw_switcheventsevent.h \
models/dialogues/qw_abstractgamedialogue.h \
models/dialogues/qw_textdialogue.h \
models/dialogues/qw_widgetdialogue.h \
models/qw_tagholder.h \
models/qw_trigger.h \
models/qw_location.h \
\
view/controls/pushbuttonsound.h \
view/controls/qw_abstractscenecontrol.h \
view/controls/scenedialoguepanel.h \
view/controls/sceneinventorypanel.h \
\
view/qw_scene.h \
view/qw_view.h
RESOURCES += \
application.qrc
DISTFILES += \
qml/test.qml

3
README.md Normal file
View File

@ -0,0 +1,3 @@
# QuestWizard
I am not really sure what this thing is going to be but anyway here is trello where I try to manage stuff
https://trello.com/b/M3kqOaDB/questwizard-functional-requirements?menu=filter&filter=label:master-merge%201.1

1
add_ico.rc Normal file
View File

@ -0,0 +1 @@
IDI_ICON1 ICON DISCARDABLE "icon.ico"

17
application.qrc Normal file
View File

@ -0,0 +1,17 @@
<RCC>
<qresource prefix="/">
<file>res/levels/level1.json</file>
<file>res/defaultsave.json</file>
<file>res/menu.json</file>
<file>res/final_background.jpg</file>
<file>res/roomkey_background.jpg</file>
<file>res/spawn_background.jpg</file>
<file>res/cell.png</file>
<file>res/door.png</file>
<file>res/inv.jpg</file>
<file>res/dialogue_panel.jpeg</file>
<file>res/sound.wav</file>
<file>res/osaka.png</file>
<file>res/config.json</file>
</qresource>
</RCC>

41
features/gamefeatures.h Normal file
View File

@ -0,0 +1,41 @@
#ifndef GAMEFEATURES_H
#define GAMEFEATURES_H
#include "game.h"
#include "qw_levelbuilder.h"
#include "qw_soundplayer.h"
#include "qw_inventorymanager.h"
#include "qw_textdialoguemanager.h"
#include "qw_widgetdialoguemanager.h"
#include "view/qw_view.h"
/* GameFeatures
* The package of all key in-game managers. This way they are easy to transport. */
struct GameFeatures final
{
public:
QWView *ptr_view;
QWScene *ptr_scene;
QWSoundPlayer *ptr_sound_player;
QWInventoryManager *ptr_inventory;
QWLevelBuilder *ptr_builder;
QWTextDialogueManager *ptr_text_dlg;
QWWidgetDialogueManager *ptr_widget_dlg;
explicit GameFeatures(Game *ptr_game)
{
ptr_scene = new QWScene(1280, 720);
ptr_view = new QWView(ptr_scene);
ptr_sound_player = new QWSoundPlayer(ptr_game);
ptr_inventory = new QWInventoryManager(ptr_scene);
ptr_builder = new QWLevelBuilder(ptr_game);
ptr_text_dlg = new QWTextDialogueManager(ptr_scene);
ptr_widget_dlg = new QWWidgetDialogueManager(ptr_scene);
}
~GameFeatures() = default;
};
#endif // GAMEFEATURES_H

View File

@ -0,0 +1,9 @@
#include "qw_abstractdialoguemanager.h"
QWAbstractDialogueManager:: QWAbstractDialogueManager(QWScene *scene) :
QObject(scene),
ptr_scene(scene)
{}
QWAbstractDialogueManager::~QWAbstractDialogueManager()
{}

View File

@ -0,0 +1,29 @@
#ifndef QWABSTRACTDIALOGUEMANAGER_H
#define QWABSTRACTDIALOGUEMANAGER_H
#include <QObject>
#include "view/qw_scene.h"
#include "models/dialogues/qw_abstractgamedialogue.h"
class QWAbstractDialogueManager : public QObject
{
Q_OBJECT
Q_DISABLE_COPY_MOVE(QWAbstractDialogueManager)
protected:
QWScene *ptr_scene;
public:
explicit QWAbstractDialogueManager(QWScene *scene = nullptr);
virtual ~QWAbstractDialogueManager() override = 0;
virtual void activateDialogue(const std::shared_ptr<QWAbstractGameDialogue> &dialogue) = 0;
public slots:
virtual void onClicked(MouseButton mouse_button) = 0;
signals:
void onEntryDialogueTransition();
void onLeaveDialogueTransition();
};
#endif // QWABSTRACTDIALOGUEMANAGER_H

View File

@ -0,0 +1,39 @@
#include "qw_dialoguefactory.h"
#include "qw_levelbuilder.h"
QWDialogueFactory::QWDialogueFactory(QWLevelBuilder *b) :
builder(b)
{}
std::shared_ptr<QWTextDialogue> QWDialogueFactory::createTextDialogue(const QJsonObject &json_object)
{
std::unique_ptr<QWTextDialogue> new_dialogue;
qDebug() << " Found QWTextDialogue. " << json_object["id"].toString() << ".";
Q_ASSERT(json_object.contains("text"));
QStringList text;
const QJsonArray text_pages = json_object["text"].toArray();
for (auto const &page : text_pages)
text << page.toString();
// add events on leave or something
new_dialogue = std::make_unique<QWTextDialogue>(text);
return std::shared_ptr<QWTextDialogue>{std::move(new_dialogue)};
}
std::shared_ptr<QWWidgetDialogue> QWDialogueFactory::createWidgetDialogue(const QJsonObject &json_object)
{
std::unique_ptr<QWWidgetDialogue> new_dialogue;
qDebug() << " Found QWWidgetDialogue. " << json_object["id"].toString() << ".";
Q_ASSERT(json_object.contains("qml_filename"));
new_dialogue = std::make_unique<QWWidgetDialogue>(json_object["qml_filename"].toString());
return std::shared_ptr<QWWidgetDialogue>{std::move(new_dialogue)};
}

View File

@ -0,0 +1,24 @@
#ifndef QWDIALOGUEFACTORY_H
#define QWDIALOGUEFACTORY_H
#include "models/dialogues/qw_textdialogue.h"
#include "models/dialogues/qw_widgetdialogue.h"
/* QWDialogueFactory
* Creates game dialogues of all kinds! */
class QWLevelBuilder;
class QWDialogueFactory final
{
private:
QWLevelBuilder *builder;
public:
explicit QWDialogueFactory(QWLevelBuilder *b);
std::shared_ptr<QWTextDialogue> createTextDialogue(const QJsonObject &json_object);
std::shared_ptr<QWWidgetDialogue> createWidgetDialogue(const QJsonObject &json_object);
};
#endif // QWDIALOGUEFACTORY_H

View File

@ -0,0 +1,221 @@
#include "qw_eventfactory.h"
#include "qw_levelbuilder.h"
#include "qw_widgetdialoguemanager.h"
#include "qw_textdialoguemanager.h"
QWEventFactory::QWEventFactory(QWLevelBuilder *b) :
builder(b)
{}
std::shared_ptr<QWDeleteFromInventoryEvent> QWEventFactory::createDeleteItEvent(const QJsonObject &json_object)
{
std::unique_ptr<QWDeleteFromInventoryEvent> new_event;
qDebug() << " Found QWDeleteFromInventoryEvent. " << json_object["id"].toString() << ".";
Q_ASSERT(json_object.contains("target"));
Q_ASSERT(builder->hash_triggers.contains(json_object["target"].toString()));
new_event = std::make_unique<QWDeleteFromInventoryEvent>(builder->hash_triggers[json_object["target"].toString()]);
new_event->setInventoryManager(builder->ptr_inventory);
return std::shared_ptr<QWDeleteFromInventoryEvent>{std::move(new_event)};
}
std::shared_ptr<QWChangeLocationEvent> QWEventFactory::createChangeLocEvent(const QJsonObject &json_object)
{
std::unique_ptr<QWChangeLocationEvent> new_event;
qDebug() << " Found QWChangeLocationEvent. " << json_object["id"].toString() << ".";
Q_ASSERT(json_object.contains("location"));
Q_ASSERT(builder->hash_locations.contains(json_object["location"].toString()));
new_event = std::make_unique<QWChangeLocationEvent>(builder->hash_locations[json_object["location"].toString()]);
new_event->setScene(builder->ptr_scene);
return std::shared_ptr<QWChangeLocationEvent>{std::move(new_event)};
}
std::shared_ptr<QWChangeTriggerPropertiesEvent> QWEventFactory::createChangeTrProperts(const QJsonObject &json_object)
{
std::unique_ptr<QWChangeTriggerPropertiesEvent> new_event;
qDebug() << " Found QWChangeTriggerPropertiesEvent. " << json_object["id"].toString() << ".";
Q_ASSERT(json_object.contains("target"));
Q_ASSERT(builder->hash_triggers.contains(json_object["target"].toString()));
new_event = std::make_unique<QWChangeTriggerPropertiesEvent>(builder->hash_triggers[json_object["target"].toString()]);
if (json_object.contains("x") && json_object.contains("y"))
new_event->setParams(json_object["x"].toDouble(), json_object["y"].toDouble(),
json_object.contains("path") ? json_object["path"].toString() : "$no_pic");
else
new_event->setParams(json_object.contains("path") ? json_object["path"].toString() : "$no_pic");
return std::shared_ptr<QWChangeTriggerPropertiesEvent>{std::move(new_event)};
}
std::shared_ptr<QWSwitchEventsEvent> QWEventFactory::createSwitchEventsEvent(const QJsonObject &json_object)
{
std::unique_ptr<QWSwitchEventsEvent> new_event;
qDebug() << " Found QWSwitchEventsEvent. " << json_object["id"].toString() << ".";
Q_ASSERT(json_object.contains("target"));
Q_ASSERT(builder->hash_triggers.contains(json_object["target"].toString()));
new_event = std::make_unique<QWSwitchEventsEvent>(builder->hash_triggers[json_object["target"].toString()]);
Q_ASSERT(json_object.contains("enable_evs") && json_object.contains("disable_evs"));
// Linking events of enabled state
QJsonArray evs = json_object["enable_evs"].toArray();
QList<std::shared_ptr<QWAbstractEvent>> list_events;
for (const auto obj : evs) {
Q_ASSERT(builder->hash_events.contains(obj.toString()));
list_events.append(builder->hash_events[obj.toString()]);
}
new_event->setEventsOnEnable(list_events);
list_events.clear();
// Linking events of disabled state
evs = json_object["disable_evs"].toArray();
for (const auto obj : evs) {
Q_ASSERT(builder->hash_events.contains(obj.toString()));
list_events.append(builder->hash_events[obj.toString()]);
}
new_event->setEventsOnDisable(list_events);
new_event->init();
return std::shared_ptr<QWSwitchEventsEvent>{std::move(new_event)};
}
std::shared_ptr<QWPickupItemEvent> QWEventFactory::createPickupItEvent(const QJsonObject &json_object)
{
std::unique_ptr<QWPickupItemEvent> new_event;
qDebug() << " Found QWPickupItemEvent. " << json_object["id"].toString() << ".";
Q_ASSERT(json_object.contains("target"));
Q_ASSERT(builder->hash_triggers.contains(json_object["target"].toString()));
new_event = std::make_unique<QWPickupItemEvent>(builder->hash_triggers[json_object["target"].toString()]);
new_event->setInventoryManager(builder->ptr_inventory);
return std::shared_ptr<QWPickupItemEvent>{std::move(new_event)};
}
std::shared_ptr<QWEndLevelEvent> QWEventFactory::createEndLevelEvent(const QJsonObject &json_object)
{
std::unique_ptr<QWEndLevelEvent> new_event;
qDebug() << " Found QWEndLevelEvent. " << json_object["id"].toString() << ".";
Q_ASSERT(json_object.contains("new_level"));
new_event = std::make_unique<QWEndLevelEvent>(json_object["target"].toString());
new_event->setLevelBuilder(builder);
return std::shared_ptr<QWEndLevelEvent>{std::move(new_event)};
}
std::shared_ptr<QWPlaySoundEvent> QWEventFactory::createPlaySoundEvent(const QJsonObject &json_object)
{
std::unique_ptr<QWPlaySoundEvent> new_event;
qDebug() << " Found QWPlaySoundEvent. " << json_object["id"].toString() << ".";
Q_ASSERT(json_object.contains("sound"));
new_event = std::make_unique<QWPlaySoundEvent>(json_object["sound"].toString());
new_event->setSoundPlayer(builder->ptr_soundplayer);
return std::shared_ptr<QWPlaySoundEvent>{std::move(new_event)};
}
std::shared_ptr<QWNewGameEvent> QWEventFactory::createNewGameEvent(const QJsonObject &json_object)
{
std::unique_ptr<QWNewGameEvent> new_event;
qDebug() << " Found QWNewGameEvent. " << json_object["id"].toString() << ".";
Q_ASSERT(json_object.contains("save_file"));
new_event = std::make_unique<QWNewGameEvent>(json_object["save_file"].toString());
new_event->setLevelBuilder(builder);
return std::shared_ptr<QWNewGameEvent>{std::move(new_event)};
}
std::shared_ptr<QWQuitGameEvent> QWEventFactory::createQuitGameEvent(const QJsonObject &json_object)
{
std::unique_ptr<QWQuitGameEvent> new_event;
qDebug() << " Found QWQuitGameEvent. " << json_object["id"].toString() << ".";
Q_ASSERT(json_object.contains("save_game"));
new_event = std::make_unique<QWQuitGameEvent>(json_object["save_game"].toBool());
new_event->setLevelBuilder(builder);
return std::shared_ptr<QWQuitGameEvent>{std::move(new_event)};
}
std::shared_ptr<QWStartDialogueEvent> QWEventFactory::createStartDlgEvent(const QJsonObject &json_object)
{
std::unique_ptr<QWStartDialogueEvent> new_event;
qDebug() << " Found QWStartTextDialogueEvent. " << json_object["id"].toString() << ".";
Q_ASSERT(json_object.contains("dialogue"));
Q_ASSERT(json_object.contains("dialogue_type"));
Q_ASSERT(builder->hash_dialogues.contains(json_object["dialogue"].toString()));
new_event = std::make_unique<QWStartDialogueEvent>(builder->hash_dialogues[json_object["dialogue"].toString()]);
switch(json_object["dialogue_type"].toInt()) {
case 1:
new_event->setDialogueManager(builder->ptr_widget_dlg);
break;
case 0:
new_event->setDialogueManager(builder->ptr_text_dlg);
break;
default:
Q_ASSERT(false);
}
return std::shared_ptr<QWStartDialogueEvent>{std::move(new_event)};
}
std::shared_ptr<QWAddTriggerEvent> QWEventFactory::createAddTrEvent(const QJsonObject &json_object)
{
std::unique_ptr<QWAddTriggerEvent> new_event;
qDebug() << " Found QWAddTriggerEvent. " << json_object["id"].toString() << ".";
Q_ASSERT(json_object.contains("trigger"));
Q_ASSERT(builder->hash_triggers.contains(json_object["trigger"].toString()));
new_event = std::make_unique<QWAddTriggerEvent>(builder->hash_triggers[json_object["trigger"].toString()]);
Q_ASSERT(json_object.contains("location"));
Q_ASSERT(builder->hash_locations.contains(json_object["location"].toString()));
new_event->setLocation(builder->hash_locations[json_object["location"].toString()]);
return std::shared_ptr<QWAddTriggerEvent>{std::move(new_event)};
}
std::shared_ptr<QWRemoveTriggerEvent> QWEventFactory::createRemoveTrEvent(const QJsonObject &json_object)
{
std::unique_ptr<QWRemoveTriggerEvent> new_event;
qDebug() << " Found QWRemoveTriggerEvent. " << json_object["id"].toString() << ".";
Q_ASSERT(json_object.contains("trigger"));
Q_ASSERT(builder->hash_triggers.contains(json_object["trigger"].toString()));
new_event = std::make_unique<QWRemoveTriggerEvent>(builder->hash_triggers[json_object["trigger"].toString()]);
Q_ASSERT(json_object.contains("location"));
Q_ASSERT(builder->hash_locations.contains(json_object["location"].toString()));
new_event->setLocation(builder->hash_locations[json_object["location"].toString()]);
return std::shared_ptr<QWRemoveTriggerEvent>{std::move(new_event)};
}

View File

@ -0,0 +1,48 @@
#ifndef EVENTFACTORY_H
#define EVENTFACTORY_H
#include <QJsonObject>
#include <QJsonArray>
#include "models/events/qw_abstractevent.h"
#include "models/events/qw_changelocationevent.h"
#include "models/events/qw_switcheventsevent.h"
#include "models/events/qw_deletefrominventoryevent.h"
#include "models/events/qw_pickupitemevent.h"
#include "models/events/qw_endlevelevent.h"
#include "models/events/qw_playsoundevent.h"
#include "models/events/qw_changetriggerpropertiesevent.h"
#include "models/events/qw_newgameevent.h"
#include "models/events/qw_quitgameevent.h"
#include "models/events/qw_startdialogueevent.h"
#include "models/events/qw_addtriggerevent.h"
#include "models/events/qw_removetriggerevent.h"
/* QWEventFactory
* Creates game events of all kinds! */
class QWLevelBuilder;
class QWEventFactory final
{
private:
QWLevelBuilder *builder;
public:
explicit QWEventFactory(QWLevelBuilder *b);
std::shared_ptr<QWDeleteFromInventoryEvent> createDeleteItEvent(const QJsonObject &json_object);
std::shared_ptr<QWChangeLocationEvent> createChangeLocEvent(const QJsonObject &json_object);
std::shared_ptr<QWChangeTriggerPropertiesEvent> createChangeTrProperts(const QJsonObject &json_object);
std::shared_ptr<QWSwitchEventsEvent> createSwitchEventsEvent(const QJsonObject &json_object);
std::shared_ptr<QWPickupItemEvent> createPickupItEvent(const QJsonObject &json_object);
std::shared_ptr<QWEndLevelEvent> createEndLevelEvent(const QJsonObject &json_object);
std::shared_ptr<QWPlaySoundEvent> createPlaySoundEvent(const QJsonObject &json_object);
std::shared_ptr<QWNewGameEvent> createNewGameEvent(const QJsonObject &json_object);
std::shared_ptr<QWQuitGameEvent> createQuitGameEvent(const QJsonObject &json_object);
std::shared_ptr<QWStartDialogueEvent> createStartDlgEvent(const QJsonObject &json_object);
std::shared_ptr<QWAddTriggerEvent> createAddTrEvent(const QJsonObject &json_object);
std::shared_ptr<QWRemoveTriggerEvent> createRemoveTrEvent(const QJsonObject &json_object);
};
#endif // EVENTFACTORY_H

View File

@ -0,0 +1,94 @@
#include "qw_inventorymanager.h"
#include "qw_globalmetadata.h"
#include "view/controls/sceneinventorypanel.h"
#include "view/qw_scene.h"
#include "models/qw_trigger.h"
QWInventoryManager::QWInventoryManager(QWScene *sc) :
ptr_scene(sc),
index_freepan(0)
{
// Loading metadata
metadata.length_wall = QWGlobalMetadata::valueBy("InventoryManager:length_wall").toInt();
metadata.length_cell = QWGlobalMetadata::valueBy("InventoryManager:length_cell").toInt();
metadata.max_amount = QWGlobalMetadata::valueBy("InventoryManager:max_amount").toInt();
metadata.first_wall = QWGlobalMetadata::valueBy("InventoryManager:first_wall").toInt();
metadata.clr_sel = Qt::GlobalColor(QWGlobalMetadata::valueBy("InventoryManager:clr_sel").toInt());
metadata.clr_sth = QWGlobalMetadata::valueBy("InventoryManager:clr_str").toReal();
item_selected_effect = new QGraphicsColorizeEffect();
item_selected_effect->setColor(metadata.clr_sel);
item_selected_effect->setStrength(metadata.clr_sth);
}
void QWInventoryManager::setInventoryPanel(const std::shared_ptr<QGraphicsWidget> &panel) noexcept
{
ptr_panel = panel;
}
int QWInventoryManager::freePanel() const noexcept
{
return index_freepan;
}
void QWInventoryManager::freePanelToRight()
{
++index_freepan;
Q_ASSERT(index_freepan <= metadata.max_amount);
}
void QWInventoryManager::freePanelToLeft()
{
--index_freepan;
Q_ASSERT(index_freepan >= 0);
}
void QWInventoryManager::addInventoryIcon(std::shared_ptr<QWTrigger> &inventory_icon)
{
inventory_icon->setParentItem(ptr_panel.get());
list_inventory_icons.append(inventory_icon);
inventory_icon->setPos(metadata.first_wall
+ ((metadata.length_wall + metadata.length_cell)
* freePanel())
, 0);
freePanelToRight();
}
void QWInventoryManager::removeInventoryIcon(std::shared_ptr<QWTrigger> &inventory_icon)
{
Index panel = metadata.max_amount + 1;
for (Index i = 0; i < list_inventory_icons.size(); ++i)
if (inventory_icon == list_inventory_icons[i])
panel = i;
Q_ASSERT(panel <= metadata.max_amount);
ptr_scene->removeItem(inventory_icon.get());
list_inventory_icons.removeAt(panel);
freePanelToLeft();
reorganizeItems(panel);
}
void QWInventoryManager::reorganizeItems(Index free_panel)
{
// When we remove item from the center we also should carefully move all the right items to the left
for (Index j = free_panel; j < list_inventory_icons.size(); ++j)
{
const std::shared_ptr<QWTrigger> &t = list_inventory_icons.at(j);
t->moveBy(-(metadata.length_cell + metadata.length_wall), 0);
if (j > 0)
list_inventory_icons[j-1] = list_inventory_icons[j];
}
}
void QWInventoryManager::onClicked()
{
for (auto &tr : list_inventory_icons)
if (tr->isUnderMouse()) {
tr->setGraphicsEffect(tr->graphicsEffect() ? nullptr : item_selected_effect);
tr->activate();
} else {
tr->setGraphicsEffect(nullptr);
}
}

View File

@ -0,0 +1,67 @@
#ifndef INVENTORYMANAGER_H
#define INVENTORYMANAGER_H
#include <memory>
#include <QGraphicsColorizeEffect>
/* QWInventoryManager
* Controls everything related to inventory slots and their items. */
class QGraphicsWidget;
class QWScene;
class QWTrigger;
class QWInventoryManager final : public QObject
{
Q_OBJECT
Q_DISABLE_COPY_MOVE(QWInventoryManager)
private:
QList<std::shared_ptr<QWTrigger>> list_inventory_icons;
std::shared_ptr<QGraphicsWidget> ptr_panel;
QWScene *ptr_scene;
QRect rect_hidden;
QRect rect_visible;
using Index = QList<std::shared_ptr<QWTrigger>>::size_type;
Index index_freepan;
QGraphicsColorizeEffect *item_selected_effect;
struct metadata
{
// the separator thinkness
int length_wall;
// the cell side
int length_cell;
// the maximum amount of items to hold
int max_amount;
// the left wall of first item slot
int first_wall;
// the color for selected items
QColor clr_sel;
// the color for selected items
qreal clr_sth;
} metadata;
void reorganizeItems(Index i);
public:
explicit QWInventoryManager(QWScene *sc);
void setInventoryPanel(const std::shared_ptr<QGraphicsWidget> &panel) noexcept;
inline int freePanel() const noexcept;
inline void freePanelToRight();
inline void freePanelToLeft();
void addInventoryIcon(std::shared_ptr<QWTrigger> &inventory_icon);
void removeInventoryIcon(std::shared_ptr<QWTrigger> &inventory_icon);
public slots:
void onClicked();
};
#endif // INVENTORYMANAGER_H

View File

@ -0,0 +1,470 @@
#include <QDebug>
#include "gamefeatures.h"
#include "qw_levelbuilder.h"
#include "qw_eventfactory.h"
#include "qw_dialoguefactory.h"
#include "qw_globalmetadata.h"
#include "view/qw_scene.h"
#include "models/qw_location.h"
#include "models/qw_trigger.h"
QWLevelBuilder::QWLevelBuilder(QObject *parent) :
QObject(parent),
str_current_level(strInitLevel())
{
// Dir for local save files
if (!QDir("save").exists()) {
QDir().mkdir("save");
}
save_dir.setPath("save");
}
template<typename MODEL>
QJsonArray writeEntitesToJsonArray(const QHash<QString, std::shared_ptr<MODEL>> &hash_models)
{
// Writing in active save file all the game elements and their state
QJsonArray json_array;
for (const auto &model : hash_models)
{
QJsonObject model_data;
model->writeToJson(model_data);
json_array.append(model_data);
}
return json_array;
}
void QWLevelBuilder::initMenuLevel()
{
str_current_level = "menu";
QFile file(":/res/menu.json");
Q_ASSERT(file.open(QIODevice::ReadOnly));
const QByteArray json_arr = file.readAll();
file.close();
QJsonObject savefile = QJsonDocument::fromJson(json_arr).object();
init(savefile);
}
void QWLevelBuilder::initSaveProfile(const QString &filename, const QString &profilename)
{
Q_UNUSED(profilename)
// Creating inital save file after beginning the new game:
str_profile_filename = filename;
str_current_level = strInitLevel();
QFile file;
str_profile_filename.remove(".json");
// We move default game description to player's save file
file.setFileName(save_dir.path() + "/" + str_profile_filename + ".json");
qDebug() << save_dir.path() + "/" + str_profile_filename + ".json";
if (!file.exists()) {
qDebug() << "copy file";
QFile::copy(":/res/defaultsave.json", file.fileName());
}
// Now we modify default json file to add the chosen profile name
/*Q_ASSERT(file.open(QIODevice::ReadOnly));
const QByteArray json_arr = file.readAll();
file.close();
QJsonObject savefile = QJsonDocument::fromJson(json_arr).object();
// Pull the saved string from new game dialogue
str_current_profile = profilename;
savefile.insert("save_profile", str_current_profile);
// Write it and resave
Q_ASSERT(file.open(QIODevice::WriteOnly));
file.write(QJsonDocument(savefile).toJson());
file.close();*/
}
void QWLevelBuilder::saveGame(/*QString filename*/)
{
qDebug() << "Save current game!";
QJsonObject savejson;
QJsonArray json_entites;
/* The first Trigger which moves player into its
* needed location where the game starts */
savejson.insert("init", "spawn");
savejson.insert("save_profile", str_current_profile);
qDebug() << "Save triggers!";
json_entites = writeEntitesToJsonArray(hash_triggers);
savejson.insert("triggers", json_entites);
qDebug() << "Save dialogues!";
json_entites = writeEntitesToJsonArray(hash_dialogues);
savejson.insert("dialogues", json_entites);
qDebug() << "Save locations!";
json_entites = writeEntitesToJsonArray(hash_locations);
savejson.insert("locations", json_entites);
qDebug() << "Save events!";
json_entites = writeEntitesToJsonArray(hash_events);
// Creating the inital event where player must appear after game loading
QJsonObject init_spawn_data;
QStringList trs;
for (auto & tr : ptr_scene->currentLocation()->triggers())
trs << tr->tag();
QList<std::shared_ptr<QWTrigger>> list_triggers;
init_spawn_data.insert("id", "spawn");
init_spawn_data.insert("type", 0);
init_spawn_data.insert("trs", QJsonArray::fromStringList(trs));
json_entites.append(init_spawn_data);
savejson.insert("events", json_entites);
// - - - //
QFile file(save_dir.dirName() + "/" + str_profile_filename + ".json");
Q_ASSERT(file.open(QIODevice::ReadOnly));
const QByteArray json_arr = file.readAll();
file.close();
QJsonObject savefile = QJsonDocument::fromJson(json_arr).object();
savefile[str_current_level] = savejson;
Q_ASSERT(file.open(QIODevice::WriteOnly));
file.write(QJsonDocument(savejson).toJson());
file.close();
}
void QWLevelBuilder::loadGame(/*QString filename*/)
{
QFile file;
hash_events.clear();
hash_triggers.clear();
hash_dialogues.clear();
hash_locations.clear();
init_trigger.reset();
file.setFileName(save_dir.dirName() + "/" + str_profile_filename + ".json");
file.open(QIODevice::ReadOnly);
const QByteArray json_arr = file.readAll();
file.close();
QJsonObject savefile = QJsonDocument::fromJson(json_arr).object();
str_current_level = savefile["init_level"].toString();
init(savefile);
}
void QWLevelBuilder::initLevel(const QString &lvlname)
{
str_current_level = lvlname;
QFile file(save_dir.dirName() + "/" + str_profile_filename + ".json");
Q_ASSERT(file.open(QIODevice::ReadOnly));
const QByteArray json_arr = file.readAll();
file.close();
emit ptr_scene->signalLeaveMenu();
QJsonObject savefile = QJsonDocument::fromJson(json_arr).object();
init(savefile);
}
void QWLevelBuilder::init(const QJsonObject & savefile)
{
qDebug() << "Init " << str_current_level << " level!";
hash_events.clear();
hash_triggers.clear();
init_trigger.reset();
level = savefile[str_current_level].toObject();
Q_ASSERT(!level.isEmpty());
// Building level from current json
if (level.contains("triggers"))
setupTriggers(level["triggers"].toArray());
if (level.contains("dialogues"))
setupDialogues(level["dialogues"].toArray());
if (level.contains("locations"))
setupLocations(level["locations"].toArray());
if (level.contains("events"))
setupEvents(level["events"].toArray());
linkEvents(level["triggers"].toArray());
init_trigger = level.contains("init") ? hash_triggers[level["init"].toString()] : nullptr;
// Start the level
Q_ASSERT(init_trigger);
init_trigger->activate();
}
QString QWLevelBuilder::strInitLevel() noexcept
{
return "start";
}
void QWLevelBuilder::setGameFeatures(std::unique_ptr<GameFeatures> &features)
{
ptr_scene = features->ptr_scene;
ptr_inventory = features->ptr_inventory;
ptr_soundplayer = features->ptr_sound_player;
ptr_text_dlg = features->ptr_text_dlg;
ptr_widget_dlg = features->ptr_widget_dlg;
}
void QWLevelBuilder::linkEvents(const QJsonArray &array)
{
qDebug() << "Link the events to triggers!";
for (const QJsonValue &json_value : array)
{
QJsonObject json_object(json_value.toObject());
if (json_object.contains("evs"))
{
qDebug() << " Trigger " << json_object["id"].toString() << " contains events!";
QJsonArray evs = json_object["evs"].toArray();
for (const QJsonValue event : evs)
{
QString obj = event.toString();
qDebug() << " Inserting " << obj << " to its trigger!";
hash_triggers[json_object["id"].toString()]->addEvents(hash_events[obj]);
qDebug() << " Success!";
}
}
if (json_object.contains("examine_dialogue"))
{
qDebug() << " Trigger " << json_object["id"].toString() << " contains examination dialogue!";
const QString dialogue_tag = json_object["examine_dialogue"].toString();
hash_triggers[json_object["id"].toString()]->setExaminationDialogueEvent(hash_events[dialogue_tag]);
}
}
}
// * * * * * * * * * * * * * * SETUP STUFF * * * * * * * * * * * * * *
//
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
void QWLevelBuilder::setupTriggers(const QJsonArray &array)
{
qDebug() << "Setup the triggers!";
QJsonObject json_object;
for (const QJsonValue &json_value : array)
{
json_object = json_value.toObject();
std::shared_ptr<QWTrigger> new_trigger;
// check if the picture exists!
Q_ASSERT(json_object.contains("id"));
QString mask = json_object.contains("mask") ? json_object["mask"].toString() : json_object["id"].toString();
new_trigger = std::make_shared<QWTrigger>(mask);
new_trigger->setTag(json_object["id"].toString());
qDebug() << "! The trigger with id " << json_object["id"].toString() << " was created.";
// setup the position on the scene
if (json_object.contains("x") && json_object.contains("y")) {
new_trigger->setPos(json_object["x"].toDouble(), json_object["y"].toDouble());
qDebug() << " The trigger was moved to "
<< new_trigger->x() << " " << new_trigger->y();
}
hash_triggers.insert(json_object["id"].toString(), new_trigger);
qDebug() << " The trigger was inserted into its map.\n - - -";
}
}
void QWLevelBuilder::setupEvents(const QJsonArray &array)
{
qDebug() << "Setup the events!";
std::unique_ptr<QWEventFactory> factory = std::make_unique<QWEventFactory>(this);
QJsonObject json_object;
QList<QJsonObject> list_later_events;
for (const QJsonValue &json_value : array)
{
json_object = json_value.toObject();
std::shared_ptr<QWAbstractEvent> new_event;
// check if the id exists!
Q_ASSERT(json_object.contains("id"));
qDebug() << "! The event with id " << json_object["id"].toString() << " is about to create.";
// independent events
Q_ASSERT(json_object.contains("type"));
int type = json_object["type"].toInt();
switch (type)
{
case (EVENT_TYPE::CHANGE_LOCATION):
new_event = factory->createChangeLocEvent(json_object);
break;
case (EVENT_TYPE::DELETE_FROM_INVENTORY):
new_event = factory->createDeleteItEvent(json_object);
break;
case (EVENT_TYPE::PICKUP_ITEM):
new_event = factory->createPickupItEvent(json_object);
break;
case (EVENT_TYPE::END_LEVEL):
new_event = factory->createEndLevelEvent(json_object);
break;
case (EVENT_TYPE::CHANGE_TRIGGER_PROPERTIES):
new_event = factory->createChangeTrProperts(json_object);
break;
case (EVENT_TYPE::NEW_GAME):
new_event = factory->createNewGameEvent(json_object);
break;
case (EVENT_TYPE::QUIT_GAME):
new_event = factory->createQuitGameEvent(json_object);
break;
case (EVENT_TYPE::START_DIALOGUE):
new_event = factory->createStartDlgEvent(json_object);
break;
case (EVENT_TYPE::ADD_TRIGGER):
new_event = factory->createAddTrEvent(json_object);
break;
case (EVENT_TYPE::REMOVE_TRIGGER):
new_event = factory->createRemoveTrEvent(json_object);
break;
default:
list_later_events.append(json_object);
continue;
}
new_event->setTag(json_object["id"].toString());
hash_events.insert(json_object["id"].toString(), new_event);
}
// Some events work with other events, so we need to initialize all
// independent events earlier than these
for (const auto &later_event : list_later_events) {
int type = later_event["type"].toInt();
std::shared_ptr<QWAbstractEvent> new_event;
switch (type)
{
case (EVENT_TYPE::SWITCH_EVENTS): // switch events
new_event = factory->createSwitchEventsEvent(later_event);
break;
default:
Q_ASSERT(false);
continue;
}
new_event->setTag(later_event["id"].toString());
hash_events.insert(later_event["id"].toString(), new_event);
}
}
void QWLevelBuilder::setupDialogues(const QJsonArray &array)
{
qDebug() << "Setup the dialogues!";
std::unique_ptr<QWDialogueFactory> factory = std::make_unique<QWDialogueFactory>(this);
QJsonObject json_object;
for (const QJsonValue &json_value : array)
{
json_object = json_value.toObject();
std::shared_ptr<QWAbstractGameDialogue> new_dialogue;
// check if the id exists!
Q_ASSERT(json_object.contains("id"));
qDebug() << "! The dialogue with id " << json_object["id"].toString() << " is about to create.";
Q_ASSERT(json_object.contains("type"));
int type = json_object["type"].toInt();
switch (type)
{
case (DIALOGUE_TYPE::TEXT):
new_dialogue = factory->createTextDialogue(json_object);
break;
case (DIALOGUE_TYPE::WIDGET):
new_dialogue = factory->createWidgetDialogue(json_object);
break;
default:
Q_ASSERT(false);
}
new_dialogue->setTag(json_object["id"].toString());
hash_dialogues.insert(json_object["id"].toString(), new_dialogue);
}
}
void QWLevelBuilder::setupLocations(const QJsonArray &array)
{
qDebug() << "Setup the locations!";
QJsonObject json_object;
for (const QJsonValue & json_value : array)
{
json_object = json_value.toObject();
std::shared_ptr<QWLocation> new_location;
Q_ASSERT(json_object.contains("id"));
qDebug() << "! The level with id " << json_object["id"].toString() << " was created.";
new_location = std::make_shared<QWLocation>();
new_location->setTag(json_object["id"].toString());
// check and add the pixmap triggers
Q_ASSERT(json_object.contains("triggers"));
if (json_object.contains("triggers")) {
qDebug() << " Found triggers!";
QJsonArray loc_triggers = json_value["triggers"].toArray();
for (const QJsonValue trg : loc_triggers)
{
qDebug() << " Added the trigger " << trg.toString();
new_location->addTriggers( hash_triggers[trg.toString()] );
}
}
if (json_object.contains("triggers"))
new_location->setDiscovered(json_object["discovered"].toBool());
// check if it has a background
if (json_object.contains("background")) {
qDebug() << " Here is a background.";
QString b = json_value["background"].toString();
new_location->addTriggers(hash_triggers[b]);
qDebug() << " Background was added.";
}
hash_locations.insert(json_object["id"].toString(), new_location);
qDebug() << " The level was inserted into its map.\n - - -";
}
}

View File

@ -0,0 +1,78 @@
#ifndef LEVELBUILDER_H
#define LEVELBUILDER_H
#include <memory>
#include <functional>
#include <QDir>
#include <QFile>
#include <QJsonObject>
#include <QJsonDocument>
#include <QJsonArray>
/* QWLevelBuilder
* Saves and loads game sessions by managing dependent json files. */
struct GameFeatures;
class QWScene;
class QWAbstractEvent;
class QWAbstractGameDialogue;
class QWInventoryManager;
class QWTextDialogueManager;
class QWWidgetDialogueManager;
class QWSoundPlayer;
class QWTrigger;
class QWLocation;
class QWLevelBuilder final : public QObject
{
Q_OBJECT
Q_DISABLE_COPY_MOVE(QWLevelBuilder)
friend class QWEventFactory;
friend class QWDialogueFactory;
private:
QDir save_dir;
QString str_profile_filename;
QString str_current_profile;
QString str_current_level;
QJsonObject level;
QWInventoryManager *ptr_inventory;
QWScene *ptr_scene;
QWSoundPlayer *ptr_soundplayer;
QWTextDialogueManager *ptr_text_dlg;
QWWidgetDialogueManager *ptr_widget_dlg;
QHash<QString, std::shared_ptr<QWAbstractEvent>> hash_events;
QHash<QString, std::shared_ptr<QWTrigger>> hash_triggers;
QHash<QString, std::shared_ptr<QWAbstractGameDialogue>> hash_dialogues;
QHash<QString, std::shared_ptr<QWLocation>> hash_locations;
std::shared_ptr<QWTrigger> init_trigger;
void setupTriggers(const QJsonArray &array);
void setupEvents(const QJsonArray &array);
void linkEvents(const QJsonArray &array);
void setupDialogues(const QJsonArray &array);
void setupLocations(const QJsonArray &array);
void init(const QJsonObject & savefile);
public:
explicit QWLevelBuilder(QObject *parent = nullptr);
void setGameFeatures(std::unique_ptr<GameFeatures> &features);
void initLevel(const QString &lvlname);
void initSaveProfile(const QString &filename, const QString &profilename);
void initMenuLevel();
static QString strInitLevel() noexcept;
public slots:
void saveGame( );
void loadGame(/*int on_id*/);
};
#endif // LEVELBUILDER_H

121
features/qw_soundplayer.cpp Normal file
View File

@ -0,0 +1,121 @@
#include "qw_soundplayer.h"
QWSoundPlayer::QWSoundPlayer(QObject *parent) :
QObject(parent),
i_volume(100),
b_muted(false),
player_loop(new QMediaPlayer(this)),
playlist_loop(new QMediaPlaylist(this)),
player_single(new QMediaPlayer(this)),
player_music(new QMediaPlayer(this)),
playlist_music(new QMediaPlaylist(this))
{
// Music
playlist_music->setPlaybackMode(QMediaPlaylist::CurrentItemInLoop);
playlist_music->setCurrentIndex(0);
player_music->setAudioRole(QAudio::MusicRole);
player_music->setPlaylist(playlist_music);
QObject::connect(this,
SIGNAL(transferSetMuteness(bool)),
player_music,
SLOT(setMuted(bool)));
QObject::connect(this,
SIGNAL(transferAdjustVolume(int)),
player_music,
SLOT(setVolume(int)));
QObject::connect(this,
SIGNAL(playMusic()),
player_music,
SLOT(play()));
// Loop sounds
playlist_loop->setPlaybackMode(QMediaPlaylist::CurrentItemInLoop);
playlist_loop->setCurrentIndex(0);
player_loop->setAudioRole(QAudio::GameRole);
player_loop->setPlaylist(playlist_loop);
QObject::connect(this,
SIGNAL(transferSetMuteness(bool)),
player_loop,
SLOT(setMuted(bool)));
QObject::connect(this,
SIGNAL(transferAdjustVolume(int)),
player_loop,
SLOT(setVolume(int)));
QObject::connect(this,
SIGNAL(playLoop()),
player_loop,
SLOT(play()));
// Single sounds
player_single->setAudioRole(QAudio::GameRole);
QObject::connect(this,
SIGNAL(transferSetMuteness(bool)),
player_single,
SLOT(setMuted(bool)));
QObject::connect(this,
SIGNAL(transferAdjustVolume(int)),
player_single,
SLOT(setVolume(int)));
QObject::connect(this,
SIGNAL(playSingle()),
player_single,
SLOT(play()));
}
int QWSoundPlayer::addMusic(const QString &path)
{
playlist_music->addMedia(QUrl::fromLocalFile(path));
playlist_music->setCurrentIndex(playlist_music->currentIndex() + 1);
return playlist_music->currentIndex() - 1;
}
bool QWSoundPlayer::isMuted() const noexcept
{
return b_muted;
}
int QWSoundPlayer::volume() const noexcept
{
return i_volume;
}
void QWSoundPlayer::playSound(QMediaContent *sound)
{
player_single->stop();
player_single->setMedia(*sound);
emit playSingle();
}
void QWSoundPlayer::playMusic(const int index)
{
playlist_music->setCurrentIndex(index);
emit playMusic();
}
void QWSoundPlayer::stopMusic()
{
player_music->stop();
}
////////////////////////
void QWSoundPlayer::setMuteness(bool mute) noexcept
{
b_muted = mute;
emit transferSetMuteness(b_muted);
}
void QWSoundPlayer::adjustVolume(int vol) noexcept
{
i_volume = vol;
emit transferAdjustVolume(i_volume);
}
void QWSoundPlayer::onEndLevel() noexcept
{
playlist_music->clear();
playlist_music->setCurrentIndex(0);
}

61
features/qw_soundplayer.h Normal file
View File

@ -0,0 +1,61 @@
#ifndef SOUNDPLAYER_H
#define SOUNDPLAYER_H
#include <memory>
#include <QMediaPlayer>
#include <QMediaPlaylist>
/////////////////////////////////////////////////////////////////
//// DOESN'T WORK! Has to be reworked in master-merge 1.2
//// https://trello.com/c/KFUhEbYh/62-reimplement-sound-system
class QWSoundPlayer final : public QObject
{
Q_OBJECT
Q_DISABLE_COPY_MOVE(QWSoundPlayer)
private:
int i_volume;
bool b_muted;
////////////////////////
////////
//// Background sounds in loop.
QMediaPlayer *player_loop;
QMediaPlaylist *playlist_loop;
////////
//// Sounds which should play once per call.
QMediaPlayer *player_single;
////////
//// Music is music.
QMediaPlayer *player_music;
QMediaPlaylist *playlist_music;
public:
explicit QWSoundPlayer(QObject *parent = nullptr);
int addMusic(const QString &path);
inline bool isMuted() const noexcept;
inline int volume() const noexcept;
void playSound(QMediaContent *sound);
void playMusic(const int index);
void stopMusic();
////////////////////////
public slots:
void setMuteness(bool mute) noexcept;
void adjustVolume(int vol) noexcept;
void onEndLevel() noexcept;
signals:
void transferSetMuteness(bool);
void transferAdjustVolume(int);
void playLoop();
void playSingle();
void playMusic();
};
#endif // SOUNDPLAYER_H

View File

@ -0,0 +1,15 @@
#include "qw_statemachine.h"
QWStateMachine::QWStateMachine(QObject *parent) :
QStateMachine(parent)
{}
void QWStateMachine::registerState(QString &&str, QState *state) noexcept
{
hash_states.insert(str, state);
}
QState *QWStateMachine::stateByKey(QString &&str) noexcept
{
return hash_states[str];
}

View File

@ -0,0 +1,23 @@
#ifndef STATEMACHINE_H
#define STATEMACHINE_H
#include <QStateMachine>
/* QWStateMachine
* Inherited realization of qt state machine for simpler state managment. */
class QWStateMachine final : public QStateMachine
{
Q_OBJECT
Q_DISABLE_COPY_MOVE(QWStateMachine)
private:
QHash<QString, QState*> hash_states;
public:
explicit QWStateMachine(QObject *parent = nullptr);
void registerState(QString &&str, QState *state) noexcept;
QState *stateByKey(QString &&str) noexcept;
};
#endif // STATEMACHINE_H

View File

@ -0,0 +1,60 @@
#include "models/dialogues/qw_textdialogue.h"
#include "qw_textdialoguemanager.h"
QWTextDialogueManager::QWTextDialogueManager(QWScene *scene) :
QWAbstractDialogueManager(scene),
p_frametext(new QGraphicsSimpleTextItem)
{
p_frametext->setFont(QFont("Arial", 25));
p_frametext->setBrush(QBrush(Qt::white));
p_frametext->setPos(12, 12);
scene->addItem(p_frametext);
}
QWTextDialogueManager::~QWTextDialogueManager()
{
delete p_frametext;
}
void QWTextDialogueManager::activateDialogue(const std::shared_ptr<QWAbstractGameDialogue> &dialogue)
{
/* Moving to text dialogue state.
* Make the panel with text visible.
* Game freezes until when player reads all
* the frames. */
ptr_text_dialogue = std::dynamic_pointer_cast<QWTextDialogue>(dialogue);
connect(ptr_scene, SIGNAL(signalClickDialogue(MouseButton)), this, SLOT(onClicked(MouseButton)));
emit onEntryDialogueTransition();
p_frametext->show();
// Show the first page of active dialogue.
p_frametext->setText(ptr_text_dialogue->currentText());
}
////////////////////////
void QWTextDialogueManager::setDialoguePanel(const std::shared_ptr<QGraphicsWidget> &panel) noexcept
{
p_textbox = panel;
}
void QWTextDialogueManager::onClicked(MouseButton mouse_button)
{
const bool has_next_pages = ptr_text_dialogue->toNextPage();
if (!has_next_pages || mouse_button == MouseButton::RIGHT) {
p_frametext->hide();
ptr_text_dialogue->resetPage();
ptr_text_dialogue->onExit(static_cast<int>(mouse_button));
disconnect(ptr_scene, SIGNAL(signalClickDialogue(MouseButton)), this, SLOT(onClicked(MouseButton)));
emit onLeaveDialogueTransition();
} else
p_frametext->setText(ptr_text_dialogue->currentText());
}

View File

@ -0,0 +1,37 @@
#ifndef DIALOGUEMANAGER_H
#define DIALOGUEMANAGER_H
#include "qw_abstractdialoguemanager.h"
#include <QGraphicsPixmapItem>
#include <QLinkedList>
#include <QObject>
/* QWTextDialogueManager
* Controls text game-freezing dialogues. */
class QWTextDialogue;
class QWTextDialogueManager final : public QWAbstractDialogueManager
{
Q_OBJECT
Q_DISABLE_COPY_MOVE(QWTextDialogueManager)
private:
std::shared_ptr<QWTextDialogue> ptr_text_dialogue;
std::shared_ptr<QGraphicsWidget> p_textbox;
QGraphicsSimpleTextItem *p_frametext;
public:
explicit QWTextDialogueManager(QWScene *scene = nullptr);
virtual ~QWTextDialogueManager() override;
virtual void activateDialogue(const std::shared_ptr<QWAbstractGameDialogue> &dialogue) override;
////////////////////////
void setDialoguePanel(const std::shared_ptr<QGraphicsWidget> &panel) noexcept;
public slots:
virtual void onClicked(MouseButton mouse_button) override;
};
#endif // DIALOGUEMANAGER_H

View File

@ -0,0 +1,50 @@
#include "models/dialogues/qw_widgetdialogue.h"
#include "qw_widgetdialoguemanager.h"
#include "qw_globalmetadata.h"
#include <QQuickWidget>
#include <QQmlEngine>
#include <QQmlContext>
QWWidgetDialogueManager::QWWidgetDialogueManager(QWScene *scene) :
QWAbstractDialogueManager(scene)
{}
QWWidgetDialogueManager::~QWWidgetDialogueManager()
{}
void QWWidgetDialogueManager::activateDialogue(const std::shared_ptr<QWAbstractGameDialogue> &dialogue)
{
widget_dialogue = std::dynamic_pointer_cast<QWWidgetDialogue>(dialogue);
connect(ptr_scene, SIGNAL(signalClickDialogue(MouseButton)), this, SLOT(onClicked(MouseButton)));
emit onEntryDialogueTransition();
quick_view = new QQuickWidget;
// Moving dialogue model into qml widget to handle the properties from inside
quick_view->engine()->rootContext()->setContextProperty("dialogue", widget_dialogue.get());
quick_view->setSource(QUrl::fromLocalFile(widget_dialogue->qmlPath()));
QObject::connect(quick_view, SIGNAL(destroyed()), this, SLOT(onDestroyingWidget()));
}
void QWWidgetDialogueManager::onClicked(MouseButton mouse_button)
{
if (mouse_button == MouseButton::RIGHT)
quick_view->close();
}
void QWWidgetDialogueManager::onDestroyingWidget()
{
// Testing
qDebug() << "Exit code:" << widget_dialogue->exitCode();
disconnect(ptr_scene, SIGNAL(signalClickDialogue(MouseButton)), this, SLOT(onClicked(MouseButton)));
if (widget_dialogue->isCustomStringToSave())
QWGlobalMetadata::setValue(widget_dialogue->tag(), widget_dialogue->customString());
widget_dialogue->onExit(widget_dialogue->exitCode());
emit onLeaveDialogueTransition();
}

View File

@ -0,0 +1,28 @@
#ifndef QWWIDGETDIALOGUEMANAGER_H
#define QWWIDGETDIALOGUEMANAGER_H
#include "qw_abstractdialoguemanager.h"
class QWWidgetDialogue;
class QQuickWidget;
class QWWidgetDialogueManager final : public QWAbstractDialogueManager
{
Q_OBJECT
Q_DISABLE_COPY_MOVE(QWWidgetDialogueManager)
private:
std::shared_ptr<QWWidgetDialogue> widget_dialogue;
QQuickWidget *quick_view;
public:
explicit QWWidgetDialogueManager(QWScene *scene = nullptr);
virtual ~QWWidgetDialogueManager() override;
virtual void activateDialogue(const std::shared_ptr<QWAbstractGameDialogue> &dialogue) override;
public slots:
virtual void onClicked(MouseButton mouse_button) override;
void onDestroyingWidget();
};
#endif // QWWIDGETDIALOGUEMANAGER_H

114
game.cpp Normal file
View File

@ -0,0 +1,114 @@
#include "game.h"
#include "features/gamefeatures.h"
#include "features/qw_levelbuilder.h"
#include "features/qw_statemachine.h"
Game::Game()
{
game_features = std::make_unique<GameFeatures>(this);
auto &[view, scene, sound_player, inventory, builder, text_dlg, widget_dlg] = *game_features;
builder->setGameFeatures(game_features);
// Connecting all the UI controls to their features
for (auto &widg : scene->inventoryWidgets())
widg->onConnect(game_features);
connect(scene, SIGNAL(signalClickInventory()), inventory, SLOT(onClicked()));
view->setFixedSize(static_cast<int>(scene->sceneRect().width() ),
static_cast<int>(scene->sceneRect().height()));
builder->initSaveProfile("test", "test");
builder->initLevel(QWLevelBuilder::strInitLevel());
buildStateMachine();
buildHotKeys();
}
Game::~Game() = default;
void Game::buildStateMachine()
{
auto *view = game_features->ptr_view;
auto *scene = game_features->ptr_scene;
QWStateMachine *state_machine = new QWStateMachine(view);
// Connecting UI elements to global state machine
for (auto &widg : scene->inventoryWidgets())
widg->onBuildingStateMachine(state_machine, game_features);
QState *state_menu = new QState;
state_machine->registerState("state_menu", state_menu);
connect(state_menu, SIGNAL(entered()), game_features->ptr_scene, SLOT(onEntryMenu()));
const auto &state_gameplay = state_machine->stateByKey("state_gameplay");
QSignalTransition *enter_gameplay_transition = new QSignalTransition(scene, SIGNAL(signalLeaveMenu()));
enter_gameplay_transition->setTargetState(state_gameplay);
state_menu->addTransition(enter_gameplay_transition);
QSignalTransition *leave_gameplay_transition = new QSignalTransition(scene, SIGNAL(signalEnterMenu()));
leave_gameplay_transition->setTargetState(state_menu);
state_gameplay->addTransition(leave_gameplay_transition);
QState *state_examination = new QState;
state_machine->registerState("state_examination", state_examination);
QSignalTransition *enter_examination_transition = new QSignalTransition(scene, SIGNAL(signalEnterExamination()));
enter_examination_transition->setTargetState(state_examination);
state_gameplay->addTransition(enter_examination_transition);
QSignalTransition *leave_examination_transition = new QSignalTransition(scene, SIGNAL(signalLeaveExamination()));
leave_examination_transition->setTargetState(state_gameplay);
state_examination->addTransition(leave_examination_transition);
QState *state_widget_dialogue = new QState;
state_machine->registerState("state_widget_dialogue", state_widget_dialogue);
connect(state_widget_dialogue, SIGNAL(entered()), game_features->ptr_scene, SLOT(onEntryDialogue()));
QSignalTransition *enter_widget_dialogue_transition = new QSignalTransition(game_features->ptr_widget_dlg, SIGNAL(onEntryDialogueTransition()));
enter_widget_dialogue_transition->setTargetState(state_widget_dialogue);
state_menu->addTransition(enter_widget_dialogue_transition);
state_gameplay->addTransition(enter_widget_dialogue_transition);
QSignalTransition *leave_widget_dialogue_transition = new QSignalTransition(game_features->ptr_widget_dlg, SIGNAL(onLeaveDialogueTransition()));
leave_widget_dialogue_transition->setTargetState(state_gameplay);
state_widget_dialogue->addTransition(leave_widget_dialogue_transition);
state_machine->addState(state_menu);
state_machine->addState(state_widget_dialogue);
state_machine->addState(state_examination);
state_machine->setInitialState(state_gameplay);
state_machine->start();
}
void Game::buildHotKeys()
{
auto *builder = game_features->ptr_builder;
auto *view = game_features->ptr_view;
/* For quick exit */
auto quit_action = new QAction(tr("E&xit"), this);
quit_action->setShortcut(tr("Ctrl+Q"));
connect(quit_action, SIGNAL(triggered()), qApp, SLOT(quit()));
view->addAction(quit_action);
/* For quick save */
auto save_action = new QAction(tr("S&ave"), this);
save_action->setShortcut(tr("Ctrl+S"));
connect(save_action, SIGNAL(triggered()), builder, SLOT(saveGame()));
view->addAction(save_action);
/* For quick load */
auto load_action = new QAction(tr("L&oad"), this);
load_action->setShortcut(tr("Ctrl+L"));
connect(load_action, SIGNAL(triggered()), builder, SLOT(loadGame()));
view->addAction(load_action);
}
void Game::start()
{
game_features->ptr_view->show();
}

View File

@ -0,0 +1,38 @@
#ifndef QWABSTRACTGAMEDIALOGUE_H
#define QWABSTRACTGAMEDIALOGUE_H
#include <memory>
#include "models/events/qw_abstractevent.h"
/* QWAbstractGameDialogue
* Interface for all in-game dialogues. */
class QWAbstractGameDialogue : public QWTagHolder
{
protected:
QList<QList<std::shared_ptr<QWAbstractEvent>>> list_events;
public:
QWAbstractGameDialogue();
virtual ~QWAbstractGameDialogue() override = 0;
virtual void onExit(int code);
virtual void setAllEvents(const QList<QList<std::shared_ptr<QWAbstractEvent>>> &evs);
virtual void addEventsList(const QList<std::shared_ptr<QWAbstractEvent>> &evs);
////////////////////////
virtual void writeToJson(QJsonObject &savejson) override = 0;
};
enum DIALOGUE_TYPE
{
// Pure visual-novel-like text
TEXT,
// External widget with inner logic described with qml
WIDGET
};
#endif // QWABSTRACTGAMEDIALOGUE_H

View File

@ -0,0 +1,48 @@
#include "qw_textdialogue.h"
QWTextDialogue::QWTextDialogue(const QStringList &pages)
{
setPages(pages);
}
////////////////////////
bool QWTextDialogue::toNextPage() noexcept
{
const bool has_next = ((it_current_page + 1) != list_pages.end());
if (has_next)
++it_current_page;
return has_next;
}
void QWTextDialogue::resetPage() noexcept
{
it_current_page = list_pages.begin();
}
void QWTextDialogue::setPages(const QStringList &pages) noexcept
{
list_pages = pages;
Q_ASSERT(!list_pages.empty());
it_current_page = list_pages.begin();
}
QStringList QWTextDialogue::pages() const noexcept
{
return list_pages;
}
QString QWTextDialogue::currentText() const noexcept
{
return *it_current_page;
}
////////////////////////
void QWTextDialogue::writeToJson(QJsonObject &savejson)
{
Q_UNUSED(savejson)
}

View File

@ -0,0 +1,35 @@
#ifndef QWTEXTDIALOGUE_H
#define QWTEXTDIALOGUE_H
#include <QStringList>
#include "qw_abstractgamedialogue.h"
/* QWTextDialogue
* Provides text visual-novel-lide dialogue. */
class QWTextDialogue : public QWAbstractGameDialogue
{
protected:
QStringList list_pages;
QStringList::iterator it_current_page;
public:
QWTextDialogue(const QStringList &pages);
virtual ~QWTextDialogue() override {}
////////////////////////
bool toNextPage() noexcept;
void resetPage() noexcept;
void setPages(const QStringList &pages) noexcept;
QStringList pages() const noexcept;
QString currentText() const noexcept;
////////////////////////
virtual void writeToJson(QJsonObject &savejson) override;
};
#endif // QWTEXTDIALOGUE_H

View File

@ -0,0 +1,63 @@
#include "qw_widgetdialogue.h"
QWWidgetDialogue::QWWidgetDialogue(const QString &path) :
qml_path(path)
{
Q_ASSERT(!qml_path.isNull());
// Filepath fixes
if (!qml_path.endsWith(".qml"))
qml_path += ".qml";
if (!qml_path.startsWith("qml/"))
qml_path = "qml/" + qml_path;
}
void QWWidgetDialogue::onExit(int code)
{
Q_UNUSED(code)
}
////////////////////////
QString QWWidgetDialogue::qmlPath() const
{
return qml_path;
}
QString QWWidgetDialogue::customString() const
{
return custom_string;
}
void QWWidgetDialogue::setCustomString(const QString &str)
{
custom_string = str;
}
int QWWidgetDialogue::exitCode() const
{
return exit_code;
}
void QWWidgetDialogue::setExitCode(int code)
{
if (code != exit_code)
exit_code = code;
}
bool QWWidgetDialogue::isCustomStringToSave() const
{
return to_save_string;
}
void QWWidgetDialogue::setCustomStringToSave(bool to_save)
{
to_save_string = to_save;
}
////////////////////////
void QWWidgetDialogue::writeToJson(QJsonObject &savejson)
{
Q_UNUSED(savejson)
}

View File

@ -0,0 +1,45 @@
#ifndef WIDGETDIALOGUE_H
#define WIDGETDIALOGUE_H
#include "qw_abstractgamedialogue.h"
#include <QObject>
class QWWidgetDialogue : public QObject, public QWAbstractGameDialogue
{
Q_OBJECT
Q_DISABLE_COPY_MOVE(QWWidgetDialogue)
Q_PROPERTY(int exit_code READ exitCode WRITE setExitCode)
Q_PROPERTY(QString custom_string READ customString WRITE setCustomString)
Q_PROPERTY(bool to_save_string READ isCustomStringToSave WRITE setCustomStringToSave)
private:
QString qml_path;
QString custom_string;
int exit_code;
bool to_save_string;
public:
explicit QWWidgetDialogue(const QString &path);
virtual ~QWWidgetDialogue() override {}
void onExit(int code) override;
////////////////////////
QString qmlPath() const;
QString customString() const;
void setCustomString(const QString &str);
int exitCode() const;
void setExitCode(int code);
bool isCustomStringToSave() const;
void setCustomStringToSave(bool to_save);
////////////////////////
void writeToJson(QJsonObject &savejson) override;
};
#endif // WIDGETDIALOGUE_H

View File

@ -0,0 +1,43 @@
#ifndef QUESTEVENT_H
#define QUESTEVENT_H
#include <QJsonObject>
#include <QJsonArray>
#include <QDebug>
#include "../qw_tagholder.h"
/* QWAbstractEvent
* Interface for all in-game events. The core of game logic process. */
class QWAbstractEvent : public QWTagHolder
{
public:
QWAbstractEvent();
virtual ~QWAbstractEvent() override = 0;
virtual void execute() = 0;
////////////////////////
virtual void writeToJson(QJsonObject &savejson) override = 0;
};
enum EVENT_TYPE
{
CHANGE_LOCATION,
SWITCH_EVENTS, // <- requires other events to be initialized
DELETE_FROM_INVENTORY,
END_LEVEL,
PICKUP_ITEM,
PLAY_SOUND,
PLAY_MUSIC,
CHANGE_TRIGGER_PROPERTIES,
NEW_GAME,
QUIT_GAME,
START_DIALOGUE,
ADD_TRIGGER,
REMOVE_TRIGGER
};
#endif // QUESTEVENT_H

View File

@ -0,0 +1,20 @@
#include "qw_abstractinventoryevent.h"
QWAbstractInventoryEvent:: QWAbstractInventoryEvent()
{}
QWAbstractInventoryEvent::~QWAbstractInventoryEvent()
{}
////////////////////////
void QWAbstractInventoryEvent::setInventoryManager(QWInventoryManager *const inv) noexcept
{
ptr_inventory = inv;
}
QWInventoryManager *QWAbstractInventoryEvent::inventoryManager() const noexcept
{
return ptr_inventory;
}

View File

@ -0,0 +1,31 @@
#ifndef QUESTABSTRACTINVENTORYEVENT_H
#define QUESTABSTRACTINVENTORYEVENT_H
#include "features/qw_inventorymanager.h"
#include "qw_abstractevent.h"
/* QWAbstractInventoryEvent
* Interface for all in-game inventory events. */
class QWAbstractInventoryEvent : public QWAbstractEvent
{
protected:
QWInventoryManager *ptr_inventory;
public:
QWAbstractInventoryEvent();
virtual ~QWAbstractInventoryEvent() override = 0;
virtual void execute() override = 0;
////////////////////////
void setInventoryManager(QWInventoryManager *const inv) noexcept;
QWInventoryManager *inventoryManager() const noexcept;
////////////////////////
virtual void writeToJson(QJsonObject &savejson) override = 0;
};
#endif // QUESTABSTRACTINVENTORYEVENT_H

View File

@ -0,0 +1,20 @@
#include "qw_abstractlevelevent.h"
QWAbstractLevelEvent:: QWAbstractLevelEvent()
{}
QWAbstractLevelEvent::~QWAbstractLevelEvent()
{}
////////////////////////
void QWAbstractLevelEvent::setLevelBuilder(QWLevelBuilder *const buil) noexcept
{
ptr_builder = buil;
}
QWLevelBuilder *QWAbstractLevelEvent::levelBuilder() const noexcept
{
return ptr_builder;
}

View File

@ -0,0 +1,31 @@
#ifndef QUESTABSTRACTLEVELEVENT_H
#define QUESTABSTRACTLEVELEVENT_H
#include "features/qw_levelbuilder.h"
#include "qw_abstractevent.h"
/* QWAbstractLevelEvent
* Interface for all in-game events which control save files and levels. */
class QWAbstractLevelEvent : public QWAbstractEvent
{
protected:
QWLevelBuilder *ptr_builder;
public:
QWAbstractLevelEvent();
virtual ~QWAbstractLevelEvent() override = 0;
virtual void execute() override = 0;
////////////////////////
void setLevelBuilder(QWLevelBuilder *const buil) noexcept;
QWLevelBuilder *levelBuilder() const noexcept;
////////////////////////
virtual void writeToJson(QJsonObject &savejson) override = 0;
};
#endif // QUESTABSTRACTLEVELEVENT_H

View File

@ -0,0 +1,19 @@
#include "qw_abstractsceneevent.h"
QWAbstractSceneEvent:: QWAbstractSceneEvent()
{}
QWAbstractSceneEvent::~QWAbstractSceneEvent()
{}
////////////////////////
void QWAbstractSceneEvent::setScene(QWScene *const scene) noexcept
{
ptr_scene = scene;
}
QWScene *QWAbstractSceneEvent::scene() const noexcept
{
return ptr_scene;
}

View File

@ -0,0 +1,31 @@
#ifndef QUESTABSTRACTSCENEEVENT_H
#define QUESTABSTRACTSCENEEVENT_H
#include "qw_abstractevent.h"
#include "view/qw_scene.h"
/* QWAbstractSceneEvent
* Interface for all in-game scene events. */
class QWAbstractSceneEvent : public QWAbstractEvent
{
protected:
QWScene *ptr_scene;
public:
QWAbstractSceneEvent();
virtual ~QWAbstractSceneEvent() override = 0;
virtual void execute() override = 0;
////////////////////////
void setScene(QWScene *const scene) noexcept;
QWScene *scene() const noexcept;
////////////////////////
virtual void writeToJson(QJsonObject &savejson) override = 0;
};
#endif // QUESTABSTRACTSCENEEVENT_H

View File

@ -0,0 +1,19 @@
#include "qw_abstractsoundevent.h"
QWAbstractSoundEvent:: QWAbstractSoundEvent()
{}
QWAbstractSoundEvent::~QWAbstractSoundEvent()
{}
////////////////////////
void QWAbstractSoundEvent::setSoundPlayer(QWSoundPlayer *const soundplayer) noexcept
{
ptr_soundplayer = soundplayer;
}
QWSoundPlayer *QWAbstractSoundEvent::soundPlayer() const noexcept
{
return ptr_soundplayer;
}

View File

@ -0,0 +1,31 @@
#ifndef QUESTABSTRACTSOUNDEVENT_H
#define QUESTABSTRACTSOUNDEVENT_H
#include "features/qw_soundplayer.h"
#include "qw_abstractevent.h"
/* QWAbstractSoundEvent
* Interface for all in-game audio events. */
class QWAbstractSoundEvent : public QWAbstractEvent
{
protected:
QWSoundPlayer *ptr_soundplayer;
public:
QWAbstractSoundEvent();
virtual ~QWAbstractSoundEvent() override = 0;
virtual void execute() override = 0;
////////////////////////
void setSoundPlayer(QWSoundPlayer *const soundplayer) noexcept;
QWSoundPlayer *soundPlayer() const noexcept;
////////////////////////
virtual void writeToJson(QJsonObject &savejson) override = 0;
};
#endif // QUESTABSTRACTSOUNDEVENT_H

View File

@ -0,0 +1,49 @@
#include "qw_addtriggerevent.h"
#include "models/qw_trigger.h"
QWAddTriggerEvent::QWAddTriggerEvent(const std::shared_ptr<QWTrigger> &tr) :
trigger(tr)
{
Q_ASSERT(trigger);
}
void QWAddTriggerEvent::execute()
{
Q_ASSERT(location);
if (location->triggers().contains(trigger))
return;
location->addTriggers(trigger);
if (location == ptr_scene->currentLocation())
ptr_scene->addItem(trigger.get());
}
////////////////////////
void QWAddTriggerEvent::setLocation(const std::shared_ptr<QWLocation> &loc) noexcept
{
location = loc;
Q_ASSERT(location);
}
void QWAddTriggerEvent::setTrigger(const std::shared_ptr<QWTrigger> &tr) noexcept
{
trigger = tr;
Q_ASSERT(trigger);
}
////////////////////////
void QWAddTriggerEvent::writeToJson(QJsonObject &event_data)
{
event_data.insert("id", tag());
event_data.insert("type", EVENT_TYPE::ADD_TRIGGER);
event_data.insert("location", location->tag());
event_data.insert("trigger", trigger->tag());
qDebug() << " The add_trigger event:\n" << " id " << tag()
<< "\n location :" << location->tag()
<< "\n trigger :" << trigger->tag();
}

View File

@ -0,0 +1,31 @@
#ifndef QWADDTRIGGER_H
#define QWADDTRIGGER_H
#include "qw_abstractsceneevent.h"
/* QWAddTriggerEvent
* Adds a trigger to its location list. */
class QWAddTriggerEvent : public QWAbstractSceneEvent
{
private:
std::shared_ptr<QWTrigger> trigger; // What to add.
std::shared_ptr<QWLocation> location; // Where to add.
public:
explicit QWAddTriggerEvent(const std::shared_ptr<QWTrigger> &tr);
virtual ~QWAddTriggerEvent() override {}
void execute() override;
////////////////////////
void setLocation(const std::shared_ptr<QWLocation> &loc) noexcept;
void setTrigger(const std::shared_ptr<QWTrigger> &tr) noexcept;
////////////////////////
void writeToJson(QJsonObject &event_data) override;
};
#endif // QWADDTRIGGER_H

View File

@ -0,0 +1,52 @@
#include "qw_changelocationevent.h"
#include "../qw_location.h"
#include "../qw_trigger.h"
QWChangeLocationEvent::QWChangeLocationEvent(const std::shared_ptr<QWLocation> &location) :
target_location(location)
{
Q_ASSERT(target_location);
}
void QWChangeLocationEvent::execute()
{
const QList<std::shared_ptr<QWTrigger>> &triggers = target_location->triggers();
// We clear all the triggers from previous location
ptr_scene->clearLocation();
ptr_scene->setCurrentLocation(target_location);
if (const auto & tr = target_location->firstVisitTrigger(); tr && !target_location->discovered())
tr->activate();
target_location->setDiscovered(true);
int z = 0;
// The first item will be below the others. The last item - above.
// Triggers[0] must be background.
for (auto &trigger : triggers)
{
trigger->setZValue(-1 * ++z);
ptr_scene->addItem(trigger.get());
}
}
////////////////////////
void QWChangeLocationEvent::setLocation(const std::shared_ptr<QWLocation> &location) noexcept
{
target_location = location;
}
////////////////////////
void QWChangeLocationEvent::writeToJson(QJsonObject &event_data)
{
event_data.insert("id", tag());
event_data.insert("type", EVENT_TYPE::CHANGE_LOCATION);
event_data.insert("location", target_location->tag());
qDebug() << " The move_to_location event:\n" << " id " << tag()
<< "\n location :" << target_location->tag();
}

View File

@ -0,0 +1,32 @@
#ifndef QUESTCHANGELOCATIONEVENT_H
#define QUESTCHANGELOCATIONEVENT_H
#include "qw_abstractsceneevent.h"
/* QWChangeLocationEvent
* Moves player to new location by replacing scene triggers. */
class QWTrigger;
class QWLocation;
class QWChangeLocationEvent : public QWAbstractSceneEvent
{
private:
std::shared_ptr<QWLocation> target_location;
public:
explicit QWChangeLocationEvent(const std::shared_ptr<QWLocation> &location);
virtual ~QWChangeLocationEvent() override {}
void execute() override;
////////////////////////
void setLocation(const std::shared_ptr<QWLocation> &location) noexcept;
////////////////////////
void writeToJson(QJsonObject &event_data) override;
};
#endif // QUESTCHANGELOCATIONEVENT_H

View File

@ -0,0 +1,25 @@
#include "qw_endlevelevent.h"
QWEndLevelEvent::QWEndLevelEvent(const QString &level) :
str_nlevel(level)
{
Q_ASSERT(!str_nlevel.isEmpty());
}
void QWEndLevelEvent::execute()
{
ptr_builder->saveGame();
ptr_builder->initLevel(str_nlevel);
}
////////////////////////
void QWEndLevelEvent::writeToJson(QJsonObject &event_data)
{
event_data.insert("id", tag());
event_data.insert("type", EVENT_TYPE::END_LEVEL);
event_data.insert("new_level", str_nlevel);
qDebug() << " The end_level event:\n" << " id " << tag()
<< "\n new_level " << str_nlevel;
}

View File

@ -0,0 +1,25 @@
#ifndef QUESTENDLEVELEVENT_H
#define QUESTENDLEVELEVENT_H
#include "qw_abstractlevelevent.h"
/* QWEndLevelEvent
* Sends its signal to QWLevelBuilder whenever it has to load next level. */
class QWEndLevelEvent : public QWAbstractLevelEvent
{
private:
QString str_nlevel;
public:
explicit QWEndLevelEvent(const QString &level);
virtual ~QWEndLevelEvent() override {}
void virtual execute() override;
////////////////////////
void writeToJson(QJsonObject &event_data) override;
};
#endif // QUESTENDLEVELEVENT_H

View File

@ -0,0 +1,45 @@
#include <QRegExp>
#include "qw_newgameevent.h"
#include "qw_globalmetadata.h"
QWNewGameEvent::QWNewGameEvent(const QString &savefile) :
str_savefile(savefile)
{
Q_ASSERT(!str_savefile.isEmpty());
}
void QWNewGameEvent::execute()
{
const QString profile_name = QWGlobalMetadata::valueBy("new_game_dialogue").toString();
str_savefile = composeFileName(profile_name);
Q_ASSERT(!profile_name.isEmpty());
Q_ASSERT(!str_savefile.isEmpty());
ptr_builder->initSaveProfile(str_savefile, profile_name);
ptr_builder->initLevel(QWLevelBuilder::strInitLevel());
}
////////////////////////
QString QWNewGameEvent::composeFileName(const QString &str)
{
//Turn the chosen by user savename into file name.
QString file_name = str;
const QRegExp regexp("[^0-9a-z]+");
file_name = file_name.toLower().remove(regexp);
return file_name;
}
////////////////////////
void QWNewGameEvent::writeToJson(QJsonObject &event_data)
{
event_data.insert("id", tag());
event_data.insert("type", EVENT_TYPE::NEW_GAME);
event_data.insert("save_file", str_savefile);
qDebug() << " The new_game event:\n" << " id " << tag()
<< "\n save_file " << str_savefile;
}

View File

@ -0,0 +1,27 @@
#ifndef QUESTNEWGAMEEVENT_H
#define QUESTNEWGAMEEVENT_H
#include "qw_abstractlevelevent.h"
/* QWNewGameEvent
* Creates new savefile and begins the game from clear sheet. */
class QWNewGameEvent : public QWAbstractLevelEvent
{
private:
QString str_savefile;
QString composeFileName(const QString &str);
public:
explicit QWNewGameEvent(const QString &savefile);
virtual ~QWNewGameEvent() override {}
void virtual execute() override;
////////////////////////
void writeToJson(QJsonObject &event_data) override;
};
#endif // QUESTNEWGAMEEVENT_H

View File

@ -0,0 +1,37 @@
#include "qw_pickupitemevent.h"
#include "../qw_trigger.h"
QWPickupItemEvent::QWPickupItemEvent(const std::shared_ptr<QWTrigger> &tr) :
ptr_inventory_trigger(tr)
{
Q_ASSERT(ptr_inventory_trigger);
}
void QWPickupItemEvent::execute()
{
ptr_inventory->addInventoryIcon(ptr_inventory_trigger);
}
////////////////////////
void QWPickupItemEvent::setInventoryTrigger(const std::shared_ptr<QWTrigger> &tr) noexcept
{
ptr_inventory_trigger = tr;
}
std::shared_ptr<QWTrigger> QWPickupItemEvent::inventoryTrigger() const noexcept
{
return ptr_inventory_trigger;
}
////////////////////////
void QWPickupItemEvent::writeToJson(QJsonObject &event_data)
{
event_data.insert("id", tag());
event_data.insert("type", EVENT_TYPE::PICKUP_ITEM);
event_data.insert("target", ptr_inventory_trigger->tag());
qDebug() << " The pickup_item event:\n" << " id " << tag()
<< "\n target " << ptr_inventory_trigger->tag();
}

View File

@ -0,0 +1,34 @@
#ifndef QUESTPLAYMUSICEVENT_H
#define QUESTPLAYMUSICEVENT_H
#include "qw_abstractsoundevent.h"
/////////////////////////////////////////////////////////////////
//// DOESN'T WORK! Has to be reworked in master-merge 1.2
//// https://trello.com/c/KFUhEbYh/62-reimplement-sound-system
class QWPlayMusicEvent : public QWAbstractSoundEvent
{
private:
QString str_musicpath;
int index;
public:
explicit QWPlayMusicEvent(const QString &path);
virtual ~QWPlayMusicEvent() override {}
void execute() override;
////////////////////////
inline void setMusicpath(const QString &path) noexcept;
inline QString musicpath() const noexcept;
void attachMusic();
////////////////////////
void writeToJson(QJsonObject &event_data) override;
};
#endif // QUESTPLAYMUSICEVENT_H

View File

@ -0,0 +1,24 @@
#include "qw_playsoundevent.h"
QWPlaySoundEvent::QWPlaySoundEvent(const QString &path) :
media_sound(new QMediaContent(QUrl("qrc:/res/" + path + ".wav")))
{
Q_ASSERT(!media_sound->isNull());
}
void QWPlaySoundEvent::execute()
{
ptr_soundplayer->playSound(media_sound);
}
////////////////////////
void QWPlaySoundEvent::writeToJson(QJsonObject &event_data)
{
event_data.insert("id", tag());
event_data.insert("type", EVENT_TYPE::PLAY_SOUND);
//event_data.insert("sound", media_sound->canonicalUrl().toString());
//qDebug() << " The play_sound event:\n" << " id " << tag()
//<< "\n sound " << media_sound->canonicalUrl().toString();
}

View File

@ -0,0 +1,30 @@
#ifndef QUESTPLAYSOUNDEVENT_H
#define QUESTPLAYSOUNDEVENT_H
#include <memory>
#include <QFile>
#include "qw_abstractsoundevent.h"
/////////////////////////////////////////////////////////////////
//// DOESN'T WORK! Has to be reworked in master-merge 1.2
//// https://trello.com/c/KFUhEbYh/62-reimplement-sound-system
class QSoundEffect;
class QWPlaySoundEvent : public QWAbstractSoundEvent
{
private:
QMediaContent *media_sound;
public:
explicit QWPlaySoundEvent(const QString &path);
virtual ~QWPlaySoundEvent() override {}
void execute() override;
////////////////////////
void writeToJson(QJsonObject &event_data) override;
};
#endif // QUESTPLAYSOUNDEVENT_H

View File

@ -0,0 +1,26 @@
#include <QCoreApplication>
#include "qw_quitgameevent.h"
QWQuitGameEvent::QWQuitGameEvent(bool savegame) :
b_savegame(savegame)
{}
void QWQuitGameEvent::execute()
{
if (b_savegame)
ptr_builder->saveGame();
QCoreApplication::quit();
}
////////////////////////
void QWQuitGameEvent::writeToJson(QJsonObject &event_data)
{
event_data.insert("id", tag());
event_data.insert("type", EVENT_TYPE::QUIT_GAME);
event_data.insert("save_game", b_savegame);
qDebug() << " The quit_game event:\n" << " id " << tag()
<< "\n save_game " << b_savegame;
}

View File

@ -0,0 +1,25 @@
#ifndef QUESTQUITGAMEEVENT_H
#define QUESTQUITGAMEEVENT_H
#include "qw_abstractlevelevent.h"
/* QWQuitGameEvent
* Immediately terminates current session. */
class QWQuitGameEvent : public QWAbstractLevelEvent
{
private:
bool b_savegame;
public:
explicit QWQuitGameEvent(bool savegame = false);
virtual ~QWQuitGameEvent() override {}
void virtual execute() override;
////////////////////////
void writeToJson(QJsonObject &event_data) override;
};
#endif // QUESTQUITGAMEEVENT_H

View File

@ -0,0 +1,49 @@
#include "qw_removetriggerevent.h"
#include "models/qw_trigger.h"
QWRemoveTriggerEvent::QWRemoveTriggerEvent(const std::shared_ptr<QWTrigger> &tr) :
trigger(tr)
{
Q_ASSERT(trigger);
}
void QWRemoveTriggerEvent::execute()
{
Q_ASSERT(location);
if (!location->triggers().contains(trigger))
return;
location->removeTrigger(trigger);
if (location == ptr_scene->currentLocation())
ptr_scene->removeItem(trigger.get());
}
////////////////////////
void QWRemoveTriggerEvent::setLocation(const std::shared_ptr<QWLocation> &loc) noexcept
{
location = loc;
Q_ASSERT(location);
}
void QWRemoveTriggerEvent::setTrigger(const std::shared_ptr<QWTrigger> &tr) noexcept
{
trigger = tr;
Q_ASSERT(trigger);
}
////////////////////////
void QWRemoveTriggerEvent::writeToJson(QJsonObject &event_data)
{
event_data.insert("id", tag());
event_data.insert("type", EVENT_TYPE::REMOVE_TRIGGER);
event_data.insert("location", location->tag());
event_data.insert("trigger", trigger->tag());
qDebug() << " The remove_trigger event:\n" << " id " << tag()
<< "\n location :" << location->tag()
<< "\n trigger :" << trigger->tag();
}

View File

@ -0,0 +1,31 @@
#ifndef QWREMOVETRIGGER_H
#define QWREMOVETRIGGER_H
#include "qw_abstractsceneevent.h"
/* QWRemoveTriggerEvent
* Removes a trigger from its location list. */
class QWRemoveTriggerEvent : public QWAbstractSceneEvent
{
private:
std::shared_ptr<QWTrigger> trigger; // What to add.
std::shared_ptr<QWLocation> location; // Where to add.
public:
explicit QWRemoveTriggerEvent(const std::shared_ptr<QWTrigger> &tr);
virtual ~QWRemoveTriggerEvent() override {}
void execute() override;
////////////////////////
void setLocation(const std::shared_ptr<QWLocation> &loc) noexcept;
void setTrigger(const std::shared_ptr<QWTrigger> &tr) noexcept;
////////////////////////
void writeToJson(QJsonObject &event_data) override;
};
#endif // QWREMOVETRIGGER_H

View File

@ -0,0 +1,36 @@
#include "models/dialogues/qw_abstractgamedialogue.h"
#include "features/qw_abstractdialoguemanager.h"
#include "qw_startdialogueevent.h"
QWStartDialogueEvent::QWStartDialogueEvent(const std::shared_ptr<QWAbstractGameDialogue> &dialogue) :
ptr_dialogue(dialogue)
{}
void QWStartDialogueEvent::execute()
{
ptr_dialogue_manager->activateDialogue(ptr_dialogue);
}
////////////////////////
void QWStartDialogueEvent::setDialogueManager(QWAbstractDialogueManager *dialogman) noexcept
{
ptr_dialogue_manager = dialogman;
}
QWAbstractDialogueManager *QWStartDialogueEvent::dialogueManager() const noexcept
{
return ptr_dialogue_manager;
}
////////////////////////
void QWStartDialogueEvent::writeToJson(QJsonObject &event_data)
{
event_data.insert("id", tag());
event_data.insert("type", EVENT_TYPE::START_DIALOGUE);
event_data.insert("dialogue", ptr_dialogue->tag());
qDebug() << " The start_dialogue event:\n" << " id " << tag()
<< "\n dialogue " << ptr_dialogue->tag();
}

View File

@ -0,0 +1,34 @@
#ifndef QWSTARTDIALOGUEEVENT_H
#define QWSTARTDIALOGUEEVENT_H
#include "qw_abstractevent.h"
/* QWStartDialogueEvent
* Starts a game-freezing dialogue by moving QWScene from gameplay state. */
class QWAbstractDialogueManager;
class QWAbstractGameDialogue;
class QWStartDialogueEvent : public QWAbstractEvent
{
private:
QWAbstractDialogueManager *ptr_dialogue_manager;
std::shared_ptr<QWAbstractGameDialogue> ptr_dialogue;
public:
explicit QWStartDialogueEvent(const std::shared_ptr<QWAbstractGameDialogue> &dialogue);
virtual ~QWStartDialogueEvent() override {}
void execute() override;
////////////////////////
void setDialogueManager(QWAbstractDialogueManager *dialogman) noexcept;
QWAbstractDialogueManager *dialogueManager() const noexcept;
////////////////////////
void writeToJson(QJsonObject &event_data) override;
};
#endif // QWSTARTDIALOGUEEVENT_H

View File

@ -0,0 +1,75 @@
#include "../qw_trigger.h"
#include "qw_switcheventsevent.h"
QWSwitchEventsEvent::QWSwitchEventsEvent(const std::shared_ptr<QWTrigger> &tr) :
ptr_target(tr),
b_active(false)
{
Q_ASSERT(ptr_target);
}
void QWSwitchEventsEvent::execute()
{
/* QWActivateItemEvent changes its state,
* Now we send other list of events for the linked trigger. */
b_active = !b_active;
ptr_target->setEvents(b_active ? list_enabled_events : list_disabled_events);
}
void QWSwitchEventsEvent::init()
{
ptr_target->setEvents(list_disabled_events);
}
////////////////////////
void QWSwitchEventsEvent::setTarget(const std::shared_ptr<QWTrigger> &tr) noexcept
{
ptr_target = tr;
}
std::shared_ptr<QWTrigger> QWSwitchEventsEvent::target() const noexcept
{
return ptr_target;
}
void QWSwitchEventsEvent::setEventsOnEnable(const QList<std::shared_ptr<QWAbstractEvent>> &evs) noexcept
{
list_enabled_events = evs;
}
void QWSwitchEventsEvent::setEventsOnDisable(const QList<std::shared_ptr<QWAbstractEvent>> &evs) noexcept
{
list_disabled_events = evs;
}
////////////////////////
void QWSwitchEventsEvent::writeToJson(QJsonObject & event_data)
{
event_data.insert("id", tag());
event_data.insert("type", EVENT_TYPE::SWITCH_EVENTS);
event_data.insert("target", ptr_target->tag());
QJsonArray trs_en, trs_dis;
for (const auto & ev : list_enabled_events) {
trs_en.append(ev->tag());
}
event_data.insert("enable_evs", trs_en);
for (const auto & ev : list_disabled_events) {
trs_dis.append(ev->tag());
}
event_data.insert("disable_evs", trs_dis);
qDebug() << " The switch_events event:\n" << " id " << tag()
<< "\n trs_en :";
for (const auto tr : trs_en)
qDebug() << " " << tr.toString();
qDebug() << "\n trs_dis :";
for (const auto tr : trs_dis)
qDebug() << " " << tr.toString();
}

View File

@ -0,0 +1,48 @@
#ifndef QUESTACTIVATEITEMEVENT_H
#define QUESTACTIVATEITEMEVENT_H
#include <memory>
#include <QList>
#include "qw_abstractevent.h"
/* QWSwitchEventsEvent
* Changes events of its linked QWTrigger.
* For example: a door is being closed until we pick up a key.
* It's initial state "to print message "go find a key you punk".
* When we activate its key, execute() changes door event to "go through". */
class QWTrigger;
class QWSwitchEventsEvent : public QWAbstractEvent
{
private:
std::shared_ptr<QWTrigger> ptr_target;
bool b_active;
QList<std::shared_ptr<QWAbstractEvent>> list_disabled_events;
QList<std::shared_ptr<QWAbstractEvent>> list_enabled_events;
public:
explicit QWSwitchEventsEvent(const std::shared_ptr<QWTrigger> &tr);
virtual ~QWSwitchEventsEvent() override {}
void execute() override;
////////////////////////
void setTarget(const std::shared_ptr<QWTrigger> &tr) noexcept;
std::shared_ptr<QWTrigger> target() const noexcept;
void setEventsOnDisable(const QList<std::shared_ptr<QWAbstractEvent>> &evs) noexcept;
void setEventsOnEnable(const QList<std::shared_ptr<QWAbstractEvent>> &evs) noexcept;
// init() sets an inital state of ptr_trigger.
void init();
////////////////////////
void writeToJson(QJsonObject &event_data) override;
};
#endif // QUESTACTIVATEITEMEVENT_H

114
models/qw_location.cpp Normal file
View File

@ -0,0 +1,114 @@
#include "qw_location.h"
#include "qw_trigger.h"
QWLocation::QWLocation() :
flag_discovered(false)
{}
void QWLocation::clearTriggers() noexcept
{
list_triggers.clear();
}
void QWLocation::setTriggers(std::initializer_list<std::shared_ptr<QWTrigger>> &&trs) noexcept
{
list_triggers.clear();
/* For some reason QList(::begin(), ::end())
* doesn't work for MSVC */
#if defined(_MSC_VER)
list_triggers = QList<std::shared_ptr<QWTrigger>>::fromStdList(std::move(trs));
#else
list_triggers = QList(trs.begin(), trs.end());
#endif
}
void QWLocation::setTriggers(const QList<std::shared_ptr<QWTrigger>> &trs) noexcept
{
list_triggers.clear();
list_triggers = trs;
}
void QWLocation::addTriggers(std::initializer_list<std::shared_ptr<QWTrigger>> &&trs) noexcept
{
list_triggers.append(std::move(QList<std::shared_ptr<QWTrigger>>(trs)));
}
void QWLocation::addTriggers(const std::shared_ptr<QWTrigger> &tr) noexcept
{
list_triggers.append(tr);
}
void QWLocation::removeTrigger(const std::shared_ptr<QWTrigger> &tr) noexcept
{
list_triggers.removeOne(tr);
}
QList<std::shared_ptr<QWTrigger>> QWLocation::triggers() const
{
return list_triggers;
}
void QWLocation::setFirstVisitTrigger(const std::shared_ptr<QWTrigger> &tr) noexcept
{
first_visit_trigger = tr;
Q_ASSERT(first_visit_trigger);
}
std::shared_ptr<QWTrigger> QWLocation::firstVisitTrigger() const noexcept
{
return first_visit_trigger;
}
void QWLocation::setDiscovered(bool discovered) noexcept
{
flag_discovered = discovered;
}
bool QWLocation::discovered() const noexcept
{
return flag_discovered;
}
void QWLocation::setMusicPath(const QString &path) noexcept
{
music_path = path;
Q_ASSERT(!music_path.isEmpty());
}
void QWLocation::removeMusic() noexcept
{
music_path.clear();
}
QString QWLocation::musicPath() const noexcept
{
return music_path;
}
////////////////////////
void QWLocation::writeToJson(QJsonObject &location_data)
{
location_data.insert("id", tag());
if (flag_discovered)
location_data.insert("discovered", flag_discovered);
if (!music_path.isEmpty())
location_data.insert("music_path", music_path);
qDebug() << " The location:\n" << " id " << tag()
<< "\n discovered " << flag_discovered
<< "\n music_path " << music_path;
// - Location triggers - //
QJsonArray json_triggers;
for (const auto &trigger : triggers()) {
json_triggers.append(trigger->tag());
qDebug() << " trigger: " << trigger->tag();
}
location_data.insert("trs", json_triggers);
}

51
models/qw_location.h Normal file
View File

@ -0,0 +1,51 @@
#ifndef QWLOCATION_H
#define QWLOCATION_H
#include <memory>
#include <QList>
#include "events/qw_abstractevent.h"
/* QWLocation
* Represents any game location. */
class QWTrigger;
class QWLocation final : public QWTagHolder
{
private:
QList<std::shared_ptr<QWTrigger>> list_triggers;
std::shared_ptr<QWTrigger> first_visit_trigger;
bool flag_discovered;
QString music_path;
public:
explicit QWLocation();
void clearTriggers() noexcept;
void setTriggers(std::initializer_list<std::shared_ptr<QWTrigger>> &&trs) noexcept;
void setTriggers(const QList<std::shared_ptr<QWTrigger>> &trs) noexcept;
void addTriggers(std::initializer_list<std::shared_ptr<QWTrigger>> &&trs) noexcept;
void addTriggers(const std::shared_ptr<QWTrigger> &tr) noexcept;
void removeTrigger(const std::shared_ptr<QWTrigger> &tr) noexcept;
QList<std::shared_ptr<QWTrigger>> triggers() const;
// Should be activated on first visit.
void setFirstVisitTrigger(const std::shared_ptr<QWTrigger> &tr) noexcept;
std::shared_ptr<QWTrigger> firstVisitTrigger() const noexcept;
void setDiscovered(bool discovered) noexcept;
bool discovered() const noexcept;
void setMusicPath(const QString &path) noexcept;
void removeMusic() noexcept;
QString musicPath() const noexcept;
////////////////////////
void writeToJson(QJsonObject &location_data) override;
};
#endif // QWLOCATION_H

113
models/qw_trigger.cpp Normal file
View File

@ -0,0 +1,113 @@
#include "qw_trigger.h"
#include <QJsonArray>
#include <QJsonObject>
#include <QDebug>
QWTrigger::QWTrigger(const QString &path)
{
setPos(0, 0);
setPixmap(QPixmap(":/res/" + path));
}
void QWTrigger::clearEvents() noexcept
{
list_events.clear();
}
void QWTrigger::setEvents(std::initializer_list<std::shared_ptr<QWAbstractEvent>> &&evs) noexcept
{
list_events.clear();
/* For some reason QList(::begin(), ::end())
* doesn't work for MSVC */
#if defined(_MSC_VER)
list_events = QList<std::shared_ptr<QWAbstractEvent>>::fromStdList(std::move(evs));
#else
list_events = QList(evs.begin(), evs.end());
#endif
}
void QWTrigger::setEvents(const QList<std::shared_ptr<QWAbstractEvent>> &evs) noexcept
{
list_events.clear();
list_events = evs;
}
void QWTrigger::addEvents(std::initializer_list<std::shared_ptr<QWAbstractEvent>> &&evs) noexcept
{
list_events.append(std::move(QList<std::shared_ptr<QWAbstractEvent>>(evs)));
}
void QWTrigger::addEvents(const std::shared_ptr<QWAbstractEvent> &ev) noexcept
{
list_events.append(ev);
}
QList<std::shared_ptr<QWAbstractEvent>> QWTrigger::events() const
{
return list_events;
}
void QWTrigger::setCover(qreal x, qreal y, const QString &path) noexcept
{
pix_path = path;
setPixmap(QPixmap(":/res/" + path));
setPos(x, y);
}
void QWTrigger::setCover(const QString &path) noexcept
{
pix_path = path;
setPixmap(QPixmap(":/res/" + path));
}
QString QWTrigger::path() const noexcept
{
return pix_path;
}
void QWTrigger::setExaminationDialogueEvent(const std::shared_ptr<QWAbstractEvent> &dialogue_event)
{
examination_event = dialogue_event;
Q_ASSERT(examination_event);
}
void QWTrigger::startExaminationDialogue() const
{
if (examination_event)
examination_event->execute();
}
void QWTrigger::activate() const
{
for (const auto &ev : list_events) {
Q_ASSERT(ev);
ev->execute();
}
}
////////////////////////
void QWTrigger::writeToJson(QJsonObject &trigger_data)
{
trigger_data.insert("id", tag());
trigger_data.insert("mask", path());
trigger_data.insert("x", x());
trigger_data.insert("y", y());
trigger_data.insert("examine_dialogue", examination_event->tag());
qDebug() << " The trigger:\n" << " id " << tag()
<< "\n mask " << tag()
<< "\n xy " << x() << " " << y()
<< "\n examine_dialogue " << examination_event->tag();
// - Trigger events - //
QJsonArray json_trevents;
for (const auto &tr_event : events()) {
json_trevents.append(tr_event->tag());
qDebug() << " event: " << tr_event->tag();
}
trigger_data.insert("evs", json_trevents);
}

46
models/qw_trigger.h Normal file
View File

@ -0,0 +1,46 @@
#ifndef TRIGGER_H
#define TRIGGER_H
#include <memory>
#include <QGraphicsPixmapItem>
#include "events/qw_abstractevent.h"
/* QWTrigger
* Represents an interactive in-game element. */
class QWStartDialogueEvent;
class QWTrigger : public QGraphicsPixmapItem, public QWTagHolder
{
private:
QList<std::shared_ptr<QWAbstractEvent>> list_events;
std::shared_ptr<QWAbstractEvent> examination_event;
QString pix_path;
public:
explicit QWTrigger(const QString &path);
void clearEvents() noexcept;
void setEvents(std::initializer_list<std::shared_ptr<QWAbstractEvent>> &&evs) noexcept;
void setEvents(const QList<std::shared_ptr<QWAbstractEvent>> &evs) noexcept;
void addEvents(std::initializer_list<std::shared_ptr<QWAbstractEvent>> &&evs) noexcept;
void addEvents(const std::shared_ptr<QWAbstractEvent> &ev) noexcept;
QList<std::shared_ptr<QWAbstractEvent>> events() const;
void setCover(qreal x, qreal y, const QString &path) noexcept;
void setCover(const QString &path) noexcept;
inline QString path() const noexcept;
void setExaminationDialogueEvent(const std::shared_ptr<QWAbstractEvent> &dialogue_event);
void startExaminationDialogue() const;
void activate() const;
////////////////////////
void writeToJson(QJsonObject &trigger_data) override;
};
#endif // TRIGGER_H

21
qml/test.qml Normal file
View File

@ -0,0 +1,21 @@
import QtQuick 2.6
import QtQuick.Controls 2.0
ApplicationWindow {
id: root
width: 300
height: 480
visible: true
/* This absolutely does not make any practical sense,
* I just try to make it work and see what's
* gonna happen */
TextField {
text: dialogue.exit_code
placeholderText: qsTr("exit code")
anchors.centerIn: parent
onTextChanged: dialogue.exit_code = text
}
}

42
qw_globalmetadata.cpp Normal file
View File

@ -0,0 +1,42 @@
#include "qw_globalmetadata.h"
#include <QString>
#include <QJsonObject>
#include <QJsonDocument>
#include <QFile>
#include <QDir>
QJsonObject QWGlobalMetadata::config = QJsonObject();
void QWGlobalMetadata::load()
{
QFile file("config.json");
if (!file.exists())
QFile::copy(":/res/config.json", file.fileName());
Q_ASSERT(file.open(QIODevice::ReadOnly));
const QByteArray json_arr = file.readAll();
file.close();
config = QJsonDocument::fromJson(json_arr).object();
}
void QWGlobalMetadata::save()
{
QFile file("config.json");
Q_ASSERT(file.open(QIODevice::WriteOnly));
file.write(QJsonDocument(config).toJson());
file.close();
}
////////////////////////
QVariant QWGlobalMetadata::valueBy(QString &&key)
{
return config[key].toVariant();
}
void QWGlobalMetadata::setValue(QString &&key, const QVariant &val) noexcept
{
config.insert(key, val.toJsonValue());
}

30
qw_globalmetadata.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef GLOBALMETADATA_H
#define GLOBALMETADATA_H
#include <QVariant>
/* QWGlobalMetadata
* Provides config options and metadata for all application classes. */
class QJsonObject;
class QString;
class QWGlobalMetadata final
{
private:
static QJsonObject config;
public:
explicit QWGlobalMetadata() = delete;
~QWGlobalMetadata() = delete;
static void load();
static void save();
////////////////////////
static QVariant valueBy(QString &&key);
static void setValue(QString &&key, const QVariant &val) noexcept;
};
#endif // GLOBALMETADATA_H

BIN
res/cell.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

28
res/config.json Normal file
View File

@ -0,0 +1,28 @@
{
"InventoryManager:length_wall": 15,
"InventoryManager:length_cell": 120,
"InventoryManager:max_amount": 7,
"InventoryManager:first_wall": 0,
"InventoryManager:clr_sel": 12,
"InventoryManager:clr_str": 0.5,
"InventoryPanel:pixmap_path": ":/res/inv.jpg",
"InventoryPanel:on_hid:bot_left_x": 220,
"InventoryPanel:on_hid:bot_left_y": -130,
"InventoryPanel:on_hid:top_right_x": 1060,
"InventoryPanel:on_hid:top_right_y": 0,
"InventoryPanel:on_shw:bot_left_x": 220,
"InventoryPanel:on_shw:bot_left_y": 50,
"InventoryPanel:on_shw:top_right_x": 1060,
"InventoryPanel:on_shw:top_right_y": 170,
"DialoguePanel:pixmap_path": ":/res/dialogue_panel.jpeg",
"DialoguePanel:on_hid:bot_left_x": 110,
"DialoguePanel:on_hid:bot_left_y": -130,
"DialoguePanel:on_hid:top_right_x": 1170,
"DialoguePanel:on_hid:top_right_y": 0,
"DialoguePanel:on_shw:bot_left_x": 110,
"DialoguePanel:on_shw:bot_left_y": 51,
"DialoguePanel:on_shw:top_right_x": 1070,
"DialoguePanel:on_shw:top_right_y": 449
}

260
res/defaultsave.json Normal file
View File

@ -0,0 +1,260 @@
{
"init_level": "start",
"start": {
"init": "spawn",
"dialogues": [
{
"id": "on_spawn",
"text": [
"\"Мастер мертв. Он даже не подозревал, что я отравил его вино.\"",
"\"Старый дурак.\"",
"\"Все его секреты заперты внутри его мастерской.\"",
"\"Он никогда не пускал меня внутрь, лишь давал свои глупые поручения.\"",
"\"Мой час настал.\"",
"\"Я заберу то, что теперь принадлежит мне, и никто не сможет меня остановить.\""
],
"type": 0
},
{
"id": "door_general_on_closed",
"text": [
"Путь преграждает дверь в виде массивного механизма.",
"Силой вскрыть не получается."
],
"type": 0
},
{
"id": "door_general_on_look",
"text": [
"\"Чертов безумец!\"",
"\"Кто же в собственную мастерскую делает такую дверь!\"",
"\"Видимо, отмычки тут не помогут.\""
],
"type": 0
},
{
"id": "diary_on_taking",
"text": [
"Старый потрепанный дневник мастера.",
"Страницы исписаны неровным подчерком,\nно кое-что полезное можно будет узнать."
],
"type": 0
},
{
"id": "diary_on_look",
"text": [
"\"Ого, это же записи мастера!\nМожет пригодиться!\""
],
"type": 0
},
{
"id": "portrait_on_click",
"text": [
"Картина покойного хозяина мастерской. Автопортрет."
],
"type": 0
},
{
"id": "portrait_on_look",
"text": [
"\"Он как будто насмехается надо мной.\nДаже после смерти...\""
],
"type": 0
},
{
"id": "table_on_look",
"text": [
"\"Обычный стол, на нём лежат какие-то бумаги.\""
]
},
{
"id": "mechanism_on_pressed",
"text": [
"Слышан характерный механический звук где-то внутри двери."
],
"type": 0
},
{
"id": "mechanism_on_failure",
"text": [
"После нажатия механизм издает резкий скрежет.",
"Все механизмы вернулись на свои места."
],
"type": 0
}
],
"locations": [
{
"id": "location_room",
"triggers": [ "location_room_background", "painting", "table", "global_door" ]
},
{
"id": "location_table",
"triggers": [ "location_table_background", "diary", "backwarder" ]
},
{
"id": "location_nearby_door",
"triggers": [ "location_nearby_door_background", "door", "backwarder" ]
}
],
"triggers": [
{
"id": "location_nearby_door_background"
},
{
"id": "location_table_background"
},
{
"id": "location_room_background"
},
{
"id": "spawn",
"evs": [
"init",
"dial_on_spawn"
]
},
{
"id": "painting",
"x": 0,
"y": 0,
"evs": [
"dial_portrait_on_click"
],
"examine_dialogue": "dial_portrait_on_look"
},
{
"id": "table",
"x": 0,
"y": 0,
"evs": [
"move_to_table"
],
"examine_dialogue": "dial_table_on_look"
},
{
"id": "backwarder",
"x": 0,
"y": 0,
"evs": [
"move_backward"
]
},
{
"id": "global_door",
"x": 0,
"y": 0,
"evs": [
"move_to_global_door"
],
"examine_dialogue": "dial_global_door_on_look"
},
{
"id": "diary",
"x": 0,
"y": 0,
"evs": [
"dial_diary_on_taking",
"take_diary"
],
"examine_dialogue": "dial_diary_on_look"
},
{
"id": "tr_inv_diary"
},
{
"id": "door",
"x": 0,
"y": 0,
"evs": [
"dial_door_general_on_closed"
],
"examine_dialogue": "dial_door_general_on_look"
}
],
"events": [
{
"id": "dial_on_spawn",
"type": 10,
"dialogue_type": 0,
"dialogue": "on_spawn"
},
{
"id": "dial_portrait_on_click",
"type": 10,
"dialogue_type": 0,
"dialogue": "portrait_on_click"
},
{
"id": "dial_door_general_on_closed",
"type": 10,
"dialogue_type": 0,
"dialogue": "door_general_on_closed"
},
{
"id": "dial_door_general_on_look",
"type": 10,
"dialogue_type": 0,
"dialogue": "door_general_on_look"
},
{
"id": "dial_diary_on_taking",
"type": 10,
"dialogue_type": 0,
"dialogue": "diary_on_taking"
},
{
"id": "dial_diary_on_look",
"type": 10,
"dialogue_type": 0,
"dialogue": "diary_on_look"
},
{
"id": "dial_portrait_on_look",
"type": 10,
"dialogue_type": 0,
"dialogue": "portrait_on_look"
},
{
"id": "dial_table_on_look",
"type": 10,
"dialogue_type": 0,
"dialogue": "table_on_look"
},
{
"id": "dial_global_door_on_look",
"type": 10,
"dialogue_type": 0,
"dialogue": "door_general_on_look"
},
{
"id": "move_to_table",
"type": 0,
"location": "location_table"
},
{
"id": "move_to_global_door",
"type": 0,
"location": "location_nearby_door"
},
{
"id": "move_backward",
"type": 0,
"location": "location_room"
},
{
"id": "take_diary",
"type": 4,
"target": "tr_inv_diary"
}
]
}
}

BIN
res/dialogue_panel.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
res/door.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 507 B

BIN
res/inv.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

111
res/levels/level1.json Normal file
View File

@ -0,0 +1,111 @@
{
"init": "spawn",
"triggers": [
{
"id": "spawn_background"
},
{
"id": "roomkey_background"
},
{
"id": "tr_door1",
"mask": "door",
"x": 55,
"y": 67,
"evs": [ "ev1", "sound_event1" ]
},
{
"id": "tr_osaka1",
"mask": "osaka",
"x": 255,
"y": 367,
"evs": [ "sound_event2" ]
},
{
"id": "tr_osaka2",
"mask": "osaka",
"x": 355,
"y": 467,
"evs": [ "sound_event3" ]
},
{
"id": "tr_osaka3",
"mask": "osaka",
"x": 490,
"y": 500,
"evs": [ "sound_event4" ]
},
{
"id": "tr_osaka4",
"mask": "osaka",
"x": 600,
"y": 200,
"evs": [ "sound_event5" ]
},
{
"id": "tr_osaka5",
"mask": "osaka",
"x": 955,
"y": 400,
"evs": [ "sound_event6" ]
},
{
"id": "spawn",
"mask": "",
"x": 0,
"y": 0,
"evs": [ "init_ev" ]
}
],
"events": [
{
"id": "init_ev",
"type": 0,
"trs": [
"tr_osaka1",
"tr_osaka2",
"tr_osaka3",
"tr_osaka4",
"tr_osaka5",
"spawn_background"
]
},
{
"id": "ev1",
"type": 0,
"trs": ["roomkey_background"]
},
{
"id": "sound_event1",
"type": 5,
"sound": "sound"
},
{
"id": "sound_event2",
"type": 5,
"sound": "sound"
},
{
"id": "sound_event3",
"type": 5,
"sound": "sound"
},
{
"id": "sound_event4",
"type": 5,
"sound": "sound"
},
{
"id": "sound_event5",
"type": 5,
"sound": "sound"
},
{
"id": "sound_event6",
"type": 5,
"sound": "sound"
}
]
}

53
res/menu.json Normal file
View File

@ -0,0 +1,53 @@
{
"init_level": "menu",
"menu":
{
"init": "spawn",
"triggers": [
{
"id": "spawn",
"evs": [ "init_ev" ]
},
{
"id": "menu_background",
"mask": "menu_background"
},
{
"id": "opt_start_new_game",
"x": 40,
"y": 216,
"evs": [ "start_new_game" ]
},
{
"id": "opt_quit_game",
"x": 40,
"y": 416,
"evs": [ "quit_game" ]
}
],
"events": [
{
"id": "init_ev",
"type": 0,
"trs": [
"opt_quit_game",
"opt_start_new_game",
"menu_background"
]
},
{
"id": "start_new_game",
"type": 8,
"save_file": "wow_new_game_test"
},
{
"id": "quit_game",
"type": 9,
"save_game": false
}
]
}
}

BIN
res/osaka.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@ -0,0 +1,37 @@
#include "pushbuttonsound.h"
#include "features/gamefeatures.h"
PushButtonSound::PushButtonSound(const QPixmap &pixmap_off, QGraphicsItem *parent) :
b_on(false),
pix_on(pixmap_off),
pix_off(pixmap_off)
{
setParentItem(parent);
Q_ASSERT(!pixmap_off.isNull());
}
void PushButtonSound::onClick()
{
b_on = !b_on;
emit signalChangeSound(b_on);
}
void PushButtonSound::onConnect(std::unique_ptr<GameFeatures> &game_features)
{
QObject::connect(this, //sender
SIGNAL(signalChangeSound(bool)),
game_features->ptr_sound_player, //receiver
SLOT(setMuteness(bool)));
}
////////////////////////
void PushButtonSound::setPixmapOn(const QPixmap &pixmap_on) noexcept
{
pix_on = pixmap_on;
}
void PushButtonSound::setPixmapOff(const QPixmap &pixmap_off) noexcept
{
pix_off = pixmap_off;
}

View File

@ -0,0 +1,40 @@
#ifndef PUSHBUTTONSOUND_H
#define PUSHBUTTONSOUND_H
#include <QPainter>
#include "qw_abstractscenecontrol.h"
/* PushButtonSound
* Switches current sound state. */
class PushButtonSound : public QWAbstractSceneControl
{
Q_OBJECT
private:
bool b_on;
QPixmap pix_on;
QPixmap pix_off;
protected:
void paint(QPainter *painter, const QStyleOptionGraphicsItem *,
QWidget *) override
{
painter->fillRect(rect(), QBrush(b_on ? pix_on : pix_off));
}
public:
explicit PushButtonSound(const QPixmap &pixmap_off, QGraphicsItem *parent = nullptr);
virtual ~PushButtonSound() override {}
void onClick() override;
void onConnect(std::unique_ptr<GameFeatures> &game_features) override;
////////////////////////
inline void setPixmapOn(const QPixmap &pixmap_on) noexcept;
inline void setPixmapOff(const QPixmap &pixmap_off) noexcept;
signals:
void signalChangeSound(bool);
};
#endif // PUSHBUTTONSOUND_H

View File

@ -0,0 +1,13 @@
#include "qw_abstractscenecontrol.h"
QWAbstractSceneControl:: QWAbstractSceneControl()
{}
QWAbstractSceneControl::~QWAbstractSceneControl()
{}
void QWAbstractSceneControl::onBuildingStateMachine(QWStateMachine *state_machine, std::unique_ptr<GameFeatures> &game_features)
{
Q_UNUSED(state_machine)
Q_UNUSED(game_features)
}

View File

@ -0,0 +1,25 @@
#ifndef ABSTRACTSCENECONTROL_H
#define ABSTRACTSCENECONTROL_H
#include <memory>
#include <QGraphicsWidget>
/* QWAbstractSceneControl
* Interface for scene graphics elements which have
* to manipulate non-logic game processes like sound, view, etc. */
struct GameFeatures;
class QWStateMachine;
class QWAbstractSceneControl : public QGraphicsWidget
{
public:
QWAbstractSceneControl();
~QWAbstractSceneControl() = 0;
virtual void onClick() = 0;
virtual void onConnect(std::unique_ptr<GameFeatures> &game_features) = 0;
virtual void onBuildingStateMachine(QWStateMachine *state_machine, std::unique_ptr<GameFeatures> &game_features);
};
#endif // ABSTRACTSCENECONTROL_H

View File

@ -0,0 +1,71 @@
#include "scenedialoguepanel.h"
#include "features/gamefeatures.h"
#include "features/qw_statemachine.h"
#include "qw_globalmetadata.h"
SceneDialoguePanel::SceneDialoguePanel()
{
metadata.pixmap_path = QWGlobalMetadata::valueBy("DialoguePanel:pixmap_path").toString();
metadata.on_hid = QRect(QPoint(QWGlobalMetadata::valueBy("DialoguePanel:on_hid:bot_left_x" ).toInt(), // x1
QWGlobalMetadata::valueBy("DialoguePanel:on_hid:bot_left_x" ).toInt()), // y1
QPoint(QWGlobalMetadata::valueBy("DialoguePanel:on_hid:top_right_x").toInt(), // x4
QWGlobalMetadata::valueBy("DialoguePanel:on_hid:top_right_y").toInt())); // y4
metadata.on_shw = QRect(QPoint(QWGlobalMetadata::valueBy("DialoguePanel:on_shw:bot_left_x" ).toInt(), // x1
QWGlobalMetadata::valueBy("DialoguePanel:on_shw:bot_left_x" ).toInt()), // y1
QPoint(QWGlobalMetadata::valueBy("DialoguePanel:on_shw:top_right_x").toInt(), // x4
QWGlobalMetadata::valueBy("DialoguePanel:on_shw:top_right_y").toInt())); // y4
/* /
* 2-------4 /
* | | <-
* 1-------3
*/
setPixmap(QPixmap(metadata.pixmap_path));
Q_ASSERT(!pix_rect.isNull());
}
void SceneDialoguePanel::onClick()
{}
void SceneDialoguePanel::onConnect(std::unique_ptr<GameFeatures> &game_features)
{
game_features->ptr_text_dlg->setDialoguePanel(shared_from_this());
}
void SceneDialoguePanel::onBuildingStateMachine(QWStateMachine *state_machine, std::unique_ptr<GameFeatures> &game_features)
{
// Establisihing animation for dialogue panel
const auto &state_gameplay = state_machine->stateByKey("state_gameplay");
QState *state_dialogue = new QState;
state_machine->registerState("state_dialogue", state_dialogue);
connect(state_dialogue, SIGNAL(entered()), game_features->ptr_scene, SLOT(onEntryDialogue()));
QSignalTransition *enter_dialogue_transition = new QSignalTransition(game_features->ptr_text_dlg, SIGNAL(onEntryDialogueTransition()));
enter_dialogue_transition->setTargetState(state_dialogue);
state_gameplay->addTransition(enter_dialogue_transition);
QSignalTransition *leave_dialogue_transition = new QSignalTransition(game_features->ptr_text_dlg, SIGNAL(onLeaveDialogueTransition()));
leave_dialogue_transition->setTargetState(state_gameplay);
state_dialogue->addTransition(leave_dialogue_transition);
state_gameplay->assignProperty(this, "geometry", metadata.on_hid);
state_dialogue->assignProperty(this, "geometry", metadata.on_shw);
state_machine->addState(state_dialogue);
}
////////////////////////
void SceneDialoguePanel::setPixmap(const QPixmap &pix) noexcept
{
pix_rect = pix;
Q_ASSERT(!pix_rect.isNull());
}
QPixmap SceneDialoguePanel::pixmap() const noexcept
{
return pix_rect;
}

View File

@ -0,0 +1,45 @@
#ifndef SCENEDIALOGUEPANEL_H
#define SCENEDIALOGUEPANEL_H
#include <QPainter>
#include "qw_abstractscenecontrol.h"
/* SceneDialoguePanel
* The view for dialogue processes like text, thoughts, etc. */
class SceneDialoguePanel : public QWAbstractSceneControl, public std::enable_shared_from_this<SceneDialoguePanel>
{
private:
QPixmap pix_rect;
struct metadata
{
// path to panel pixmap
QString pixmap_path;
// rect when panel is hidden
QRect on_hid;
// rect when panel is shown
QRect on_shw;
} metadata;
protected:
void paint(QPainter *painter, const QStyleOptionGraphicsItem *,
QWidget *) override
{
painter->fillRect(rect(), QBrush(pix_rect));
}
public:
explicit SceneDialoguePanel();
virtual ~SceneDialoguePanel() override {}
void onClick() override;
void onConnect(std::unique_ptr<GameFeatures> &game_features) override;
void onBuildingStateMachine(QWStateMachine *state_machine, std::unique_ptr<GameFeatures> &game_features) override;
////////////////////////
inline void setPixmap(const QPixmap &pix) noexcept;
inline QPixmap pixmap() const noexcept;
};
#endif // SCENEDIALOGUEPANEL_H

View File

@ -0,0 +1,85 @@
#include "sceneinventorypanel.h"
#include "features/gamefeatures.h"
#include "features/qw_statemachine.h"
#include "qw_globalmetadata.h"
SceneInventoryPanel::SceneInventoryPanel()
{
metadata.pixmap_path = QWGlobalMetadata::valueBy("InventoryPanel:pixmap_path").toString();
metadata.on_hid = QRect(QPoint(QWGlobalMetadata::valueBy("InventoryPanel:on_hid:bot_left_x" ).toInt(), // x1
QWGlobalMetadata::valueBy("InventoryPanel:on_hid:bot_left_y" ).toInt()), // y1
QPoint(QWGlobalMetadata::valueBy("InventoryPanel:on_hid:top_right_x").toInt(), // x4
QWGlobalMetadata::valueBy("InventoryPanel:on_hid:top_right_y").toInt())); // y4
metadata.on_shw = QRect(QPoint(QWGlobalMetadata::valueBy("InventoryPanel:on_shw:bot_left_x" ).toInt(), // x1
QWGlobalMetadata::valueBy("InventoryPanel:on_shw:bot_left_y" ).toInt()), // y1
QPoint(QWGlobalMetadata::valueBy("InventoryPanel:on_shw:top_right_x").toInt(), // x4
QWGlobalMetadata::valueBy("InventoryPanel:on_shw:top_right_y").toInt())); // y4
/* /
* 2-------4 /
* | | <-
* 1-------3
*/
setPixmap(QPixmap(metadata.pixmap_path));
}
void SceneInventoryPanel::onClick()
{
emit signalOnInventory();
}
void SceneInventoryPanel::onConnect(std::unique_ptr<GameFeatures> &game_features)
{
game_features->ptr_inventory->setInventoryPanel(shared_from_this());
QObject::connect(this, //sender
SIGNAL(signalOnInventory()),
game_features->ptr_inventory, // receiver
SLOT(onClicked()));
}
void SceneInventoryPanel::onBuildingStateMachine(QWStateMachine *state_machine, std::unique_ptr<GameFeatures> &game_features)
{
// Establisihing animation for inventory panel
QPropertyAnimation *anim = new QPropertyAnimation(shared_from_this().get(), "geometry");
anim->setDuration(200);
anim->setEasingCurve(QEasingCurve::InBack);
QState *state_gameplay = new QState;
state_machine->registerState("state_gameplay", state_gameplay);
connect(state_gameplay, SIGNAL(entered()), game_features->ptr_scene, SLOT(onEntryGameplay()));
QState *state_inventory = new QState;
state_machine->registerState("state_inventory", state_inventory);
connect(state_inventory, SIGNAL(entered()), game_features->ptr_scene, SLOT(onEntryInventory()));
QEventTransition *enter_inventory_transition = new QEventTransition(game_features->ptr_view, QEvent::Wheel);
enter_inventory_transition->setTargetState(state_inventory);
enter_inventory_transition->addAnimation(anim);
state_gameplay->addTransition(enter_inventory_transition);
QEventTransition *leave_inventory_transition = new QEventTransition(game_features->ptr_view, QEvent::Wheel);
leave_inventory_transition->setTargetState(state_gameplay);
leave_inventory_transition->addAnimation(anim);
state_inventory->addTransition(leave_inventory_transition);
state_gameplay->assignProperty(this, "geometry", metadata.on_hid);
state_inventory->assignProperty(this, "geometry", metadata.on_shw);
state_machine->addState(state_gameplay);
state_machine->addState(state_inventory);
}
////////////////////////
void SceneInventoryPanel::setPixmap(const QPixmap &pix) noexcept
{
pix_rect = pix;
Q_ASSERT(!pix_rect.isNull());
}
QPixmap SceneInventoryPanel::pixmap() const noexcept
{
return pix_rect;
}

View File

@ -0,0 +1,49 @@
#ifndef SCENEINVENTORYPANEL_H
#define SCENEINVENTORYPANEL_H
#include <QPainter>
#include "qw_abstractscenecontrol.h"
/* SceneInventoryPanel
* The view for inventory and all its items on the scene. */
class SceneInventoryPanel : public QWAbstractSceneControl, public std::enable_shared_from_this<SceneInventoryPanel>
{
Q_OBJECT
private:
QPixmap pix_rect;
struct metadata
{
// path to panel pixmap
QString pixmap_path;
// rect when panel is hidden
QRect on_hid;
// rect when panel is shown
QRect on_shw;
} metadata;
protected:
void paint(QPainter *painter, const QStyleOptionGraphicsItem *,
QWidget *) override
{
painter->fillRect(rect(), QBrush(pix_rect));
}
public:
explicit SceneInventoryPanel();
virtual ~SceneInventoryPanel() override {}
void onClick() override;
void onConnect(std::unique_ptr<GameFeatures> &game_features) override;
void onBuildingStateMachine(QWStateMachine *state_machine, std::unique_ptr<GameFeatures> &game_features) override;
////////////////////////
inline void setPixmap(const QPixmap &pix) noexcept;
inline QPixmap pixmap() const noexcept;
signals:
void signalOnInventory();
};
#endif // SCENEINVENTORYPANEL_H

128
view/qw_scene.cpp Normal file
View File

@ -0,0 +1,128 @@
#include "qw_scene.h"
#include "models/qw_trigger.h"
#include "controls/sceneinventorypanel.h"
#include "controls/pushbuttonsound.h"
#include "controls/scenedialoguepanel.h"
QWScene::QWScene(int x, int y) :
QGraphicsScene(0, 0, x, y)
{
QLinkedList<std::shared_ptr<QWAbstractSceneControl>> widgt_list =
{ std::make_shared<SceneInventoryPanel>(),
std::make_shared<SceneDialoguePanel>()
//std::make_shared<PushButtonSound>(QPixmap(":/res/cell.png")/*, ptr_inventory_panel.get()*/),
};
foreach (std::shared_ptr<QWAbstractSceneControl> widgt, widgt_list) {
addItem(widgt.get());
list_on_inventory_widgets.append(std::move(widgt));
}
}
QLinkedList<std::shared_ptr<QWAbstractSceneControl>> QWScene::inventoryWidgets() const noexcept
{
return list_on_inventory_widgets;
}
void QWScene::onEntryGameplay() noexcept
{
status = GAMEPLAY;
}
void QWScene::onEntryInventory() noexcept
{
status = INVENTORY;
}
void QWScene::onEntryMenu() noexcept
{
status = MENU;
emit signalEnterMenu();
}
void QWScene::onEntryDialogue() noexcept
{
status = DIALOGUE;
}
void QWScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
switch (status)
{
case MENU:
case GAMEPLAY:
// On GAMEPLAY and MENU state we check all the in-game entities.
foreach (std::shared_ptr<QWTrigger> tr, location->triggers()) {
if (tr->isUnderMouse() && event->button() == Qt::LeftButton)
tr->activate();
}
break;
case INVENTORY:
// On INVENTORY state we check all the system controls like buttons for sound, etc.
foreach (std::shared_ptr<QWAbstractSceneControl> tr, list_on_inventory_widgets) {
if (tr->isUnderMouse() && event->button() == Qt::LeftButton)
tr->onClick();
}
break;
case DIALOGUE:
// On DIALOGUE state we interact with current dialogue only.
switch (event->button()) {
case Qt::LeftButton:
emit signalClickDialogue(MouseButton::LEFT);
break;
case Qt::RightButton:
emit signalClickDialogue(MouseButton::RIGHT);
break;
default:
break;
}
break;
case EXAMINATION:
// On EXAMINATION state we activate examination events of triggers
foreach (std::shared_ptr<QWTrigger> tr, location->triggers()) {
if (tr->isUnderMouse() && event->button() == Qt::LeftButton)
emit signalLeaveExamination();
tr->startExaminationDialogue();
}
break;
}
}
void QWScene::keyReleaseEvent(QKeyEvent *event)
{
switch (status)
{
case GAMEPLAY:
if (event->key() == Qt::Key_E)
emit signalEnterExamination();
break;
default:
return;
}
}
void QWScene::clearLocation()
{
if (!location)
return;
// Moving to another location by erasing current
foreach (const std::shared_ptr<QWTrigger> trigger, location->triggers())
removeItem(trigger.get());
location = nullptr;
}
void QWScene::setCurrentLocation(const std::shared_ptr<QWLocation> &loc) noexcept
{
location = loc;
}
std::shared_ptr<QWLocation> QWScene::currentLocation() const noexcept
{
return location;
}

61
view/qw_scene.h Normal file
View File

@ -0,0 +1,61 @@
#ifndef QUESTSCENE_H
#define QUESTSCENE_H
#include <memory>
#include <QGraphicsScene>
#include <QGraphicsSceneMouseEvent>
#include <QGraphicsEffect>
#include <QLinkedList>
#include "models/qw_location.h"
#include "controls/qw_abstractscenecontrol.h"
/* QWScene
* The game scene itself. */
enum class MouseButton { LEFT, RIGHT };
class QWDialogueFrame;
class QWScene final : public QGraphicsScene
{
Q_OBJECT
Q_DISABLE_COPY_MOVE(QWScene)
private:
std::shared_ptr<QWLocation> location;
QLinkedList<std::shared_ptr<QWAbstractSceneControl>> list_on_inventory_widgets;
enum SceneStatus { GAMEPLAY, INVENTORY, MENU, DIALOGUE, EXAMINATION };
SceneStatus status;
protected:
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
void keyReleaseEvent(QKeyEvent *event) override;
public:
explicit QWScene(int x, int y);
QLinkedList<std::shared_ptr<QWAbstractSceneControl>> inventoryWidgets() const noexcept;
void setCurrentLocation(const std::shared_ptr<QWLocation> &loc) noexcept;
std::shared_ptr<QWLocation> currentLocation() const noexcept;
void clearLocation();
void onEndLevel(const QString &str) noexcept;
signals:
void signalClickInventory();
void signalClickDialogue(MouseButton);
void signalEnterMenu();
void signalLeaveMenu();
void signalEnterExamination();
void signalLeaveExamination();
public slots:
void onEntryGameplay() noexcept;
void onEntryInventory() noexcept;
void onEntryMenu() noexcept;
void onEntryDialogue() noexcept;
};
#endif // QUESTSCENE_H

9
view/qw_view.cpp Normal file
View File

@ -0,0 +1,9 @@
#include "qw_view.h"
QWView::QWView(QWScene *sc) :
scene(sc)
{
setScene(sc);
//setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
//setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
}

29
view/qw_view.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef QUESTVIEW_H
#define QUESTVIEW_H
#include <QGraphicsView>
#include "qw_scene.h"
/* QWView
* The same QGraphicsView but this one ignores wheel events,
* because wheels are for loosers. */
class QWView final : public QGraphicsView
{
Q_OBJECT
Q_DISABLE_COPY_MOVE(QWView)
private:
QWScene *scene;
protected:
void wheelEvent(QWheelEvent *ev) override
{
ev->ignore();
}
public:
explicit QWView(QWScene *sc);
};
#endif // QUESTVIEW_H