From 51eef56a820929d6411a05dad8abc82e818b9f43 Mon Sep 17 00:00:00 2001 From: Insineer Date: Wed, 9 Oct 2019 03:08:57 +0300 Subject: [PATCH] feat(solidity): add solidity rotating with direction changes Make direction and solidity fields auto synchronizable fix #21 --- GameLogic/Engine/Geometry.py | 12 ++++++--- GameLogic/Objects/Turfs/Airlock.py | 15 ++++++----- GameLogic/Objects/Turfs/Wall.py | 4 +-- GameLogic/Objects/Turfs/Window.py | 4 +-- .../Sources/Graphics/TileGrid/Object.cpp | 16 ++++++------ .../Sources/Graphics/TileGrid/Object.hpp | 2 -- .../Sources/Graphics/TileGrid/Tile.cpp | 2 +- .../Sources/Graphics/TileGrid/TileGrid.cpp | 8 ------ .../Sources/Graphics/TileGrid/TileGrid.hpp | 1 - .../Sources/Network/SyncCommandsProcessor.cpp | 2 -- OSS13 Server/Sources/World/Objects/Object.cpp | 13 ++-------- OSS13 Server/Sources/World/Objects/Object.hpp | 4 +-- OSS13 Server/Sources/World/Tile.cpp | 4 +-- .../Sources/Shared/Geometry/DirectionSet.cpp | 25 +++++++++++++++++++ .../Sources/Shared/Geometry/DirectionSet.h | 12 ++++----- .../Sources/Shared/Network/ISerializable.cpp | 1 - .../Network/Protocol/ServerToClient/Diff.h | 8 ------ .../Sources/Shared/Network/Syncable.h | 2 ++ .../Network/Syncable/ObjectSyncFields.h | 7 +++++- 19 files changed, 74 insertions(+), 68 deletions(-) diff --git a/GameLogic/Engine/Geometry.py b/GameLogic/Engine/Geometry.py index f266377..c8628a1 100644 --- a/GameLogic/Engine/Geometry.py +++ b/GameLogic/Engine/Geometry.py @@ -280,7 +280,7 @@ def NextDirection(dir: Direction) -> Direction: raise TypeError("Bad direction type!") -class DirectionSet(eDirectionSet): +class DirectionSet(): """ A class used to represent a set of directions. You can add directions and check which are already added. Any composite direction will be broken to its components. @@ -304,8 +304,14 @@ class DirectionSet(eDirectionSet): """ - def __init__(self, impl = eDirectionSet()): - self._impl = impl + def __init__(self, *args): + if len(args) > 0 and isinstance(args[0], eDirectionSet): + self._impl = args[0] + else: + self._impl = eDirectionSet() + + if len(args) > 0 and isinstance(args[0], list): + self.Add(args[0]) def Add(self, directions: List[Direction]): self._impl.Add(directions) diff --git a/GameLogic/Objects/Turfs/Airlock.py b/GameLogic/Objects/Turfs/Airlock.py index 21d2d99..ccc3e58 100644 --- a/GameLogic/Objects/Turfs/Airlock.py +++ b/GameLogic/Objects/Turfs/Airlock.py @@ -1,4 +1,4 @@ -from Engine.Geometry import Direction +from Engine.Geometry import Direction, DirectionSet from Objects.Turf import Turf class Airlock(Turf): @@ -7,12 +7,15 @@ class Airlock(Turf): def __init__(self): super().__init__() - self.__closedSolidity = [Direction.CENTER] - self.solidity.Add(self.__closedSolidity) + self.__closedSolidity = DirectionSet() + self.__closedSolidity.Add([Direction.CENTER]) + + self.solidity = self.__closedSolidity + self.opened = False self.locked = False - + def InteractedBy(self, object): if not self.IsCloseTo(object): return False @@ -30,7 +33,7 @@ def Activate(self): return self.sprite = "airlock" self.opened = False - self.solidity.Add(self.__closedSolidity) + self.solidity = self.__closedSolidity else: if not self.PlayAnimation("airlock_opening", lambda: self.__animationOpeningCallback()): return @@ -44,7 +47,7 @@ def Unlock(self): def __animationOpeningCallback(self): self.opened = True - self.solidity.Reset() + self.solidity = DirectionSet() def __autocloseCallback(self): if self.opened: diff --git a/GameLogic/Objects/Turfs/Wall.py b/GameLogic/Objects/Turfs/Wall.py index 97737f4..9a9c3fd 100644 --- a/GameLogic/Objects/Turfs/Wall.py +++ b/GameLogic/Objects/Turfs/Wall.py @@ -1,4 +1,4 @@ -from Engine.Geometry import Direction +from Engine.Geometry import Direction, DirectionSet from Objects.Turf import Turf class Wall(Turf): @@ -8,4 +8,4 @@ class Wall(Turf): def __init__(self): super().__init__() self.isWall = True - self.solidity.Add([Direction.CENTER]) + self.solidity = DirectionSet([Direction.CENTER]) diff --git a/GameLogic/Objects/Turfs/Window.py b/GameLogic/Objects/Turfs/Window.py index 5f4972c..79a6bc7 100644 --- a/GameLogic/Objects/Turfs/Window.py +++ b/GameLogic/Objects/Turfs/Window.py @@ -1,4 +1,4 @@ -from Engine.Geometry import Direction +from Engine.Geometry import Direction, DirectionSet from Engine.World import Object from Objects.Turf import Turf @@ -11,4 +11,4 @@ class Window(Turf): def __init__(self): super().__init__() self.layer = 80 - self.solidity.Add([Direction.SOUTH]) + self.solidity = DirectionSet([Direction.SOUTH]) diff --git a/OSS13 Client/Sources/Graphics/TileGrid/Object.cpp b/OSS13 Client/Sources/Graphics/TileGrid/Object.cpp index c8e7e4b..670f0d8 100644 --- a/OSS13 Client/Sources/Graphics/TileGrid/Object.cpp +++ b/OSS13 Client/Sources/Graphics/TileGrid/Object.cpp @@ -19,9 +19,7 @@ Object::Object(network::protocol::ObjectInfo &&objectInfo) { id = objectInfo.id; layer = objectInfo.layer; - direction = objectInfo.direction; density = objectInfo.density; - solidity = objectInfo.solidity; opacity = objectInfo.opacity; moveSpeed = objectInfo.moveSpeed; speed = objectInfo.speed; @@ -49,6 +47,13 @@ void Object::Draw(sf::RenderTarget *target, uf::vec2i pos) { } void Object::Update(sf::Time timeElapsed) { + if (direction.PopChangedState()) { + for (auto &sprite : sprites) { + if (sprite.IsValid()) sprite.SetDirection(direction); + } + if (animation.IsValid()) animation.SetDirection(direction); + } + // Movement uf::vec2f deltaShift = uf::phys::countDeltaShift(timeElapsed, shift, moveSpeed, moveIntent, speed); @@ -95,13 +100,8 @@ void Object::PlayAnimation(uint id) { void Object::SetDirection(const uf::Direction newdirection) { if (newdirection == uf::Direction::NONE) return; - - // cut the diagonal directions + // cut the diagonal directions direction = uf::Direction(char(newdirection) % 4); - for (auto &sprite : sprites) { - if (sprite.IsValid()) sprite.SetDirection(direction); - } - if (animation.IsValid()) animation.SetDirection(direction); } void Object::SetMoveSpeed(float moveSpeed) { diff --git a/OSS13 Client/Sources/Graphics/TileGrid/Object.hpp b/OSS13 Client/Sources/Graphics/TileGrid/Object.hpp index 0837f01..df4c051 100644 --- a/OSS13 Client/Sources/Graphics/TileGrid/Object.hpp +++ b/OSS13 Client/Sources/Graphics/TileGrid/Object.hpp @@ -66,11 +66,9 @@ class Object : public network::sync::ObjectSyncFields { std::vector<::Sprite> sprites; ::Sprite animation; bool animationProcess{}; - uf::Direction direction{uf::Direction::NONE}; uint layer{}; bool density{}; - uf::DirectionSet solidity; uf::DirectionSetFractional opacity; uf::vec2f shift; diff --git a/OSS13 Client/Sources/Graphics/TileGrid/Tile.cpp b/OSS13 Client/Sources/Graphics/TileGrid/Tile.cpp index 8cedeff..77c0d33 100644 --- a/OSS13 Client/Sources/Graphics/TileGrid/Tile.cpp +++ b/OSS13 Client/Sources/Graphics/TileGrid/Tile.cpp @@ -126,6 +126,6 @@ bool Tile::IsBlocked() const { bool Tile::IsBlocked(uf::DirectionSet directions) const { for (auto &obj : content) - if (obj->GetSolidity().DoesExistOne(directions)) return true; + if (obj->GetSolidity().Rotate(obj->GetDirection()).DoesExistOne(directions)) return true; return false; } diff --git a/OSS13 Client/Sources/Graphics/TileGrid/TileGrid.cpp b/OSS13 Client/Sources/Graphics/TileGrid/TileGrid.cpp index ff69596..1a3b64d 100644 --- a/OSS13 Client/Sources/Graphics/TileGrid/TileGrid.cpp +++ b/OSS13 Client/Sources/Graphics/TileGrid/TileGrid.cpp @@ -443,14 +443,6 @@ void TileGrid::PlayAnimation(uint id, uint animation_id) { } } -void TileGrid::ChangeObjectDirection(uint id, uf::Direction direction) { - auto iter = objects.find(id); - if (iter != objects.end()) { - Object *obj = iter->second.get(); - obj->SetDirection(direction); - } -} - void TileGrid::Stunned(uint id, sf::Time duration) { if (id == controllable->GetID()) stun = duration; diff --git a/OSS13 Client/Sources/Graphics/TileGrid/TileGrid.hpp b/OSS13 Client/Sources/Graphics/TileGrid/TileGrid.hpp index e8c2e17..0117fe4 100644 --- a/OSS13 Client/Sources/Graphics/TileGrid/TileGrid.hpp +++ b/OSS13 Client/Sources/Graphics/TileGrid/TileGrid.hpp @@ -47,7 +47,6 @@ class TileGrid : public Container { void MoveObject(uint id, uf::Direction direction, float speed); void UpdateObjectIcons(uint id, const std::vector &icons); void PlayAnimation(uint id, uint animation_id); - void ChangeObjectDirection(uint id, uf::Direction direction); void Stunned(uint id, sf::Time duration); void ShiftBlocks(apos newFirst); diff --git a/OSS13 Client/Sources/Network/SyncCommandsProcessor.cpp b/OSS13 Client/Sources/Network/SyncCommandsProcessor.cpp index 710ba92..c63ccaf 100644 --- a/OSS13 Client/Sources/Network/SyncCommandsProcessor.cpp +++ b/OSS13 Client/Sources/Network/SyncCommandsProcessor.cpp @@ -91,8 +91,6 @@ void SyncCommandsProcessor::commandProcessor_GraphicsUpdateCommand(network::prot tileGrid->UpdateObjectIcons(diff->objId, diff->iconsIds); } else if (auto *diff = dynamic_cast(generalDiff.get())) { tileGrid->PlayAnimation(diff->objId, diff->animationId); - } else if (auto *diff = dynamic_cast(generalDiff.get())) { - tileGrid->ChangeObjectDirection(diff->objId, diff->direction); } else if (auto *diff = dynamic_cast(generalDiff.get())) { tileGrid->Stunned(diff->objId, sf::microseconds(diff->duration.count())); }; diff --git a/OSS13 Server/Sources/World/Objects/Object.cpp b/OSS13 Server/Sources/World/Objects/Object.cpp index e050066..3497c2e 100644 --- a/OSS13 Server/Sources/World/Objects/Object.cpp +++ b/OSS13 Server/Sources/World/Objects/Object.cpp @@ -16,8 +16,7 @@ Object::Object() : movable(true), spriteState(Global::ItemSpriteState::DEFAULT), - layer(0), - direction(uf::Direction::NONE), + layer(0), tile(nullptr), holder(nullptr), moveSpeed(0) @@ -201,12 +200,6 @@ void Object::SetDirection(uf::Direction direction) { if (direction > uf::Direction::EAST) direction = uf::Direction(char(direction) % 4); this->direction = direction; - if (tile) { - auto changeDirectionDiff = std::make_shared(); - changeDirectionDiff->objId = ID(); - changeDirectionDiff->direction = direction; - tile->AddDiff(std::move(changeDirectionDiff), this); - } } uf::Direction Object::GetDirection() { return direction; } @@ -234,7 +227,7 @@ bool Object::GetDensity() const { return density; } void Object::SetDensity(bool density) { this->density = density; } void Object::SetSolidity(uf::DirectionSet directions) { solidity = directions; } -const uf::DirectionSet &Object::GetSolidity() const { return solidity; } +uf::DirectionSet Object::GetSolidity() const { return solidity; } void Object::SetOpacity(uf::DirectionSetFractional fractionalDirections) { opacity = fractionalDirections; } const uf::DirectionSetFractional &Object::GetOpacity() const { return opacity; } @@ -329,9 +322,7 @@ network::protocol::ObjectInfo Object::GetObjectInfo() const { objectInfo.id = id; objectInfo.fields = *this; objectInfo.layer = layer; - objectInfo.direction = direction; objectInfo.density = density; - objectInfo.solidity = solidity; objectInfo.opacity = opacity; objectInfo.moveSpeed = moveSpeed; objectInfo.speed = speed; diff --git a/OSS13 Server/Sources/World/Objects/Object.hpp b/OSS13 Server/Sources/World/Objects/Object.hpp index 171d6a5..9babccc 100644 --- a/OSS13 Server/Sources/World/Objects/Object.hpp +++ b/OSS13 Server/Sources/World/Objects/Object.hpp @@ -69,7 +69,7 @@ class Object : public network::sync::ObjectSyncFields, public VerbsHolder, publi bool GetDensity() const; void SetSolidity(uf::DirectionSet directions); - const uf::DirectionSet &GetSolidity() const; + uf::DirectionSet GetSolidity() const; void SetOpacity(uf::DirectionSetFractional fractionalDirections); const uf::DirectionSetFractional &GetOpacity() const; @@ -135,10 +135,8 @@ class Object : public network::sync::ObjectSyncFields, public VerbsHolder, publi uf::Timer animationTimer; // Object layer 0-100. The smaller layer is lower. uint layer; - uf::Direction direction; bool density{false}; // object can't pass through solid objects - uf::DirectionSet solidity; uf::DirectionSetFractional opacity; uf::DirectionSetFractional airtightness; diff --git a/OSS13 Server/Sources/World/Tile.cpp b/OSS13 Server/Sources/World/Tile.cpp index 6c2a54c..b9138d8 100644 --- a/OSS13 Server/Sources/World/Tile.cpp +++ b/OSS13 Server/Sources/World/Tile.cpp @@ -219,7 +219,7 @@ const std::list &Tile::Content() const { Object *Tile::GetDenseObject(uf::DirectionSet directions) const { for (auto &obj : content) - if (obj->GetSolidity().DoesExistOne(directions)) return obj; + if (obj->GetSolidity().Rotate(obj->GetDirection()).DoesExistOne(directions)) return obj; return nullptr; } @@ -231,7 +231,7 @@ Map *Tile::GetMap() const { return map; } bool Tile::IsDense(uf::DirectionSet directions) const { for (auto &obj : content) - if (obj->GetSolidity().DoesExistOne(directions)) return true; + if (obj->GetSolidity().Rotate(obj->GetDirection()).DoesExistOne(directions)) return true; return false; } diff --git a/SharedLibrary/Sources/Shared/Geometry/DirectionSet.cpp b/SharedLibrary/Sources/Shared/Geometry/DirectionSet.cpp index 96c69e0..d8358da 100644 --- a/SharedLibrary/Sources/Shared/Geometry/DirectionSet.cpp +++ b/SharedLibrary/Sources/Shared/Geometry/DirectionSet.cpp @@ -55,6 +55,31 @@ bool DirectionSet::DoExistAll(const std::list &directions) const { return DoExistAll(DirectionSet(directions)); } +DirectionSet DirectionSet::Rotate(Direction direction) const { + size_t shift; + switch (direction) { + case Direction::WEST: + shift = 1; + break; + case Direction::NORTH: + shift = 2; + break; + case Direction::EAST: + shift = 3; + break; + default: + return *this; + } + + DirectionSet result; + + for (size_t i = 0; i < 3; i++) + result.buffer[(i + shift) % 4] = buffer[i]; + result.buffer[4] = buffer[4]; + + return result; +} + void DirectionSet::Reset() { buffer.reset(); } diff --git a/SharedLibrary/Sources/Shared/Geometry/DirectionSet.h b/SharedLibrary/Sources/Shared/Geometry/DirectionSet.h index 9a79a3c..85793a7 100644 --- a/SharedLibrary/Sources/Shared/Geometry/DirectionSet.h +++ b/SharedLibrary/Sources/Shared/Geometry/DirectionSet.h @@ -6,20 +6,16 @@ #include #include +#include #include namespace uf { -class DirectionSet { +class DirectionSet : public ICopyable { public: - DirectionSet() = default; + DirectionSet() { }; DirectionSet(std::list directions); - DirectionSet(const DirectionSet &) = default; - DirectionSet(DirectionSet &&) = default; - DirectionSet &operator=(const DirectionSet &) = default; - DirectionSet &operator=(DirectionSet &&) = default; - void Add(DirectionSet directions); void Add(const std::list &directions); @@ -32,6 +28,8 @@ class DirectionSet { bool DoExistAll(DirectionSet directions) const; bool DoExistAll(const std::list &directions) const; + DirectionSet Rotate(Direction direction) const; + void Reset(); const std::bitset<5> &GetBuffer() const; diff --git a/SharedLibrary/Sources/Shared/Network/ISerializable.cpp b/SharedLibrary/Sources/Shared/Network/ISerializable.cpp index fe90167..957a2d2 100644 --- a/SharedLibrary/Sources/Shared/Network/ISerializable.cpp +++ b/SharedLibrary/Sources/Shared/Network/ISerializable.cpp @@ -81,7 +81,6 @@ std::unique_ptr CreateSerializableById(uint32_t id) { DECLARE_SER(MoveDiff) DECLARE_SER(UpdateIconsDiff) DECLARE_SER(PlayAnimationDiff) - DECLARE_SER(ChangeDirectionDiff) DECLARE_SER(StunnedDiff) } diff --git a/SharedLibrary/Sources/Shared/Network/Protocol/ServerToClient/Diff.h b/SharedLibrary/Sources/Shared/Network/Protocol/ServerToClient/Diff.h index 97bc679..096654f 100644 --- a/SharedLibrary/Sources/Shared/Network/Protocol/ServerToClient/Diff.h +++ b/SharedLibrary/Sources/Shared/Network/Protocol/ServerToClient/Diff.h @@ -97,14 +97,6 @@ DEFINE_SERIALIZABLE(PlayAnimationDiff, Diff) } DEFINE_SERIALIZABLE_END -DEFINE_SERIALIZABLE(ChangeDirectionDiff, Diff) - uf::Direction direction; - void Serialize(uf::Archive &ar) override { - Diff::Serialize(ar); - ar & direction; - } -DEFINE_SERIALIZABLE_END - DEFINE_SERIALIZABLE(StunnedDiff, Diff) std::chrono::microseconds duration; void Serialize(uf::Archive &ar) override { diff --git a/SharedLibrary/Sources/Shared/Network/Syncable.h b/SharedLibrary/Sources/Shared/Network/Syncable.h index 2886d7d..88960fd 100644 --- a/SharedLibrary/Sources/Shared/Network/Syncable.h +++ b/SharedLibrary/Sources/Shared/Network/Syncable.h @@ -29,6 +29,8 @@ DEFINE_SERIALIZABLE(GeneralSyncField, uf::ISerializable) GeneralSyncField(GeneralSyncField &&other) : changed(std::move(other.changed)) { } GeneralSyncField &operator=(GeneralSyncField &&other) { this->changed = std::move(other.changed); return *this; } + bool PopChangedState() { bool temp = changed; changed = false; return temp; } + protected: void setChanged(); diff --git a/SharedLibrary/Sources/Shared/Network/Syncable/ObjectSyncFields.h b/SharedLibrary/Sources/Shared/Network/Syncable/ObjectSyncFields.h index 1e818e6..8eef83b 100644 --- a/SharedLibrary/Sources/Shared/Network/Syncable/ObjectSyncFields.h +++ b/SharedLibrary/Sources/Shared/Network/Syncable/ObjectSyncFields.h @@ -2,6 +2,7 @@ #include #include +#include namespace network { namespace sync { @@ -9,10 +10,14 @@ namespace sync { DEFINE_SYNCABLE(ObjectSyncFields) protected: uf::SyncField name; + uf::SyncField direction; + uf::SyncField solidity; public: ObjectSyncFields() { - DECLARE_SYNCABLE_FIELD(&ObjectSyncFields::name); + DECLARE_SYNCABLE_FIELD(&ObjectSyncFields::name); + DECLARE_SYNCABLE_FIELD(&ObjectSyncFields::direction); + DECLARE_SYNCABLE_FIELD(&ObjectSyncFields::solidity); }; DEFINE_SYNCABLE_END