📄 gd18-02.cpp
字号:
// ============================================================================
// GD18-02.cpp
// Conditional Finite State Machine Demo
// ============================================================================
#include "SDLGUI.h"
#include "Graph.h"
#include <stdlib.h>
#include <time.h>
// ============================================================================
// Global Constants
// ============================================================================
const char PROGRAM_NAME[] = "Conditional FSM Graphical Demonstration";
const int WIDTH = 800;
const int HEIGHT = 600;
const int ITEMS = 32;
const int ARIAL = 0;
// ============================================================================
// Classes
// ============================================================================
enum AIState
{
GUARDING,
ATTACKING,
FINDINGHEALTH,
FINDINGAMMO
};
enum AIEvent
{
SEEENEMY,
KILLENEMY,
FOUNDHEALTH,
FOUNDAMMO
};
enum HealthState
{
GOODHEALTH,
BADHEALTH
};
enum AmmoState
{
HIGHAMMO,
LOWAMMO
};
// ============================================================================
// Global Variables
// ============================================================================
SDLGUI* g_gui;
AIState g_machine[4][4][2][2];
// used for selecting the current node;
int g_currentstate = GUARDING;
char g_healthstr[5] = "100";
char g_ammostr[5] = "100";
int g_health = 100;
int g_ammo = 100;
HealthState g_hs = GOODHEALTH;
AmmoState g_as = HIGHAMMO;
// Boxes
SDL_Surface* g_redbox;
SDL_Surface* g_back;
int g_coords[4][2] = { { 130, 139 },
{ 537, 139 },
{ 537, 419 },
{ 130, 419 } };
// ============================================================================
// Draw Algorithm
// ============================================================================
void DrawMachine()
{
int x;
g_gui->Blit( g_back, 0, 0 );
for( x = 0; x < 4; x++ )
{
// draw the box
if( x == g_currentstate )
{
g_gui->Blit( g_redbox, g_coords[x][0], g_coords[x][1] );
}
}
}
// ============================================================================
// Algorithms
// ============================================================================
void InitMachine()
{
int state;
int event;
// fill the machine with default values first
for( state = 0; state < 4; state++ )
{
for( event = 0; event < 4; event ++ )
{
g_machine[state][event][0][0] = (AIState)state;
g_machine[state][event][0][1] = (AIState)state;
g_machine[state][event][1][0] = (AIState)state;
g_machine[state][event][1][1] = (AIState)state;
}
}
// now fill the machine in with the real values
g_machine[GUARDING][SEEENEMY][GOODHEALTH][HIGHAMMO] = ATTACKING;
g_machine[GUARDING][SEEENEMY][GOODHEALTH][LOWAMMO] = ATTACKING;
g_machine[GUARDING][SEEENEMY][BADHEALTH][HIGHAMMO] = ATTACKING;
g_machine[GUARDING][SEEENEMY][BADHEALTH][LOWAMMO] = ATTACKING;
g_machine[ATTACKING][KILLENEMY][GOODHEALTH][HIGHAMMO] = GUARDING;
g_machine[ATTACKING][KILLENEMY][GOODHEALTH][LOWAMMO] = FINDINGAMMO;
g_machine[ATTACKING][KILLENEMY][BADHEALTH][HIGHAMMO] = FINDINGHEALTH;
g_machine[ATTACKING][KILLENEMY][BADHEALTH][LOWAMMO] = FINDINGHEALTH;
g_machine[FINDINGHEALTH][SEEENEMY][GOODHEALTH][HIGHAMMO] = ATTACKING;
g_machine[FINDINGHEALTH][SEEENEMY][GOODHEALTH][LOWAMMO] = ATTACKING;
g_machine[FINDINGHEALTH][SEEENEMY][BADHEALTH][HIGHAMMO] = ATTACKING;
g_machine[FINDINGHEALTH][SEEENEMY][BADHEALTH][LOWAMMO] = ATTACKING;
g_machine[FINDINGHEALTH][FOUNDHEALTH][BADHEALTH][HIGHAMMO] = GUARDING;
g_machine[FINDINGHEALTH][FOUNDHEALTH][BADHEALTH][LOWAMMO] = FINDINGAMMO;
g_machine[FINDINGAMMO][SEEENEMY][GOODHEALTH][HIGHAMMO] = ATTACKING;
g_machine[FINDINGAMMO][SEEENEMY][GOODHEALTH][LOWAMMO] = ATTACKING;
g_machine[FINDINGAMMO][SEEENEMY][BADHEALTH][HIGHAMMO] = ATTACKING;
g_machine[FINDINGAMMO][SEEENEMY][BADHEALTH][LOWAMMO] = ATTACKING;
g_machine[FINDINGAMMO][FOUNDAMMO][GOODHEALTH][HIGHAMMO] = GUARDING;
g_machine[FINDINGAMMO][FOUNDAMMO][GOODHEALTH][LOWAMMO] = GUARDING;
g_machine[FINDINGAMMO][FOUNDAMMO][BADHEALTH][HIGHAMMO] = GUARDING;
g_machine[FINDINGAMMO][FOUNDAMMO][BADHEALTH][LOWAMMO] = GUARDING;
}
void UpdateHealthAmmoValues()
{
itoa( g_health, g_healthstr, 10 );
itoa( g_ammo, g_ammostr, 10 );
}
void UpdateHealthAmmoStates()
{
g_health = atoi( g_healthstr );
if( g_health < 50 )
g_hs = BADHEALTH;
else
g_hs = GOODHEALTH;
g_ammo = atoi( g_ammostr );
if( g_ammo < 50 )
g_as = LOWAMMO;
else
g_as = HIGHAMMO;
UpdateHealthAmmoValues();
}
// ============================================================================
// Button Callbacks
// ============================================================================
void SeeEnemy()
{
UpdateHealthAmmoStates();
g_currentstate = g_machine[g_currentstate][SEEENEMY][g_hs][g_as];
}
void KillEnemy()
{
UpdateHealthAmmoStates();
g_currentstate = g_machine[g_currentstate][KILLENEMY][g_hs][g_as];
}
void FoundHealth()
{
UpdateHealthAmmoStates();
g_currentstate = g_machine[g_currentstate][FOUNDHEALTH][g_hs][g_as];
g_health += 100;
UpdateHealthAmmoValues();
}
void FoundAmmo()
{
UpdateHealthAmmoStates();
g_currentstate = g_machine[g_currentstate][FOUNDAMMO][g_hs][g_as];
g_ammo += 100;
UpdateHealthAmmoValues();
}
// ============================================================================
// Main
// ============================================================================
int main( int argc, char* argv[] )
{
int x;
int y;
srand( time(0) );
//initialize systems
SDL_Init( SDL_INIT_VIDEO | SDL_INIT_TIMER );
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 );
SDL_EnableUNICODE( 1 );
// init the machine
InitMachine();
// load the bmps
g_redbox = SDL_LoadBMP( "boxred.bmp" );
g_back = SDL_LoadBMP( "background.bmp" );
// set the color keys of the BMPs
SDL_SetColorKey( g_redbox, SDL_SRCCOLORKEY,
SDL_MapRGB( g_redbox->format, 255, 255, 255 ));
SDL_SetColorKey( g_back, SDL_SRCCOLORKEY,
SDL_MapRGB( g_back->format, 255, 255, 255 ));
// add the items to the g_gui
g_gui->AddButton( 0, 0, "gbup.bmp", "gbdown.bmp", "See Enemy", ARIAL,
BLACK, WHITE, SeeEnemy );
g_gui->AddButton( 0, 64, "gbup.bmp", "gbdown.bmp", "Kill Enemy", ARIAL,
BLACK, WHITE, KillEnemy );
g_gui->AddButton( 0, 128, "gbup.bmp", "gbdown.bmp", "Found Health", ARIAL,
BLACK, WHITE, FoundHealth );
g_gui->AddButton( 0, 192, "gbup.bmp", "gbdown.bmp", "Found Ammo", ARIAL,
BLACK, WHITE, FoundAmmo );
g_gui->AddLabel( 192, 0, "Health:", ARIAL, BLACK, WHITE );
g_gui->AddLabel( 192, 33, "Ammo:", ARIAL, BLACK, WHITE );
g_gui->AddTextBox( 256, 0, 64, 32, g_healthstr, 4, ARIAL, BLACK, WHITE, true, 0 );
g_gui->AddTextBox( 256, 33, 64, 32, g_ammostr, 4, ARIAL, BLACK, WHITE, true, 0 );
// 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 );
}
// 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 );
}
if( event.type == SDL_KEYDOWN )
{
// 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 );
}
// 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();
DrawMachine();
g_gui->Update();
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -