home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2009 February / maximum-cd-2009-02.iso / DiscContents / SMC_1.6_win32.exe / src / enemies / turtle.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2008-09-26  |  20.8 KB  |  939 lines

  1. /***************************************************************************
  2.  * turtle.cpp  -  turtle enemy class
  3.  *
  4.  * Copyright (C) 2003 - 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 "../enemies/turtle.h"
  17. #include "../core/game_core.h"
  18. #include "../objects/box.h"
  19. #include "../video/animation.h"
  20. #include "../player/player.h"
  21. #include "../level/level.h"
  22. #include "../gui/hud.h"
  23. #include "../video/gl_surface.h"
  24. #include "../user/savegame.h"
  25. #include "../core/sprite_manager.h"
  26. #include "../core/i18n.h"
  27.  
  28. /* *** *** *** *** *** *** cTurtle *** *** *** *** *** *** *** *** *** *** *** */
  29.  
  30. cTurtle :: cTurtle( float x, float y )
  31. : cEnemy( x, y )
  32. {
  33.     cTurtle::Init();
  34. }
  35.  
  36. cTurtle :: cTurtle( CEGUI::XMLAttributes &attributes )
  37. : cEnemy()
  38. {
  39.     cTurtle::Init();
  40.     cTurtle::Create_from_Stream( attributes );
  41. }
  42.  
  43. cTurtle :: ~cTurtle( void )
  44. {
  45.     //
  46. }
  47.  
  48. void cTurtle :: Init( void )
  49. {
  50.     type = TYPE_TURTLE;
  51.     posz = 0.091f;
  52.  
  53.     state = STA_WALK;
  54.     turtle_state = TURTLE_WALK;    // Walking
  55.     playercounter = 0;
  56.  
  57.     color_type = COL_DEFAULT;
  58.     Set_Color( COL_RED );
  59.     Set_Direction( DIR_RIGHT, 1 );
  60.  
  61.     kill_sound = "stomp_4.ogg";
  62. }
  63.  
  64. cTurtle *cTurtle :: Copy( void )
  65. {
  66.     cTurtle *turtle = new cTurtle( startposx, startposy );
  67.     turtle->Set_Direction( start_direction, 1 );
  68.     turtle->Set_Color( color_type );
  69.  
  70.     return turtle;
  71. }
  72.  
  73. void cTurtle :: Create_from_Stream( CEGUI::XMLAttributes &attributes )
  74. {
  75.     // position
  76.     Set_Pos( static_cast<float>(attributes.getValueAsInteger( "posx" )), static_cast<float>(attributes.getValueAsInteger( "posy" )), 1 );
  77.     // direction
  78.     Set_Direction( Get_Direction_Id( attributes.getValueAsString( "direction", Get_Direction_Name( start_direction ) ).c_str() ), 1 );
  79.     // color
  80.     Set_Color( static_cast<DefaultColor>(Get_Color_Id( attributes.getValueAsString( "color", Get_Color_Name( color_type ) ).c_str() )) );
  81. }
  82.  
  83. void cTurtle :: Save_to_Stream( ofstream &file )
  84. {
  85.     // begin enemy
  86.     file << "\t<enemy>" << std::endl;
  87.  
  88.     // name
  89.     file << "\t\t<Property name=\"type\" value=\"turtle\" />" << std::endl;
  90.     // position
  91.     file << "\t\t<Property name=\"posx\" value=\"" << static_cast<int>(startposx) << "\" />" << std::endl;
  92.     file << "\t\t<Property name=\"posy\" value=\"" << static_cast<int>(startposy) << "\" />" << std::endl;
  93.     // color
  94.     file << "\t\t<Property name=\"color\" value=\"" << Get_Color_Name( color_type ) << "\" />" << std::endl;
  95.     // direction
  96.     file << "\t\t<Property name=\"direction\" value=\"" << Get_Direction_Name( start_direction ) << "\" />" << std::endl;
  97.  
  98.     // end enemy
  99.     file << "\t</enemy>" << std::endl;
  100. }
  101.  
  102. void cTurtle :: Load_from_Savegame( cSave_Level_Object *save_object )
  103. {
  104.     cEnemy::Load_from_Savegame( save_object );
  105.  
  106.     // turtle_state
  107.     if( save_object->exists( "turtle_state" ) )
  108.     {
  109.         turtle_state = static_cast<Turtle_state>(string_to_int( save_object->Get_Value( "turtle_state" ) ));
  110.  
  111.         if( turtle_state == TURTLE_SHELL_STAND || turtle_state == TURTLE_SHELL_RUN )
  112.         {
  113.             // todo : create a Set_State function
  114.             // set shell image without position changes
  115.             cSprite::Set_Image( images[5] );
  116.         }
  117.     }
  118.     
  119.     Update_Rotation_Hor_velx();
  120. }
  121.  
  122. cSave_Level_Object *cTurtle :: Save_to_Savegame( void )
  123. {
  124.     cSave_Level_Object *save_object = cEnemy::Save_to_Savegame();
  125.  
  126.     // turtle_state ( only save if needed )
  127.     if( turtle_state != TURTLE_WALK )
  128.     {
  129.         save_object->properties.push_back( cSave_Level_Object_Property( "turtle_state", int_to_string( turtle_state ) ) );
  130.     }
  131.  
  132.     return save_object;
  133. }
  134.  
  135. void cTurtle :: Set_Direction( ObjectDirection dir, bool new_start_direction /* = 0 */ )
  136. {
  137.     if( dir != DIR_RIGHT && dir != DIR_LEFT )
  138.     {
  139.         printf( "Warning : Unknown Turtle direction set %d\n", dir );
  140.         return;
  141.     }
  142.  
  143.     cEnemy::Set_Direction( dir, new_start_direction );
  144.  
  145.     if( direction == DIR_RIGHT )
  146.     {
  147.         if( turtle_state == TURTLE_WALK )
  148.         {
  149.             velx = speed_walk;
  150.         }
  151.         else
  152.         {
  153.             velx = speed_shell;
  154.         }
  155.     }
  156.     else
  157.     {
  158.         if( turtle_state == TURTLE_WALK )
  159.         {
  160.             velx = -speed_walk;
  161.         }
  162.         else
  163.         {
  164.             velx = -speed_shell;
  165.         }
  166.     }
  167.  
  168.     Update_Rotation_Hor_velx( new_start_direction );
  169.  
  170.     if( new_start_direction )
  171.     {
  172.         Create_Name();
  173.     }
  174. }
  175.  
  176. void cTurtle :: Set_Color( DefaultColor col )
  177. {
  178.     // already set
  179.     if( color_type == col )
  180.     {
  181.         return;
  182.     }
  183.  
  184.     color_type = col;
  185.  
  186.     string filename_dir;
  187.  
  188.     if( color_type == COL_RED )
  189.     {
  190.         filename_dir = "red";
  191.  
  192.         speed_walk = 3.6f;
  193.         speed_shell = 14;
  194.         kill_points = 50;
  195.     }
  196.     else if( color_type == COL_GREEN )
  197.     {
  198.         filename_dir = "green";
  199.  
  200.         speed_walk = 4.5f;
  201.         speed_shell = 17;
  202.         kill_points = 150;
  203.     }
  204.     // unknown color
  205.     else
  206.     {
  207.         printf( "Error : Unknown Turtle color : %d\n", color_type );
  208.     }
  209.  
  210.     Clear_Images();
  211.  
  212.     // Walk
  213.     images.push_back( pVideo->Get_Surface( "enemy/turtle/" + filename_dir + "/walk_0.png" ) );
  214.     images.push_back( pVideo->Get_Surface( "enemy/turtle/" + filename_dir + "/walk_1.png" ) );
  215.     images.push_back( pVideo->Get_Surface( "enemy/turtle/" + filename_dir + "/walk_2.png" ) );
  216.     images.push_back( pVideo->Get_Surface( "enemy/turtle/" + filename_dir + "/walk_1.png" ) );
  217.     // Walk Turn
  218.     //images.push_back( pVideo->Get_Surface( "enemy/turtle/" + filename_dir + "/turn_1.png" ) );
  219.     images.push_back( NULL );
  220.     // Shell
  221.     images.push_back( pVideo->Get_Surface( "enemy/turtle/" + filename_dir + "/shell_front.png" ) );
  222.     images.push_back( pVideo->Get_Surface( "enemy/turtle/" + filename_dir + "/shell_move_1.png" ) );
  223.     images.push_back( pVideo->Get_Surface( "enemy/turtle/" + filename_dir + "/shell_move_2.png" ) );
  224.     images.push_back( pVideo->Get_Surface( "enemy/turtle/" + filename_dir + "/shell_move_3.png" ) );
  225.     images.push_back( pVideo->Get_Surface( "enemy/turtle/" + filename_dir + "/shell_active.png" ) );
  226.  
  227.     Set_Image( 0, 1 );
  228.     Create_Name();
  229. }
  230.  
  231. void cTurtle :: Turn_Around( ObjectDirection col_dir /* = DIR_UNDEFINED */ )
  232. {
  233.     cEnemy::Turn_Around( col_dir );
  234.  
  235.     if( turtle_state == TURTLE_WALK )
  236.     {
  237.         // hack : disable turn image
  238.         //walk_count = 0;
  239.         //Set_Image( 4 );
  240.     }
  241.  
  242.     Update_Rotation_Hor_velx();
  243. }
  244.  
  245. void cTurtle :: DownGrade( bool force /* = 0 */ )
  246. {
  247.     if( !force )
  248.     {
  249.         // normal walking
  250.         if( turtle_state == TURTLE_WALK )
  251.         {
  252.             counter = 0;
  253.             state = STA_STAY;
  254.             turtle_state = TURTLE_SHELL_STAND;
  255.  
  256.             Set_Image( 5 );
  257.             Col_Move( 0, images[0]->col_h - images[5]->col_h, 1, 1 );
  258.         }
  259.         // staying
  260.         else if( turtle_state == TURTLE_SHELL_STAND )
  261.         {
  262.             counter = 0;
  263.             state = STA_RUN;
  264.             turtle_state = TURTLE_SHELL_RUN;
  265.             player_range = 5000;
  266.  
  267.             // move into random direction
  268.             if( rand() % 2 != 1 )
  269.             {
  270.                 // right
  271.                 velx = speed_shell;
  272.             }
  273.             else
  274.             {
  275.                 // left
  276.                 velx = -speed_shell;
  277.             }
  278.  
  279.             Update_Direction();
  280.             Update_Rotation_Hor_velx();
  281.         }
  282.         // running shell
  283.         else if( turtle_state == TURTLE_SHELL_RUN )
  284.         {
  285.             counter = 0;
  286.             state = STA_STAY;
  287.             turtle_state = TURTLE_SHELL_STAND;
  288.             player_range = 2000;
  289.         }
  290.     }
  291.     // falling death
  292.     else
  293.     {
  294.         counter = 8;
  295.         Set_Dead( 1 );
  296.         massivetype = MASS_PASSIVE;
  297.         velx = 0;
  298.         vely = 0;
  299.  
  300.         if( turtle_state == TURTLE_WALK )
  301.         {
  302.             Move( 0, images[0]->h - images[5]->h, 1 );
  303.         }
  304.  
  305.         Set_Image( 5 );
  306.     }
  307. }
  308.  
  309. void cTurtle :: DieStep( void )
  310. {
  311.     counter += pFramerate->speedfactor * 0.5f;
  312.  
  313.     // if not below the screen fall
  314.     if( posy < game_res_h + col_rect.h )
  315.     {
  316.         float speed_y = counter;
  317.  
  318.         // first a little bit upwards
  319.         if( speed_y < 10 )
  320.         {
  321.             speed_y *= -1;
  322.         }
  323.         // limit falling speed
  324.         else if( speed_y > 25 )
  325.         {
  326.             speed_y = 25;
  327.         }
  328.  
  329.         float speed_x = pFramerate->speedfactor;
  330.  
  331.         if( direction == DIR_LEFT )
  332.         {
  333.             speed_x *= -1;
  334.         }
  335.  
  336.         Add_Rotation_Z( speed_x );
  337.  
  338.         Move( speed_x * 15, speed_y );
  339.     }
  340.     // if below disable
  341.     else
  342.     {
  343.         Set_Visible( 0 );
  344.         rotz = 0;
  345.         state = STA_STAY;
  346.         turtle_state = TURTLE_DEAD;
  347.     }
  348. }
  349.  
  350. void cTurtle :: Update( void )
  351. {
  352.     cEnemy::Update();
  353.  
  354.     if( !valid_update || !is_Player_range() )
  355.     {
  356.         return;
  357.     }
  358.  
  359.     // walking
  360.     if( turtle_state == TURTLE_WALK )
  361.     {
  362.         walk_count += pFramerate->speedfactor * 0.3f;
  363.  
  364.         // if not turn around image
  365.         if( curr_img != 4 )
  366.         {
  367.             if( walk_count >= 4 )
  368.             {
  369.                 walk_count = 0;
  370.             }
  371.  
  372.             Set_Image( static_cast<int>(walk_count) );
  373.         }
  374.         // turn around image
  375.         else
  376.         {
  377.             // set normal image back
  378.             if( walk_count >= 4 )
  379.             {
  380.                 Set_Image( static_cast<int>(walk_count) );
  381.                 Update_Rotation_Hor_velx();
  382.             }
  383.             // rotate the turn image
  384.             else if( walk_count >= 2 )
  385.             {
  386.                 if( velx < 0 )
  387.                 {
  388.                     roty = 180;
  389.                 }
  390.                 else
  391.                 {
  392.                     roty = 0;
  393.                 }
  394.             }
  395.         }
  396.     }
  397.     // standing shell
  398.     else if( turtle_state == TURTLE_SHELL_STAND )
  399.     {
  400.         counter += pFramerate->speedfactor;
  401.  
  402.         // waiting
  403.         if( counter < 160 )
  404.         {
  405.             Set_Image( 5 ); // front
  406.         }
  407.         else
  408.         {
  409.             // animation
  410.             if( counter < 192 )
  411.             {
  412.                 if( static_cast<int>(counter) % 5 == 1 )
  413.                 {
  414.                     Set_Image( 9 ); // active
  415.                 }
  416.                 else
  417.                 {
  418.                     Set_Image( 5 ); // front
  419.                 }
  420.             }
  421.             // activate
  422.             else
  423.             {
  424.                 counter = 0;
  425.                 turtle_state = TURTLE_WALK;
  426.                 state = STA_WALK;
  427.  
  428.                 if( direction == DIR_RIGHT )
  429.                 {
  430.                     velx = speed_walk;
  431.                 }
  432.                 else
  433.                 {
  434.                     velx = -speed_walk;
  435.                 }
  436.  
  437.                 Update_Direction();
  438.                 Update_Rotation_Hor_velx();
  439.  
  440.                 // todo : create again
  441.                 //pAudio->PlaySound( "enemy/turtle/power_up.ogg" );
  442.  
  443.                 if( curr_img > 4 )
  444.                 {
  445.                     Col_Move( 0, images[5]->col_h - images[0]->col_h, 1, 1 );
  446.                 }
  447.  
  448.                 Set_Image( 0 ); // walk
  449.             }
  450.         }
  451.  
  452.  
  453.         if( velx != 0 )
  454.         {
  455.             Add_Velocity( -velx * 0.2f, 0 );
  456.  
  457.             if( velx < 0.3f && velx > -0.3f )
  458.             {
  459.                 velx = 0;
  460.             }
  461.         }
  462.     }
  463.     // moving shell
  464.     else if( turtle_state == TURTLE_SHELL_RUN )
  465.     {
  466.         walk_count += pFramerate->speedfactor * 0.4f;
  467.  
  468.         if( walk_count >= 3 )
  469.         {
  470.             walk_count = 0;
  471.         }
  472.  
  473.         Set_Image( 6 + static_cast<int>(walk_count) );
  474.     }
  475.  
  476.     if( playercounter > 0 )
  477.     {
  478.         playercounter -= pFramerate->speedfactor;
  479.  
  480.         if( playercounter <= 0 )
  481.         {
  482.             // do not start collision detection if in maryo
  483.             if( Col_Box( &pPlayer->col_rect, &col_rect ) )
  484.             {
  485.                 playercounter = 5;
  486.             }
  487.             else
  488.             {
  489.                 playercounter = 0;
  490.             }
  491.         }
  492.     }
  493.  
  494.     // gravity
  495.     Update_Gravity();
  496. }
  497.  
  498. bool cTurtle :: Is_Update_Valid( void )
  499. {
  500.     if( dead || freeze_counter || state == STA_OBJ_LINKED )
  501.     {
  502.         return 0;
  503.     }
  504.  
  505.     return 1;
  506. }
  507.  
  508. unsigned int cTurtle :: Validate_Collision( cSprite *obj )
  509. {
  510.     // basic validation checking
  511.     int basic_valid = Validate_Collision_Ghost( obj );
  512.  
  513.     // found valid collision
  514.     if( basic_valid > -1 )
  515.     {
  516.         return basic_valid;
  517.     }
  518.  
  519.     if( obj->massivetype == MASS_MASSIVE )
  520.     {
  521.         if( obj->type == TYPE_PLAYER )
  522.         {
  523.             // player is invincible
  524.             if( pPlayer->invincible )
  525.             {
  526.                 return 0;
  527.             }
  528.             // player counter is active
  529.             if( turtle_state == TURTLE_SHELL_RUN && playercounter > 0 )
  530.             {
  531.                 return 0;
  532.             }
  533.         }
  534.         else if( obj->sprite_array == ARRAY_ENEMY )
  535.         {
  536.             if( obj->type == TYPE_JPIRANHA )
  537.             {
  538.                 // if walking
  539.                 if( turtle_state == TURTLE_WALK )
  540.                 {
  541.                     return 0;
  542.                 }
  543.                 // shell
  544.                 if( turtle_state == TURTLE_SHELL_STAND || turtle_state == TURTLE_SHELL_RUN )
  545.                 {
  546.                     return 1;
  547.                 }
  548.             }
  549.             if( obj->type == TYPE_ROKKO )
  550.             {
  551.                 return 0;
  552.             }
  553.             if( obj->type == TYPE_GEE )
  554.             {
  555.                 if( turtle_state == TURTLE_SHELL_STAND || turtle_state == TURTLE_SHELL_RUN )
  556.                 {
  557.                     return 1;
  558.                 }
  559.  
  560.                 return 0;
  561.             }
  562.             if( obj->type == TYPE_STATIC_ENEMY )
  563.             {
  564.                 return 0;
  565.             }
  566.  
  567.             // if moving shell don't collide with enemies
  568.             if( turtle_state == TURTLE_SHELL_RUN )
  569.             {
  570.                 return 1;
  571.             }
  572.         }
  573.  
  574.         return 2;
  575.     }
  576.     if( obj->type == TYPE_ENEMY_STOPPER )
  577.     {
  578.         if( turtle_state == TURTLE_WALK )
  579.         {
  580.             return 2;
  581.         }
  582.  
  583.         return 0;
  584.     }
  585.     if( obj->massivetype == MASS_HALFMASSIVE )
  586.     {
  587.         // if moving downwards and object is on top
  588.         if( vely >= 0 && Is_on_Top( obj ) )
  589.         {
  590.             return 2;
  591.         }
  592.     }
  593.  
  594.     return 0;
  595. }
  596.  
  597. void cTurtle :: Handle_Collision_Player( cObjectCollision *collision )
  598. {
  599.     if( collision->direction == DIR_UNDEFINED || ( turtle_state == TURTLE_SHELL_RUN && playercounter > 0 ) || state == STA_OBJ_LINKED )
  600.     {
  601.         return;
  602.     }
  603.  
  604.     if( collision->direction == DIR_TOP && pPlayer->state != STA_FLY )
  605.     {
  606.         if( turtle_state == TURTLE_WALK )
  607.         {
  608.             pointsdisplay->Add_Points( 25, pPlayer->posx, pPlayer->posy );
  609.             pAudio->Play_Sound( "enemy/turtle/hit.ogg" );
  610.         }
  611.         else if( turtle_state == TURTLE_SHELL_STAND )
  612.         {
  613.             pointsdisplay->Add_Points( 10, pPlayer->posx, pPlayer->posy );
  614.             pAudio->Play_Sound( "enemy/turtle/shell/hit.ogg" );
  615.         }
  616.         else if( turtle_state == TURTLE_SHELL_RUN )
  617.         {
  618.             pointsdisplay->Add_Points( 5, pPlayer->posx, pPlayer->posy );
  619.             pAudio->Play_Sound( "enemy/turtle/shell/hit.ogg" );
  620.         }
  621.  
  622.         // animation
  623.         cParticle_Emitter *anim = new cParticle_Emitter();
  624.         anim->Set_Pos( posx + ( col_rect.w / 2 ), posy + ( col_rect.h / 2 ) );
  625.         Generate_Hit_Animation( anim );
  626.  
  627.         anim->Set_Speed( 4, 0.8f );
  628.         anim->Set_Scale( 0.6f );
  629.         // add animation
  630.         pAnimation_Manager->Add( anim );
  631.  
  632.         DownGrade();
  633.  
  634.         // if now running
  635.         if( turtle_state == TURTLE_SHELL_RUN )
  636.         {
  637.             // if player is on the left side
  638.             if( ( pPlayer->col_rect.w / 2 ) + pPlayer->posx < ( col_rect.w / 2 ) + posx )
  639.             {
  640.                 velx = speed_shell;
  641.             }
  642.             // on the right side
  643.             else
  644.             {
  645.                 velx = -speed_shell;
  646.             }
  647.  
  648.             Update_Direction();
  649.         }
  650.  
  651.         pPlayer->Action_Jump( 1 );
  652.     }
  653.     else
  654.     {
  655.         if( turtle_state == TURTLE_WALK )
  656.         {
  657.             pPlayer->DownGrade();
  658.             Turn_Around( collision->direction );
  659.         }
  660.         else if( turtle_state == TURTLE_SHELL_STAND )
  661.         {
  662.             pAudio->Play_Sound( "enemy/turtle/shell/hit.ogg" );
  663.             DownGrade();
  664.  
  665.             cParticle_Emitter *anim = NULL;
  666.             if( collision->direction == DIR_RIGHT )
  667.             {
  668.                 anim = new cParticle_Emitter();
  669.                 anim->Set_Pos( posx + col_pos.x + col_rect.w, posy + ( col_rect.h / 2 ) );
  670.                 anim->Set_Direction_Range( 90, 180 );
  671.                 velx = -speed_shell;
  672.             }
  673.             else if( collision->direction == DIR_LEFT )
  674.             {
  675.                 anim = new cParticle_Emitter();
  676.                 anim->Set_Pos( posx, posy + ( col_rect.h / 2 ) );
  677.                 anim->Set_Direction_Range( 270, 180 );
  678.                 velx = speed_shell;
  679.             }
  680.             else
  681.             {
  682.                 anim = new cParticle_Emitter();
  683.                 anim->Set_Pos( posx + ( col_rect.w / 2 ), posy + col_pos.y + col_rect.h );
  684.                 anim->Set_Direction_Range( 180, 180 );
  685.  
  686.                 // if player is on the left side
  687.                 if( ( pPlayer->col_rect.w / 2 ) + pPlayer->posx < ( col_rect.w / 2 ) + posx )
  688.                 {
  689.                     velx = speed_shell;
  690.                 }
  691.                 // on the right side
  692.                 else
  693.                 {
  694.                     velx = -speed_shell;
  695.                 }
  696.             }
  697.             
  698.             anim->Set_Image( pVideo->Get_Surface( "animation/particles/light.png" ) );
  699.             anim->Set_Quota( 4 );
  700.             anim->Set_Pos_Z( posz + 0.0001f );
  701.             anim->Set_Time_to_Live( 0.3f );
  702.             anim->Set_Speed( 4, 0.5f );
  703.             anim->Set_Scale( 0.6f );
  704.             anim->Set_Fading_Size( 1 );
  705.             anim->Set_Color( Color( static_cast<Uint8>(254), 200, 100 ) );
  706.             pAnimation_Manager->Add( anim );
  707.  
  708.             Update_Direction();
  709.  
  710.             playercounter = speedfactor_fps * 0.13f;
  711.  
  712.             // small upwards kick
  713.             if( collision->direction == DIR_BOTTOM )
  714.             {
  715.                 vely = -5 + (pPlayer->vely * 0.3f);
  716.             }
  717.         }
  718.         else if( turtle_state == TURTLE_SHELL_RUN )
  719.         {
  720.             // bottom kicks upwards
  721.             if( collision->direction == DIR_BOTTOM )
  722.             {
  723.                 // small upwards kick
  724.                 if( collision->direction == DIR_BOTTOM )
  725.                 {
  726.                     vely = -5 + (pPlayer->vely * 0.3f);
  727.                 }
  728.             }
  729.             // other directions downgrade
  730.             else
  731.             {
  732.                 pPlayer->DownGrade();
  733.                 Turn_Around( collision->direction );
  734.             }
  735.         }
  736.     }
  737. }
  738.  
  739. void cTurtle :: Handle_Collision_Enemy( cObjectCollision *collision )
  740. {
  741.     if( turtle_state == TURTLE_SHELL_STAND )
  742.     {
  743.         cEnemy *enemy = static_cast<cEnemy *>(pActive_Sprite_Manager->Get_Pointer( collision->number ));
  744.  
  745.         // if able to collide
  746.         if( state == STA_OBJ_LINKED || vely < -5 )
  747.         {
  748.             // don't collide with already dead enemies
  749.             if( enemy->dead )
  750.             {
  751.                 return;
  752.             }
  753.  
  754.             // Shells can't hit the boss
  755.             if( enemy->type == TYPE_TURTLE_BOSS )
  756.             {
  757.                 return;
  758.             }
  759.  
  760.             // hit enemy
  761.             pAudio->Play_Sound( enemy->kill_sound );
  762.             pointsdisplay->Add_Points( enemy->kill_points, posx + image->w / 3, posy - 5, "", static_cast<Uint8>(255), 1 );
  763.             enemy->DownGrade( 1 );
  764.  
  765.             DownGrade( 1 );
  766.             pPlayer->Add_Kill_Multiplier();
  767.         }
  768.     }
  769.     else if( turtle_state == TURTLE_SHELL_RUN )
  770.     {
  771.         cEnemy *enemy = static_cast<cEnemy *>(pActive_Sprite_Manager->Get_Pointer( collision->number ));
  772.  
  773.         // don't collide with already dead enemies
  774.         if( enemy->dead )
  775.         {
  776.             return;
  777.         }
  778.  
  779.         // Shells can't hit the boss
  780.         if( enemy->type == TYPE_TURTLE_BOSS )
  781.         {
  782.             return;
  783.         }
  784.  
  785.         // if red shell check if colliding turtle is green and also running
  786.         if( color_type == COL_RED && enemy->type == TYPE_TURTLE )
  787.         {
  788.             cTurtle *turtle = static_cast<cTurtle *>(enemy);
  789.  
  790.             // red shell can't kill green shells
  791.             if( turtle->color_type == COL_GREEN && turtle->state == STA_RUN )
  792.             {
  793.                 return;
  794.             }
  795.         }
  796.  
  797.         // hit enemy
  798.         pAudio->Play_Sound( enemy->kill_sound );
  799.         pointsdisplay->Add_Points( enemy->kill_points, posx + image->w / 3, posy - 5, "", static_cast<Uint8>(255), 1 );
  800.         enemy->DownGrade( 1 );
  801.  
  802.         // create animation
  803.         cParticle_Emitter *anim = new cParticle_Emitter();
  804.  
  805.         anim->Set_Emitter_Rect( col_rect.x + ( col_rect.w * 0.2f ), col_rect.y + ( col_rect.h * 0.2f ), col_rect.w * 0.6f, col_rect.h * 0.8f );
  806.         anim->Set_Image( pVideo->Get_Surface( "animation/particles/light.png" ) );
  807.         anim->Set_Quota( 5 );
  808.         anim->Set_Pos_Z( posz + 0.000001f );
  809.         anim->Set_Time_to_Live( 0.3f );
  810.         anim->Set_Speed( 1.2f, 0.8f );
  811.         anim->Set_Scale( 0.7f );
  812.         anim->Set_Fading_Alpha( 1 );
  813.         anim->Set_Blending( BLEND_ADD );
  814.  
  815.         if( collision->direction == DIR_RIGHT )
  816.         {
  817.             anim->Set_Direction_Range( 0 );
  818.         }
  819.         else if( collision->direction == DIR_LEFT )
  820.         {
  821.             anim->Set_Direction_Range( 180 );
  822.         }
  823.         
  824.         // add animation
  825.         pAnimation_Manager->Add( anim );
  826.  
  827.         pPlayer->Add_Kill_Multiplier();
  828.     }
  829.     else if( turtle_state == TURTLE_WALK )
  830.     {
  831.         Turn_Around( collision->direction );
  832.         Send_Collision( collision );
  833.     }
  834. }
  835.  
  836. void cTurtle :: Handle_Collision_Massive( cObjectCollision *collision )
  837. {
  838.     if( turtle_state == TURTLE_WALK )
  839.     {
  840.         //
  841.     }
  842.     else if( turtle_state == TURTLE_SHELL_RUN )
  843.     {
  844.         if( collision->direction == DIR_RIGHT || collision->direction == DIR_LEFT )
  845.         {
  846.             cSprite *col_object = pActive_Sprite_Manager->Get_Pointer( collision->number );
  847.  
  848.             // animation
  849.             cParticle_Emitter *anim = NULL;
  850.             if( collision->direction == DIR_RIGHT )
  851.             {
  852.                 anim = new cParticle_Emitter();
  853.                 anim->Set_Pos( col_object->posx + col_object->col_pos.x + 4, posy + ( col_rect.h / 1.35f ) );
  854.                 anim->Set_Direction_Range( 140, 100 );
  855.             }
  856.             else
  857.             {
  858.                 anim = new cParticle_Emitter();
  859.                 anim->Set_Pos( col_object->posx + col_object->col_pos.x + col_object->col_rect.w - 4, posy + ( col_rect.h / 1.35f ) );
  860.                 anim->Set_Direction_Range( 320, 100 );
  861.             }
  862.  
  863.             anim->Set_Image( pVideo->Get_Surface( "animation/particles/smoke.png" ) );
  864.             anim->Set_Quota( 5 );
  865.             anim->Set_Pos_Z( col_object->posz - 0.0001f, 0.0002f );
  866.             anim->Set_Time_to_Live( 0.2f, 0.2f );
  867.             anim->Set_Speed( 1, 1 );
  868.             anim->Set_Scale( 0.5f, 0.4f );
  869.             pAnimation_Manager->Add( anim );
  870.         }
  871.  
  872.         // active object collision
  873.         if( collision->type == CO_ACTIVE )
  874.         {
  875.             Send_Collision( collision );
  876.         }
  877.     }
  878.     else if( turtle_state == TURTLE_SHELL_STAND )
  879.     {
  880.         // if able to collide
  881.         if( state == STA_OBJ_LINKED || vely < -5 )
  882.         {
  883.             // active object box collision
  884.             if( collision->type == CO_ACTIVE )
  885.             {
  886.                 // get colliding object
  887.                 cSprite *col_object = pActive_Sprite_Manager->Get_Pointer( collision->number );
  888.  
  889.                 if( col_object->type == TYPE_BONUSBOX || col_object->type == TYPE_SPINBOX )
  890.                 {
  891.                     // get basebox
  892.                     cBaseBox *box = static_cast<cBaseBox *>(col_object);
  893.  
  894.                     // if useable
  895.                     if( box->useable_count != 0 )
  896.                     {
  897.                         pointsdisplay->Add_Points( 50, posx + image->w / 3, posy - 5 );
  898.                         Send_Collision( collision );
  899.                         DownGrade( 1 );
  900.                         return;
  901.                     }
  902.                 }
  903.             }
  904.         }
  905.     }
  906.  
  907.     if( state == STA_OBJ_LINKED )
  908.     {
  909.         return;
  910.     }
  911.     
  912.     if( collision->direction == DIR_TOP )
  913.     {
  914.         if( vely > 0 )
  915.         {
  916.             vely = 0;
  917.         }
  918.     }
  919.     else if( collision->direction == DIR_BOTTOM )
  920.     {
  921.         if( vely < 0 )
  922.         {
  923.             vely = 0;
  924.         }
  925.     }
  926.     else
  927.     {
  928.         Turn_Around( collision->direction );
  929.     }
  930. }
  931.  
  932. void cTurtle :: Create_Name( void )
  933. {
  934.     name = "Turtle ";
  935.     name += _(Get_Color_Name( color_type ).c_str());
  936.     name += " ";
  937.     name += _(Get_Direction_Name( start_direction ).c_str());
  938. }
  939.