Upstream for PGE updates.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
olcPixelGameEngine/Videos/CarCrimeCity/Part2/cAutomata.cpp

207 lines
5.2 KiB

#include "cAutomata.h"
cAuto_Node::cAuto_Node()
{
pos = { 0,0 };
}
cAuto_Node::cAuto_Node(const olc::vf2d &worldpos)
{
pos = worldpos;
}
olc::vf2d cAuto_Track::GetPostion(float t, cAuto_Node *pStart)
{
// pStart indicates the node the automata first encounted this track
if (node[0] == pStart)
{
return node[0]->pos + (node[1]->pos - node[0]->pos) * (t / fTrackLength);
}
else
{
return node[1]->pos + (node[0]->pos - node[1]->pos) * (t / fTrackLength);
}
}
cAuto_Body::cAuto_Body()
{
}
cAuto_Body::~cAuto_Body()
{
}
void cAuto_Body::UpdateAuto(float fElapsedTime)
{
// Work out which node is the target destination
cAuto_Node *pExitNode = pCurrentTrack->node[0];
if (pExitNode == pTrackOriginNode)
pExitNode = pCurrentTrack->node[1];
bool bAutomataCanMove = true;
float fDistanceToAutoInFront = 1.0f;
// First check if the vehicle overlaps with the one in front of it
// Get an iterator for this automata
auto itThisAutomata = std::find(pCurrentTrack->listAutos.begin(), pCurrentTrack->listAutos.end(), this);
// If this automata is at the front of this track segment
if (*itThisAutomata == pCurrentTrack->listAutos.front())
{
// Then check all the following track segments. Take the position of
// each vehicle at the back of the track segments auto list
for (auto &track : pExitNode->listTracks)
{
if (track != pCurrentTrack && !track->listAutos.empty())
{
// Get Auto at back
float fDistanceFromTrackStartToAutoRear = track->listAutos.back()->fAutoPos - track->listAutos.back()->fAutoLength;
if ((*itThisAutomata)->fAutoPos < (pCurrentTrack->fTrackLength + fDistanceFromTrackStartToAutoRear - fAutoLength))
{
// Move Automata along track, as there is space
//bAutomataCanMove = true;
fDistanceToAutoInFront = (pCurrentTrack->fTrackLength + fDistanceFromTrackStartToAutoRear - 0.1f) - (*itThisAutomata)->fAutoPos;
}
else
{
// No space, so do not move automata
bAutomataCanMove = false;
}
}
else
{
// Track in front was empty, node is clear to pass through so
//bAutomataCanMove = true;
}
}
}
else
{
// Get the automata in front
auto itAutomataInFront = itThisAutomata;
itAutomataInFront--;
// If the distance between the front of the automata in front and the fornt of this automata
// is greater than the length of the automata in front, then there is space for this automata
// to enter
if (fabs((*itAutomataInFront)->fAutoPos - (*itThisAutomata)->fAutoPos) > ((*itAutomataInFront)->fAutoLength + 0.1f))
{
// Move Automata along track
//bAutomataCanMove = true;
fDistanceToAutoInFront = ((*itAutomataInFront)->fAutoPos - (*itAutomataInFront)->fAutoLength - 0.1f) - (*itThisAutomata)->fAutoPos;
}
else
{
// No space, so do not move automata
bAutomataCanMove = false;
}
}
if (bAutomataCanMove)
{
if (fDistanceToAutoInFront > pCurrentTrack->fTrackLength) fDistanceToAutoInFront = pCurrentTrack->fTrackLength;
fAutoPos += fElapsedTime * std::max(fDistanceToAutoInFront, 1.0f) * (fAutoLength < 0.1f ? 0.3f : 0.5f);
}
if (fAutoPos >= pCurrentTrack->fTrackLength)
{
// Automata has reached end of current track
// Check if it can transition beyond node
if (!pExitNode->bBlock)
{
// It can, so reset position along track back to start
fAutoPos -= pCurrentTrack->fTrackLength;
// Choose a track from the node not equal to this one, that has an unblocked exit node
// For now choose at random
cAuto_Track *pNewTrack = nullptr;
if (pExitNode->listTracks.size() == 2)
{
// Automata is travelling along straight joined sections, one of the
// tracks is the track its just come in on, the other is the exit, so
// choose the exit.
auto it = pExitNode->listTracks.begin();
pNewTrack = (*it);
if (pCurrentTrack == pNewTrack)
{
++it;
pNewTrack = (*it);
}
}
else
{
// Automata has reached a junction with several exits
while (pNewTrack == nullptr)
{
int i = rand() % pExitNode->listTracks.size();
int j = 0;
for (auto it = pExitNode->listTracks.begin(); it != pExitNode->listTracks.end(); ++it)
{
cAuto_Track* track = (*it);
// Work out which node is the target destination
cAuto_Node *pNewExitNode = track->node[0];
if (pNewExitNode == pExitNode)
pNewExitNode = track->node[1];
if (j == i && track != pCurrentTrack && !pNewExitNode->bBlock /*((*it)->cell != pCurrentTrack->cell)*/)
{
pNewTrack = track;
break;
}
j++;
}
}
}
// Change to new track, the origin node of the next
// track is the same as the exit node to the current track
pTrackOriginNode = pExitNode;
// Remove the automata from the front of the queue
// on the current track
pCurrentTrack->listAutos.pop_front();
// Switch the automatas track link to the new track
pCurrentTrack = pNewTrack;
// Push the automata onto the back of the new track queue
pCurrentTrack->listAutos.push_back(this);
}
else
{
// It cant pass the node, so clamp automata at this location
fAutoPos = pCurrentTrack->fTrackLength;
}
}
else
{
// Automata is travelling
vAutoPos = pCurrentTrack->GetPostion(fAutoPos, pTrackOriginNode);
}
}