diff --git a/Samples/SM_BasePillar.obj b/Samples/SM_BasePillar.obj new file mode 100644 index 0000000..767104c --- /dev/null +++ b/Samples/SM_BasePillar.obj @@ -0,0 +1,26 @@ +# Exported from 3D Builder +mtllib Base.mtl + +o Object.1 +v -0.25 4.000000 -0.25 +v -0.25 4.000000 0.25 +v 0.25 4.000000 -0.25 +v 0.25 4.000000 0.25 +v -0.25 0.000000 -0.25 +v -0.25 0.000000 0.25 +v 0.25 0.000000 -0.25 +v 0.25 0.000000 0.25 + +usemtl Green_0 +f 1 2 3 +f 3 2 4 +f 2 6 4 +f 4 6 8 +f 4 8 3 +f 3 8 7 +f 2 5 6 +f 2 1 5 +f 1 3 5 +f 5 3 7 +f 5 7 8 +f 5 8 6 \ No newline at end of file diff --git a/Source/DungeonGenerator/Private/Core/DrawLots.h b/Source/DungeonGenerator/Private/Core/DrawLots.h index 1bc8336..b96f8f5 100644 --- a/Source/DungeonGenerator/Private/Core/DrawLots.h +++ b/Source/DungeonGenerator/Private/Core/DrawLots.h @@ -36,19 +36,19 @@ namespace dungeon auto weight = pred(*i); if (weight < 1) weight = 1; - weights.emplace_back(weight, i); - totalWeight += weight; + const auto currentWeight = totalWeight + weight; + weights.emplace_back(currentWeight, i); + totalWeight = currentWeight; } // TODO: specify random numbers externally. - std::size_t rnd = random() % totalWeight; + const std::size_t rnd = random() % totalWeight; for (const auto& weight : weights) { + // cppcheck-suppress [useStlAlgorithm] if (rnd < weight.mWeight) return weight.mBody; - - rnd -= weight.mWeight; } return last; diff --git a/Source/DungeonGenerator/Private/Core/Generator.cpp b/Source/DungeonGenerator/Private/Core/Generator.cpp index ec4d1ce..9c5216e 100644 --- a/Source/DungeonGenerator/Private/Core/Generator.cpp +++ b/Source/DungeonGenerator/Private/Core/Generator.cpp @@ -1065,17 +1065,7 @@ namespace dungeon continue; generatedEdges.emplace(&aisle); - if (room != room0) - { - // TODO::判定関数を作成して下さい - if (room0->GetItem() == Room::Item::Empty && - room0->GetParts() != Room::Parts::Unidentified && - room0->GetParts() != Room::Parts::Start && - room0->GetParts() != Room::Parts::Goal) - result.push_back(room0); - FindByRoute(result, generatedEdges, room0); - } - else + if (room == room0) { // TODO::判定関数を作成して下さい if (room1->GetItem() == Room::Item::Empty && @@ -1085,6 +1075,16 @@ namespace dungeon result.push_back(room1); FindByRoute(result, generatedEdges, room1); } + else + { + // TODO::判定関数を作成して下さい + if (room0->GetItem() == Room::Item::Empty && + room0->GetParts() != Room::Parts::Unidentified && + room0->GetParts() != Room::Parts::Start && + room0->GetParts() != Room::Parts::Goal) + result.push_back(room0); + FindByRoute(result, generatedEdges, room0); + } } } } diff --git a/Source/DungeonGenerator/Private/Core/MinimumSpanningTree.cpp b/Source/DungeonGenerator/Private/Core/MinimumSpanningTree.cpp index fd6fa8c..38d85ee 100644 --- a/Source/DungeonGenerator/Private/Core/MinimumSpanningTree.cpp +++ b/Source/DungeonGenerator/Private/Core/MinimumSpanningTree.cpp @@ -230,7 +230,7 @@ namespace dungeon mStartPoint = FindStartPoint(); size_t startPointIndex = verteces.Find(mStartPoint); - // cppcheck-suppress [knownConditionTrueFalse] + // cppcheck-suppress [knownConditionTrueFalse, unmatchedSuppression] if (startPointIndex != static_cast(~0)) { // スタートから各部屋の深さ(部屋の数)を設定 diff --git a/Source/DungeonGenerator/Private/Core/MissionGraph/MissionGraph.cpp b/Source/DungeonGenerator/Private/Core/MissionGraph/MissionGraph.cpp index 5d2ef37..f10a590 100644 --- a/Source/DungeonGenerator/Private/Core/MissionGraph/MissionGraph.cpp +++ b/Source/DungeonGenerator/Private/Core/MissionGraph/MissionGraph.cpp @@ -1,13 +1,21 @@ /* MissionGraph +Generate dungeon strategy information ダンジョンの攻略情報を生成します +Algorithm for generating keys and doors +1. set a goal door in the passage connecting to the goal room +2. collect reachable aisle and rooms separated by doors +3. place a key (or goal key) somewhere in the reachable room +4. place a door somewhere in the reachable aisle +5. if more keys and doors can be placed, go back to 2. + 鍵と扉の生成アルゴリズム -1. ゴール部屋に接続する通路にゴール鍵を設定する -2. 通路に到達可能な部屋のどこかにゴール鍵を置く(別ブランチは抽選の優先度を上げる) -3. ゴール部屋よりも浅い深度の通路に鍵を設定する -4. 通路に到達可能な部屋のどこかに鍵を置く(別ブランチは抽選の優先度を上げる) -5. 深度1より探索深度が不快なら3に戻る +1. ゴール部屋に接続する通路にゴール扉を設定する +2. 扉で仕切られた到達可能な部屋と通路を集める +3. 到達可能な部屋のどこかに鍵(またはゴール鍵)を置く +4. 到達可能な通路のどこかに扉を置く +5. さらに鍵と扉が置けるなら2へ戻る 敵配置の生成アルゴリズム @@ -28,13 +36,60 @@ namespace dungeon MissionGraph::MissionGraph(const std::shared_ptr& generator, const std::shared_ptr& goal) noexcept : mGenerator(generator) { - Generate(goal->GetOwnerRoom()); + const auto room = goal->GetOwnerRoom(); + + // Choose an aisle close to the entrance + if (Aisle* aisle = SelectAisle(room)) + { + // Locked. (to limit FindByRoute search scope) + aisle->SetUniqueLock(true); + + const auto& room0 = aisle->GetPoint(0)->GetOwnerRoom(); + const auto& room1 = aisle->GetPoint(1)->GetOwnerRoom(); + const auto& connectingRoom = room == room0 ? room1 : room0; + + // Gathering reachable rooms + std::vector> keyRooms; + keyRooms = mGenerator->FindByRoute(connectingRoom); + if (keyRooms.size() > 0) + { + // TODO:DrawLots内で乱数を使っています + const uint8_t roomBranch = room->GetBranchId(); + const auto keyRoom = DrawLots(keyRooms.begin(), keyRooms.end(), [roomBranch](const std::shared_ptr& room) + { + uint32_t weight = room->GetDepthFromStart(); + if (room->GetBranchId() - roomBranch) + weight *= 3; + if (room->GetParts() == Room::Parts::Hanare) + weight *= 3; + return weight; + } + ); + if (keyRoom != keyRooms.end()) + { + check((*keyRoom)->GetItem() == Room::Item::Empty); + (*keyRoom)->SetItem(Room::Item::UniqueKey); + + Generate(connectingRoom); + } + else + { + // It did not decide on a room to put the key, so it will be unlocked + aisle->SetUniqueLock(false); + } + } + else + { + // It did not decide on a room to put the key, so it will be unlocked + aisle->SetUniqueLock(false); + } + } } /* TODO:乱数を共通化して下さい */ - void MissionGraph::Generate(const std::shared_ptr& room, const uint8_t count) noexcept + void MissionGraph::Generate(const std::shared_ptr& room) noexcept { #if 0 { @@ -42,65 +97,88 @@ namespace dungeon mGenerator->DumpAisle(TCHAR_TO_UTF8(*path)); } #endif - + // Choose an aisle close to the entrance if (Aisle* aisle = SelectAisle(room)) { - if (count == 0) - aisle->SetUniqueLock(true); - else - aisle->SetLock(true); + // Locked. (to limit FindByRoute search scope) + aisle->SetLock(true); - const size_t halfRoomCount = mGenerator->GetRoomCount() / 2; - const uint8_t roomBranch = room->GetBranchId(); - const uint8_t roomDepth = room->GetDepthFromStart(); const auto& room0 = aisle->GetPoint(0)->GetOwnerRoom(); const auto& room1 = aisle->GetPoint(1)->GetOwnerRoom(); + // Gathering reachable rooms std::vector> keyRooms; keyRooms = mGenerator->FindByRoute(room == room0 ? room1 : room0); if (keyRooms.size() > 0) { +#if 0 // TODO:DrawLots内で乱数を使っています - const auto keyRoom = DrawLots(keyRooms.begin(), keyRooms.end(), [halfRoomCount, roomBranch, roomDepth](const std::shared_ptr& room) + const uint8_t roomBranch = room->GetBranchId(); + const auto keyRoom = DrawLots(keyRooms.begin(), keyRooms.end(), [roomBranch](const std::shared_ptr& room) { - const auto deltaBranch = std::abs(roomBranch - room->GetBranchId()); - const auto addition = room->GetParts() == Room::Parts::Hanare ? halfRoomCount : 0; - return deltaBranch + room->GetDepthFromStart() + addition; + const uint32_t deltaBranch = std::abs(roomBranch - room->GetBranchId()); + const uint32_t depthFromStart = room->GetDepthFromStart(); + uint32_t weight = deltaBranch + depthFromStart; + //if (room->GetParts() == Room::Parts::Hanare) + // weight *= 2; + return weight; } ); if (keyRoom != keyRooms.end()) { - // 鍵を置く部屋が決まった + // That's the room where I'm supposed to put the key. check((*keyRoom)->GetItem() == Room::Item::Empty); - (*keyRoom)->SetItem(count == 0 ? Room::Item::UniqueKey : Room::Item::Key); + (*keyRoom)->SetItem(Room::Item::Key); +#if 0 + Generate(*keyRoom); +#else + //const auto lockRoom = keyRooms[std::rand() % keyRooms.size()]; + const auto lockRoom = DrawLots(keyRooms.begin(), keyRooms.end(), [](const std::shared_ptr& room) + { + return room->GetDepthFromStart(); + } + ); + Generate(*lockRoom); +#endif } else { - // 鍵を置く部屋が決まらなかった - if (count == 0) - aisle->SetUniqueLock(false); - else - aisle->SetLock(false); + // It did not decide on a room to put the key, so it will be unlocked + aisle->SetLock(false); + } +#else + // That's the room where I'm supposed to put the key. + { + // TODO:共通の乱数を使用してください + const auto keyRoom = keyRooms[std::rand() % keyRooms.size()]; + check(keyRoom->GetItem() == Room::Item::Empty); + keyRoom->SetItem(Room::Item::Key); } - // 次の鍵 - if (roomDepth >= 3) + // TODO:DrawLots内で乱数を使っています + const auto lockRoom = DrawLots(keyRooms.begin(), keyRooms.end(), [](const std::shared_ptr& room) + { + const uint32_t depthFromStart = room->GetDepthFromStart(); + return depthFromStart * 10; + } + ); + if (lockRoom != keyRooms.end()) { - const auto& depths = mGenerator->FindByDepth(roomDepth - 2); - const auto index = std::rand() % depths.size(); - Generate(depths[index], count + 1); + Generate(*lockRoom); } +#endif } else { - if (count == 0) - aisle->SetUniqueLock(false); - else - aisle->SetLock(false); + // It did not decide on a room to put the key, so it will be unlocked + aisle->SetLock(false); } } } + /* + Choose an aisle close to the entrance. + */ Aisle* MissionGraph::SelectAisle(const std::shared_ptr& room) const noexcept { const uint8_t roomDepth = room->GetDepthFromStart(); @@ -112,19 +190,15 @@ namespace dungeon { const auto& room0 = edge.GetPoint(0)->GetOwnerRoom(); const auto& room1 = edge.GetPoint(1)->GetOwnerRoom(); - if (room0->GetDepthFromStart() <= roomDepth || room1->GetDepthFromStart() <= roomDepth) + if (room0->GetDepthFromStart() <= roomDepth && room1->GetDepthFromStart() <= roomDepth) aisles.emplace_back(&edge); } return false; } ); + // TODO:抽選してください const size_t size = aisles.size(); - return size > 0 ? aisles[0 % size] : nullptr; - } - - Aisle* MissionGraph::SelectAisle(const std::shared_ptr& point) const noexcept - { - return SelectAisle(point->GetOwnerRoom()); + return size > 0 ? aisles[0] : nullptr; } } diff --git a/Source/DungeonGenerator/Private/Core/MissionGraph/MissionGraph.h b/Source/DungeonGenerator/Private/Core/MissionGraph/MissionGraph.h index b535c76..8847a6d 100644 --- a/Source/DungeonGenerator/Private/Core/MissionGraph/MissionGraph.h +++ b/Source/DungeonGenerator/Private/Core/MissionGraph/MissionGraph.h @@ -1,17 +1,13 @@ /* MissionGraph -ダンジョンの攻略情報を生成します +Generate dungeon strategy information -鍵と扉の生成アルゴリズム -1. ゴール部屋に接続する通路にゴール鍵を設定する -2. 通路に到達可能な部屋のどこかにゴール鍵を置く(別ブランチは抽選の優先度を上げる) -3. ゴール部屋よりも浅い深度の通路に鍵を設定する -4. 通路に到達可能な部屋のどこかに鍵を置く(別ブランチは抽選の優先度を上げる) -5. 深度1より探索深度が不快なら3に戻る - -敵配置の生成アルゴリズム - -部屋の装飾アルゴリズム +Algorithm for generating keys and doors +1. set a goal door in the passage connecting to the goal room +2. collect reachable aisle and rooms separated by doors +3. place a key (or goal key) somewhere in the reachable room +4. place a door somewhere in the reachable aisle +5. if more keys and doors can be placed, go back to 2. \author Shun Moriya \copyright 2023- Shun Moriya @@ -28,16 +24,24 @@ namespace dungeon class Point; class Room; + /* + Generate dungeon strategy information + */ class MissionGraph { public: + // constructor MissionGraph(const std::shared_ptr& generator, const std::shared_ptr& goal) noexcept; + + // destructor virtual ~MissionGraph() = default; private: - void Generate(const std::shared_ptr& room, const uint8_t count = 0) noexcept; + // generate mission graph + void Generate(const std::shared_ptr& room) noexcept; + + // choose an aisle close to the entrance. Aisle* SelectAisle(const std::shared_ptr& room) const noexcept; - Aisle* SelectAisle(const std::shared_ptr& point) const noexcept; private: std::shared_ptr mGenerator; diff --git a/Source/DungeonGenerator/Private/Core/PathFinder.cpp b/Source/DungeonGenerator/Private/Core/PathFinder.cpp index 9dda8dc..0398b17 100644 --- a/Source/DungeonGenerator/Private/Core/PathFinder.cpp +++ b/Source/DungeonGenerator/Private/Core/PathFinder.cpp @@ -159,7 +159,7 @@ namespace dungeon return false; // 最もコストの低いノードを検索 - std::unordered_map::iterator result; + std::unordered_map::iterator result = mOpen.begin(); uint32_t minimumCost = std::numeric_limits::max(); for (std::unordered_map::iterator i = mOpen.begin(); i != mOpen.end(); ++i) { diff --git a/Source/DungeonGenerator/Private/DungeonDoor.cpp b/Source/DungeonGenerator/Private/DungeonDoor.cpp new file mode 100644 index 0000000..d787029 --- /dev/null +++ b/Source/DungeonGenerator/Private/DungeonDoor.cpp @@ -0,0 +1,46 @@ +/** +\author Shun Moriya +\copyright 2023- Shun Moriya +All Rights Reserved. +*/ + +#include "DungeonDoor.h" + +ADungeonDoor::ADungeonDoor(const FObjectInitializer& initializer) + : Super(initializer) +{ +} + +void ADungeonDoor::Initialize(const EDungeonRoomProps props) +{ + Finalize(); + + Props = props; + OnInitialize(props); + + mState = State::Initialized; +} + +void ADungeonDoor::Finalize() +{ + if (mState == State::Initialized) + { + OnFinalize(); + mState = State::Finalized; + } +} + +void ADungeonDoor::Reset() +{ + OnReset(); +} + +EDungeonRoomProps ADungeonDoor::GetRoomProps() const +{ + return Props; +} + +void ADungeonDoor::SetRoomProps(const EDungeonRoomProps props) +{ + Props = props; +} diff --git a/Source/DungeonGenerator/Private/DungeonGenerateParameter.cpp b/Source/DungeonGenerator/Private/DungeonGenerateParameter.cpp index 2a35f27..c8a7052 100644 --- a/Source/DungeonGenerator/Private/DungeonGenerateParameter.cpp +++ b/Source/DungeonGenerator/Private/DungeonGenerateParameter.cpp @@ -26,29 +26,29 @@ namespace } //////////////////////////////////////////////////////////////////////////////////////////////////// -FTransform FDungeonParts::CalculateWorldTransform(const FTransform& transform) const noexcept +FTransform FDungeonPartsTransform::CalculateWorldTransform(const FTransform& transform) const noexcept { return CalculateWorldTransform_(transform, RelativeTransform); } -FTransform FDungeonParts::CalculateWorldTransform(const FVector& position, const FRotator& rotator) const noexcept +FTransform FDungeonPartsTransform::CalculateWorldTransform(const FVector& position, const FRotator& rotator) const noexcept { const FTransform transform(rotator, position); return CalculateWorldTransform(transform); } -FTransform FDungeonParts::CalculateWorldTransform(const FVector& position, const float yaw) const noexcept +FTransform FDungeonPartsTransform::CalculateWorldTransform(const FVector& position, const float yaw) const noexcept { const FRotator rotator(0, yaw, 0); return CalculateWorldTransform(position, rotator); } -FTransform FDungeonParts::CalculateWorldTransform(const FVector& position, const dungeon::Direction& direction) const noexcept +FTransform FDungeonPartsTransform::CalculateWorldTransform(const FVector& position, const dungeon::Direction& direction) const noexcept { return CalculateWorldTransform(position, direction.ToDegree()); } -FTransform FDungeonParts::CalculateWorldTransform(dungeon::Random& random, const FTransform& transform, const EDungeonPartsPlacementDirection placementDirection) const noexcept +FTransform FDungeonPartsTransform::CalculateWorldTransform(dungeon::Random& random, const FTransform& transform, const EDungeonPartsPlacementDirection placementDirection) const noexcept { if (static_cast(placementDirection) < static_cast(EDungeonPartsPlacementDirection::West)) { @@ -69,77 +69,67 @@ FTransform FDungeonParts::CalculateWorldTransform(dungeon::Random& random, const return CalculateWorldTransform_(transform, RelativeTransform); } - // ここまで来ていたらエラー + // Error if you have come here return transform; } -FTransform FDungeonParts::CalculateWorldTransform(dungeon::Random& random, const FVector& position, const FRotator& rotator, const EDungeonPartsPlacementDirection placementDirection) const noexcept +FTransform FDungeonPartsTransform::CalculateWorldTransform(dungeon::Random& random, const FVector& position, const FRotator& rotator, const EDungeonPartsPlacementDirection placementDirection) const noexcept { const FTransform transform(rotator, position); return CalculateWorldTransform(random, transform, placementDirection); } -FTransform FDungeonParts::CalculateWorldTransform(dungeon::Random& random, const FVector& position, const float yaw, const EDungeonPartsPlacementDirection placementDirection) const noexcept +FTransform FDungeonPartsTransform::CalculateWorldTransform(dungeon::Random& random, const FVector& position, const float yaw, const EDungeonPartsPlacementDirection placementDirection) const noexcept { const FRotator rotator(0, yaw, 0); return CalculateWorldTransform(random, position, rotator, placementDirection); } -FTransform FDungeonParts::CalculateWorldTransform(dungeon::Random& random, const FVector& position, const dungeon::Direction& direction, const EDungeonPartsPlacementDirection placementDirection) const noexcept +FTransform FDungeonPartsTransform::CalculateWorldTransform(dungeon::Random& random, const FVector& position, const dungeon::Direction& direction, const EDungeonPartsPlacementDirection placementDirection) const noexcept { return CalculateWorldTransform(random, position, direction.ToDegree(), placementDirection); } //////////////////////////////////////////////////////////////////////////////////////////////////// -UClass* FDungeonObjectParts::GetActorClass() -{ - if (IsValid(ActorClass) == false && ActorPath.IsValid() == true) - { - ActorClass = TSoftClassPtr(FSoftObjectPath(ActorPath.ToString() + "_C")).LoadSynchronous(); - } - return ActorClass; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -FTransform FDungeonMeshPartsWithDirection::CalculateWorldTransform(dungeon::Random& random, const FTransform& transform) const noexcept +FTransform FDungeonActorPartsWithDirection::CalculateWorldTransform(dungeon::Random& random, const FTransform& transform) const noexcept { - return FDungeonParts::CalculateWorldTransform(random, transform, PlacementDirection); + return FDungeonPartsTransform::CalculateWorldTransform(random, transform, PlacementDirection); } -FTransform FDungeonMeshPartsWithDirection::CalculateWorldTransform(dungeon::Random& random, const FVector& position, const FRotator& rotator) const noexcept +FTransform FDungeonActorPartsWithDirection::CalculateWorldTransform(dungeon::Random& random, const FVector& position, const FRotator& rotator) const noexcept { - return FDungeonParts::CalculateWorldTransform(random, position, rotator, PlacementDirection); + return FDungeonPartsTransform::CalculateWorldTransform(random, position, rotator, PlacementDirection); } -FTransform FDungeonMeshPartsWithDirection::CalculateWorldTransform(dungeon::Random& random, const FVector& position, const float yaw) const noexcept +FTransform FDungeonActorPartsWithDirection::CalculateWorldTransform(dungeon::Random& random, const FVector& position, const float yaw) const noexcept { - return FDungeonParts::CalculateWorldTransform(random, position, yaw, PlacementDirection); + return FDungeonPartsTransform::CalculateWorldTransform(random, position, yaw, PlacementDirection); } -FTransform FDungeonMeshPartsWithDirection::CalculateWorldTransform(dungeon::Random& random, const FVector& position, const dungeon::Direction& direction) const noexcept +FTransform FDungeonActorPartsWithDirection::CalculateWorldTransform(dungeon::Random& random, const FVector& position, const dungeon::Direction& direction) const noexcept { - return FDungeonParts::CalculateWorldTransform(random, position, direction, PlacementDirection); + return FDungeonPartsTransform::CalculateWorldTransform(random, position, direction, PlacementDirection); } //////////////////////////////////////////////////////////////////////////////////////////////////// -FTransform FDungeonActorPartsWithDirection::CalculateWorldTransform(dungeon::Random& random, const FTransform& transform) const noexcept +FTransform FDungeonMeshPartsWithDirection::CalculateWorldTransform(dungeon::Random& random, const FTransform& transform) const noexcept { - return FDungeonParts::CalculateWorldTransform(random, transform, PlacementDirection); + return FDungeonPartsTransform::CalculateWorldTransform(random, transform, PlacementDirection); } -FTransform FDungeonActorPartsWithDirection::CalculateWorldTransform(dungeon::Random& random, const FVector& position, const FRotator& rotator) const noexcept +FTransform FDungeonMeshPartsWithDirection::CalculateWorldTransform(dungeon::Random& random, const FVector& position, const FRotator& rotator) const noexcept { - return FDungeonParts::CalculateWorldTransform(random, position, rotator, PlacementDirection); + return FDungeonPartsTransform::CalculateWorldTransform(random, position, rotator, PlacementDirection); } -FTransform FDungeonActorPartsWithDirection::CalculateWorldTransform(dungeon::Random& random, const FVector& position, const float yaw) const noexcept +FTransform FDungeonMeshPartsWithDirection::CalculateWorldTransform(dungeon::Random& random, const FVector& position, const float yaw) const noexcept { - return FDungeonParts::CalculateWorldTransform(random, position, yaw, PlacementDirection); + return FDungeonPartsTransform::CalculateWorldTransform(random, position, yaw, PlacementDirection); } -FTransform FDungeonActorPartsWithDirection::CalculateWorldTransform(dungeon::Random& random, const FVector& position, const dungeon::Direction& direction) const noexcept +FTransform FDungeonMeshPartsWithDirection::CalculateWorldTransform(dungeon::Random& random, const FVector& position, const dungeon::Direction& direction) const noexcept { - return FDungeonParts::CalculateWorldTransform(random, position, direction, PlacementDirection); + return FDungeonPartsTransform::CalculateWorldTransform(random, position, direction, PlacementDirection); } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -166,28 +156,28 @@ int32 UDungeonGenerateParameter::SelectDungeonMeshPartsIndex(const size_t gridIn } } -// aka: SelectDungeonMeshParts, SelectDungeonRandomObjectParts -FDungeonObjectParts* UDungeonGenerateParameter::SelectDungeonObjectParts(const size_t gridIndex, const dungeon::Grid& grid, dungeon::Random& random, const TArray& parts, const EDungeonPartsSelectionMethod partsSelectionMethod) const +// aka: SelectParts, SelectRandomActorParts +FDungeonActorParts* UDungeonGenerateParameter::SelectActorParts(const size_t gridIndex, const dungeon::Grid& grid, dungeon::Random& random, const TArray& parts, const EDungeonPartsSelectionMethod partsSelectionMethod) const { const int32 size = parts.Num(); if (size <= 0) return nullptr; const int32 index = SelectDungeonMeshPartsIndex(gridIndex, grid, random, size, partsSelectionMethod); - FDungeonObjectParts* actorParts = const_cast(&parts[index]); - return IsValid(actorParts->GetActorClass()) ? actorParts : nullptr; + FDungeonActorParts* actorParts = const_cast(&parts[index]); + return IsValid(actorParts->ActorClass) ? actorParts : nullptr; } -// aka: SelectDungeonMeshParts, SelectDungeonObjectParts -FDungeonRandomObjectParts* UDungeonGenerateParameter::SelectDungeonRandomObjectParts(const size_t gridIndex, const dungeon::Grid& grid, dungeon::Random& random, const TArray& parts, const EDungeonPartsSelectionMethod partsSelectionMethod) const +// aka: SelectParts, SelectActorParts +FDungeonRandomActorParts* UDungeonGenerateParameter::SelectRandomActorParts(const size_t gridIndex, const dungeon::Grid& grid, dungeon::Random& random, const TArray& parts, const EDungeonPartsSelectionMethod partsSelectionMethod) const { const int32 size = parts.Num(); if (size <= 0) return nullptr; const int32 index = SelectDungeonMeshPartsIndex(gridIndex, grid, random, size, partsSelectionMethod); - FDungeonRandomObjectParts* actorParts = const_cast(&parts[index]); - if (!IsValid(actorParts->GetActorClass())) + FDungeonRandomActorParts* actorParts = const_cast(&parts[index]); + if (!IsValid(actorParts->ActorClass)) return nullptr; const float value = random.Get(); @@ -244,79 +234,79 @@ float UDungeonGenerateParameter::GetGridSize() const const FDungeonMeshPartsWithDirection* UDungeonGenerateParameter::SelectFloorParts(const size_t gridIndex, const dungeon::Grid& grid, dungeon::Random& random) const { - return SelectDungeonMeshParts(gridIndex, grid, random, FloorParts, FloorPartsSelectionMethod); + return SelectParts(gridIndex, grid, random, FloorParts, FloorPartsSelectionMethod); } void UDungeonGenerateParameter::EachFloorParts(std::function func) const { - EachMeshParts(FloorParts, func); + EachParts(FloorParts, func); } const FDungeonMeshParts* UDungeonGenerateParameter::SelectSlopeParts(const size_t gridIndex, const dungeon::Grid& grid, dungeon::Random& random) const { - return SelectDungeonMeshParts(gridIndex, grid, random, SlopeParts, SloopPartsSelectionMethod); + return SelectParts(gridIndex, grid, random, SlopeParts, SloopPartsSelectionMethod); } void UDungeonGenerateParameter::EachSlopeParts(std::function func) const { - EachMeshParts(SlopeParts, func); + EachParts(SlopeParts, func); } const FDungeonMeshParts* UDungeonGenerateParameter::SelectWallParts(const size_t gridIndex, const dungeon::Grid& grid, dungeon::Random& random) const { - return SelectDungeonMeshParts(gridIndex, grid, random, WallParts, WallPartsSelectionMethod); + return SelectParts(gridIndex, grid, random, WallParts, WallPartsSelectionMethod); } void UDungeonGenerateParameter::EachWallParts(std::function func) const { - EachMeshParts(WallParts, func); + EachParts(WallParts, func); } const FDungeonMeshPartsWithDirection* UDungeonGenerateParameter::SelectRoomRoofParts(const size_t gridIndex, const dungeon::Grid& grid, dungeon::Random& random) const { - return SelectDungeonMeshParts(gridIndex, grid, random, RoomRoofParts, RoomRoofPartsSelectionMethod); + return SelectParts(gridIndex, grid, random, RoomRoofParts, RoomRoofPartsSelectionMethod); } void UDungeonGenerateParameter::EachRoomRoofParts(std::function func) const { - EachMeshParts(RoomRoofParts, func); + EachParts(RoomRoofParts, func); } const FDungeonMeshPartsWithDirection* UDungeonGenerateParameter::SelectAisleRoofParts(const size_t gridIndex, const dungeon::Grid& grid, dungeon::Random& random) const { - return SelectDungeonMeshParts(gridIndex, grid, random, AisleRoofParts, AisleRoofPartsSelectionMethod); + return SelectParts(gridIndex, grid, random, AisleRoofParts, AisleRoofPartsSelectionMethod); } void UDungeonGenerateParameter::EachAisleRoofParts(std::function func) const { - EachMeshParts(AisleRoofParts, func); + EachParts(AisleRoofParts, func); } const FDungeonMeshParts* UDungeonGenerateParameter::SelectPillarParts(const size_t gridIndex, const dungeon::Grid& grid, dungeon::Random& random) const { - return SelectDungeonMeshParts(gridIndex, grid, random, PillarParts, PillarPartsSelectionMethod); + return SelectParts(gridIndex, grid, random, PillarParts, PillarPartsSelectionMethod); } void UDungeonGenerateParameter::EachPillarParts(std::function func) const { - EachMeshParts(PillarParts, func); + EachParts(PillarParts, func); } -const FDungeonRandomObjectParts* UDungeonGenerateParameter::SelectTorchParts(const size_t gridIndex, const dungeon::Grid& grid, dungeon::Random& random) const +const FDungeonRandomActorParts* UDungeonGenerateParameter::SelectTorchParts(const size_t gridIndex, const dungeon::Grid& grid, dungeon::Random& random) const { - return SelectDungeonRandomObjectParts(gridIndex, grid, random, TorchParts, TorchPartsSelectionMethod); + return SelectRandomActorParts(gridIndex, grid, random, TorchParts, TorchPartsSelectionMethod); } #if 0 -const FDungeonObjectParts* UDungeonGenerateParameter::SelectChandelierParts(const size_t gridIndex, const dungeon::Grid& grid, dungeon::Random& random) const +const FDungeonActorParts* UDungeonGenerateParameter::SelectChandelierParts(const size_t gridIndex, const dungeon::Grid& grid, dungeon::Random& random) const { - return SelectDungeonRandomObjectParts(gridIndex, grid, random, ChandelierParts, ChandelierPartsSelectionMethod); + return SelectRandomActorParts(gridIndex, grid, random, ChandelierParts, ChandelierPartsSelectionMethod); } #endif -const FDungeonObjectParts* UDungeonGenerateParameter::SelectDoorParts(const size_t gridIndex, const dungeon::Grid& grid, dungeon::Random& random) const +const FDungeonDoorActorParts* UDungeonGenerateParameter::SelectDoorParts(const size_t gridIndex, const dungeon::Grid& grid, dungeon::Random& random) const { - return SelectDungeonObjectParts(gridIndex, grid, random, DoorParts, DoorPartsSelectionMethod); + return SelectParts(gridIndex, grid, random, DoorParts, DoorPartsSelectionMethod); } const FDungeonActorPartsWithDirection& UDungeonGenerateParameter::GetStartParts() const @@ -417,9 +407,9 @@ void UDungeonGenerateParameter::DumpToJson() const // TArray RoomRoofParts; // TArray AisleRoofParts; // TArray PillarParts; - // TArray TorchParts; - // TArray ChandelierParts; - // TArray DoorParts; + // TArray TorchParts; + // TArray ChandelierParts; + // TArray DoorParts; // FDungeonActorPartsWithDirection StartParts; // FDungeonActorPartsWithDirection GoalParts; // UClass* DungeonRoomSensorClass = ADungeonRoomSensor::StaticClass(); diff --git a/Source/DungeonGenerator/Private/DungeonGenerator.cpp b/Source/DungeonGenerator/Private/DungeonGenerator.cpp index 2bb3093..a4c30bf 100644 --- a/Source/DungeonGenerator/Private/DungeonGenerator.cpp +++ b/Source/DungeonGenerator/Private/DungeonGenerator.cpp @@ -6,7 +6,7 @@ All Rights Reserved. #include "DungeonGenerator.h" #include "DungeonGenerateParameter.h" -#include "DungeonDoorInterface.h" +#include "DungeonDoor.h" #include "DungeonRoomProps.h" #include "DungeonRoomSensor.h" #include "Core/Debug/Debug.h" @@ -31,7 +31,7 @@ All Rights Reserved. #endif // 定義するとミッショングラフのデバッグファイル(PlantUML)を出力します -//#define DEBUG_GENERATE_MISSION_GRAPH_FILE +#define DEBUG_GENERATE_MISSION_GRAPH_FILE static const FName DungeonGeneratorTag("DungeonGenerator"); @@ -363,7 +363,7 @@ void CDungeonGenerator::AddTerraine() // 水平以外に対応が必要? if (wallCount == 2) { - if (const FDungeonObjectParts* parts = parameter->SelectTorchParts(gridIndex, grid, dungeon::Random::Instance())) + if (const FDungeonActorParts* parts = parameter->SelectTorchParts(gridIndex, grid, dungeon::Random::Instance())) { #if 0 const FTransform worldTransform = transform * parts->RelativeTransform; @@ -383,13 +383,9 @@ void CDungeonGenerator::AddTerraine() } // 扉の生成通知 - if (const FDungeonObjectParts* parts = parameter->SelectDoorParts(gridIndex, grid, dungeon::Random::Instance())) + if (const FDungeonDoorActorParts* parts = parameter->SelectDoorParts(gridIndex, grid, dungeon::Random::Instance())) { const EDungeonRoomProps props = static_cast(grid.GetProps()); - if (grid.GetProps() != dungeon::Grid::Props::None) - { - int i = 0; - } if (grid.CanBuildGate(mGenerator->GetVoxel()->Get(location.X, location.Y - 1, location.Z), dungeon::Direction::North)) { @@ -462,7 +458,7 @@ void CDungeonGenerator::AddTerraine() #if 0 if (mOnResetChandelier) { - if (const FDungeonObjectParts* parts = parameter->SelectChandelierParts(dungeon::Random::Instance())) + if (const FDungeonActorParts* parts = parameter->SelectChandelierParts(dungeon::Random::Instance())) { mOnResetChandelier(parts->ActorClass, worldTransform); } @@ -784,19 +780,16 @@ void CDungeonGenerator::SpawnActorOnFloor(UClass* actorClass, const FTransform& void CDungeonGenerator::SpawnDoorActor(UClass* actorClass, const FTransform& transform, EDungeonRoomProps props) const { - AActor* actor = SpawnActorDeferred(actorClass, TEXT("Dungeon/Actors"), transform, ESpawnActorCollisionHandlingMethod::AlwaysSpawn); + ADungeonDoor* actor = SpawnActorDeferred(actorClass, TEXT("Dungeon/Actors"), transform, ESpawnActorCollisionHandlingMethod::AlwaysSpawn); if (IsValid(actor)) { - // execute OnInitialize interface function - if (actor->GetClass()->ImplementsInterface(UDungeonDoorInterface::StaticClass())) - { - IDungeonDoorInterface::Execute_OnInitialize(actor, props); - } + actor->Initialize(props); if (mOnResetDoor) { mOnResetDoor(actor, props); } + actor->FinishSpawning(transform); } } diff --git a/Source/DungeonGenerator/Private/DungeonRoomSensor.cpp b/Source/DungeonGenerator/Private/DungeonRoomSensor.cpp index d7ce941..e977165 100644 --- a/Source/DungeonGenerator/Private/DungeonRoomSensor.cpp +++ b/Source/DungeonGenerator/Private/DungeonRoomSensor.cpp @@ -60,6 +60,7 @@ void ADungeonRoomSensor::Tick(float DeltaSeconds) { Super::Tick(DeltaSeconds); + // cppcheck-suppress [knownConditionTrueFalse] if (ShowDebugInfomation || ForceShowDebugInfomation) { TArray output; @@ -106,15 +107,11 @@ void ADungeonRoomSensor::Initialize( DepthFromStart = depthFromStart; DeepestDepthFromStart = deepestDepthFromStart; - OnInitialize(); + OnInitialize(parts, item, depthFromStart); mState = State::Initialized; } -void ADungeonRoomSensor::OnInitialize_Implementation() -{ -} - void ADungeonRoomSensor::Finalize() { if (mState == State::Initialized) @@ -124,19 +121,11 @@ void ADungeonRoomSensor::Finalize() } } -void ADungeonRoomSensor::OnFinalize_Implementation() -{ -} - void ADungeonRoomSensor::Reset() { OnReset(); } -void ADungeonRoomSensor::OnReset_Implementation() -{ -} - UBoxComponent* ADungeonRoomSensor::GetBounding() { return Bounding; diff --git a/Source/DungeonGenerator/Public/DungeonDoor.h b/Source/DungeonGenerator/Public/DungeonDoor.h new file mode 100644 index 0000000..68001d7 --- /dev/null +++ b/Source/DungeonGenerator/Public/DungeonDoor.h @@ -0,0 +1,95 @@ +/** +\author Shun Moriya +\copyright 2023- Shun Moriya +All Rights Reserved. +*/ + +#pragma once + +#include "DungeonRoomProps.h" +#include "DungeonDoor.generated.h" + +UCLASS(Blueprintable, BlueprintType) +class DUNGEONGENERATOR_API ADungeonDoor : public AActor +{ + GENERATED_BODY() + +public: + /* + constructor + */ + explicit ADungeonDoor(const FObjectInitializer& initializer); + + /* + destructor + */ + virtual ~ADungeonDoor() = default; + + /* + Initialize + */ + void Initialize(const EDungeonRoomProps props); + + /* + Get DungeonRoomProps + */ + EDungeonRoomProps GetRoomProps() const; + + /* + Set DungeonRoomProps + */ + void SetRoomProps(const EDungeonRoomProps props); + + /** + Function called during initialization after object creation + */ + UFUNCTION(BlueprintNativeEvent, BlueprintCallable, CallInEditor, Category = "DungeonGenerator") + void OnInitialize(const EDungeonRoomProps props); + virtual void OnInitialize_Implementation(const EDungeonRoomProps props); + + /** + Function called before object destruction + */ + void Finalize(); + + UFUNCTION(BlueprintNativeEvent, BlueprintCallable, CallInEditor, Category = "DungeonGenerator") + void OnFinalize(); + virtual void OnFinalize_Implementation(); + + /** + Reset + */ + UFUNCTION(BlueprintCallable, Category = "DungeonGenerator") + void Reset(); + + /** + Function called on reset + */ + UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "DungeonGenerator") + void OnReset(); + virtual void OnReset_Implementation(); + +private: + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "DungeonGenerator", meta = (AllowPrivateAccess = "true")) + EDungeonRoomProps Props = EDungeonRoomProps::None; + + enum class State : uint8_t + { + Invalid, + Initialized, + Finalized, + }; + State mState = State::Invalid; +}; + +inline void ADungeonDoor::OnInitialize_Implementation(const EDungeonRoomProps props) +{ +} + +inline void ADungeonDoor::OnFinalize_Implementation() +{ +} + +inline void ADungeonDoor::OnReset_Implementation() +{ +} diff --git a/Source/DungeonGenerator/Public/DungeonDoorInterface.h b/Source/DungeonGenerator/Public/DungeonDoorInterface.h deleted file mode 100644 index 5b0d176..0000000 --- a/Source/DungeonGenerator/Public/DungeonDoorInterface.h +++ /dev/null @@ -1,41 +0,0 @@ -/** -\author Shun Moriya -\copyright 2023- Shun Moriya -All Rights Reserved. -*/ - -#pragma once -#include "DungeonRoomProps.h" -#include -#include "DungeonDoorInterface.generated.h" - -/** -Dungeon Door Interface Class -*/ -UINTERFACE(MinimalAPI, Blueprintable) -class UDungeonDoorInterface : public UInterface -{ - GENERATED_BODY() -}; - -/** -Dungeon Door Interface Class -*/ -class DUNGEONGENERATOR_API IDungeonDoorInterface -{ - GENERATED_BODY() - -public: - /** - Function called during initialization after object creation - \param[in] props Types of props that need to be installed on the door - */ - UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "DungeonGenerator") - void OnInitialize(EDungeonRoomProps props); - - /** - Function called on reset - */ - UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "DungeonGenerator") - void OnReset(); -}; diff --git a/Source/DungeonGenerator/Public/DungeonGenerateParameter.h b/Source/DungeonGenerator/Public/DungeonGenerateParameter.h index 73140bd..c233b0d 100644 --- a/Source/DungeonGenerator/Public/DungeonGenerateParameter.h +++ b/Source/DungeonGenerator/Public/DungeonGenerateParameter.h @@ -10,7 +10,7 @@ All Rights Reserved. #include #include "DungeonGenerateParameter.generated.h" -// 前方宣言 +// forward declaration class UDungeonRoomAsset; namespace dungeon @@ -21,7 +21,7 @@ namespace dungeon } /** -パーツ配置方向 +Part placement direction */ UENUM(BlueprintType) enum class EDungeonPartsPlacementDirection : uint8 @@ -35,7 +35,7 @@ enum class EDungeonPartsPlacementDirection : uint8 }; /** -パーツ選択方法 +Part Selection Method */ UENUM(BlueprintType) enum class EDungeonPartsSelectionMethod : uint8 @@ -46,14 +46,14 @@ enum class EDungeonPartsSelectionMethod : uint8 }; /** -メッシュパーツ構造体 +Parts transform */ USTRUCT(BlueprintType) -struct DUNGEONGENERATOR_API FDungeonParts +struct DUNGEONGENERATOR_API FDungeonPartsTransform { GENERATED_BODY() - // 相対的なトランスフォーム +public: UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "DungeonGenerator") FTransform RelativeTransform; @@ -63,13 +63,6 @@ struct DUNGEONGENERATOR_API FDungeonParts FTransform CalculateWorldTransform(const FVector& position, const dungeon::Direction& direction) const noexcept; protected: - /** - パーツのトランスフォームを計算します - \param[in] random dungeon::Random& - \param[in] transform FTransform - \param[in] placementDirection EDungeonPartsPlacementDirection - \return EDungeonPartsPlacementDirectionに応じたトランスフォーム - */ FTransform CalculateWorldTransform(dungeon::Random& random, const FTransform& transform, const EDungeonPartsPlacementDirection placementDirection) const noexcept; FTransform CalculateWorldTransform(dungeon::Random& random, const FVector& position, const FRotator& rotator, const EDungeonPartsPlacementDirection placementDirection) const noexcept; FTransform CalculateWorldTransform(dungeon::Random& random, const FVector& position, const float yaw, const EDungeonPartsPlacementDirection placementDirection) const noexcept; @@ -77,71 +70,56 @@ struct DUNGEONGENERATOR_API FDungeonParts }; /** -メッシュパーツ構造体 +Actor Parts */ USTRUCT(BlueprintType) -struct DUNGEONGENERATOR_API FDungeonMeshParts : public FDungeonParts +struct DUNGEONGENERATOR_API FDungeonActorParts : public FDungeonPartsTransform { GENERATED_BODY() - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "DungeonGenerator") - UStaticMesh* StaticMesh = nullptr; +public: + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "DungeonGenerator", meta = (AllowedClasses = "Actor")) + UClass* ActorClass = nullptr; }; /** -方向指定付きメッシュパーツ構造体 +Door actor Parts */ USTRUCT(BlueprintType) -struct DUNGEONGENERATOR_API FDungeonMeshPartsWithDirection : public FDungeonMeshParts +struct DUNGEONGENERATOR_API FDungeonDoorActorParts : public FDungeonPartsTransform { GENERATED_BODY() - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "DungeonGenerator") - EDungeonPartsPlacementDirection PlacementDirection = EDungeonPartsPlacementDirection::RandomDirection; - - /** - パーツのトランスフォームを計算します - \param[in] random dungeon::Random& - \param[in] transform FTransform - \param[in] placementDirection EDungeonPartsPlacementDirection - \return EDungeonPartsPlacementDirectionに応じたトランスフォーム - */ - FTransform CalculateWorldTransform(dungeon::Random& random, const FTransform& transform) const noexcept; - FTransform CalculateWorldTransform(dungeon::Random& random, const FVector& position, const FRotator& rotator) const noexcept; - FTransform CalculateWorldTransform(dungeon::Random& random, const FVector& position, const float yaw) const noexcept; - FTransform CalculateWorldTransform(dungeon::Random& random, const FVector& position, const dungeon::Direction& direction) const noexcept; +public: + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "DungeonGenerator", meta = (AllowedClasses = "DungeonDoor")) + UClass* ActorClass = nullptr; }; /** -アクターパーツ構造体 +Mesh Parts */ USTRUCT(BlueprintType) -struct DUNGEONGENERATOR_API FDungeonActorParts : public FDungeonParts +struct DUNGEONGENERATOR_API FDungeonMeshParts : public FDungeonPartsTransform { GENERATED_BODY() - UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "DungeonGenerator", meta = (AllowedClasses = "Actor")) - UClass* ActorClass = nullptr; +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "DungeonGenerator") + UStaticMesh* StaticMesh = nullptr; }; /** -方向指定付きアクターパーツ構造体 +Actor parts with direction specification */ USTRUCT(BlueprintType) struct DUNGEONGENERATOR_API FDungeonActorPartsWithDirection : public FDungeonActorParts { GENERATED_BODY() +public: UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "DungeonGenerator") EDungeonPartsPlacementDirection PlacementDirection = EDungeonPartsPlacementDirection::RandomDirection; - /** - パーツのトランスフォームを計算します - \param[in] random dungeon::Random& - \param[in] transform FTransform - \param[in] placementDirection EDungeonPartsPlacementDirection - \return EDungeonPartsPlacementDirectionに応じたトランスフォーム - */ FTransform CalculateWorldTransform(dungeon::Random& random, const FTransform& transform) const noexcept; FTransform CalculateWorldTransform(dungeon::Random& random, const FVector& position, const FRotator& rotator) const noexcept; FTransform CalculateWorldTransform(dungeon::Random& random, const FVector& position, const float yaw) const noexcept; @@ -149,34 +127,34 @@ struct DUNGEONGENERATOR_API FDungeonActorPartsWithDirection : public FDungeonAct }; /** -アクターおよびブループリント構造体 +Mesh parts with direction specification */ USTRUCT(BlueprintType) -struct DUNGEONGENERATOR_API FDungeonObjectParts : public FDungeonParts +struct DUNGEONGENERATOR_API FDungeonMeshPartsWithDirection : public FDungeonMeshParts { GENERATED_BODY() - UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "DungeonGenerator", meta = (AllowedClasses = "Actor, Blueprint")) - FSoftObjectPath ActorPath; - - UPROPERTY(Transient, BlueprintReadOnly, Category = "DungeonGenerator") - UClass* ActorClass = nullptr; - UClass* GetActorClass(); - +public: UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "DungeonGenerator") EDungeonPartsPlacementDirection PlacementDirection = EDungeonPartsPlacementDirection::RandomDirection; + + FTransform CalculateWorldTransform(dungeon::Random& random, const FTransform& transform) const noexcept; + FTransform CalculateWorldTransform(dungeon::Random& random, const FVector& position, const FRotator& rotator) const noexcept; + FTransform CalculateWorldTransform(dungeon::Random& random, const FVector& position, const float yaw) const noexcept; + FTransform CalculateWorldTransform(dungeon::Random& random, const FVector& position, const dungeon::Direction& direction) const noexcept; }; /** -確率付きアクターおよびブループリント構造体 +Actor parts with Probability */ USTRUCT(BlueprintType) -struct DUNGEONGENERATOR_API FDungeonRandomObjectParts : public FDungeonObjectParts +struct DUNGEONGENERATOR_API FDungeonRandomActorParts : public FDungeonActorPartsWithDirection { GENERATED_BODY() - // 生成頻度 - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "DungeonGenerator", meta = (ClampMin="0.", ClampMax = "1.")) +public: + // Production frequency + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "DungeonGenerator", meta = (ClampMin = "0.", ClampMax = "1.")) float Frequency = 1.f; }; @@ -231,10 +209,10 @@ class DUNGEONGENERATOR_API UDungeonGenerateParameter : public UObject const FDungeonMeshParts* SelectPillarParts(const size_t gridIndex, const dungeon::Grid& grid, dungeon::Random& random) const; void EachPillarParts(std::function func) const; - const FDungeonRandomObjectParts* SelectTorchParts(const size_t gridIndex, const dungeon::Grid& grid, dungeon::Random& random) const; - //const FDungeonRandomObjectParts* SelectChandelierParts(const size_t gridIndex, const dungeon::Grid& grid, dungeon::Random& random) const; + const FDungeonRandomActorParts* SelectTorchParts(const size_t gridIndex, const dungeon::Grid& grid, dungeon::Random& random) const; + //const FDungeonRandomActorParts* SelectChandelierParts(const size_t gridIndex, const dungeon::Grid& grid, dungeon::Random& random) const; - const FDungeonObjectParts* SelectDoorParts(const size_t gridIndex, const dungeon::Grid& grid, dungeon::Random& random) const; + const FDungeonDoorActorParts* SelectDoorParts(const size_t gridIndex, const dungeon::Grid& grid, dungeon::Random& random) const; const FDungeonActorPartsWithDirection& GetStartParts() const; @@ -244,25 +222,13 @@ class DUNGEONGENERATOR_API UDungeonGenerateParameter : public UObject UClass* GetRoomSensorClass() const; - /* - Converts from a grid coordinate system to a world coordinate system - 2D空間は(X軸:前 Y軸:右) - 3D空間は(X軸:前 Y軸:右 Z軸:上)である事に注意 - */ + // Converts from a grid coordinate system to a world coordinate system FVector ToWorld(const FIntVector& location) const; - /* - Converts from a grid coordinate system to a world coordinate system - 2D空間は(X軸:前 Y軸:右) - 3D空間は(X軸:前 Y軸:右 Z軸:上)である事に注意 - */ + // Converts from a grid coordinate system to a world coordinate system FVector ToWorld(const uint32_t x, const uint32_t y, const uint32_t z) const; - /* - Converts from a grid coordinate system to a world coordinate system - 2D空間は(X軸:前 Y軸:右) - 3D空間は(X軸:前 Y軸:右 Z軸:上)である事に注意 - */ + // Converts from a grid coordinate system to a world coordinate system FIntVector ToGrid(const FVector& location) const; #if WITH_EDITOR @@ -273,14 +239,14 @@ class DUNGEONGENERATOR_API UDungeonGenerateParameter : public UObject int32 SelectDungeonMeshPartsIndex(const size_t gridIndex, const dungeon::Grid& grid, dungeon::Random& random, const int32 size, const EDungeonPartsSelectionMethod partsSelectionMethod) const; template - T* SelectDungeonMeshParts(const size_t gridIndex, const dungeon::Grid& grid, dungeon::Random& random, const TArray& parts, const EDungeonPartsSelectionMethod partsSelectionMethod) const; + T* SelectParts(const size_t gridIndex, const dungeon::Grid& grid, dungeon::Random& random, const TArray& parts, const EDungeonPartsSelectionMethod partsSelectionMethod) const; - FDungeonObjectParts* SelectDungeonObjectParts(const size_t gridIndex, const dungeon::Grid& grid, dungeon::Random& random, const TArray& parts, const EDungeonPartsSelectionMethod partsSelectionMethod) const; + FDungeonActorParts* SelectActorParts(const size_t gridIndex, const dungeon::Grid& grid, dungeon::Random& random, const TArray& parts, const EDungeonPartsSelectionMethod partsSelectionMethod) const; - FDungeonRandomObjectParts* SelectDungeonRandomObjectParts(const size_t gridIndex, const dungeon::Grid& grid, dungeon::Random& random, const TArray& parts, const EDungeonPartsSelectionMethod partsSelectionMethod) const; + FDungeonRandomActorParts* SelectRandomActorParts(const size_t gridIndex, const dungeon::Grid& grid, dungeon::Random& random, const TArray& parts, const EDungeonPartsSelectionMethod partsSelectionMethod) const; template - void EachMeshParts(const TArray& parts, std::function func) const; + void EachParts(const TArray& parts, std::function func) const; #if WITH_EDITOR FString GetJsonDefaultDirectory() const; @@ -295,9 +261,7 @@ class DUNGEONGENERATOR_API UDungeonGenerateParameter : public UObject UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Transient, Category = "DungeonGenerator") int32 GeneratedRandomSeed = 0; - /** - dungeon level - */ + // dungeon level UPROPERTY(EditAnywhere, Category = "DungeonGenerator", BlueprintReadWrite, meta = (ClampMin = "1")) uint8 NumberOfCandidateFloors = 3; @@ -390,12 +354,12 @@ class DUNGEONGENERATOR_API UDungeonGenerateParameter : public UObject //! Torch (pillar lighting) parts UPROPERTY(EditAnywhere, Category = "DungeonGenerator|Torch", BlueprintReadWrite) - TArray TorchParts; + TArray TorchParts; /* シャンデリア(天井の照明)のパーツ UPROPERTY(EditAnywhere, Category="DungeonGenerator", BlueprintReadWrite) - TArray ChandelierParts; + TArray ChandelierParts; */ //! How to generate door parts @@ -404,7 +368,7 @@ class DUNGEONGENERATOR_API UDungeonGenerateParameter : public UObject // Door Parts UPROPERTY(EditAnywhere, Category = "DungeonGenerator|Door", BlueprintReadWrite) - TArray DoorParts; + TArray DoorParts; // starting point UPROPERTY(EditAnywhere, Category = "DungeonGenerator", BlueprintReadWrite) @@ -426,9 +390,9 @@ class DUNGEONGENERATOR_API UDungeonGenerateParameter : public UObject friend class CDungeonGenerator; }; -// aka: SelectDungeonObjectParts, SelectDungeonRandomObjectParts +// aka: SelectActorParts, SelectRandomActorParts template -inline T* UDungeonGenerateParameter::SelectDungeonMeshParts(const size_t gridIndex, const dungeon::Grid& grid, dungeon::Random& random, const TArray& parts, const EDungeonPartsSelectionMethod partsSelectionMethod) const +inline T* UDungeonGenerateParameter::SelectParts(const size_t gridIndex, const dungeon::Grid& grid, dungeon::Random& random, const TArray& parts, const EDungeonPartsSelectionMethod partsSelectionMethod) const { const int32 size = parts.Num(); if (size <= 0) @@ -439,7 +403,7 @@ inline T* UDungeonGenerateParameter::SelectDungeonMeshParts(const size_t gridInd } template -inline void UDungeonGenerateParameter::EachMeshParts(const TArray& parts, std::function func) const +inline void UDungeonGenerateParameter::EachParts(const TArray& parts, std::function func) const { for (const auto& part : parts) { diff --git a/Source/DungeonGenerator/Public/DungeonRoomSensor.h b/Source/DungeonGenerator/Public/DungeonRoomSensor.h index 0a0a892..bda83b6 100644 --- a/Source/DungeonGenerator/Public/DungeonRoomSensor.h +++ b/Source/DungeonGenerator/Public/DungeonRoomSensor.h @@ -49,8 +49,8 @@ class DUNGEONGENERATOR_API ADungeonRoomSensor : public AActor Function called during initialization after object creation */ UFUNCTION(BlueprintNativeEvent, BlueprintCallable, CallInEditor, Category = "DungeonGenerator") - void OnInitialize(); - virtual void OnInitialize_Implementation(); + void OnInitialize(const EDungeonRoomParts parts, const EDungeonRoomItem item, const uint8 depthFromStart); + virtual void OnInitialize_Implementation(const EDungeonRoomParts parts, const EDungeonRoomItem item, const uint8 depthFromStart); /** Function called before object destruction @@ -175,3 +175,15 @@ class DUNGEONGENERATOR_API ADungeonRoomSensor : public AActor }; State mState = State::Invalid; }; + +inline void ADungeonRoomSensor::OnInitialize_Implementation(const EDungeonRoomParts parts, const EDungeonRoomItem item, const uint8 depthFromStart) +{ +} + +inline void ADungeonRoomSensor::OnFinalize_Implementation() +{ +} + +inline void ADungeonRoomSensor::OnReset_Implementation() +{ +}