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

📄 gd23-05.cpp

📁 游戏开发数据结构-Data.Structures.for.Game.Programmers
💻 CPP
字号:
// ============================================================================
//  GD23-01.cpp
//  Pathfinding Demo
// ============================================================================
#include "SDLGUI.h"
#include <stdlib.h>
#include <time.h>
#include "Array2D.h"
#include "Queue.h"
#include "Pathfinding.h"

// ============================================================================
//  Global Constants
// ============================================================================
const char PROGRAM_NAME[]   = "Pathfinding Graphical Demonstration";
const int WIDTH             = 800;
const int HEIGHT            = 600;
const int ITEMS             = 32;
const int ARIAL             = 0;
const int MAPX              = 32;
const int MAPY              = 20;


// ============================================================================
//  classes
// ============================================================================


// ============================================================================
//  Global Variables
// ============================================================================
SDLGUI* g_gui;

SDL_Surface* g_blackbox = 0;
SDL_Surface* g_redbox = 0;
SDL_Surface* g_greenbox = 0;
SDL_Surface* g_bluebox = 0;
SDL_Surface* g_wallbox = 0;
SDL_Surface* g_start = 0;
SDL_Surface* g_goal = 0;

Array2D<Cell> g_map( MAPX, MAPY );

int g_startx = -1, 
    g_starty = -1;
int g_goalx = -1, 
    g_goaly = -1;
int g_currentx = -1,
    g_currenty = -1;

bool g_processing = false;
bool g_done = false;

bool g_mousedown = false;
bool g_walldraw = false;
float g_weight = 1.0f;


// ============================================================================
//  Drawing
// ============================================================================
void DrawMap()
{
    int x;
    int y;

    SDL_Surface* color;
    SDL_Color col;
    Cell cell;

    for( y = 0; y < MAPY; y++ )
    {
        for( x = 0; x < MAPX; x++ )
        {
            // get the cell
            cell = g_map.Get( x, y );

            // get the color of the cell
            if( x == g_currentx && y == g_currenty )
                color = g_redbox;
            else if( cell.m_marked == true )
                color = g_bluebox;
            else if( cell.m_passable == false )
                color = g_wallbox;
            else
                color = g_blackbox;
                
            // blit the cell
            col.r = 255 - (cell.m_weight - 1) * 28;
            col.g = 255 - (cell.m_weight - 1) * 28;
            col.b = 255 - (cell.m_weight - 1) * 28;

            g_gui->Box( x * 24, y * 24, 24, 24, col );
            g_gui->Blit( color, x * 24, y * 24 );
        }
    }

    // go through again and draw the pointer lines
    for( y = 0; y < MAPY; y++ )
    {
        for( x = 0; x < MAPX; x++ )
        {
            // get the cell
            cell = g_map.Get( x, y );
            // if the cell has a pointer, draw the line
            if( cell.m_lastx != -1 && cell.m_lasty != -1 )
            {
                g_gui->Line( x * 24 + 12, 
                             y * 24 + 12, 
                             cell.m_lastx * 24 + 12, 
                             cell.m_lasty * 24 + 12,
                             BLACK );
            }
        }
    }

    if( g_startx != -1 && g_starty != -1 )
        g_gui->Blit( g_start, g_startx * 24, g_starty * 24 );
    if( g_goalx != -1 && g_goaly != -1 )
        g_gui->Blit( g_goal, g_goalx * 24, g_goaly * 24 );

    if( g_done == true )
    {
        x = g_goalx;
        y = g_goaly;

        // make sure there was a path
        if( g_map.Get( x, y ).m_lastx != -1 )
        {
            while( x != g_startx || y != g_starty )
            {
                cell = g_map.Get( x, y );
                g_gui->Line( x * 24 + 12, 
                             y * 24 + 12, 
                             cell.m_lastx * 24 + 12, 
                             cell.m_lasty * 24 + 12,
                             RED );
                g_gui->Line( x * 24 + 12, 
                             y * 24 + 13, 
                             cell.m_lastx * 24 + 12, 
                             cell.m_lasty * 24 + 13,
                             RED );
                g_gui->Line( x * 24 + 12, 
                             y * 24 + 11, 
                             cell.m_lastx * 24 + 12, 
                             cell.m_lasty * 24 + 11,
                             RED );
                x = cell.m_lastx;
                y = cell.m_lasty;
            }
        }
    }

    // draw the color square
    col.r = 255 - (g_weight - 1) * 28;
    col.g = 255 - (g_weight - 1) * 28;
    col.b = 255 - (g_weight - 1) * 28;
    g_gui->Box( WIDTH - 50, HEIGHT - 50, 50, 50, BLACK );
    g_gui->Box( WIDTH - 49, HEIGHT - 49, 48, 48, col );
}





// ============================================================================
//  Other Algorithms
// ============================================================================
void Clear()
{
    int x;
    int y;

    for( y = 0; y < MAPY; y++ )
    {
        for( x = 0; x < MAPX; x++ )
        {
            g_map.Get( x, y ).m_weight = 1.0f;
            g_map.Get( x, y ).m_passable = true;
        }
    }
}

void RandomizeWeights()
{
    int x;
    int y;

    for( y = 0; y < MAPY; y++ )
    {
        for( x = 0; x < MAPX; x++ )
        {
            g_map.Get( x, y ).m_weight = (float)(rand() % 256);
        }
    }
}


// ============================================================================
//  Button Callbacks
// ============================================================================

void Distance()
{
    if( g_startx == -1 || g_starty == -1 || g_goalx == -1 || g_goaly == -1 )
        return;

    PathDistanceFirst( g_map, g_startx, g_starty, g_goalx, g_goaly );
    g_done = true;
    
}

void Simple()
{
    if( g_startx == -1 || g_starty == -1 || g_goalx == -1 || g_goaly == -1 )
        return;

    PathSimpleHeuristic( g_map, g_startx, g_starty, g_goalx, g_goaly );
    g_done = true;
    
}

void Complex()
{
    if( g_startx == -1 || g_starty == -1 || g_goalx == -1 || g_goaly == -1 )
        return;

    PathComplexHeuristic( g_map, g_startx, g_starty, g_goalx, g_goaly );
    g_done = true;
    
}

void AStar()
{
    if( g_startx == -1 || g_starty == -1 || g_goalx == -1 || g_goaly == -1 )
        return;

    PathAStar( g_map, g_startx, g_starty, g_goalx, g_goaly );
    g_done = true;
    
}


void ClearMap()
{
    ClearCells( g_map );
    g_done = false;
}

// ============================================================================
//  Main
// ============================================================================
int main( int argc, char* argv[] )
{
    int x;
    int y;

    //initialize systems
    SDL_Init( SDL_INIT_VIDEO | SDL_INIT_TIMER );
    SDL_EnableUNICODE( true );
    SDL_WM_SetCaption( PROGRAM_NAME, 0); 
    TTF_Init();
    g_gui = new SDLGUI( WIDTH, HEIGHT, ITEMS, WHITE );
    g_gui->SetFont( "arial.ttf", ARIAL, 18, TTF_STYLE_NORMAL );

    g_gui->AddButton( 0, HEIGHT - 64, "gbup.bmp", "gbdown.bmp", "Distance",
                      ARIAL, BLACK, WHITE, Distance );
    g_gui->AddButton( 128, HEIGHT - 64, "gbup.bmp", "gbdown.bmp", "Simple",
                      ARIAL, BLACK, WHITE, Simple );
    g_gui->AddButton( 256, HEIGHT - 64, "gbup.bmp", "gbdown.bmp", "Complex",
                      ARIAL, BLACK, WHITE, Complex );
    g_gui->AddButton( 384, HEIGHT - 64, "gbup.bmp", "gbdown.bmp", "A*",
                      ARIAL, BLACK, WHITE, AStar );
    g_gui->AddButton( 512, HEIGHT - 64, "gbup.bmp", "gbdown.bmp", "Clear",
                      ARIAL, BLACK, WHITE, ClearMap );

    // load the bmps
    g_blackbox = SDL_LoadBMP( "boxblack.bmp" );
    g_redbox = SDL_LoadBMP( "boxred.bmp" );
    g_greenbox = SDL_LoadBMP( "boxgreen.bmp" );
    g_bluebox = SDL_LoadBMP( "boxblue.bmp" );
    g_wallbox = SDL_LoadBMP( "boxwall.bmp" );
    g_start = SDL_LoadBMP( "start.bmp" );
    g_goal = SDL_LoadBMP( "goal.bmp" );


    // set the color keys of the BMPs
    SDL_SetColorKey( g_blackbox, SDL_SRCCOLORKEY, 
                     SDL_MapRGB( g_blackbox->format, 255, 255, 255 ));
    SDL_SetColorKey( g_redbox, SDL_SRCCOLORKEY, 
                     SDL_MapRGB( g_redbox->format, 255, 255, 255 ));
    SDL_SetColorKey( g_greenbox, SDL_SRCCOLORKEY, 
                     SDL_MapRGB( g_greenbox->format, 255, 255, 255 ));
    SDL_SetColorKey( g_bluebox, SDL_SRCCOLORKEY, 
                     SDL_MapRGB( g_bluebox->format, 255, 255, 255 ));
    SDL_SetColorKey( g_wallbox, SDL_SRCCOLORKEY, 
                     SDL_MapRGB( g_wallbox->format, 255, 255, 255 ));
    SDL_SetColorKey( g_start, SDL_SRCCOLORKEY, 
                     SDL_MapRGB( g_start->format, 255, 255, 255 ));
    SDL_SetColorKey( g_goal, SDL_SRCCOLORKEY, 
                     SDL_MapRGB( g_goal->format, 255, 255, 255 ));
    

    Clear();
    ClearCells( g_map );
    //RandomizeWeights();

    // set our at exit function
    atexit( SDL_Quit ) ;

    // declare event variable
    SDL_Event event;

    g_gui->Draw();
    g_gui->Update();

    // loop until we get a quit message.
    while( 1 )
    {
        //look for an event
        if( SDL_PollEvent( &event ) )
        {
            //an event was found
            if( event.type == SDL_QUIT ) 
                break;

            // mouse button was pressed
            if( event.type == SDL_MOUSEBUTTONDOWN ) 
            {
                // get the mouse g_state.
                SDL_GetMouseState( &x, &y );

                // tell the GUI that a button has been pressed
                g_gui->MouseDown( x, y );

                g_mousedown = true;
                // see if the user clicked on a square
                x = x / 24;
                y = y / 24;
                if( x < MAPX && y < MAPY )
                {
                    if( g_weight == 10 )
                        g_walldraw = true;
                    else
                        g_walldraw = false;
                }
            }

            // mouse button was released
            if( event.type == SDL_MOUSEBUTTONUP ) 
            {
                // get the mouse state.
                SDL_GetMouseState( &x, &y );

                // tell the GUI that a button has been released
                g_gui->MouseUp( x, y );

                g_mousedown = false;
                // see if the user clicked on a square
                x = x / 24;
                y = y / 24;
                if( x < MAPX && y < MAPY && g_processing == false )
                {
                    // flip the drawing state
                    g_map.Get( x, y ).m_passable = !g_walldraw;
                    g_map.Get( x, y ).m_weight = (float)g_weight;
                }
            }

            if( event.type == SDL_MOUSEMOTION )
            {
                // get the mouse state.
                SDL_GetMouseState( &x, &y );

                // see if the user is over a square
                x = x / 24;
                y = y / 24;
                if( x < MAPX && y < MAPY && g_mousedown == true && g_processing == false )
                {
                    // draw the current wall state
                    g_map.Get( x, y ).m_passable = !g_walldraw;
                    g_map.Get( x, y ).m_weight = (float)g_weight;
                }
            }

            if( event.type == SDL_KEYDOWN )
            {
                // get the mouse state.
                SDL_GetMouseState( &x, &y );

                // a key was pressed.
                if( event.key.keysym.sym == SDLK_ESCAPE )
                {
                    // if ESC was pressed, quit the program.
                    SDL_Event quit;
                    quit.type = SDL_QUIT;
                    SDL_PushEvent( &quit );
                }

                if( event.key.keysym.unicode >= '0' &&
                    event.key.keysym.unicode <= '9' )
                {
                    g_weight = (float)(event.key.keysym.unicode - '0') + 1.0f;
                }

                if( event.key.keysym.sym == SDLK_g )
                {
                    x = x / 24;
                    y = y / 24;
                    if( x < MAPX && y < MAPY )
                    {
                        // if the program isn't processing, set the goal
                        if( g_processing == false && g_done == false )
                        {
                            if( g_map.Get( x, y ).m_passable != false )
                            {
                                g_goalx = x;
                                g_goaly = y;
                            }
                        }
                    }
                }

                if( event.key.keysym.sym == SDLK_s )
                {
                    x = x / 24;
                    y = y / 24;
                    if( x < MAPX && y < MAPY )
                    {
                        // if the program isn't processing, set the goal
                        if( g_processing == false && g_done == false )
                        {
                            if( g_map.Get( x, y ).m_passable != false )
                            {
                                g_startx = x;
                                g_starty = y;
                            }
                        }
                    }
                }

                // tell the GUI that a key was pressed.
                g_gui->KeyDown( event.key.keysym.sym, 
                                event.key.keysym.mod,
                                event.key.keysym.unicode );
            }
        }


        // draw the g_gui at the end of each loop.
        g_gui->Draw();

        DrawMap();

        g_gui->Update();
    }

    return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -