Browse Source

ConsoleMovementComponentManager first pass, Position helpers

- Added Scale() and GetSafeNormal() vector helper functions
- ConsoleMovementComponentManager should now theoretically be at parity with UnrealMovementComponent. It is untested though
- Hooked up stuff to ConsoleMovementComponents but did not test
combatComponentRefactor
Macoy Madson 6 years ago
parent
commit
eb5258e0c1
  1. 123
      src/frontends/consoleOnly/ConsoleMovementComponentManager.cpp
  2. 29
      src/frontends/consoleOnly/ConsoleMovementComponentManager.hpp
  3. 88
      src/frontends/consoleOnly/ConsoleOnlyMain.cpp
  4. 14
      src/project/galavantSublime/galavant.sublime-project
  5. 20
      src/world/Position.cpp
  6. 4
      src/world/Position.hpp

123
src/frontends/consoleOnly/ConsoleMovementComponentManager.cpp

@ -1,5 +1,7 @@
#include "ConsoleMovementComponentManager.hpp"
#include <algorithm>
ConsoleMovementComponentManager g_ConsoleMovementComponentManager;
ConsoleMovementComponentManager::ConsoleMovementComponentManager()
@ -13,12 +15,133 @@ void ConsoleMovementComponentManager::Initialize(
TaskEventCallbacks = taskEventCallbacks;
}
void ConsoleMovementComponentManager::UnsubscribeEntitiesInternal(const gv::EntityList& entities)
{
for (MovementComponentList::iterator it = MovementComponents.begin();
it != MovementComponents.end();)
{
gv::Entity currentEntity = (*it).entity;
bool foundEntity = false;
for (const gv::Entity& unsubscribeEntity : entities)
{
if (currentEntity == unsubscribeEntity)
{
it = MovementComponents.erase(it);
foundEntity = true;
break;
}
}
if (!foundEntity)
++it;
}
}
void ConsoleMovementComponentManager::CreateMovementComponents(
const gv::EntityList& entities, MovementComponentRefList& newMovementComponents)
{
// Only create MovementComponents which aren't already subscribed
gv::EntityList entitiesToSubscribe = entities;
gv::EntityListRemoveNonUniqueEntitiesInSuspect(Subscribers, entitiesToSubscribe);
unsigned int endBeforeResize = MovementComponents.size();
MovementComponents.resize(MovementComponents.size() + entitiesToSubscribe.size());
int numEntitiesCreated = 0;
for (unsigned int i = endBeforeResize; i < MovementComponents.size(); i++)
{
MovementComponent* newMovementComponent = &MovementComponents[i];
newMovementComponent->entity = entitiesToSubscribe[numEntitiesCreated++];
newMovementComponents.push_back(newMovementComponent);
}
// We've already made sure all entities in the list are unique
gv::EntityListAppendList(Subscribers, entitiesToSubscribe);
}
void ConsoleMovementComponentManager::Update(float deltaSeconds)
{
Htn::TaskEventList eventList;
gv::EntityList entitiesToUnsubscribe;
for (MovementComponent& component : MovementComponents)
{
gv::Position targetPosition;
// Decide where we're going to go
{
if (component.GoalWorldPosition)
{
if (component.Position.ManhattanTo(component.GoalWorldPosition) >
component.GoalManDistanceTolerance)
{
targetPosition = component.GoalWorldPosition;
}
else
{
component.GoalWorldPosition.Reset();
Htn::TaskEvent goalPositionReachedEvent{
Htn::TaskEvent::TaskResult::TaskSucceeded, component.entity};
eventList.push_back(goalPositionReachedEvent);
}
}
}
if (component.ResourceType != gv::WorldResourceType::None &&
!component.ResourcePosition.Equals(component.Position, 100.f))
{
// Give ResourceLocator our new position
gv::WorldResourceLocator::MoveResource(component.ResourceType, component.entity,
component.ResourcePosition, component.Position);
component.ResourcePosition = component.Position;
}
// Perform movement
if (targetPosition)
{
gv::Position deltaPosition = targetPosition - component.Position;
gv::Position deltaVelocity = deltaPosition.GetSafeNormal(0.1f);
deltaVelocity.Scale(component.MaxSpeed * deltaSeconds);
// Disallow flying
deltaVelocity[2] = 0;
component.Position += deltaVelocity;
}
}
if (TaskEventCallbacks && !eventList.empty())
{
for (gv::CallbackCall<Htn::TaskEventCallback>& callback : TaskEventCallbacks->Callbacks)
callback.Callback(eventList, callback.UserData);
}
if (!entitiesToUnsubscribe.empty())
UnsubscribeEntities(entitiesToUnsubscribe);
}
// TODO: This should return whether it was actually successful (i.e. the entity exists)
void ConsoleMovementComponentManager::PathEntitiesTo(const gv::EntityList& entities,
const gv::PositionList& positions)
{
if (entities.empty() || entities.size() != positions.size())
return;
for (unsigned int i = 0; i < entities.size(); i++)
{
const gv::Entity& entityToMove = entities[i];
const gv::Position& targetPosition = positions[i];
// For now, entities which are not subscribed will be tossed out
if (std::find(Subscribers.begin(), Subscribers.end(), entityToMove) == Subscribers.end())
continue;
for (MovementComponent& component : MovementComponents)
{
if (component.entity == entityToMove)
{
component.GoalWorldPosition = targetPosition;
}
}
}
}

29
src/frontends/consoleOnly/ConsoleMovementComponentManager.hpp

@ -8,16 +8,45 @@
#include "game/agent/MovementManager.hpp"
#include "util/CallbackContainer.hpp"
struct MovementComponent
{
gv::Entity entity;
gv::Position Position;
gv::Position GoalWorldPosition;
float GoalManDistanceTolerance = 400.f;
float MaxSpeed = 500.f;
// If provided, this entity will be registered in the WorldResourceLocator under this type
gv::WorldResourceType ResourceType = gv::WorldResourceType::None;
// The last position we told the ResourceLocator we were at (used so that when we move we can
// find the agent to move in ResourceLocator)
gv::Position ResourcePosition;
};
typedef std::vector<MovementComponent> MovementComponentList;
typedef std::vector<MovementComponent*> MovementComponentRefList;
class ConsoleMovementComponentManager : public gv::ComponentManager, public gv::MovementManager
{
private:
gv::CallbackContainer<Htn::TaskEventCallback>* TaskEventCallbacks;
MovementComponentList MovementComponents;
protected:
virtual void UnsubscribeEntitiesInternal(const gv::EntityList& entities);
public:
ConsoleMovementComponentManager();
virtual ~ConsoleMovementComponentManager() = default;
void Initialize(gv::CallbackContainer<Htn::TaskEventCallback>* taskEventCallbacks);
void CreateMovementComponents(const gv::EntityList& entities,
MovementComponentRefList& newMovementComponents);
virtual void Update(float deltaSeconds);
// TODO: This should return whether it was actually successful (i.e. the entity exists)

88
src/frontends/consoleOnly/ConsoleOnlyMain.cpp

@ -39,7 +39,7 @@ void ConsoleOnlyLogOutput(const gv::Logging::Record& record)
if (IsError)
{
std::cout << "Error: " << buffer << "\n";
std::cout << "Error: " << buffer << "\n";
}
else if (IsWarning)
{
@ -47,7 +47,7 @@ void ConsoleOnlyLogOutput(const gv::Logging::Record& record)
}
else
{
std::cout << "Log: " << buffer << "\n";
std::cout << "Log: " << buffer << "\n";
}
}
@ -171,26 +171,22 @@ void InitializeEntityTests()
gv::g_EntityComponentManager.GetNewEntities(testEntities, numTestEntities);
// Add Movement components to all of them
/*{
UnrealMovementComponent::UnrealMovementComponentList newEntityMovementComponents(
numTestEntities);
float spacing = 500.f;
int i = 0;
for (gv::EntityListIterator it = testEntities.begin(); it != testEntities.end(); ++it, i++)
{
newEntityMovementComponents[i].entity = (*it);
newEntityMovementComponents[i].data.ResourceType = gv::WorldResourceType::Agent;
newEntityMovementComponents[i].data.SpawnParams.CharacterToSpawn =
DefaultAgentCharacter;
newEntityMovementComponents[i].data.WorldPosition.Set(0.f, i * spacing,
TestEntityCreationZ);
newEntityMovementComponents[i].data.GoalManDistanceTolerance = 600.f;
newEntityMovementComponents[i].data.MaxSpeed = 500.f;
}
g_ConsoleMovementComponentManager.SubscribeEntities(newEntityMovementComponents);
}*/
{
MovementComponentRefList newMovementComponents;
newMovementComponents.reserve(numTestEntities);
g_ConsoleMovementComponentManager.CreateMovementComponents(testEntities,
newMovementComponents);
float spacing = 500.f;
int i = 0;
for (MovementComponent* newAgentMovementComponent : newMovementComponents)
{
newAgentMovementComponent->ResourceType = gv::WorldResourceType::Agent;
newAgentMovementComponent->Position.Set(0.f, i++ * spacing, 0.f);
newAgentMovementComponent->GoalManDistanceTolerance = 600.f;
newAgentMovementComponent->MaxSpeed = 500.f;
}
}
// Setup agent components for all of them and give them a need
{
@ -222,36 +218,32 @@ void InitializeEntityTests()
testFoodEntities.reserve(numFood);
gv::g_EntityComponentManager.GetNewEntities(testFoodEntities, numFood);
// UnrealMovementComponent::UnrealMovementComponentList newFood(numFood);
MovementComponentRefList newMovementComponents;
newMovementComponents.reserve(numFood);
g_ConsoleMovementComponentManager.CreateMovementComponents(testFoodEntities,
newMovementComponents);
gv::PickupRefList newPickups;
newPickups.reserve(numFood);
gv::g_InteractComponentManager.CreatePickups(testFoodEntities, newPickups);
//float spacing = 2000.f;
// Movement components
float spacing = 2000.f;
int i = 0;
for (gv::EntityListIterator it = testFoodEntities.begin(); it != testFoodEntities.end();
++it, i++)
for (MovementComponent* newFoodMovementComponent : newMovementComponents)
{
// Movement component
/*{
FVector location(-2000.f, i * spacing, TestEntityCreationZ);
newFood[i].entity = (*it);
newFood[i].data.WorldPosition.Set(location.X, location.Y, location.Z);
newFood[i].data.ResourceType = gv::WorldResourceType::Food;
newFood[i].data.SpawnParams.ActorToSpawn = TestFoodActor;
}*/
// Pickup component
if (i < (int)newPickups.size())
{
newPickups[i]->AffectsNeed = gv::NeedType::Hunger;
newPickups[i]->DestroySelfOnPickup = true;
}
newFoodMovementComponent->ResourceType = gv::WorldResourceType::Food;
newFoodMovementComponent->Position.Set(-2000.f, i++ * spacing, 0.f);
// Food doesn't move
newFoodMovementComponent->MaxSpeed = 0.f;
}
// g_ConsoleMovementComponentManager.SubscribeEntities(newFood);
// Pickup components
for (gv::Pickup* newPickup : newPickups)
{
newPickup->AffectsNeed = gv::NeedType::Hunger;
newPickup->DestroySelfOnPickup = true;
}
}
}
@ -304,7 +296,7 @@ void InitializeGalavant()
{
static gv::WorldStateManager WorldStateManager;
gv::g_PlanComponentManager.Initialize(&WorldStateManager, &TaskEventCallbacks);
gv::g_PlanComponentManager.DebugPrint = true;
//gv::g_PlanComponentManager.DebugPrint = true;
}
{
@ -312,7 +304,7 @@ void InitializeGalavant()
gv::g_AgentComponentManager.DebugPrint = true;
}
//gv::g_CombatComponentManager.Initialize(&CombatFxHandler);
// gv::g_CombatComponentManager.Initialize(&CombatFxHandler);
gv::g_CombatComponentManager.Initialize(nullptr);
}
@ -369,7 +361,7 @@ int main()
gv::g_EntityComponentManager.DestroyEntitiesPendingDestruction();
//GalavantMain.Update(deltaTime);
// GalavantMain.Update(deltaTime);
gv::g_CombatComponentManager.Update(deltaTime);
gv::g_AgentComponentManager.Update(deltaTime);
@ -379,7 +371,7 @@ int main()
numTicks++;
}
LOGI << "******** Finished; cleaning up... (ticked "<< numTicks << " times) ********";
LOGI << "******** Finished; cleaning up... (ticked " << numTicks << " times) ********";
// Cleanup
{

14
src/project/galavantSublime/galavant.sublime-project

@ -211,19 +211,5 @@
// "commandline": "gdb --interpreter=mi ./htnTest"
//},
},
"SublimeAnarchyDebug": {
"debug": {
"executable": "/home/macoy/Development/code/3rdParty/repositories/UnrealEngine/Engine/Binaries/Linux/UE4Editor",
"params": [
"/home/macoy/Development/code/repositories/galavant-unreal/GalavantUnreal/GalavantUnreal.uproject"
],
"path": [
],
"environment": [
],
//"working_dir": "${project_path}"
}
}
}
}

20
src/world/Position.cpp

@ -36,6 +36,26 @@ float Position::ManhattanTo(const Position& otherPosition) const
return fabs(X - otherPosition.X) + fabs(Y - otherPosition.Y) + fabs(Z - otherPosition.Z);
}
Position Position::GetSafeNormal(float tolerance) const
{
float squareSum = X * X + Y * Y + Z * Z;
if (squareSum == 1.f)
return Position(X, Y, Z);
else if (squareSum < tolerance)
return Position(0.f, 0.f, 0.f);
float scale = std::sqrt(squareSum);
return Position(X * scale, Y * scale, Z * scale);
}
void Position::Scale(float scale)
{
X *= scale;
Y *= scale;
Z *= scale;
}
Position::operator bool() const
{
// Only return false if we're exactly zero (don't use tolerances)

4
src/world/Position.hpp

@ -27,6 +27,10 @@ struct Position
float ManhattanTo(const Position& otherPosition) const;
Position GetSafeNormal(float tolerance) const;
void Scale(float scale);
// Returns true if the Position is exactly zero
explicit operator bool() const;

Loading…
Cancel
Save