Browse Source

Standalone/Debug commands, Gameplay time, small ECS changes

- Marked the location of @Latelinks for refactoring/searchability
- Added the concept of GameplayTime, a time which can be paused and played. Gameplay code should use this instead of world time
- Math macros no longer have semicolons, making them useful in for loops etc.
- I had to comment out std::cout calls in Logging.cpp because Unreal gets upset when those are executed
- Added several build systems and debug options to get both a full debug Unreal Editor and standalone game client working and convenient to use
- Added SetEntitySpeeds() to the MovementManager interface. The idea is that if things die their speeds can be set to zero. This will likely be replaced with something cleaner
- Added the ability to interface with EntityComponentManager with a single UnsubscribeEntities function instead of a whole ComponentManager derived class. This is proving to be a somewhat dumb idea. I still need to figure out this whole interface
master
Macoy Madson 6 years ago
parent
commit
ac1918e8b2
  1. 12
      Notes.md
  2. 28
      TODO.tasks
  3. 27
      src/entityComponentSystem/EntityComponentManager.cpp
  4. 13
      src/entityComponentSystem/EntityComponentManager.hpp
  5. 15
      src/frontends/consoleOnly/ConsoleMovementComponentManager.cpp
  6. 1
      src/frontends/consoleOnly/ConsoleMovementComponentManager.hpp
  7. 13
      src/frontends/consoleOnly/ConsoleOnlyMain.cpp
  8. 38
      src/game/agent/AgentComponentManager.cpp
  9. 6
      src/game/agent/AgentComponentManager.hpp
  10. 7
      src/game/agent/MovementManager.hpp
  11. 2
      src/game/agent/combat/CombatComponentManager.cpp
  12. 2
      src/game/agent/combat/CombatComponentManager.hpp
  13. 7
      src/main.cpp
  14. 74
      src/project/galavantSublime/galavant.sublime-project
  15. 3
      src/util/Jamfile
  16. 9
      src/util/Logging.cpp
  17. 4
      src/util/Math.hpp
  18. 60
      src/util/Time.cpp
  19. 14
      src/util/Time.hpp

12
Notes.md

@ -10,10 +10,20 @@ you get the latest Galavant changes when using Unreal's hot reloading
- Even if you `make` the project, you'll still need to hit the Compile button in the editor to get Unreal to compile and hotreload your code
- I added a hack which makes the engine auto scale to my desired DPI settings. You'll probably want to change these to fit your preferences. Change the value of `FSlateApplication::Get().SetApplicationScale(1.53f)` in `AGalavantUnrealMain::AGalavantUnrealMain()` to your desired DPI (1.f is the engine default).
### Useful Unreal Commands
- `r.setRes 1920x1080f`: Set screen resolution (w = windowed, f = fullscreen, wf = windowed fullscreen)
- `'`: (Hit apostrophe in gameplay): Debug gameplay interface. Use NumPad for various views
- `stat fps`: Show FPS in corner
## Comment Tags
Future tasks:
- TODO: Something needs to get done. I use TodoReview for Sublime to find all of these easily.
- @Performance: Not justifiable as a TODO, but could be looked at when thinking about performance
- @Purity: Look into changing the code for code purity/cleanliness' sake
- @Stability: Should be changed in order to make the code more stable (segfault protection etc.)
Structure labels:
- @Callback: The marked function is used as a callback. Preferably @Callback [Callback type name]
- @Stability: Should be changed in order to make the code more stable (segfault protection etc.)
- @Latelink: The marked thing is latelinked. Frontends must define them before linking can complete
- @LatelinkDef: The marked thing is the frontend definition of a latelinked thing

28
TODO.txt → TODO.tasks

@ -20,10 +20,6 @@ Minimap
Scaling is completely wrong between WorldResource position and noise sample
Actually, this doesn't seem to be the problem
Some sort of resource system
Could be something like ResourceDictionary<key, ResourceType> resources
then things could stuff in things from load or even hard coded (via resources["new thing"] = {})
Position vs GlobalPosition
As soon as possible, I need to decide if I need Chunk XYZ with Position XYZ
This depends on whether I ever want to support really large worlds
@ -47,19 +43,11 @@ Combat System
Goal #2: Minecraft but with strategy (this can be the stopping point for now)
Goal #3: Something closer to Chivalry instead of Minecraft
Massive convenience feature: Fuck, totally forgot as I was writing this. Fuck!
Was it Entity Actor integration?
Add player HUD UI - Only needs Minimap, Need bars
Save Jamfile documentation to repository
Cereal integration
Fix debug text over AgentCharacter for combat test
Automatic apply UEngine patch script
Cereal integration
Goal retrying needs rethinking (goal retry status is forgotten once goal completely fails)
@ -67,15 +55,29 @@ After extended period of time, PlanComponentManager is constantly trying to unsu
Replaying in editor seems to do strange things with needs/timers. Are things being reset properly?
Development
Save Jamfile documentation to repository
Automatic apply UEngine patch script
------------------
Doing
------------------
Combat System
Pause/play might not work (component managers / agents behaving strangely, maybe after resume)
Get standalone full debug game working
Clean way to manage Galavant -> Character interactions (e.g. how to properly handle ragdoll)
------------------
Done
------------------
Some sort of resource system
Could be something like ResourceDictionary<key, ResourceType> resources
then things could stuff in things from load or even hard coded (via resources["new thing"] = {})
Combat System
Input
Make callbacks in player character which talk to combat system/do things. For now, maybe

27
src/entityComponentSystem/EntityComponentManager.cpp

@ -40,6 +40,23 @@ void EntityComponentManager::RemoveComponentManager(ComponentManager *manager)
}
}
void EntityComponentManager::AddUnsubscribeOnlyManager(UnsubscribeEntitiesFunc unsubscribeFunc)
{
for (UnsubscribeEntitiesFunc currentFunc : UnsubscribeOnlyManagers)
{
// Already added
if (currentFunc == unsubscribeFunc)
return;
}
UnsubscribeOnlyManagers.push_back(unsubscribeFunc);
}
void EntityComponentManager::ClearUnsubscribeOnlyManagers()
{
UnsubscribeOnlyManagers.clear();
}
void EntityComponentManager::GetNewEntities(EntityList &list, int count)
{
for (int i = 0; i < count; i++)
@ -65,10 +82,16 @@ void EntityComponentManager::UnsubscribeEntitiesFromAllManagers(EntityList &enti
// that's fine
for (ComponentManager *currentComponentManager : ComponentManagers)
{
LOGD << "Destroying " << entitiesToUnsubscribe.size() << " entities from "
<< currentComponentManager->DebugName << " (they might not all be subscribed)";
LOGD_IF(DebugPrint) << "Destroying " << entitiesToUnsubscribe.size() << " entities from "
<< currentComponentManager->DebugName
<< " (they might not all be subscribed)";
currentComponentManager->UnsubscribeEntities(entitiesToUnsubscribe);
}
for (UnsubscribeEntitiesFunc currentUnsubscribeEntities : UnsubscribeOnlyManagers)
{
currentUnsubscribeEntities(entitiesToUnsubscribe);
}
}
// Destroy all entities which have been marked for destruction. Because an entity is just an ID

13
src/entityComponentSystem/EntityComponentManager.hpp

@ -18,15 +18,21 @@ every ComponentManager which is registered with this ECM. This is less than opti
permissable.
*/
typedef std::vector<ComponentManager *> ComponentManagerList;
// Circumvent the class rigamaroll and just give the ECM a way to tell you to delete dead shit
typedef void (*UnsubscribeEntitiesFunc)(const EntityList &entities);
class EntityComponentManager
{
private:
typedef std::vector<ComponentManager *> ComponentManagerList;
typedef ComponentManagerList::iterator ComponentManagerListIterator;
ComponentManagerList ComponentManagers;
typedef std::vector<UnsubscribeEntitiesFunc> UnsubscribeOnlyManagerList;
UnsubscribeOnlyManagerList UnsubscribeOnlyManagers;
EntityList ActiveEntities;
EntityList EntitiesPendingDestruction;
@ -39,12 +45,17 @@ private:
void UnsubscribeEntitiesFromAllManagers(EntityList &entitiesToUnsubscribe);
public:
bool DebugPrint = false;
EntityComponentManager();
~EntityComponentManager();
void AddComponentManager(ComponentManager *manager);
void RemoveComponentManager(ComponentManager *manager);
void AddUnsubscribeOnlyManager(UnsubscribeEntitiesFunc unsubscribeFunc);
void ClearUnsubscribeOnlyManagers();
// Creates the given number of entities, adds them to the ActiveEntities list, and appends them
// to the provided list
void GetNewEntities(EntityList &list, int count);

15
src/frontends/consoleOnly/ConsoleMovementComponentManager.cpp

@ -1,5 +1,7 @@
#include "ConsoleMovementComponentManager.hpp"
#include "util/Math.hpp"
#include <algorithm>
ConsoleMovementComponentManager g_ConsoleMovementComponentManager;
@ -145,3 +147,16 @@ void ConsoleMovementComponentManager::PathEntitiesTo(const gv::EntityList& entit
}
}
}
void ConsoleMovementComponentManager::SetEntitySpeeds(const gv::EntityList& entities,
const std::vector<float>& speeds)
{
for (MovementComponent& currentComponent : MovementComponents)
{
for (size_t i = 0; i < MIN(entities.size(), speeds.size()); i++)
{
if (currentComponent.entity == entities[i])
currentComponent.MaxSpeed = speeds[i];
}
}
}

1
src/frontends/consoleOnly/ConsoleMovementComponentManager.hpp

@ -51,6 +51,7 @@ public:
// TODO: This should return whether it was actually successful (i.e. the entity exists)
virtual void PathEntitiesTo(const gv::EntityList& entities, const gv::PositionList& positions);
virtual void SetEntitySpeeds(const gv::EntityList& entities, const std::vector<float>& speeds);
};
extern ConsoleMovementComponentManager g_ConsoleMovementComponentManager;

13
src/frontends/consoleOnly/ConsoleOnlyMain.cpp

@ -2,6 +2,7 @@
#include "world/WorldResourceLocator.hpp"
#include "world/ProceduralWorld.hpp"
#include "entityComponentSystem/EntityTypes.hpp"
#include "entityComponentSystem/EntityComponentManager.hpp"
#include "game/agent/PlanComponentManager.hpp"
@ -12,9 +13,11 @@
#include "ai/htn/HTNTasks.hpp"
#include "game/agent/htnTasks/MovementTasks.hpp"
#include "game/agent/htnTasks/InteractTasks.hpp"
#include "util/CallbackContainer.hpp"
#include "game/EntityLevelOfDetail.hpp"
#include "util/CallbackContainer.hpp"
#include "util/StringHashing.hpp"
#include "util/Time.hpp"
#include "ConsoleMovementComponentManager.hpp"
@ -273,6 +276,8 @@ void InitializeGalavant()
{
LOGI << "Initializing Galavant...";
gv::ResetGameplayTime();
InitializeProceduralWorld();
gv::WorldResourceLocator::ClearResources();
@ -296,11 +301,12 @@ void InitializeGalavant()
{
static gv::WorldStateManager WorldStateManager;
gv::g_PlanComponentManager.Initialize(&WorldStateManager, &TaskEventCallbacks);
//gv::g_PlanComponentManager.DebugPrint = true;
// gv::g_PlanComponentManager.DebugPrint = true;
}
{
gv::g_AgentComponentManager.Initialize(&gv::g_PlanComponentManager);
gv::g_AgentComponentManager.Initialize(&gv::g_PlanComponentManager,
&g_ConsoleMovementComponentManager);
gv::g_AgentComponentManager.DebugPrint = true;
}
@ -389,6 +395,7 @@ int main()
// Latelinked functions
namespace gv
{
// @LatelinkDef
float GetWorldTime()
{
return s_currentWorldTime;

38
src/game/agent/AgentComponentManager.cpp

@ -22,9 +22,11 @@ AgentComponentManager::~AgentComponentManager()
{
}
void AgentComponentManager::Initialize(PlanComponentManager* newPlanComponentManager)
void AgentComponentManager::Initialize(PlanComponentManager* newPlanComponentManager,
MovementManager* newMovementComponentManager)
{
PlanManager = newPlanComponentManager;
MovementComponentManager = newMovementComponentManager;
}
void AddGoalIfUniqueType(AgentGoalList& goals, AgentGoal& goalToAdd)
@ -49,6 +51,7 @@ void AgentComponentManager::Update(float deltaSeconds)
EntityList entitiesToUnsubscribe;
EntityList entitiesToDestroy;
PlanComponentManager::PlanComponentList newPlans;
std::vector<gv::PooledComponent<AgentComponentData>*> newlyDeadAgents;
if (!PlanManager)
{
@ -119,7 +122,8 @@ void AgentComponentManager::Update(float deltaSeconds)
LOGD_IF(DebugPrint) << "Agent Entity " << currentEntity
<< " has hit need trigger for need " << need.Def->Name;
if (needLevelTrigger.SetConsciousState != AgentConsciousState::None)
if (needLevelTrigger.SetConsciousState != AgentConsciousState::None &&
currentComponent->data.ConsciousState != needLevelTrigger.SetConsciousState)
{
currentComponent->data.ConsciousState = needLevelTrigger.SetConsciousState;
@ -128,12 +132,7 @@ void AgentComponentManager::Update(float deltaSeconds)
currentComponent->data.IsAlive = false;
LOGD_IF(DebugPrint) << "Agent Entity " << currentEntity
<< " has died from need " << need.Def->Name;
// temporary
static CombatActionDef deathActionDef;
deathActionDef.Die = true;
CombatAction deathAction{&deathActionDef, nullptr, 0.f};
g_CombatComponentManager.ActivateCombatAction(currentComponent->entity,
deathAction);
newlyDeadAgents.push_back(currentComponent);
}
}
@ -267,13 +266,32 @@ void AgentComponentManager::Update(float deltaSeconds)
if (!newPlans.empty())
PlanManager->SubscribeEntities(newPlans);
if (!newlyDeadAgents.empty())
{
EntityList deadEntities;
std::vector<float> deadEntitySpeeds;
for (gv::PooledComponent<AgentComponentData>* currentComponent : newlyDeadAgents)
{
// temporary
static CombatActionDef deathActionDef;
deathActionDef.Die = true;
CombatAction deathAction{&deathActionDef, nullptr, 0.f};
g_CombatComponentManager.ActivateCombatAction(currentComponent->entity, deathAction);
deadEntities.push_back(currentComponent->entity);
deadEntitySpeeds.push_back(0.f);
}
// TODO: @Purity: How do I want other systems to interact? Is this dirty, or fine?
if (MovementComponentManager)
MovementComponentManager->SetEntitySpeeds(deadEntities, deadEntitySpeeds);
}
if (!entitiesToUnsubscribe.empty())
UnsubscribeEntities(entitiesToUnsubscribe);
if (!entitiesToDestroy.empty())
{
g_EntityComponentManager.MarkDestroyEntities(entitiesToDestroy);
}
}
void AgentComponentManager::SubscribeEntitiesInternal(const EntityList& subscribers,

6
src/game/agent/AgentComponentManager.hpp

@ -4,6 +4,7 @@
#include "entityComponentSystem/PooledComponentManager.hpp"
#include "entityComponentSystem/EntityTypes.hpp"
#include "MovementManager.hpp"
#include "PlanComponentManager.hpp"
#include "Needs.hpp"
@ -46,6 +47,8 @@ private:
PlanComponentManager* PlanManager;
MovementManager* MovementComponentManager;
protected:
typedef std::vector<PooledComponent<AgentComponentData>*> AgentComponentRefList;
@ -62,7 +65,8 @@ public:
AgentComponentManager();
virtual ~AgentComponentManager();
void Initialize(PlanComponentManager* newPlanComponentManager);
void Initialize(PlanComponentManager* newPlanComponentManager,
MovementManager* newMovementComponentManager);
virtual void Update(float deltaSeconds);

7
src/game/agent/MovementManager.hpp

@ -1,7 +1,9 @@
#pragma once
#include "../../entityComponentSystem/EntityTypes.hpp"
#include "../../world/Position.hpp"
#include "entityComponentSystem/EntityTypes.hpp"
#include "world/Position.hpp"
#include <vector>
namespace gv
{
@ -15,5 +17,6 @@ class MovementManager
public:
virtual ~MovementManager() = default;
virtual void PathEntitiesTo(const EntityList& entities, const PositionList& positions) = 0;
virtual void SetEntitySpeeds(const EntityList& entities, const std::vector<float>& speeds) = 0;
};
}

2
src/game/agent/combat/CombatComponentManager.cpp

@ -97,7 +97,7 @@ void CombatComponentManager::Update(float deltaSeconds)
{
float actionEndTime =
combatant.CurrentAction.ActivateTime + combatant.CurrentAction.Def->Duration;
if (gv::GetWorldTime() < actionEndTime)
if (gv::GetGameplayTime() < actionEndTime)
{
combatant.CurrentAction = {nullptr, nullptr, 0.f};
}

2
src/game/agent/combat/CombatComponentManager.hpp

@ -5,6 +5,8 @@
namespace gv
{
// @Latelink: CombatFx is a frontend-specific structure which will be provided to
// CombatFxHandler::OnActivateCombatAction() for frontend handling
typedef struct CombatFx CombatFx;
struct CombatActionDef

7
src/main.cpp

@ -7,13 +7,18 @@ int main()
return 0;
}
// Latelinked things
// @LatelinkDef Latelinked things
namespace gv
{
class CombatFx
{
};
float GetGameplayTime()
{
return 0.f;
}
float GetWorldTime()
{
return 0.f;

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

@ -9,7 +9,7 @@
"path": "../../../../galavant",
"name": "Galavant",
"folder_exclude_patterns": ["project", "thirdParty"],
"file_include_patterns": ["*.c", "*.cpp", "*.h", "*.hpp", "*.txt", "Jam*", "*.md"]
"file_include_patterns": ["*.c", "*.cpp", "*.h", "*.hpp", "*.txt", "Jam*", "*.md", "*.tasks"]
},
{
"path": "../../../../galavant-unreal/GalavantUnreal/Source",
@ -66,6 +66,14 @@
"syntax":"JamUnrealBuildOutput.sublime-syntax"
},
{
"name": "Full Build Debug (build Galavant lib and Unreal)",
"shell_cmd": "cd galavant && jam -j4 -q -sUNREAL=true GalavantPseudotarget && cd ../galavant-unreal/GalavantUnreal && make GalavantUnreal-Linux-Debug",
"working_dir": "$project_path/../../../..",
"file_regex": "^([a-zA-Z\/][^:\n]*):([0-9]+):?([0-9]+)?:? (.*)$",
"syntax":"JamUnrealBuildOutput.sublime-syntax"
},
//
// Galavant Unreal
//
@ -77,6 +85,15 @@
"syntax":"JamUnrealBuildOutput.sublime-syntax"
},
{
"name": "GalavantUnreal Build Debug",
"shell_cmd": "make GalavantUnreal-Linux-Debug",
"working_dir": "$project_path/../../../../galavant-unreal/GalavantUnreal",
"file_regex": "^([a-zA-Z\/][^:\n]*):([0-9]+):?([0-9]+)?:? (.*)$",
"syntax":"JamUnrealBuildOutput.sublime-syntax"
},
// This is useful when it complains that Linux headers have changed
{
"name": "GalavantUnreal Quick Clean",
"shell_cmd": "rm -r Intermediate/Build",
@ -92,7 +109,36 @@
{
"name": "GalavantUnreal Generate Project Files",
"shell_cmd": "/home/macoy/Development/code/3rdParty/repositories/UnrealEngine/GenerateProjectFiles.sh -project=/home/macoy/Development/code/repositories/galavant-unreal/GalavantUnreal/GalavantUnreal.uproject -game -editor",
"working_dir": "$project_path/../../../../galavant-unreal/GalavantUnreal"
"working_dir": "$project_path/../../../../galavant-unreal/GalavantUnreal",
"syntax":"JamUnrealBuildOutput.sublime-syntax"
},
//
// GalavantUnreal Standalone
//
{
"name": "GalavantUnreal Standalone Package",
"shell_cmd": "mono AutomationTool.exe -ScriptsForProject=/home/macoy/Development/code/repositories/galavant-unreal/GalavantUnreal/GalavantUnreal.uproject BuildCookRun -nocompile -nocompileeditor -nop4 -project=/home/macoy/Development/code/repositories/galavant-unreal/GalavantUnreal/GalavantUnreal.uproject -cook -stage -archive -archivedirectory=/home/macoy/Development/code/repositories/galavant-unreal/GalavantUnreal/LOCAL_package/package/ -package -clientconfig=Development -ue4exe=UE4Editor-Linux-Debug -pak -prereqs -nodebuginfo -nativizeAssets -targetplatform=Linux -build -utf8output",
// "working_dir": "$project_path/../../../../galavant-unreal/GalavantUnreal",
"working_dir": "/home/macoy/Development/code/3rdParty/repositories/UnrealEngine/Engine/Binaries/DotNET",
"syntax":"JamUnrealBuildOutput.sublime-syntax"
},
{
"name": "GalavantUnreal Standalone Package Debug",
"shell_cmd": "mono AutomationTool.exe -ScriptsForProject=/home/macoy/Development/code/repositories/galavant-unreal/GalavantUnreal/GalavantUnreal.uproject BuildCookRun -nocompile -nocompileeditor -nop4 -project=/home/macoy/Development/code/repositories/galavant-unreal/GalavantUnreal/GalavantUnreal.uproject -cook -stage -archive -archivedirectory=/home/macoy/Development/code/repositories/galavant-unreal/GalavantUnreal/LOCAL_package/package/ -package -clientconfig=Debug -ue4exe=UE4Editor-Linux-Debug -pak -prereqs -nativizeAssets -targetplatform=Linux -build -utf8output",
// "working_dir": "$project_path/../../../../galavant-unreal/GalavantUnreal",
"working_dir": "/home/macoy/Development/code/3rdParty/repositories/UnrealEngine/Engine/Binaries/DotNET",
"syntax":"JamUnrealBuildOutput.sublime-syntax"
},
{
"name": "Standalone Full Build Debug (build Galavant lib and Unreal)",
"shell_cmd": "cd galavant && jam -j4 -q -sUNREAL=true GalavantPseudotarget && cd ../galavant-unreal/GalavantUnreal && make GalavantUnreal-Linux-Debug && cp -r -u -v Binaries/ LOCAL_package/package/LinuxNoEditor/GalavantUnreal/",
"working_dir": "$project_path/../../../..",
"file_regex": "^([a-zA-Z\/][^:\n]*):([0-9]+):?([0-9]+)?:? (.*)$",
"syntax":"JamUnrealBuildOutput.sublime-syntax"
},
//
@ -113,6 +159,14 @@
"syntax":"JamUnrealBuildOutput.sublime-syntax"
},
{
"name": "Unreal Engine Build Debug",
"shell_cmd": "make UE4Editor-Linux-Debug",
"working_dir": "/home/macoy/Development/code/3rdParty/repositories/UnrealEngine",
"file_regex": "^([a-zA-Z\/][^:\n]*):([0-9]+):?([0-9]+)?:? (.*)$",
"syntax":"JamUnrealBuildOutput.sublime-syntax"
},
{
"name": "Unreal Engine Run (no debug)",
"shell_cmd": "./Engine/Binaries/Linux/UE4Editor",
@ -199,11 +253,17 @@
"commandline": "gdb --interpreter=mi ./UE4Editor /home/macoy/Development/code/repositories/galavant-unreal/GalavantUnreal/GalavantUnreal.uproject"
},
//"UnrealEditor Debug":
//{
// "workingdir": "/home/macoy/Development/code/3rdParty/repositories/UnrealEngine/Engine/Binaries/Linux",
// "commandline": "gdb --interpreter=mi ./UE4Editor-Linux-Debug /home/macoy/Development/code/repositories/galavant-unreal/GalavantUnreal/GalavantUnreal.uproject"
//},
"UnrealEditor Debug":
{
"workingdir": "/home/macoy/Development/code/3rdParty/repositories/UnrealEngine/Engine/Binaries/Linux",
"commandline": "gdb --interpreter=mi ./UE4Editor-Linux-Debug /home/macoy/Development/code/repositories/galavant-unreal/GalavantUnreal/GalavantUnreal.uproject"
},
"GalavantUnreal Standalone":
{
"workingdir": "/home/macoy/Development/code/repositories/galavant-unreal/GalavantUnreal",
"commandline": "gdb --interpreter=mi --args ./LOCAL_package/package/LinuxNoEditor/GalavantUnreal/Binaries/Linux/GalavantUnreal -windowed -resx=1920 -resy=1080"
},
//"htnTest":
//{

3
src/util/Jamfile

@ -4,6 +4,7 @@ SubDirC++Flags $(ALLLIBSC++FLAGS) ;
Library libGalaUtil : Logging.cpp
StringHashing.cpp
ResourceDictionary.cpp ;
ResourceDictionary.cpp
Time.cpp ;
MakeLocate libGalaUtil.a : lib ;

9
src/util/Logging.cpp

@ -89,7 +89,7 @@ Logger::Logger(Severity maxSeverity, CustomLogOutputFunc customOutputFunc)
: MaxSeverity(maxSeverity), CustomOutputFunc(customOutputFunc)
{
Singleton = this;
std::cout << "Logger initialized at " << Singleton << "\n";
// std::cout << "Logger initialized at " << Singleton << "\n";
}
bool Logger::checkSeverity(Severity severity) const
{
@ -110,9 +110,10 @@ void Logger::operator+=(const Record& record)
}
Logger* Logger::GetSingleton()
{
if (!Singleton)
std::cout << "Warning: something tried to access Logger before any Logger had been "
"initialized!\n";
// TODO: @Stability: This could be a problem. We can't print yet though...
// if (!Singleton)
// std::cout << "Warning: something tried to access Logger before any Logger had been "
// "initialized!\n";
return Singleton;
}

4
src/util/Math.hpp

@ -1,5 +1,5 @@
#pragma once
#define CLAMP(value, min, max) if (value > max) value = max; else if (value < min) value = min;
#define MIN(a, b) a <= b ? a : b;
#define MAX(a, b) a >= b ? a : b;
#define MIN(a, b) (a <= b ? a : b)
#define MAX(a, b) (a >= b ? a : b)

60
src/util/Time.cpp

@ -0,0 +1,60 @@
#include "Time.hpp"
namespace gv
{
struct GameplayTimeManager
{
// The difference between gameplay time and world time. This makes sure gameplay time stays
// ignorant of pausing
float GameplayTimeWorldTimeDelta;
bool IsPlaying;
float PausedAtWorldTime;
};
static GameplayTimeManager s_GameplayTimeManager;
float GetGameplayTime()
{
if (s_GameplayTimeManager.IsPlaying)
{
return GetWorldTime() - s_GameplayTimeManager.GameplayTimeWorldTimeDelta;
}
else
{
// If we're paused, we want to return the same time regardless of world time
return s_GameplayTimeManager.PausedAtWorldTime -
s_GameplayTimeManager.GameplayTimeWorldTimeDelta;
}
}
bool GameIsPlaying()
{
return s_GameplayTimeManager.IsPlaying;
}
void GameSetPlaying(bool shouldPlay)
{
// Pausing
if (!shouldPlay && s_GameplayTimeManager.IsPlaying)
{
s_GameplayTimeManager.PausedAtWorldTime = GetWorldTime();
}
// Resuming
else if (shouldPlay && !s_GameplayTimeManager.IsPlaying)
{
float thisPauseTimeDelta =
GetWorldTime() - s_GameplayTimeManager.GameplayTimeWorldTimeDelta;
s_GameplayTimeManager.GameplayTimeWorldTimeDelta += thisPauseTimeDelta;
}
s_GameplayTimeManager.IsPlaying = shouldPlay;
}
void ResetGameplayTime()
{
s_GameplayTimeManager.GameplayTimeWorldTimeDelta = 0.f;
s_GameplayTimeManager.IsPlaying = true;
s_GameplayTimeManager.PausedAtWorldTime = 0.f;
}
}

14
src/util/Time.hpp

@ -2,5 +2,19 @@
namespace gv
{
// Get the time for any gameplay purposes. This is affected by pausing/time step scaling.
float GetGameplayTime();
bool GameIsPlaying();
// If shouldPlay = false gameplay is paused
void GameSetPlaying(bool shouldPlay);
void ResetGameplayTime();
// @Latelink: GetWorldTime() is a front-end specific function. It should return the amount of time
// since the game/world started. This value should NOT respect any Gameplay timing or pausing
// This should not be used for gameplay. Use GetGameplayTime() instead
float GetWorldTime();
}
Loading…
Cancel
Save