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

📄 gd18-02.cpp

📁 游戏开发数据结构Data Structures for Game Programmers
💻 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 + -