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

📄 g18-01.cpp

📁 游戏开发数据结构Data Structures for Game Programmers
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    {
        g_AIs[p_AI].m_state = g_defender[g_AIs[p_AI].m_state][p_event][health];
    }
}



// this moves an AI player towards the specified coordinates.
// Don't worry if you don't know what any of this means,
// I didn't teach this in the book. If you want to know how this works,
// then you should find a good tutorial or a book on trigonometry.
// For now, all you need to know is that it moves the AI towards the given
// coordinates with a speed of AISPEED pixels per second.
void MoveAI( int p_index, int p_x, int p_y )
{
    // figure out the angle from the AI to the coordinates
    float theta;
    float distance = Distance( p_x, p_y, g_AIs[p_index].m_x, g_AIs[p_index].m_y );
    theta = acos( (p_x - g_AIs[p_index].m_x) / distance );

    // reverse theta if needed. 
    if( p_y < g_AIs[p_index].m_y )
        theta = 6.283185f - theta;

    // jitter the angle a bit
    theta += (float)(rand()%21 - 10) / 25.0f;

    g_AIs[p_index].m_x += ((float)(g_timedelta * AISPEED) / 1000.0f) * cos(theta);
    g_AIs[p_index].m_y += ((float)(g_timedelta * AISPEED) / 1000.0f) * sin(theta);

}


// this makes the AI attack the player, if the time is right.
void AIAttack()
{
    int i;
    
    // if 1000 milliseconds have passed since the last time the attack 
    // counter was reset.
    if( SDL_GetTicks() - g_combattimer >= 1000 )
    {
        // take off 0-9 damage
        g_health -= rand() % 10;

        // check to see if player was killed.
        if( g_health <= 0 )
        {
            // tell everyone that the intruder was killed
            for( i = 0; i < g_numAIs; i++ )
                Event( i, KILLINTRUDER );

            // reset the player
            g_health = 75;
            g_x = 700;
            g_y = 500;
        }
    }
}


void ProcessAI( int p_AI )
{
    int i;    

    // check if the AI picked up some health.
    i = MatchHealthPacks( g_AIs[p_AI].m_x, g_AIs[p_AI].m_y );
    if( i != -1 )
    {
        Event( p_AI, FOUNDHEALTH );
        g_AIs[p_AI].m_health = 100;
        AddHealthPack( i );
    }

    // check if the AI found the base
    if( Distance( g_AIs[p_AI].m_x, g_AIs[p_AI].m_y, g_basex, g_basey ) <= VISUALZONE )
        Event( p_AI, FOUNDBASE );


    // check if the AI sees an intruder
    if( Distance( g_AIs[p_AI].m_x, g_AIs[p_AI].m_y, g_x, g_y ) <= VISUALZONE )
        Event( p_AI, SEEINTRUDER );

    // check if the AI went out of bounds
    // note that this is a stupid algorithm; a smarter method would be to
    // only send this event when the AI first steps out of bounds, but it works
    // just fine anyway, just a little slower.
    if( Distance( g_AIs[p_AI].m_x, g_AIs[p_AI].m_y, g_basex, g_basey ) >= DEFENSEZONE )
        Event( p_AI, OUTOFBOUNDS );


    // perform combat.
    if( g_AIs[p_AI].m_state == ATTACKING )
    {
        // attack if player is in range
        if( Distance( g_AIs[p_AI].m_x, g_AIs[p_AI].m_y, g_x, g_y ) <= ATTACKZONE )
        {
            AIAttack();
        }
        else
        {
            // move the AI closer to the player
            MoveAI( p_AI, g_x, g_y );
        }
    }

    if( g_AIs[p_AI].m_state == FINDINGBASE )
    {
        // move the AI closer to the base
        MoveAI( p_AI, g_basex, g_basey );
    }


    if( g_AIs[p_AI].m_state == FINDINGHEALTH )
    {
        // Find the closest health pack
        i = FindClosestHealthPack( g_AIs[p_AI].m_x, g_AIs[p_AI].m_y );
        
        // move the AI closer to the closest health pack
        MoveAI( p_AI, g_healthPacks[i][0], g_healthPacks[i][1] );
    }
}





void AddAIs()
{
    int i;

    g_numAIs = 8;

    // init the attackers.
    for( i = 0; i < 2; i++ )
    {
        g_AIs[i].Init( ATTACKER, rand()%128+ g_basex, 
                       rand()%128 + g_basey, 100 );
    }

    // init the defenders
    for( i = 2; i < 8; i++ )
    {
        g_AIs[i].Init( DEFENDER, rand()%128+ g_basex, 
                       rand()%128 + g_basey, 100 );
    }


}





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


    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 );
    SDL_EnableKeyRepeat( 0, 0 );

    // load the bmps
    g_dzone = SDL_LoadBMP( "dzone.bmp" );
    g_vzone = SDL_LoadBMP( "vzone.bmp" );

    // set the color keys of the BMPs
    SDL_SetColorKey( g_dzone, SDL_SRCCOLORKEY, 
                     SDL_MapRGB( g_dzone->format, 255, 255, 255 ));
    SDL_SetColorKey( g_vzone, SDL_SRCCOLORKEY, 
                     SDL_MapRGB( g_vzone->format, 255, 255, 255 ));

    // init the machines
    InitMachines();

    AddAIs();
    for( x = 0; x < 8; x++ )
        AddHealthPack( x );

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

    // declare event variable
    SDL_Event event;

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


    // reset the timers
    g_timer = SDL_GetTicks();
    g_combattimer = SDL_GetTicks();

    // 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_KEYUP )
            {
                if( event.key.keysym.sym == SDLK_LEFT )
                {
                    g_dx += 1;
                }
                if( event.key.keysym.sym == SDLK_RIGHT )
                {
                    g_dx -= 1;
                }
                if( event.key.keysym.sym == SDLK_UP )
                {
                    g_dy += 1;
                }
                if( event.key.keysym.sym == SDLK_DOWN )
                {
                    g_dy -= 1;
                }
            }
            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 );
                }
                if( event.key.keysym.sym == SDLK_LEFT )
                {
                    g_dx -= 1;
                }
                if( event.key.keysym.sym == SDLK_RIGHT )
                {
                    g_dx += 1;
                }
                if( event.key.keysym.sym == SDLK_UP )
                {
                    g_dy -= 1;
                }
                if( event.key.keysym.sym == SDLK_DOWN )
                {
                    g_dy += 1;
                }

                // 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();

        // record the amount of time that has passed since last iteration
        g_timedelta = SDL_GetTicks() - g_timer;
        g_timer = SDL_GetTicks();


        // find out if the player picked up any health packs
        x = MatchHealthPacks( g_x, g_y );
        if( x != -1 )
        {
            g_health = 100;
            AddHealthPack( x );
        }

        // move the player
        g_x += ((float)(g_timedelta * PLAYERSPEED) / 1000.0f) * g_dx;
        g_y += ((float)(g_timedelta * PLAYERSPEED) / 1000.0f) * g_dy;

        // perform enemy AI calculations
        for( x = 0; x < g_numAIs; x++ )
        {
            ProcessAI( x );
        }

        // process combat
        if( SDL_GetTicks() - g_combattimer >= 1000 )
        {
            x = FindClosestAI();
            if( Distance( g_x, g_y, g_AIs[x].m_x, g_AIs[x].m_y ) <= ATTACKZONE )
            {
                // take off 5-14 damage
                g_AIs[x].m_health -= rand() % 10 + 5;

                // check if the AI died.
                if( g_AIs[x].m_health <= 0 )
                {
                    // fast remove algorithm
                    g_AIs[x] = g_AIs[g_numAIs-1];
                    g_numAIs--;
                }
            }
            g_combattimer = SDL_GetTicks();
        }

        Draw();

        // draw the health bar background
        g_gui->Box( 4, 124, 40, 264, BLACK );

        // calculate the size of the bar
        y = (g_health * 256) / 100;
        g_gui->Box( 8, 128 + 256 - y, 32, y, RED );


        g_gui->Update();
    }

    return 0;
}

⌨️ 快捷键说明

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