📄 gd23-05.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 + -