#include "testfwk/Fwk.h"
#include "labengine/utils/labengineutils.h"
namespace
{
class MyGameEntity
{
public:
MyGameEntity()
: m_startPosition(0.0f, 0.0f, 0.0f)
, m_destinationPosition(0.0f, 0.0f, 0.0f)
, m_position(0.0f, 0.0f, 0.0f)
, m_velocity(0.0f, 0.0f, 0.0f)
, m_navBot(nullptr)
{}
void Destroy();
void UpdateLogic(
KyFloat32 simulationStepsInSeconds);
void UpdatePhysics(
KyFloat32 simulationStepsInSeconds);
bool HasArrived();
public:
Kaim::Ptr<Kaim::Bot> m_navBot;
};
{
m_position = startPosition;
m_startPosition = startPosition;
m_destinationPosition = destination;
botInitConfig.
m_startPosition = m_position;
m_navBot->Init(botInitConfig);
m_navBot->SetCurrentVisualDebugLOD(Kaim::VisualDebugLOD_Maximal);
m_navBot->AddToDatabase();
}
void MyGameEntity::Destroy()
{
if (m_navBot)
{
m_navBot->RemoveFromDatabase();
m_navBot = nullptr;
}
}
{
if (m_navBot->GetFollowedPath() == nullptr && m_navBot->IsComputingPath() == false)
{
m_navBot->ComputeAStarQueryAsync(m_destinationPosition);
}
if (HasArrived())
{
m_navBot->ClearFollowedPath();
m_destinationPosition = m_startPosition;
m_startPosition = swap;
m_navBot->ComputeAStarQueryAsync(m_destinationPosition);
}
}
void MyGameEntity::UpdatePhysics(
KyFloat32 simulationStepsInSeconds)
{
m_velocity = m_navBot->GetBotOutput().m_outputVelocity;
m_position = m_navBot->ComputeMoveOnNavMesh(m_velocity, simulationStepsInSeconds);
m_navBot->SetPositionAndVelocityAndFrontDirection(m_position, simulationStepsInSeconds);
}
bool MyGameEntity::HasArrived()
{
KyFloat32 arrivalPrecisionRadius = m_navBot->GetConfig().m_pathProgressConfig.m_checkPointRadius;
if (m_navBot->HasReachedPosition(m_destinationPosition, arrivalPrecisionRadius))
{
return true;
}
return false;
}
class MyGameLevel
{
public:
MyGameLevel()
: m_navData(nullptr)
, m_astarQuery(nullptr)
{
}
void UpdateLogic(float deltaTimeInSeconds);
void UpdatePhysics(float deltaTimeInSeconds);
void Destroy();
protected:
Kaim::Ptr<Kaim::NavData> m_navData;
Kaim::Ptr<Kaim::AStarQuery<Kaim::DefaultTraverseLogic> > m_astarQuery;
MyGameEntity m_entity;
};
{
Kaim::Ptr<Kaim::File> kaimFile;
const std::string navdataFilePath = NavTest::Dirs::AbsoluteInputDir + "generated/castle/castle.NavData";
if(kaimFile == nullptr)
return false;
loadingResult = m_navData->Load(kaimFile);
kaimFile ->Close();
kaimFile = nullptr;
return false;
m_navData->AddToDatabaseImmediate();
m_entity.Initialize(world,
Kaim::Vec3f(-11.5963f,1.06987f,10.4563f),
Kaim::Vec3f(-16.636f,-26.7078f,8.10107f));
return true;
}
{
if(m_astarQuery->m_processStatus == Kaim::QueryNotStarted)
{
m_astarQuery->Initialize(startPos, destPos);
m_astarQuery->PerformQueryBlocking();
}
else if (m_astarQuery->m_processStatus == Kaim::QueryDone)
{
switch( result )
{
{
break;
}
default:
displayList.PushLine(startPos, destPos , Kaim::Color::Red);
break;
}
m_astarQuery->SendVisualDebug();
}
}
{
if (m_astarQuery->m_processStatus == Kaim::QueryDone)
{
{
if (resultPath->
GetEdgeCount() == 0)
return;
ratio += 0.00005f;
if (ratio > 1.0f)
ratio = 0.0f;
KyFloat32 positionRatio = ratio * resultPath->GetEdgeCount();
Kaim::Vec3f edgeStart = resultPath->
GetNodePosition(currentEdge);
Kaim::Vec3f edgeEnd = resultPath->GetNodePosition(currentEdge + 1);
Kaim::Vec3f objectPosition = edgeStart + (positionRatio - currentEdge) * (edgeEnd - edgeStart);
displayList.PushArrowTube(objectPosition.
OffsetZ(2.0f), objectPosition, 0.05f,
}
}
}
void MyGameLevel::UpdateLogic(float deltaTimeInSeconds)
{
TestAStarQuery(m_entity.m_navBot->GetWorld());
TestPath(m_entity.m_navBot->GetWorld());
m_entity.UpdateLogic(deltaTimeInSeconds);
}
void MyGameLevel::UpdatePhysics(float deltaTimeInSeconds)
{
m_entity.UpdatePhysics(deltaTimeInSeconds);
}
void MyGameLevel::Destroy()
{
m_entity.Destroy();
if (m_navData)
{
m_navData->RemoveFromDatabaseImmediate();
m_navData = nullptr;
}
m_astarQuery = nullptr;
}
class MyGameWorld
{
public:
MyGameWorld() : m_gameFrameIdx(0), m_navWorld(nullptr) {}
bool Initialize(bool doVisualDebugTutorial);
void Update(float deltaTimeInSeconds);
void Destroy();
private:
void UpdateLogic(float deltaTimeInSeconds);
void UpdateNavigation(float deltaTimeInSeconds);
void UpdatePhysics(float deltaTimeInSeconds);
void TestVisualDebugger();
public:
Kaim::Ptr<Kaim::World> m_navWorld;
MyGameLevel m_gameLevel;
};
bool MyGameWorld::Initialize(bool doVisualDebugTutorial)
{
m_coordSystem.Setup(oneMeterInClientUnits, clientAxisForX, clientAxisForY, clientAxisForZ);
KY_UNUSED(doVisualDebugTutorial);
#if defined(KY_CONFIG_DEBUG_OR_DEV)
if (doVisualDebugTutorial)
{
const KyUInt32 serverPort = Kaim::VisualDebugServerConfig::DefaultServerPort();
KyResult startResult = m_navWorld->StartVisualDebug(visualDebugServerConfig);
{
return false;
}
}
#endif
return m_gameLevel.Initialize(m_navWorld);
}
void MyGameWorld::Update(float deltaTimeInSeconds)
{
m_navWorld->NewVisualDebugFrame(m_gameFrameIdx);
++m_gameFrameIdx;
UpdateLogic(deltaTimeInSeconds);
UpdateNavigation(deltaTimeInSeconds);
UpdatePhysics(deltaTimeInSeconds);
TestVisualDebugger();
}
void MyGameWorld::UpdateLogic(float deltaTimeInSeconds) { m_gameLevel.UpdateLogic(deltaTimeInSeconds); }
void MyGameWorld::UpdateNavigation(float deltaTimeInSeconds) { m_navWorld->Update(deltaTimeInSeconds); }
void MyGameWorld::UpdatePhysics(float deltaTimeInSeconds) { m_gameLevel.UpdatePhysics(deltaTimeInSeconds); }
void MyGameWorld::Destroy()
{
m_gameLevel.Destroy();
m_navWorld->StopVisualDebug();
m_navWorld = nullptr;
}
void MyGameWorld::TestVisualDebugger()
{
#if defined(KY_CONFIG_DEBUG_OR_DEV)
Kaim::VisualDebugServer* visualDebugServer = m_navWorld->GetVisualDebugServer();
if (visualDebugServer == nullptr || visualDebugServer->IsReadyToSend() == false)
return;
const char* myCategoryName = "MyGame";
KY_LOG_MESSAGE(("FrameCount: %d", framecount));
framecount++;
visualDebugServer->SendUInt32("SomeKindOfInformation", someKindOfInformation, myCategoryName);
const char* someKindOfStat = "SomeKindOfStat";
visualDebugServer->SendStats(someKindOfStat, currentValue, averageValue, maxValue, minValue, myCategoryName);
boxLowerCornerPosition = m_coordSystem.ClientToNavigation_Pos( boxLowerCornerPosition );
boxExtents = m_coordSystem.ClientToNavigation_Pos( boxExtents );
positionA = m_coordSystem.ClientToNavigation_Pos( positionA );
positionB = m_coordSystem.ClientToNavigation_Pos( positionB );
radius = m_coordSystem.ClientToNavigation_Dist( radius );
height = m_coordSystem.ClientToNavigation_Dist( height );
{
}
{
displayList.PushVerticalOctogon(positionA, height, radius, Kaim::ShapeColor::FillAndLine(Kaim::Color::Yellow));
displayList.PushLine(positionA, positionB, Kaim::Color::Red);
Kaim::Box3f someBox(boxLowerCornerPosition, boxLowerCornerPosition + boxExtents);
displayList.PushBox(someBox, Kaim::ShapeColor::FillAndLine(Kaim::Color::Green));
}
#endif
}
class MyGame
{
public:
~MyGame()
{
m_gameWorld.Destroy();
}
bool Initialize(bool doVisualDebugTutorial)
{
{
return false;
}
return m_gameWorld.Initialize(doVisualDebugTutorial);
}
void Update(float deltaTimeInSeconds)
{
m_gameWorld.Update(deltaTimeInSeconds);
}
bool HasFinished()
{
if (m_gameWorld.m_navWorld->GetVisualDebugServer() != nullptr)
return m_gameWorld.m_navWorld->GetVisualDebugServer()->IsConnectionEstablished() == false;
else
return m_gameWorld.m_gameFrameIdx >= 60;
}
protected:
MyGameWorld m_gameWorld;
};
#define KT_TEST_ENV_CLASS NavTest::Env
KT_TEST_ENV {}
KT_TUTORIAL
{
KT_LOG_TITLE_BEGIN("TUTORIAL - First Integration Test");
MyGame myGame;
bool doVisualDebugTutorial = false;
KT_ASSERT(myGame.Initialize(doVisualDebugTutorial));
const KyFloat32 loopDurationInSecond = 1.0f / 60.0f;
while (myGame.HasFinished() == false)
{
myGame.Update(loopDurationInSecond);
LabEngine::Utils::TimedBusyWait(1000.0f * loopDurationInSecond);
}
}
}