⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 directionmap.h

📁 游戏开发数据结构-Data.Structures.for.Game.Programmers
💻 H
📖 第 1 页 / 共 2 页
字号:
                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 + -