📄 directionmap.h
字号:
SDLBlit( item->GetGraphic(), p_surface, px, py );
if( person != 0 )
SDLBlit( person->GetGraphic(), p_surface, px, py );
}
}
// -------------------------------------------------------
// Name: CanMove
// Description: Determines if the given person can move
// in the given direction
// -------------------------------------------------------
bool CanMove( Person* p_person, int p_direction )
{
return CanMove( p_person->GetCell(), p_direction );
}
bool CanMove( int p_cell, int p_direction )
{
int cell = GetCellNumber( p_cell, p_direction );
if( cell == -1 )
return false;
// check to see if the path is blocked or not.
if( m_rooms[cell].m_blocked == true )
return false;
// check to see if there is a person blocking the way
if( m_rooms[cell].m_person != 0 )
return false;
// check to see if there in an item blocking the way
if( m_rooms[cell].m_item != 0 )
{
// some items can block, others can't
if( m_rooms[cell].m_item->CanBlock() == true )
return false;
}
return true;
}
// -------------------------------------------------------
// Name: Move
// Description: Moves the given person in the given
// direction
// -------------------------------------------------------
void Move( Person* p_person, int p_direction )
{
int newcell;
// make sure the player can move
if( CanMove( p_person, p_direction ) == true )
{
// get the number of the new cell
newcell = GetCellNumber( p_person->GetCell(), p_direction );
// move the person to the new cell
m_rooms[newcell].m_person = p_person;
// clear the person pointer in the old cell
m_rooms[p_person->GetCell()].m_person = 0;
// set the new x, y, and cell variables
p_person->SetX( m_rooms[newcell].m_x );
p_person->SetY( m_rooms[newcell].m_y );
p_person->SetCell( newcell );
}
}
// -------------------------------------------------------
// Name: GetItem
// Description: Gets a pointer to the item in the given
// cell
// -------------------------------------------------------
Item* GetItem( int p_cell )
{
// check to see if the cell is in bounds first
if( p_cell >= GetNumberOfCells() || p_cell < 0 )
return 0;
return m_rooms[p_cell].m_item;
}
// -------------------------------------------------------
// Name: SetItem
// Description: Sets the item in the given cell.
// -------------------------------------------------------
void SetItem( int p_cell, Item* p_item )
{
// check to see if the cell is in bounds first
if( p_cell >= GetNumberOfCells() || p_cell < 0 )
return;
m_rooms[p_cell].m_item = p_item;
}
// -------------------------------------------------------
// Name: GetPerson
// Description: Gets a pointer to the person in the given
// cell
// -------------------------------------------------------
Person* GetPerson( int p_cell )
{
// check to see if the cell is in bounds first
if( p_cell >= GetNumberOfCells() || p_cell < 0 )
return 0;
return m_rooms[p_cell].m_person;
}
// -------------------------------------------------------
// Name: SetPerson
// Description: sets the person in the given cell.
// -------------------------------------------------------
void SetPerson( int p_cell, Person* p_person )
{
// check to see if the cell is in bounds first
if( p_cell >= GetNumberOfCells() || p_cell < 0 )
return;
m_rooms[p_cell].m_person = p_person;
}
// -------------------------------------------------------
// Name: GetCellNumber
// Description: Gets the number of the cell in the
// given direction
// -------------------------------------------------------
int GetCellNumber( int p_cell, int p_direction )
{
return m_rooms[p_cell].m_exits[p_direction];
}
// -------------------------------------------------------
// Name: GetNumberOfCells
// Description: Gets the number of cells in the map
// -------------------------------------------------------
int GetNumberOfCells()
{
return m_rooms.Size();
}
// -------------------------------------------------------
// Name: GetClosestDirection
// Description: Gets the direction that will move the
// first person closer to the second person.
// -------------------------------------------------------
int GetClosestDirection( Person* p_one, Person* p_two )
{
// calculate the path between the two persons
AStar( p_one, p_two );
int lastcell, cell, d;
// now follow the path from the goal to the start
cell = p_two->GetCell();
// loop through the path while the current cell
// isn't the goal.
while( cell != p_one->GetCell() )
{
// save the last cell number
lastcell = cell;
// calculate the next cell number
cell = m_rooms[cell].m_lastcell;
if( cell == -1 )
{
// the path is unreachable, so return a random
// direction.
// this makes the AI seem frustrated.
return rand() % 4;
}
}
// the path was reached, so calculate which direction the person
// needs to move to get closer.
for( d = 0; d < 4; d++ )
{
if( lastcell == m_rooms[cell].m_exits[d] )
return d;
}
// if execution reaches this point, you're in trouble.
// theoretically, this should never get here. This is
// a good place to add error-detection code.
}
// =======================================================
// Pathfinding Functions
// =======================================================
// -------------------------------------------------------
// Name: ClearCells
// Description: Clears all the pathfinding information
// for each cell
// -------------------------------------------------------
void ClearCells()
{
int x;
for( x = 0; x < m_rooms.Size(); x++ )
{
m_rooms[x].m_marked = false;
m_rooms[x].m_distance = 0.0f;
m_rooms[x].m_lastcell = -1;
}
}
// -------------------------------------------------------
// Name: Heuristic
// Description: Computes the Heuristic for the cell
// -------------------------------------------------------
float Heuristic( int p_cell, int p_goal )
{
// note that this algorithm assumes that the cell
// will be valid.
return Distance( m_rooms[p_cell].m_x,
m_rooms[p_cell].m_y,
m_rooms[p_goal].m_x,
m_rooms[p_goal].m_y );
}
// -------------------------------------------------------
// Name: AStar
// Description: calculates the path from one cell to
// another using the A* pathfinder
// -------------------------------------------------------
void AStar( Person* p_one, Person* p_two )
{
CellCoordinate c;
int cell;
int adjacentcell;
int dir;
float distance;
static Heap<CellCoordinate> queue( 1024, CompareCellCoordinates );
// clear the queue
queue.m_count = 0;
// clear the cells first.
ClearCells();
// enqueue the starting cell in the queue
c.cell = p_one->GetCell();
queue.Enqueue( c );
// start the main loop
while( queue.m_count != 0 )
{
// pull the first cell off the queue and process it.
cell = queue.Item().cell;
queue.Dequeue();
// make sure the cell isn't already marked. If it is, do
// nothing.
if( m_rooms[cell].m_marked == false )
{
// mark the cell as it is pulled off the queue.
m_rooms[cell].m_marked = true;
// quit out if the goal has been reached.
if( cell == p_two->GetCell() )
break;
// loop through each direction.
for( dir = 0; dir < 4; dir++ )
{
// retrieve the index of the current adjacent cell
adjacentcell = m_rooms[cell].m_exits[dir];
// check to see if the adjacent cell passable,
// and not marked.
// note that the CanMove function will return false
// when adjacentcell is the same as the goal, since there
// is a person on that cell. Therefore, you need to make
// a special exception to allow that cell to be processed.
if( ( CanMove( cell, dir ) &&
m_rooms[adjacentcell].m_marked == false ) ||
adjacentcell == p_two->GetCell() )
{
// calculate the distance to get into this cell.
distance = m_rooms[cell].m_distance + 1;
// check if the node has already been calculated before
if( m_rooms[adjacentcell].m_lastcell != -1 )
{
// the cell has already been calculated, see if the
// new distance is shorter. If so, update the links.
if( distance < m_rooms[adjacentcell].m_distance )
{
// the new distance is shorter, update the links
m_rooms[adjacentcell].m_lastcell = cell;
m_rooms[adjacentcell].m_distance = distance;
// add the cell to the queue.
c.cell = adjacentcell;
c.heuristic = distance +
Heuristic( adjacentcell,
p_two->GetCell() );
queue.Enqueue( c );
}
}
else
{
// set the links and the distance
m_rooms[adjacentcell].m_lastcell = cell;
m_rooms[adjacentcell].m_distance = distance;
// add the cell to the queue.
c.cell = adjacentcell;
c.heuristic = distance +
Heuristic( adjacentcell,
p_two->GetCell() );
queue.Enqueue( c );
}
}
}
}
}
}
};
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -