home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2009 February / maximum-cd-2009-02.iso / DiscContents / SMC_1.6_win32.exe / src / objects / ball.cpp next >
Encoding:
C/C++ Source or Header  |  2008-05-26  |  9.8 KB  |  443 lines

  1. /***************************************************************************
  2.  * ball.cpp  -  ball class
  3.  *
  4.  * Copyright (C) 2006 - 2008 Florian Richter
  5.  ***************************************************************************/
  6. /*
  7.    This program is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 3 of the License, or
  10.    (at your option) any later version.
  11.    
  12.    You should have received a copy of the GNU General Public License
  13.    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  14. */
  15.  
  16. #include "../objects/ball.h"
  17. #include "../core/game_core.h"
  18. #include "../enemies/enemy.h"
  19. #include "../objects/goldpiece.h"
  20. #include "../enemies/gee.h"
  21. #include "../enemies/spika.h"
  22. #include "../player/player.h"
  23. #include "../video/animation.h"
  24. #include "../level/level.h"
  25. #include "../gui/hud.h"
  26. #include "../core/sprite_manager.h"
  27.  
  28. /* *** *** *** *** *** *** cBall *** *** *** *** *** *** *** *** *** *** *** */
  29.  
  30. cBall :: cBall( float x, float y, cSprite *origin_object /* = NULL */, ball_effect btype /* = FIREBALL_DEFAULT */  )
  31. : cMovingSprite( NULL, x, y )
  32. {
  33.     sprite_array = ARRAY_ACTIVE;
  34.     type = TYPE_BALL;
  35.     posz = 0.095f;
  36.  
  37.     spawned = 1;
  38.     player_range = 2000;
  39.  
  40.     massivetype = MASS_MASSIVE;
  41.     counter = 0;
  42.  
  43.     glim_mod = 1;
  44.     glim_counter = 0;
  45.  
  46.     if( btype == FIREBALL_DEFAULT || btype == FIREBALL_EXPLOSION )
  47.     {
  48.         Set_Image( pVideo->Get_Surface( "animation/fireball/1.png" ) );
  49.         ball_type = FIREBALL_DEFAULT;
  50.     }
  51.     else if( btype == ICEBALL_DEFAULT || btype == ICEBALL_EXPLOSION )
  52.     {
  53.         Set_Image( pVideo->Get_Surface( "animation/iceball/1.png" ) );
  54.         ball_type = ICEBALL_DEFAULT;
  55.     }
  56.     else
  57.     {
  58.         printf( "Warning : Ball unknown type %d\n", btype );
  59.         cMovingSprite::Destroy();
  60.         return;
  61.     }
  62.  
  63.     if( origin_object )
  64.     {
  65.         origin_array = origin_object->sprite_array;
  66.         origin_type = origin_object->type;
  67.  
  68.         if( origin_type == TYPE_PLAYER )
  69.         {
  70.             if( ball_type == FIREBALL_DEFAULT || ball_type == ICEBALL_DEFAULT )
  71.             {
  72.                 pPlayer->shoot_counter = speedfactor_fps;
  73.             }
  74.         }
  75.     }
  76.     // if origin not set
  77.     else
  78.     {
  79.         printf( "Warning : Ball origin not set\n" );
  80.         origin_array = ARRAY_UNDEFINED;
  81.         origin_type = TYPE_UNDEFINED;
  82.     }
  83. }
  84.  
  85. cBall :: ~cBall( void )
  86. {
  87.     // always destroy
  88.     if( !destroy )
  89.     {
  90.         cBall::Destroy();
  91.     }
  92. }
  93.  
  94. void cBall :: Destroy( void )
  95. {
  96.     if( destroy )
  97.     {
  98.         return;
  99.     }
  100.  
  101.     if( ball_type == FIREBALL_DEFAULT )
  102.     {
  103.         pAnimation_Manager->Add( new cAnimation_Fireball( posx + col_rect.w / 2, posy + col_rect.h / 2 ) );
  104.     }
  105.     else if( ball_type == ICEBALL_DEFAULT )
  106.     {
  107.         // create animation
  108.         cParticle_Emitter *anim = new cParticle_Emitter();
  109.         Generate_Particles( anim );
  110.         anim->Set_Quota( 15 );
  111.         // add animation
  112.         pAnimation_Manager->Add( anim );
  113.     }
  114.  
  115.     cMovingSprite::Destroy();
  116. }
  117.  
  118. void cBall :: Update( void )
  119. {
  120.     if( !valid_update )
  121.     {
  122.         return;
  123.     }
  124.  
  125.     // right
  126.     if( velx > 0 )
  127.     {
  128.         rotz += pFramerate->speedfactor * 40;
  129.     }
  130.     // left
  131.     else
  132.     {
  133.         rotz -= pFramerate->speedfactor * 40;
  134.     }
  135.  
  136.     if( vely < 30 )
  137.     {
  138.         Add_Velocity( 0, 1 );
  139.     }
  140.  
  141.     // if ball is out of Player Range
  142.     if( !is_Player_range() )
  143.     {
  144.         Destroy();
  145.     }
  146.  
  147.     // glim animation
  148.     if( glim_mod )
  149.     {
  150.         glim_counter += pFramerate->speedfactor * 0.1f;
  151.  
  152.         if( glim_counter > 1 )
  153.         {
  154.             glim_counter = 1;
  155.             glim_mod = 0;
  156.         }
  157.     }
  158.     else
  159.     {
  160.         glim_counter -= pFramerate->speedfactor * 0.1f;
  161.  
  162.         if( glim_counter < 0 )
  163.         {
  164.             glim_counter = 0;
  165.             glim_mod = 1;
  166.         }
  167.     }
  168.  
  169.     // Particle animation
  170.     Generate_Particles();
  171. }
  172.  
  173. void cBall :: Draw( cSurfaceRequest *request /* = NULL */ )
  174. {
  175.     if( !valid_draw )
  176.     {
  177.         return;
  178.     }
  179.  
  180.     // don't draw if leveleditor mode
  181.     if( editor_level_enabled )
  182.     {
  183.         return;
  184.     }
  185.  
  186.     if( ball_type == FIREBALL_DEFAULT )
  187.     {
  188.         Set_Color_Combine( glim_counter, glim_counter / 1.2f, glim_counter / 2, GL_ADD );
  189.     }
  190.     else if( ball_type == ICEBALL_DEFAULT )
  191.     {
  192.         Set_Color_Combine( glim_counter / 2.5f, glim_counter / 2.5f, glim_counter / 1.7f, GL_ADD );
  193.     }
  194.  
  195.     cMovingSprite::Draw( request );
  196. }
  197.  
  198. void cBall :: Generate_Particles( cParticle_Emitter *anim /* = NULL */ )
  199. {
  200.     bool create_anim = 0;
  201.  
  202.     if( !anim )
  203.     {
  204.         create_anim = 1;
  205.         // create animation
  206.         anim = new cParticle_Emitter();
  207.     }
  208.  
  209.     anim->Set_Emitter_Rect( col_rect );
  210.     anim->Set_Image( pVideo->Get_Surface( "animation/particles/light.png" ) );
  211.     anim->Set_Pos_Z( posz + 0.0001f );
  212.     if( ball_type == FIREBALL_DEFAULT )
  213.     {
  214.         anim->Set_Time_to_Live( 0.2f );
  215.         anim->Set_Color( Color( static_cast<Uint8>(250), 140, 90 ) );
  216.     }
  217.     else if( ball_type == ICEBALL_DEFAULT )
  218.     {
  219.         anim->Set_Time_to_Live( 0.5f );
  220.         anim->Set_Color( Color( static_cast<Uint8>(90), 90, 255 ) );
  221.     }
  222.     anim->Set_Blending( BLEND_ADD );
  223.     anim->Set_Speed( 0.35f, 0.3f );
  224.     anim->Set_Scale( 0.4f, 0.2f );
  225.     
  226.     if( create_anim )
  227.     {
  228.         // add animation
  229.         pAnimation_Manager->Add( anim );
  230.     }
  231. }
  232.  
  233. unsigned int cBall :: Validate_Collision( cSprite *obj )
  234. {
  235.     // basic validation checking
  236.     int basic_valid = Validate_Collision_Ghost( obj );
  237.  
  238.     // found valid collision
  239.     if( basic_valid > -1 )
  240.     {
  241.         return basic_valid;
  242.     }
  243.  
  244.     // player
  245.     if( obj->type == TYPE_PLAYER )
  246.     {
  247.         if( origin_type != TYPE_PLAYER )
  248.         {
  249.             return 2;
  250.         }
  251.  
  252.         return 0;
  253.     }
  254.     // massive
  255.     if( obj->massivetype == MASS_MASSIVE )
  256.     {
  257.         if( obj->type == TYPE_BALL )
  258.         {
  259.             return 0;
  260.         }
  261.         else if( obj->sprite_array == ARRAY_ENEMY && origin_array == ARRAY_ENEMY )
  262.         {
  263.             return 0;
  264.         }
  265.  
  266.         return 2;
  267.     }
  268.     else if( obj->massivetype == MASS_HALFMASSIVE )
  269.     {
  270.         // if moving downwards and object is on top
  271.         if( vely >= 0 && Is_on_Top( obj ) )
  272.         {
  273.             return 2;
  274.         }
  275.     }
  276.  
  277.     return 0;
  278. }
  279.  
  280. void cBall :: Handle_Collision( cObjectCollision *collision )
  281. {
  282.     // already destroyed
  283.     if( destroy )
  284.     {
  285.         return;
  286.     }
  287.  
  288.     cMovingSprite::Handle_Collision( collision );
  289. }
  290.  
  291. void cBall :: Handle_Collision_Player( cObjectCollision *collision )
  292. {
  293.     // velocity hit
  294.     if( direction == DIR_LEFT )
  295.     {
  296.         pPlayer->velx -= 5;
  297.     }
  298.     else if( direction == DIR_RIGHT )
  299.     {
  300.         pPlayer->velx += 5;
  301.     }
  302.     else if( direction == DIR_UP )
  303.     {
  304.         pPlayer->vely -= 5;
  305.     }
  306.     else if( direction == DIR_DOWN )
  307.     {
  308.         pPlayer->vely += 5;
  309.     }
  310.  
  311.     Destroy();
  312. }
  313.  
  314. void cBall :: Handle_Collision_Enemy( cObjectCollision *collision )
  315. {
  316.     cEnemy *enemy = static_cast<cEnemy *>(pActive_Sprite_Manager->Get_Pointer( collision->number ));
  317.  
  318.     // if enemy is not destroyable
  319.     if( ( ball_type == FIREBALL_DEFAULT && enemy->fire_resistant ) || ( ball_type == ICEBALL_DEFAULT && enemy->ice_resistance >= 1 ) )
  320.     {
  321.         pAudio->Play_Sound( "tock.ogg" );
  322.     }
  323.     // destroy enemy
  324.     else
  325.     {
  326.         // enemy rect particle animation
  327.         for( unsigned int w = 0; w < enemy->col_rect.w; w += 15 )
  328.         {
  329.             for( unsigned int h = 0; h < enemy->col_rect.h; h += 15 )
  330.             {
  331.                 // animation
  332.                 cParticle_Emitter *anim = new cParticle_Emitter();
  333.                 anim->Set_Pos( enemy->posx + w, enemy->posy + h );
  334.  
  335.                 anim->Set_Image( pVideo->Get_Surface( "animation/particles/light.png" ) );
  336.                 anim->Set_Time_to_Live( 0.2f, 0.4f );
  337.                 Color anim_color, anim_color_rand;
  338.                 if( ball_type == FIREBALL_DEFAULT )
  339.                 {
  340.                     anim_color = Color( static_cast<Uint8>(250), 170, 150 );
  341.                     anim_color_rand = Color( static_cast<Uint8>( rand() % 5 ), rand() % 85, rand() % 25 );
  342.                 }
  343.                 else
  344.                 {
  345.                     anim_color = Color( static_cast<Uint8>(150), 150, 240 );
  346.                     anim_color_rand = Color( static_cast<Uint8>( rand() % 80 ), rand() % 80, rand() % 10 );
  347.                 }
  348.                 anim->Set_Color( anim_color, anim_color_rand );
  349.                 anim->Set_Fading_Alpha( 1 );
  350.                 anim->Set_Fading_Size( 1 );
  351.                 anim->Set_Speed( 0.5f, 2.2f );
  352.                 anim->Set_Blending( BLEND_DRIVE );
  353.                 // add animation
  354.                 pAnimation_Manager->Add( anim );
  355.             }
  356.         }
  357.  
  358.         // play enemy kill sound
  359.         pAudio->Play_Sound( enemy->kill_sound );
  360.  
  361.         if( ball_type == FIREBALL_DEFAULT )
  362.         {
  363.             // get points
  364.             pointsdisplay->Add_Points( enemy->kill_points, posx, posy, "", static_cast<Uint8>(255), 1 );
  365.  
  366.             // create goldpiece
  367.             cMovingSprite *goldpiece = new cFGoldpiece( enemy->col_rect.x, enemy->col_rect.y + enemy->col_rect.h, collision->direction );
  368.             // set optimal position
  369.             goldpiece->Col_Move( -( ( goldpiece->col_rect.w - enemy->col_rect.w ) / 2 ), -( goldpiece->col_pos.y + goldpiece->col_rect.h ), 1, 1 );
  370.             // add goldpiece
  371.             pActive_Sprite_Manager->Add( goldpiece );
  372.  
  373.             enemy->Set_Visible( 0 );
  374.             enemy->DownGrade( 1 );
  375.             pPlayer->Add_Kill_Multiplier();
  376.         }
  377.         else if( ball_type == ICEBALL_DEFAULT )
  378.         {
  379.             enemy->Freeze();
  380.         }
  381.     }
  382.  
  383.     Destroy();
  384. }
  385.  
  386. void cBall :: Handle_Collision_Massive( cObjectCollision *collision )
  387. {
  388.     if( collision->direction == DIR_DOWN )
  389.     {
  390.         // if directly hitting the ground
  391.         if( velx < 0.1f && velx > -0.1f )
  392.         {
  393.             Destroy();
  394.             return;
  395.         }
  396.  
  397.         if( ball_type == FIREBALL_DEFAULT )
  398.         {
  399.             vely = -10;    
  400.             
  401.             // create animation
  402.             cAnimation_Fireball *anim = new cAnimation_Fireball( posx + col_rect.w / 2, posy + col_rect.h / 2 );
  403.             anim->Set_Fading_Speed( 3 );
  404.             pAnimation_Manager->Add( anim );
  405.         }
  406.         else if( ball_type == ICEBALL_DEFAULT )
  407.         {
  408.             vely = -5;
  409.  
  410.             // create animation
  411.             cParticle_Emitter *anim = new cParticle_Emitter();
  412.             anim->Set_Pos( posx + col_rect.w / 2, posy + col_rect.h / 2 );
  413.             anim->Set_Image( pVideo->Get_Surface( "animation/particles/cloud.png" ) );
  414.             anim->Set_Direction_Range( 0, 180 );
  415.             anim->Set_Quota( 3 );
  416.             anim->Set_Time_to_Live( 0.8f );
  417.             anim->Set_Pos_Z( posz + 0.0001f );
  418.             anim->Set_Color( Color( static_cast<Uint8>(50), 50, 250 ) );
  419.             anim->Set_Blending( BLEND_ADD );
  420.             anim->Set_Speed( 0.5f, 0.4f );
  421.             anim->Set_Scale( 0.3f, 0.4f );
  422.             // add animation
  423.             pAnimation_Manager->Add( anim );
  424.         }
  425.     }
  426.     // other directions
  427.     else
  428.     {
  429.         Destroy();
  430.     }
  431. }
  432.  
  433. void cBall :: Handle_out_of_Level( ObjectDirection dir )
  434. {
  435.     // ignore top
  436.     if( dir == DIR_TOP )
  437.     {
  438.         return;
  439.     }
  440.  
  441.     Destroy();
  442. }
  443.