ase_losapproxboard.cpp
来自「A*算法的演示程序」· C++ 代码 · 共 637 行 · 第 1/2 页
CPP
637 行
const int kEntries = GetNumberOfColumns() * GetNumberOfRows();
for ( unsigned int idx = 0; idx < kEntries; ++idx )
{
unsigned int row;
unsigned int col;
GetRowAndColumnForIndex(idx, row, col);
if ( m_kTerrainBoard->IsLocationImpassable(row, col) )
{
ASE_CoordPair pos(row, col);
m_ObstaclePositions.push_back(pos);
}
}
}
bool ASE_LOSApproximationBoard::IsAnyObstacleWithinRange(int x, int y, int theRange) const
{
const int rangeSqr = theRange * theRange;
CoordPairList::const_iterator pos;
for ( pos = m_ObstaclePositions.begin();
pos != m_ObstaclePositions.end();
++pos
)
{
int dx;
int dy;
int dsqr;
dx = pos->x - x;
dy = pos->y - y;
dsqr = dx * dx + dy * dy;
if ( dsqr <= rangeSqr )
return true;
}
return false;
}
bool ASE_LOSApproximationBoard::IsAnyObstacleWithinRangeAndSector(int x, int y, int theRange, unsigned int aSector) const
{
const int rangeSqr = theRange * theRange;
CoordPairList::const_iterator pos;
for ( pos = m_ObstaclePositions.begin();
pos != m_ObstaclePositions.end();
++pos
)
{
int dx;
int dy;
int dsqr;
dx = pos->x - x;
dy = pos->y - y;
dsqr = dx * dx + dy * dy;
if ( dsqr > rangeSqr )
continue;
unsigned int sector;
sector = ASE_LineOfSightScan::GetSectorForLine(dx, dy);
if ( sector == aSector )
return true;
}
return false;
}
unsigned int ASE_LOSApproximationBoard::GetDistanceToNearestObstacleWithinRangeAndSector(int x, int y, int theRange, unsigned int aSector) const
{
const int rangeSqr = theRange * theRange;
int minSqr = ( (theRange + 1) * (theRange + 1) );
CoordPairList::const_iterator pos;
for ( pos = m_ObstaclePositions.begin();
pos != m_ObstaclePositions.end();
++pos
)
{
int dx;
int dy;
int dsqr;
dx = pos->x - x;
dy = pos->y - y;
dsqr = dx * dx + dy * dy;
if ( dsqr > rangeSqr )
continue;
unsigned int sector;
sector = ASE_LineOfSightScan::GetSectorForLine(dx, dy);
if ( sector == aSector )
{
minSqr = min(minSqr, dsqr);
}
}
return static_cast<unsigned int>(minSqr);
}
void ASE_LOSApproximationBoard::SetLocationAsLackingAnyCover(int x, int y)
{
ASE_LineOfSightScan los;
los.SetNoCoverAtAll();
unsigned int idx;
idx = GetIndexForRowColumn(x, y);
m_LineOfSightScanInfos[idx] = los;
}
void ASE_LOSApproximationBoard::ApproximateLOFForLocationBySector(int x, int y)
{
unsigned int idx;
idx = GetIndexForRowColumn(x, y);
m_LineOfSightScanInfos[idx].Clear();
for ( unsigned int sector = 0; sector < ASE_LineOfSightScan::GetNumberOfSectors(); ++sector )
{
unsigned int obstSqr;
obstSqr = GetDistanceToNearestObstacleWithinRangeAndSector(x, y, m_kThreatBoard->GetMaxThreatReach(), sector);
if ( ( ASE_LineOfSightScan::IsOutOfReachSqrd(obstSqr) )
|| ( ASE_LineOfSightScan::IsAFarDistanceSqrd(obstSqr) )
)
{
m_LineOfSightScanInfos[idx].UpdateSector(sector, ASE_LineOfSightScan::eObservedFromFarDistance);
}
else
{
ComputeSectorLOSForLocation(x, y, sector, m_kThreatBoard->GetMaxThreatReach());
}
}
}
void ASE_LOSApproximationBoard::ComputeSectorLOSForLocation(int x, int y, unsigned int aSector, unsigned int aRange)
{
// try each applicable ray from the template for this sector, until getting a eObservedFromFarDistance
const ASE_PieScan* pie = m_kThreatBoard->GetLineOfSightTemplate();
unsigned int nr_of_rays;
nr_of_rays = pie->GetNumberOfRays();
ASE_CoordPair here(x, y);
CoordPairList raytrace;
const int minmaxdistsqr = static_cast<int>(aRange * aRange);
int maxdistsqr = 0;
for ( unsigned int ray = 0; ray < nr_of_rays; ++ray )
{
if ( pie->IsRayInSector(ray, aSector) )
{
raytrace.clear();
pie->GetRayForLocation(ray, here, raytrace);
CoordPairList::const_iterator pos;
for ( pos = raytrace.begin();
pos != raytrace.end();
++pos
)
{
if ( !IsValidBoardLocation(pos->x, pos->y) )
break;
if ( m_kTerrainBoard->IsLocationImpassable(pos->x, pos->y) )
break;
}
// determine distance sqr
if ( ( pos != raytrace.end() )
&& ( pos != raytrace.begin() )
)
{
int dx;
int dy;
int dsqr;
dx = pos->x - x;
dy = pos->y - y;
dsqr = (dx * dx) + (dy * dy);
maxdistsqr = max(maxdistsqr, dsqr);
}
else
if ( pos == raytrace.end() )
{
maxdistsqr = minmaxdistsqr;
}
// test for bail out
if ( maxdistsqr >= minmaxdistsqr )
break;
}
}
// check max distance, and set los accordingly
ASE_LineOfSightScan::ScanValue value;
if ( ( ASE_LineOfSightScan::IsOutOfReachSqrd(maxdistsqr) )
|| ( ASE_LineOfSightScan::IsAFarDistanceSqrd(maxdistsqr) )
)
value = ASE_LineOfSightScan::eObservedFromFarDistance;
else
if ( maxdistsqr == 0 )
value = ASE_LineOfSightScan::eNotObserved;
else
if ( ASE_LineOfSightScan::IsAMediumDistanceSqrd(maxdistsqr) )
value = ASE_LineOfSightScan::eObservedFromMediumDistance;
else
value = ASE_LineOfSightScan::eObservedFromNearDistance;
unsigned int idx;
idx = GetIndexForRowColumn(x, y);
m_LineOfSightScanInfos[idx].UpdateSector(aSector, value);
}
void ASE_LOSApproximationBoard::UpdateBoard()
{
/*! now update the board values, signaling danger positions
given current threats
1. set all cells to safe (0)
2. iterate over each threat
- then iterate over every position within reach of the threat
- if position is visible by threat, mark as danger
*/
const int kEntries = GetNumberOfColumns() * GetNumberOfRows();
CoordPairList kThreatPositions;
m_kThreatBoard->GetThreatPositions(kThreatPositions);
for ( unsigned int idx = 0; idx < kEntries; ++idx )
{
unsigned int row;
unsigned int col;
GetRowAndColumnForIndex(idx, row, col);
CellValue value;
value = 0;
// iterate over all known threats, and update value accordingly
CoordPairList::const_iterator threat;
for ( threat = kThreatPositions.begin();
threat != kThreatPositions.end();
++threat
)
{
ASE_LineOfSightScan::ScanValue los1;
ASE_LineOfSightScan::ScanValue los2;
los1 = m_LineOfSightScanInfos[idx].GetObservationFromPosition(row, col, threat->x, threat->y);
unsigned int jdx;
jdx = GetIndexForRowColumn(threat->x, threat->y);
los2 = m_LineOfSightScanInfos[jdx].GetObservationFromPosition(threat->x, threat->y, row, col);
if ( ( los1 != ASE_LineOfSightScan::eNotObserved )
&& ( los2 != ASE_LineOfSightScan::eNotObserved )
)
{
value = max(value, static_cast<CellValue>(los1));
}
}
// skip over 'green' value
if ( value > 0 )
value++;
SetCellValue(idx, value);
}
}
/*
void ASE_LOSApproximationBoard::ComputeLinesOfFireApproximation()
{
ComputeLinesOfFireApproximation2();
if ( !DidAnythingChange() )
return;
ASE_LineOfSightScan::SetThreatReachDistance(m_kThreatBoard->GetMaxThreatReach());
int minx;
int miny;
int maxx;
int maxy;
GetChangeRange(minx, miny, maxx, maxy);
// adjust for threat range
minx = max(0, minx - m_kThreatBoard->GetMaxThreatReach());
miny = max(0, miny - m_kThreatBoard->GetMaxThreatReach());
maxx = min(-1 + GetNumberOfColumns(), maxx + m_kThreatBoard->GetMaxThreatReach());
maxy = min(-1 + GetNumberOfRows(), maxy + m_kThreatBoard->GetMaxThreatReach());
InitObserversLOS(minx, miny, maxx, maxy);
// fall back on original area
GetChangeRange(minx, miny, maxx, maxy);
minx = max(0, minx);
miny = max(0, miny);
maxx = min(-1 + GetNumberOfColumns(), maxx);
maxy = min(-1 + GetNumberOfRows(), maxy);
ProcessLocations(minx, miny, maxx, maxy);
UpdateBoard(minx, miny, maxx, maxy);
ResetChangeRange();
}
*/
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?