Commit a7005a2f authored by Felix Huther's avatar Felix Huther
Browse files

Observer pattern

parent cccb4e58
......@@ -6,12 +6,16 @@ CONFIG -= qt
SOURCES += \
abstractui.cpp \
character.cpp \
door.cpp \
dungeoncrawler.cpp \
floor.cpp \
level.cpp \
main.cpp \
observerpassive.cpp \
portal.cpp \
position2d.cpp \
subjectactiv.cpp \
switch.cpp \
terminalui.cpp \
tile.cpp \
wall.cpp
......@@ -19,11 +23,15 @@ SOURCES += \
HEADERS += \
abstractui.h \
character.h \
door.h \
dungeoncrawler.h \
floor.h \
level.h \
observerpassive.h \
portal.h \
position2d.h \
subjectactiv.h \
switch.h \
terminalui.h \
tile.h \
wall.h
#include "door.h"
Door::Door(const std::string &texture, Character *currentCharacter, const Position2D &position)
: Tile(texture, currentCharacter, position),isClosed(true)
{}
void Door::update()
{
if(isClosed) isClosed = false;
}
Tile *Door::onEnter(Tile *fromTile, Character *who)
{
if(this->getIsClosed()) return nullptr;
else return this;
}
bool Door::moveTo(Tile *destTile, Character *who)
{
if(isClosed) return false;
else if(!destTile->hasCharacter()){
destTile->setCurrentCharacter(this->currentCharacter);
currentCharacter->setCurrentTile(destTile);
this->setCurrentCharacter(nullptr);
return true;
};
return false;
}
Tile *Door::onLeave(Tile *destTile, Character *who)
{
return nullptr;
}
bool Door::getIsClosed() const
{
return isClosed;
}
#ifndef DOOR_H
#define DOOR_H
#include "tile.h"
#include "observerpassive.h"
class Door : public Tile, public ObserverPassive
{
public:
//CONSTRUCTOR AND DESTRUCTOR
Door(const std::string &texture, Character *currentCharacter, const Position2D &position);
~Door() = default;
// ObserverPassive interface
public:
void update() override;
// Tile interface
public:
Tile *onEnter(Tile *fromTile, Character *who) override;
bool moveTo(Tile *destTile, Character *who) override;
Tile *onLeave(Tile *destTile, Character *who) override;
bool getIsClosed() const;
private:
bool isClosed;
};
#endif // DOOR_H
......@@ -2,7 +2,7 @@
#include <iostream>
DungeonCrawler::DungeonCrawler(Level *level, AbstractUI* UI)
: mCurrentLevel(level), mUserInterface(UI){
: mCurrentLevel(level), mUserInterface(UI){
}
......@@ -14,6 +14,25 @@ DungeonCrawler::~DungeonCrawler()
delete mUserInterface;
}
void DungeonCrawler::ifSubjectNotify(Tile* tile)
{
if(typeid(*tile) == typeid(Switch)){
Switch* pSwitch = static_cast<Switch*>(tile);
pSwitch->notify();
}
}
void DungeonCrawler::ifPortalDestPortalLogic(Tile*& tile, Position2D& pos )
{
if(typeid(*tile) == typeid(Portal)){
Portal* portal = static_cast<Portal*>(tile);
tile = portal->getDestPortal();
pos = tile->getPosition();
tile = mCurrentLevel->getTileAtPos(pos);
}
}
void DungeonCrawler::play() {
while(true) {
......@@ -30,104 +49,86 @@ void DungeonCrawler::play() {
movingDirection = mUserInterface->askMoveFromUser();
switch (movingDirection) {
case 'w': {
int oneRowUp = characterPos.getRow()-1;
int sameColumn = characterPos.getColumn();
case 'w': {
int oneRowUp = characterPos.getRow()-1;
int sameColumn = characterPos.getColumn();
Position2D onePosUp(oneRowUp, sameColumn);
Position2D onePosUp(oneRowUp, sameColumn);
Tile *oneTileUp = mCurrentLevel->getTileAtPos(onePosUp);
Tile *oneTileUp = mCurrentLevel->getTileAtPos(onePosUp);
if(typeid(*oneTileUp) == typeid(Portal)){
Portal* portal = static_cast<Portal*>(oneTileUp);
oneTileUp = portal->getDestPortal();
onePosUp = oneTileUp->getPosition();
oneTileUp = mCurrentLevel->getTileAtPos(onePosUp);
ifPortalDestPortalLogic(oneTileUp,onePosUp);
}
movPossible = oneTileUp->onEnter(characterTile, currentChar);
movPossible = oneTileUp->onEnter(characterTile, currentChar);
if (movPossible) {
characterTile->moveTo(oneTileUp, currentChar);
}
break;
if (movPossible) {
characterTile->moveTo(oneTileUp, currentChar);
ifSubjectNotify(oneTileUp);
}
case 'a':{
int sameRow = characterPos.getRow();
int oneColumnLeft = characterPos.getColumn()-1;
break;
}
case 'a':{
int sameRow = characterPos.getRow();
int oneColumnLeft = characterPos.getColumn()-1;
Position2D onePosLeft(sameRow, oneColumnLeft);
Position2D onePosLeft(sameRow, oneColumnLeft);
Tile *oneTileLeft = mCurrentLevel->getTileAtPos(onePosLeft);
Tile *oneTileLeft = mCurrentLevel->getTileAtPos(onePosLeft);
if(typeid(*oneTileLeft) == typeid(Portal)){
Portal* portal = static_cast<Portal*>(oneTileLeft);
oneTileLeft = portal->getDestPortal();
onePosLeft= oneTileLeft->getPosition();
oneTileLeft = mCurrentLevel->getTileAtPos(onePosLeft);
ifPortalDestPortalLogic(oneTileLeft,onePosLeft);
}
movPossible = oneTileLeft->onEnter(characterTile, currentChar);
movPossible = oneTileLeft->onEnter(characterTile, currentChar);
if (movPossible){
if (movPossible){
characterTile->moveTo(oneTileLeft, currentChar);
characterTile->moveTo(oneTileLeft, currentChar);
ifSubjectNotify(oneTileLeft);
}
break;
}
case 's':{
int oneRowDown = characterPos.getRow() +1;
int sameColumn = characterPos.getColumn();
break;
Position2D onePosDown(oneRowDown, sameColumn);
Tile *oneTileDown = mCurrentLevel->getTileAtPos(onePosDown);
}
case 's':{
int oneRowDown = characterPos.getRow() +1;
int sameColumn = characterPos.getColumn();
if(typeid(*oneTileDown) == typeid(Portal)){
Portal* portal = static_cast<Portal*>(oneTileDown);
oneTileDown = portal->getDestPortal();
onePosDown = oneTileDown->getPosition();
oneTileDown = mCurrentLevel->getTileAtPos(onePosDown);
Position2D onePosDown(oneRowDown, sameColumn);
}
Tile *oneTileDown = mCurrentLevel->getTileAtPos(onePosDown);
movPossible = oneTileDown->onEnter(characterTile, currentChar);
if (movPossible){
characterTile->moveTo(oneTileDown, currentChar);
ifPortalDestPortalLogic(oneTileDown,onePosDown);
}
break;
movPossible = oneTileDown->onEnter(characterTile, currentChar);
if (movPossible){
characterTile->moveTo(oneTileDown, currentChar);
ifSubjectNotify(oneTileDown);
}
case 'd':{
int sameRow = characterPos.getRow();
int oneColumnRight = characterPos.getColumn()+1;
break;
Position2D onePosRight(sameRow, oneColumnRight);
Tile *oneTileRight = mCurrentLevel->getTileAtPos(onePosRight);
}
case 'd':{
int sameRow = characterPos.getRow();
int oneColumnRight = characterPos.getColumn()+1;
if(typeid(*oneTileRight) == typeid(Portal)){
Portal* portal = static_cast<Portal*>(oneTileRight);
oneTileRight = portal->getDestPortal();
onePosRight = oneTileRight->getPosition();
oneTileRight = mCurrentLevel->getTileAtPos(onePosRight);
Position2D onePosRight(sameRow, oneColumnRight);
}
Tile *oneTileRight = mCurrentLevel->getTileAtPos(onePosRight);
movPossible = oneTileRight->onEnter(characterTile, currentChar);
if (movPossible) {
characterTile->moveTo(oneTileRight, currentChar);
ifPortalDestPortalLogic(oneTileRight,onePosRight);
}
break;
movPossible = oneTileRight->onEnter(characterTile, currentChar);
if (movPossible) {
characterTile->moveTo(oneTileRight, currentChar);
ifSubjectNotify(oneTileRight);
}
break;
}
}
}
......
......@@ -13,6 +13,13 @@ public:
~DungeonCrawler();
void play();
void ifSubjectNotify(Tile* tile);
void ifPortalDestPortalLogic(Tile*& tile, Position2D& pos);
private:
Level* mCurrentLevel;
AbstractUI* mUserInterface;
......
......@@ -55,9 +55,15 @@ Character *Level::getCharacter() const {
void Level::setStructure() {
std::string stwall = "wall";
std::string stportal = "portal";
std::string stfloor = "floor";
std::string stSwitch = "switch";
std::string stDoor = "door";
Door* doorPointer;
Switch* switchPointer;
for(int i = 0 ; i < mheight; i++){
std::vector<Tile*> vec;
......@@ -65,7 +71,7 @@ void Level::setStructure() {
for(int j = 0 ; j < mwidth;j++)
{
Position2D pos = Position2D(i,j);
//draws wall arround the field
//WALL ARROUND THE FIELD
if((i == 0 && j < mwidth) ||
j == 0 || j == mwidth-1 ||
i == mheight-1
......@@ -74,17 +80,29 @@ void Level::setStructure() {
Tile* wallpointer = new Wall(stwall,nullptr,pos);
mLevel.at(i).push_back(wallpointer);
}
else if(j == 6)
} // SOME MORE WALLS
else if(j == 6 || j == 18)
{
if(j == 18 && i == 5)
{
doorPointer = new Door(stDoor,nullptr,pos);
mLevel.at(i).push_back(doorPointer);
}
else
{
Tile* wallpointer = new Wall(stwall,nullptr,pos);
mLevel.at(i).push_back(wallpointer);
}
}
// PLACE A SWITCH
else if(i == 8 && j == 15)
{
switchPointer = new Switch(stSwitch,nullptr,pos);
mLevel.at(i).push_back(switchPointer);
}
// creates the portals
// PLACES PORTAL
else if((i == 4 && j == 4) || (i == 8 && j == 8))
{
Tile* portalOne;
......@@ -105,7 +123,7 @@ void Level::setStructure() {
}
}
else //fills field with floor
else //PLACES FLOOR
{
Tile* floorPointer= new Floor(stfloor, nullptr,pos);
mLevel.at(i).push_back(floorPointer);
......@@ -113,11 +131,16 @@ void Level::setStructure() {
}
}
connectObserver(doorPointer,switchPointer);
}
void Level::connectObserver(Door *observer, Switch *subject)
{
subject->registerOberserver(observer);
}
......@@ -2,13 +2,17 @@
#define LEVEL_H
#include <vector>
#include "typeinfo"
#include "tile.h"
#include "portal.h"
#include "wall.h"
#include "floor.h"
#include "switch.h"
#include "door.h"
#include "position2d.h"
class Level {
//MEMBER VARIABLES
private:
const int mwidth;
......@@ -16,27 +20,28 @@ private:
Character* mcharacter;
std::vector<std::vector<Tile*>>mLevel;
//SET STRUCTURE OF LEVEL
void setStructure();
void connectObserver(Door* observer, Switch* subject);
//CONSTRUCTOR
//CONSTRUCTOR AND DESTRUCTOR
public:
~Level();
explicit Level(int height,int width);
~Level();
//GETTER AND SETTER
public:
[[nodiscard]] int getHeight() const;
[[nodiscard]] int getWidth() const;
int getHeight() const;
int getWidth() const;
Tile* getTileAtPos(Position2D position);
const Tile* constGetTileAtPos(Position2D position);
Character *getCharacter() const;
void placeCharacter(Character* character, Position2D position);
const std::vector<std::vector<Tile *>> &getMLevel() const;
void placeCharacter(Character* character, Position2D position);
};
#endif // LEVEL_H
#include "observerpassive.h"
ObserverPassive::ObserverPassive()
{
}
#ifndef OBSERVERPASSIVE_H
#define OBSERVERPASSIVE_H
class ObserverPassive
{
public:
ObserverPassive();
virtual void update() = 0 ;
};
#endif // OBSERVERPASSIVE_H
#include "subjectactiv.h"
SubjectActiv::SubjectActiv()
{
}
#ifndef SUBJECTACTIV_H
#define SUBJECTACTIV_H
#include "observerpassive.h"
#include <vector>
class SubjectActiv
{
public:
SubjectActiv();
virtual void registerOberserver(ObserverPassive* observer)= 0;
virtual void removeObserver(ObserverPassive* observer) = 0 ;
virtual void notify() = 0;
protected:
std::vector<ObserverPassive*> observers;
};
#endif // SUBJECTACTIV_H
#include "switch.h"
#include <algorithm>
Switch::Switch(const std::string &texture, Character *currentCharacter, const Position2D &position)
: Tile(texture, currentCharacter, position)
{}
void Switch::registerOberserver(ObserverPassive *observer)
{
observers.push_back(observer);
}
void Switch::removeObserver(ObserverPassive *observer)
{
observers.erase(std::remove(observers.begin(),observers.end(), observer),observers.end());
}
void Switch::notify()
{
for(auto observer : observers)
{
observer->update();
}
}
Tile *Switch::onEnter(Tile *fromTile, Character *who)
{
return this;
}
bool Switch::moveTo(Tile *destTile, Character *who)
{
if(!destTile->hasCharacter()){
destTile->setCurrentCharacter(this->currentCharacter);
currentCharacter->setCurrentTile(destTile);
this->setCurrentCharacter(nullptr);
return true;
};
return false;
}
Tile *Switch::onLeave(Tile *destTile, Character *who)
{
}
#ifndef SWITCH_H
#define SWITCH_H
#include "tile.h"
#include "subjectactiv.h"
class Switch : public Tile, public SubjectActiv
{
public:
Switch(const std::string &texture, Character *currentCharacter, const Position2D &position);
// SubjectActiv interface
public:
void registerOberserver(ObserverPassive *observer) override;
void removeObserver(ObserverPassive *observer) override;
void notify() override;
// Tile interface
public:
Tile *onEnter(Tile *fromTile, Character *who) override;
bool moveTo(Tile *destTile, Character *who) override;
Tile *onLeave(Tile *destTile, Character *who) override;
};
#endif // SWITCH_H
......@@ -21,6 +21,13 @@ void TerminalUI::draw(Level *pLevel) {
if(item->hasCharacter()) std::cout << "X";
else if(typeid(*item) == typeid(Floor)) std::cout << "." ;
else if(typeid(*item) == typeid(Portal))std::cout<< "O";
else if(typeid(*item) == typeid(Switch))std::cout <<"?";
else if(typeid(*item) == typeid(Door)){
Door* doorPointer = dynamic_cast<Door*>(item);
bool isCLosed = doorPointer->getIsClosed();
isCLosed ? std::cout << "|" : std::cout << "/";
}
else std::cout << "#"; //respresent wall
}
std::cout << std::endl;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment