📄 g18-01.cpp
字号:
{
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 + -