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

  1. /***************************************************************************
  2.  * jpiranha.cpp  -  jumping piranha plant
  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/jpiranha.h"
  17. #include "../core/game_core.h"
  18. #include "../core/camera.h"
  19. #include "../player/player.h"
  20. #include "../core/obj_manager.h"
  21. #include "../video/animation.h"
  22. #include "../user/savegame.h"
  23. #include "../core/math/utilities.h"
  24. #include "../input/mouse.h"
  25. #include "../core/i18n.h"
  26.  
  27. /* *** *** *** *** *** *** cjPiranha *** *** *** *** *** *** *** *** *** *** *** */
  28.  
  29. cjPiranha :: cjPiranha( float x, float y )
  30. : cEnemy( x, y )
  31. {
  32.     cjPiranha::Init();
  33. }
  34.  
  35. cjPiranha :: cjPiranha( CEGUI::XMLAttributes &attributes )
  36. : cEnemy()
  37. {
  38.     cjPiranha::Init();
  39.     cjPiranha::Create_from_Stream( attributes );
  40. }
  41.  
  42. cjPiranha :: ~cjPiranha( void )
  43. {
  44.     //
  45. }
  46.  
  47. void cjPiranha :: Init( void  )
  48. {
  49.     type = TYPE_JPIRANHA;
  50.     posz = 0.06f;
  51.     editor_posz = 0.089f;
  52.     player_range = 1000;
  53.  
  54.     state = STA_STAY;
  55.     Set_Direction( DIR_UP );
  56.     Set_Max_Distance( 200 );
  57.     Set_Speed( 5.8f );
  58.  
  59.     kill_sound = "enemy/jpiranha/die.ogg";
  60.     kill_points = 100;
  61.  
  62.     walk_count = Get_Random_Float( 0, 4 );
  63.     wait_time = Get_Random_Float( 0, 70 );
  64.     move_back = 0;
  65. }
  66.  
  67. cjPiranha *cjPiranha :: Copy( void )
  68. {
  69.     cjPiranha *jpiranha = new cjPiranha( startposx, startposy );
  70.     jpiranha->Set_Direction( start_direction );
  71.     jpiranha->Set_Max_Distance( max_distance );
  72.     jpiranha->Set_Speed( speed );
  73.     return jpiranha;
  74. }
  75.  
  76. void cjPiranha :: Create_from_Stream( CEGUI::XMLAttributes &attributes )
  77. {
  78.     // position
  79.     Set_Pos( static_cast<float>(attributes.getValueAsInteger( "posx" )), static_cast<float>(attributes.getValueAsInteger( "posy" )), 1 );
  80.     // direction
  81.     Set_Direction( Get_Direction_Id( attributes.getValueAsString( "direction", Get_Direction_Name( start_direction ) ).c_str() ) );
  82.     // max distance
  83.     Set_Max_Distance( attributes.getValueAsFloat( "max_distance", max_distance ) );
  84.     // speed
  85.     Set_Speed( attributes.getValueAsFloat( "speed", speed ) );
  86. }
  87.  
  88. void cjPiranha :: Save_to_Stream( ofstream &file )
  89. {
  90.     // begin enemy
  91.     file << "\t<enemy>" << std::endl;
  92.  
  93.     // name
  94.     file << "\t\t<Property name=\"type\" value=\"jpiranha\" />" << std::endl;
  95.     // position
  96.     file << "\t\t<Property name=\"posx\" value=\"" << static_cast<int>(startposx) << "\" />" << std::endl;
  97.     file << "\t\t<Property name=\"posy\" value=\"" << static_cast<int>(startposy) << "\" />" << std::endl;
  98.     // direction
  99.     file << "\t\t<Property name=\"direction\" value=\"" << Get_Direction_Name( start_direction ) << "\" />" << std::endl;
  100.     // max distance
  101.     file << "\t\t<Property name=\"max_distance\" value=\"" << static_cast<int>(max_distance) << "\" />" << std::endl;
  102.     // speed
  103.     file << "\t\t<Property name=\"speed\" value=\"" << speed << "\" />" << std::endl;
  104.  
  105.     // end enemy
  106.     file << "\t</enemy>" << std::endl;
  107. }
  108.  
  109. void cjPiranha :: Load_from_Savegame( cSave_Level_Object *save_object )
  110. {
  111.     cEnemy::Load_from_Savegame( save_object );
  112.  
  113.     // move_back
  114.     if( save_object->exists( "move_back" ) )
  115.     {
  116.         move_back = string_to_int( save_object->Get_Value( "move_back" ) ) > 0;
  117.     }
  118. }
  119.  
  120. cSave_Level_Object *cjPiranha :: Save_to_Savegame( void )
  121. {
  122.     cSave_Level_Object *save_object = cEnemy::Save_to_Savegame();
  123.  
  124.     // move_back ( only save if needed )
  125.     if( move_back )
  126.     {
  127.         save_object->properties.push_back( cSave_Level_Object_Property( "move_back", int_to_string( move_back ) ) );
  128.     }
  129.  
  130.     return save_object;
  131. }
  132.  
  133. void cjPiranha :: Set_Direction( ObjectDirection dir )
  134. {
  135.     // already set
  136.     if( direction == dir )
  137.     {
  138.         return;
  139.     }
  140.  
  141.     // clear old images
  142.     Clear_Images();
  143.  
  144.     cEnemy::Set_Direction( dir, 1 );
  145.  
  146.     string filename_dir = Get_Direction_Name( start_direction );
  147.     name = "jPiranha ";
  148.     name += _(filename_dir.c_str());
  149.  
  150.     if( direction != DIR_UP && direction != DIR_DOWN && direction != DIR_LEFT && direction != DIR_RIGHT )
  151.     {
  152.         Set_Dead( 1 );
  153.         Set_Visible( 0 );
  154.  
  155.         printf( "Error : Unknown jPiranha direction %d\n", direction );
  156.         return;
  157.     }
  158.  
  159.     images.push_back( pVideo->Get_Surface( "enemy/jpiranha/" + filename_dir + "_closed_1.png" ) );
  160.     images.push_back( pVideo->Get_Surface( "enemy/jpiranha/" + filename_dir + "_closed_2.png" ) );
  161.     images.push_back( pVideo->Get_Surface( "enemy/jpiranha/" + filename_dir + "_open_1.png" ) );
  162.     images.push_back( pVideo->Get_Surface( "enemy/jpiranha/" + filename_dir + "_open_2.png" ) );
  163.  
  164.     Set_Image( 0, 1 );
  165. }
  166.  
  167. void cjPiranha :: Set_Max_Distance( float nmax_distance )
  168. {
  169.     max_distance = nmax_distance;
  170.  
  171.     if( max_distance < 0 )
  172.     {
  173.         max_distance = 0;
  174.     }
  175. }
  176.  
  177. void cjPiranha :: Set_Speed( float val )
  178. {
  179.     if( speed < 0.1f )
  180.     {
  181.         speed = 0.1f;
  182.     }
  183.  
  184.     speed = val;
  185.  
  186.     Update_Dest_Vel();
  187. }
  188.  
  189. void cjPiranha :: DownGrade( bool force /* = 0 */ )
  190. {
  191.     Set_Dead( 1 );
  192.     massivetype = MASS_PASSIVE;
  193.     counter = 0;
  194.     velx = 0;
  195.     vely = 0;
  196.  
  197.     if( !force )
  198.     {
  199.         // animation
  200.         cParticle_Emitter *anim = new cParticle_Emitter();
  201.         anim->Set_Pos( posx + ( col_rect.w / 2 ), posy + ( col_rect.h / 2 ) );
  202.         Generate_Hit_Animation( anim );
  203.  
  204.         anim->Set_Speed( 5, 0.6f );
  205.         anim->Set_Scale( 0.8f );
  206.         // add animation
  207.         pAnimation_Manager->Add( anim );
  208.     }
  209.     else
  210.     {
  211.         Set_Rotation_Z( 180 );
  212.     }
  213. }
  214.  
  215. void cjPiranha :: DieStep( void )
  216. {
  217.     counter += pFramerate->speedfactor;
  218.  
  219.     // default death
  220.     if( rotz != 180 )
  221.     {
  222.         Set_Visible( 0 );
  223.     }
  224.     // falling death
  225.     else
  226.     {
  227.         // a little bit upwards first
  228.         if( counter < 5 )
  229.         {
  230.             Move( 0, -5 );
  231.         }
  232.         // if not below the screen fall
  233.         else if( posy < game_res_h + col_rect.h )
  234.         {
  235.             Move( 0, 20 );
  236.         }
  237.         // if below disable
  238.         else
  239.         {
  240.             rotz = 0;
  241.             Set_Visible( 0 );
  242.         }
  243.     }
  244. }
  245.  
  246. void cjPiranha :: Update( void )
  247. {
  248.     cEnemy::Update();
  249.  
  250.     if( !valid_update || !is_Player_range() )
  251.     {
  252.         return;
  253.     }
  254.  
  255.     // standing ( waiting )
  256.     if( state == STA_STAY )
  257.     {
  258.         // if waiting time
  259.         if( wait_time > 0 )
  260.         {
  261.             wait_time -= pFramerate->speedfactor;
  262.  
  263.             if( wait_time < 0 )
  264.             {
  265.                 wait_time = 0;
  266.             }
  267.         }
  268.         // no more waiting try to jump out
  269.         else
  270.         {
  271.             GL_rect rect1 = col_rect;
  272.  
  273.             if( direction == DIR_UP )
  274.             {
  275.                 rect1.y -= 40;
  276.                 rect1.h += 40;
  277.             }
  278.             else if( direction == DIR_DOWN )
  279.             {
  280.                 rect1.y += 40;
  281.                 rect1.h -= 40;
  282.             }
  283.             else if( direction == DIR_LEFT )
  284.             {
  285.                 rect1.x -= 35;
  286.                 rect1.w += 35;
  287.             }
  288.             else if( direction == DIR_RIGHT )
  289.             {
  290.                 rect1.x += 35;
  291.                 rect1.w += 35;
  292.             }
  293.  
  294.             // if player is in front wait again
  295.             if( pPlayer->maryo_type != MARYO_GHOST && Col_Box( &pPlayer->col_rect, &rect1 ) )
  296.             {
  297.                 wait_time = speedfactor_fps * 2;
  298.             }
  299.             // if not jump out
  300.             else
  301.             {
  302.                 state = STA_FLY;
  303.  
  304.                 velx = dest_velx;
  305.                 vely = dest_vely;
  306.                 move_back = 0;
  307.             }
  308.         }
  309.     }
  310.     // flying ( moving into the destination direction )
  311.     else
  312.     {
  313.         // distance to final position
  314.         float dist_to_final_pos = Get_End_Distance();
  315.         // multiplier for the minimal velocity
  316.         float vel_mod_min = ( dist_to_final_pos + ( max_distance * 0.1f ) ) / max_distance;
  317.  
  318.         // if behind max distance
  319.         if( vel_mod_min <= 0.1f )
  320.         {
  321.             vel_mod_min = 0.1f;
  322.         }
  323.  
  324.         /* slow down
  325.          * with the velocity mod which is calculated from the distance to the final position
  326.         */
  327.         switch( direction )
  328.         {
  329.         case DIR_LEFT:
  330.         {
  331.             // move forward
  332.             if( !move_back )
  333.             {
  334.                 velx = dest_velx * vel_mod_min;
  335.             }
  336.             // move back
  337.             else
  338.             {
  339.                 velx = -dest_velx * vel_mod_min;
  340.             }
  341.             break;
  342.         }
  343.         case DIR_RIGHT:
  344.         {
  345.             // move forward
  346.             if( !move_back )
  347.             {
  348.                 velx = dest_velx * vel_mod_min;
  349.             }
  350.             // move back
  351.             else
  352.             {
  353.                 velx = -dest_velx * vel_mod_min;
  354.             }
  355.             break;
  356.         }
  357.         case DIR_UP:
  358.         {
  359.             // move forward
  360.             if( !move_back )
  361.             {
  362.                 vely = dest_vely * vel_mod_min;
  363.             }
  364.             // move back
  365.             else
  366.             {
  367.                 vely = -dest_vely * vel_mod_min;
  368.             }
  369.             break;
  370.         }
  371.         case DIR_DOWN:
  372.         {
  373.             // move forward
  374.             if( !move_back )
  375.             {
  376.                 vely = dest_vely * vel_mod_min;
  377.             }
  378.             // move back
  379.             else
  380.             {
  381.                 vely = -dest_vely * vel_mod_min;
  382.             }
  383.             break;
  384.         }
  385.         default:
  386.         {
  387.             break;
  388.         }
  389.         }
  390.  
  391.         walk_count += 0.23f * pFramerate->speedfactor;
  392.  
  393.         if( walk_count >= 4 )
  394.         {
  395.             walk_count = 0;
  396.         }
  397.  
  398.         Set_Image( static_cast<int>(walk_count) );
  399.  
  400.         // moving forward
  401.         if( !move_back )
  402.         {
  403.             // reached final position move back
  404.             if( dist_to_final_pos < 0 )
  405.             {
  406.                 velx = -dest_velx * 0.01f;
  407.                 vely = -dest_vely * 0.01f;
  408.  
  409.                 move_back = 1;
  410.             }
  411.  
  412.         }
  413.         // moving back
  414.         else if( move_back )
  415.         {
  416.             // reached original position
  417.             if( dist_to_final_pos > max_distance )
  418.             {
  419.                 state = STA_STAY;
  420.                 Set_Pos( startposx, startposy );
  421.                 velx = 0;
  422.                 vely = 0;
  423.  
  424.                 move_back = 0;
  425.                 wait_time = speedfactor_fps * 2;
  426.                 Set_Image( 0 );
  427.             }
  428.         }
  429.     }
  430. }
  431.  
  432. void cjPiranha :: Draw( cSurfaceRequest *request /* = NULL */ )
  433. {
  434.     if( !valid_draw )
  435.     {
  436.         return;
  437.     }
  438.  
  439.     // draw distance rect
  440.     if( editor_level_enabled )
  441.     {
  442.         if( start_direction == DIR_RIGHT )
  443.         {
  444.             pVideo->Draw_Rect( startposx - pActive_Camera->x, startposy + ( rect.h * 0.5f ) - 5 - pActive_Camera->y, max_distance + rect.w, 10, editor_posz - 0.000001f, &whitealpha128 );
  445.         }
  446.         else if( start_direction == DIR_LEFT )
  447.         {
  448.             pVideo->Draw_Rect( startposx - pActive_Camera->x + rect.w, startposy + ( rect.h * 0.5f ) - 5 - pActive_Camera->y, -( rect.w + max_distance ), 10, editor_posz - 0.000001f, &whitealpha128 );
  449.         }
  450.         else if( start_direction == DIR_DOWN )
  451.         {
  452.             pVideo->Draw_Rect( startposx + ( rect.w * 0.5f ) - 5 - pActive_Camera->x, startposy - pActive_Camera->y, 10, max_distance + rect.h, editor_posz - 0.000001f, &whitealpha128 );
  453.         }
  454.         else if( start_direction == DIR_UP )
  455.         {
  456.             pVideo->Draw_Rect( startposx + ( rect.w * 0.5f ) - 5 - pActive_Camera->x, startposy - pActive_Camera->y + rect.h, 10, -( rect.h + max_distance ), editor_posz - 0.000001f, &whitealpha128 );
  457.         }
  458.     }
  459.  
  460.     cEnemy::Draw( request );
  461. }
  462.  
  463. float cjPiranha :: Get_End_Distance(void )
  464. {
  465.     switch( direction )
  466.     {
  467.     case DIR_LEFT:
  468.     {
  469.         return max_distance - ( startposx - posx );
  470.     }
  471.     case DIR_RIGHT:
  472.     {
  473.         return max_distance + ( startposx - posx );
  474.     }
  475.     case DIR_UP:
  476.     {
  477.         return max_distance - ( startposy - posy );
  478.     }
  479.     case DIR_DOWN:
  480.     {
  481.         return max_distance + ( startposy - posy );
  482.     }
  483.     default:
  484.     {
  485.         break;
  486.     }
  487.     }
  488.     
  489.     return 0;
  490. }
  491.  
  492. void cjPiranha :: Update_Dest_Vel( void )
  493. {
  494.     if( direction == DIR_UP )
  495.     {
  496.         dest_velx = 0;
  497.         dest_vely = -speed;
  498.     }
  499.     else if( direction == DIR_DOWN )
  500.     {
  501.         dest_velx = 0;
  502.         dest_vely = speed;
  503.     }
  504.     else if( direction == DIR_LEFT )
  505.     {
  506.         dest_velx = -speed;
  507.         dest_vely = 0;
  508.     }
  509.     else if( direction == DIR_RIGHT )
  510.     {
  511.         dest_velx = speed;
  512.         dest_vely = 0;
  513.     }
  514.     else
  515.     {
  516.         dest_velx = 0;
  517.         dest_vely = 0;
  518.     }
  519. }
  520.  
  521. bool cjPiranha :: Is_Update_Valid( void )
  522. {
  523.     if( dead || freeze_counter )
  524.     {
  525.         return 0;
  526.     }
  527.  
  528.     return 1;
  529. }
  530.  
  531. bool cjPiranha :: Is_Draw_Valid( void )
  532. {
  533.     if( cEnemy::Is_Draw_Valid() == 1 )
  534.     {
  535.         return 1;
  536.     }
  537.  
  538.     // if not editor enabled or not active mouse object
  539.     if( !editor_enabled || pMouseCursor->active_object != this )
  540.     {
  541.         return 0;
  542.     }
  543.  
  544.     return 1;
  545. }
  546.  
  547. unsigned int cjPiranha :: Validate_Collision( cSprite *obj )
  548. {
  549.     if( obj->type == TYPE_PLAYER )
  550.     {
  551.         return 1;
  552.     }
  553.     if( obj->type == TYPE_BALL )
  554.     {
  555.         return 2;
  556.     }
  557.  
  558.     return 0;
  559. }
  560.  
  561. void cjPiranha :: Handle_Collision_Player( cObjectCollision *collision )
  562. {
  563.     // unknown direction
  564.     if( collision->direction == DIR_UNDEFINED )
  565.     {
  566.         return;
  567.     }
  568.  
  569.     if( pPlayer->maryo_type != MARYO_SMALL && !pPlayer->invincible && collision->direction == direction )
  570.     {
  571.         // todo : create again
  572.         //pAudio->PlaySound( "player/maryo_au.ogg", RID_MARYO_AU );
  573.         pPlayer->Action_Jump( 1 );
  574.     }
  575.  
  576.     pPlayer->DownGrade();
  577. }
  578.  
  579. void cjPiranha :: Editor_Activate( void )
  580. {
  581.     CEGUI::WindowManager &wmgr = CEGUI::WindowManager::getSingleton();
  582.  
  583.     // max distance
  584.     CEGUI::Editbox *editbox = static_cast<CEGUI::Editbox *>(wmgr.createWindow( "TaharezLook/Editbox", "editor_jpiranha_max_distance" ));
  585.     Editor_Add( UTF8_("Distance"), _("Movable Distance into its direction"), editbox, 90 );
  586.  
  587.     editbox->setText( int_to_string( static_cast<int>(max_distance) ) );
  588.     editbox->subscribeEvent( CEGUI::Editbox::EventKeyUp, CEGUI::Event::Subscriber( &cjPiranha::Editor_Max_Distance_Key, this ) );
  589.  
  590.     // speed
  591.     editbox = static_cast<CEGUI::Editbox *>(wmgr.createWindow( "TaharezLook/Editbox", "editor_jpiranha_speed" ));
  592.     Editor_Add( UTF8_("Speed"), UTF8_("Initial speed when jumping out"), editbox, 120 );
  593.  
  594.     editbox->setText( float_to_string( speed ) );
  595.     editbox->subscribeEvent( CEGUI::Editbox::EventKeyUp, CEGUI::Event::Subscriber( &cjPiranha::Editor_Speed_Key, this ) );
  596.  
  597.     // init
  598.     Editor_Init();
  599. }
  600.  
  601. bool cjPiranha :: Editor_Max_Distance_Key( const CEGUI::EventArgs &event )
  602. {
  603.     const CEGUI::WindowEventArgs &windowEventArgs = static_cast<const CEGUI::WindowEventArgs&>( event );
  604.     string str_text = static_cast<CEGUI::Editbox *>( windowEventArgs.window )->getText().c_str();
  605.  
  606.     Set_Max_Distance( static_cast<float>(string_to_int( str_text )) );
  607.  
  608.     return 1;
  609. }
  610.  
  611. bool cjPiranha :: Editor_Speed_Key( const CEGUI::EventArgs &event )
  612. {
  613.     const CEGUI::WindowEventArgs &windowEventArgs = static_cast<const CEGUI::WindowEventArgs&>( event );
  614.     string str_text = static_cast<CEGUI::Editbox *>( windowEventArgs.window )->getText().c_str();
  615.  
  616.     Set_Speed( string_to_float( str_text ) );
  617.  
  618.     return 1;
  619. }
  620.