home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2009 February / maximum-cd-2009-02.iso / DiscContents / SMC_1.6_win32.exe / src / objects / moving_platform.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2008-09-25  |  27.2 KB  |  1,018 lines

  1. /***************************************************************************
  2.  * moving_platform.cpp  -  default moving platforms handler
  3.  *
  4.  * Copyright (C) 2005 - 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/moving_platform.h"
  17. #include "../core/camera.h"
  18. #include "../core/game_core.h"
  19. #include "../video/gl_surface.h"
  20. #include "../core/framerate.h"
  21. #include "../video/renderer.h"
  22. #include "../user/savegame.h"
  23. #include "../core/i18n.h"
  24.  
  25. /* *** *** *** *** *** *** *** cMoving_Platform *** *** *** *** *** *** *** *** *** *** */
  26.  
  27. cMoving_Platform :: cMoving_Platform( float x, float y )
  28. : cImageObjectSprite( x, y )
  29. {
  30.     cMoving_Platform::Init();
  31. }
  32.  
  33. cMoving_Platform :: cMoving_Platform( CEGUI::XMLAttributes &attributes )
  34. : cImageObjectSprite()
  35. {
  36.     cMoving_Platform::Init();
  37.     cMoving_Platform::Create_from_Stream( attributes );
  38. }
  39.  
  40. cMoving_Platform :: ~cMoving_Platform( void )
  41. {
  42.     //
  43. }
  44.  
  45. void cMoving_Platform :: Init( void )
  46. {
  47.     sprite_array = ARRAY_ACTIVE;
  48.     type = TYPE_MOVING_PLATFORM;
  49.     posz = 0.085f;
  50.  
  51.     player_range = 2000;
  52.     can_be_ground = 1;
  53.  
  54.     platform_state = PLATFORM_STAY;
  55.     touch_counter = 0;
  56.     shake_dir_counter = 0;
  57.     shake_counter = 0;
  58.  
  59.     Set_Massive_Type( MASS_HALFMASSIVE );
  60.     Set_Max_Distance( 150 );
  61.     Set_Speed( 3 );
  62.     Set_Touch_Time( 0 );
  63.     Set_Shake_Time( 16 );
  64.     Set_Touch_Move_Time( 0 );
  65.  
  66.     Set_Direction( DIR_RIGHT, 1 );
  67.  
  68.     Set_Middle_Count( 2 );
  69.     // create default images
  70.     images.push_back( pVideo->Get_Surface( "slider/grey_1/slider_left.png" ) );
  71.     images.push_back( pVideo->Get_Surface( "slider/grey_1/slider_middle.png" ) );
  72.     images.push_back( pVideo->Get_Surface( "slider/grey_1/slider_right.png" ) );
  73.     Set_Image( 1, 1 );
  74.  
  75.     Update_Rect();
  76.  
  77.     Create_Name();
  78. }
  79.  
  80. cMoving_Platform *cMoving_Platform :: Copy( void )
  81. {
  82.     cMoving_Platform *moving_platform = new cMoving_Platform( startposx, startposy );
  83.     moving_platform->Set_Massive_Type( massivetype );
  84.     moving_platform->Set_Direction( start_direction, 1 );
  85.     moving_platform->Set_Max_Distance( max_distance );
  86.     moving_platform->Set_Speed( speed );
  87.     moving_platform->Set_Touch_Time( touch_time );
  88.     moving_platform->Set_Shake_Time( shake_time );
  89.     moving_platform->Set_Touch_Move_Time( touch_move_time );
  90.     moving_platform->Set_Middle_Count( middle_count );
  91.     moving_platform->Set_Image_Top_Left( images[0] );
  92.     moving_platform->Set_Image_Top_Middle( images[1] );
  93.     moving_platform->Set_Image_Top_Right( images[2] );
  94.  
  95.     return moving_platform;
  96. }
  97.  
  98. void cMoving_Platform :: Create_from_Stream( CEGUI::XMLAttributes &attributes )
  99. {
  100.     // position
  101.     Set_Pos( static_cast<float>(attributes.getValueAsInteger( "posx" )), static_cast<float>(attributes.getValueAsInteger( "posy" )), 1 );
  102.     // massive type
  103.     Set_Massive_Type( Get_Massive_Type_Id( attributes.getValueAsString( "massive_type", Get_Massive_Type_Name( massivetype ) ).c_str() ) );
  104.     // direction
  105.     Set_Direction( Get_Direction_Id( attributes.getValueAsString( "direction", Get_Direction_Name( start_direction ) ).c_str() ), 1 );
  106.     // max distance
  107.     Set_Max_Distance( attributes.getValueAsInteger( "max_distance", max_distance ) );
  108.     // speed
  109.     Set_Speed( attributes.getValueAsFloat( "speed", speed ) );
  110.     // touch_time
  111.     Set_Touch_Time( attributes.getValueAsFloat( "touch_time", touch_time ) );
  112.     // shake time
  113.     Set_Shake_Time( attributes.getValueAsFloat( "shake_time", shake_time ) );
  114.     // touch move time
  115.     Set_Touch_Move_Time( attributes.getValueAsFloat( "touch_move_time", touch_move_time ) );
  116.     // middle image count
  117.     Set_Middle_Count( attributes.getValueAsInteger( "middle_img_count", middle_count ) );
  118.     // image top left
  119.     Set_Image_Top_Left( pVideo->Get_Surface( attributes.getValueAsString( "image_top_left", images[0]->Get_Filename() ).c_str() ) );
  120.     // image top middle
  121.     Set_Image_Top_Middle( pVideo->Get_Surface( attributes.getValueAsString( "image_top_middle", images[1]->Get_Filename() ).c_str() ) );
  122.     // image top right
  123.     Set_Image_Top_Right( pVideo->Get_Surface( attributes.getValueAsString( "image_top_right", images[2]->Get_Filename() ).c_str() ) );
  124. }
  125.  
  126. void cMoving_Platform :: Save_to_Stream( ofstream &file )
  127. {
  128.     // begin moving_platform
  129.     file << "\t<moving_platform>" << std::endl;
  130.  
  131.     // position
  132.     file << "\t\t<Property name=\"posx\" value=\"" << static_cast<int>(startposx) << "\" />" << std::endl;
  133.     file << "\t\t<Property name=\"posy\" value=\"" << static_cast<int>(startposy) << "\" />" << std::endl;
  134.     // massive type
  135.     file << "\t\t<Property name=\"massive_type\" value=\"" << Get_Massive_Type_Name( massivetype ) << "\" />" << std::endl;
  136.     // direction
  137.     file << "\t\t<Property name=\"direction\" value=\"" << Get_Direction_Name( start_direction ) << "\" />" << std::endl;
  138.     // max distance
  139.     file << "\t\t<Property name=\"max_distance\" value=\"" << max_distance << "\" />" << std::endl;
  140.     // speed
  141.     file << "\t\t<Property name=\"speed\" value=\"" << speed << "\" />" << std::endl;
  142.     // touch time
  143.     file << "\t\t<Property name=\"touch_time\" value=\"" << touch_time << "\" />" << std::endl;
  144.     // shake time
  145.     file << "\t\t<Property name=\"shake_time\" value=\"" << shake_time << "\" />" << std::endl;
  146.     // touch move time
  147.     file << "\t\t<Property name=\"touch_move_time\" value=\"" << touch_move_time << "\" />" << std::endl;
  148.     // middle image count
  149.     file << "\t\t<Property name=\"middle_img_count\" value=\"" << middle_count << "\" />" << std::endl;
  150.     // image top left
  151.     file << "\t\t<Property name=\"image_top_left\" value=\"" << images[0]->Get_Filename( 1 ) << "\" />" << std::endl;
  152.     // image top middle
  153.     file << "\t\t<Property name=\"image_top_middle\" value=\"" << images[1]->Get_Filename( 1 ) << "\" />" << std::endl;
  154.     // image top right
  155.     file << "\t\t<Property name=\"image_top_right\" value=\"" << images[2]->Get_Filename( 1 ) << "\" />" << std::endl;
  156.  
  157.     // end moving_platform
  158.     file << "\t</moving_platform>" << std::endl;
  159. }
  160.  
  161. void cMoving_Platform :: Load_from_Savegame( cSave_Level_Object *save_object )
  162. {
  163.     // direction
  164.     if( save_object->exists( "direction" ) )
  165.     {
  166.         direction = static_cast<ObjectDirection>(string_to_int( save_object->Get_Value( "direction" ) ));
  167.     }
  168.  
  169.     // platform state
  170.     if( save_object->exists( "platform_state" ) )
  171.     {
  172.         platform_state = static_cast<Moving_Platform_State>(string_to_int( save_object->Get_Value( "platform_state" ) ));
  173.     }
  174.  
  175.     // new position x
  176.     if( save_object->exists( "new_posx" ) )
  177.     {
  178.         Set_Pos_X( string_to_float( save_object->Get_Value( "new_posx" ) ) );
  179.     }
  180.  
  181.     // new position y
  182.     if( save_object->exists( "new_posy" ) )
  183.     {
  184.         Set_Pos_Y( string_to_float( save_object->Get_Value( "new_posy" ) ) );
  185.     }
  186.  
  187.     // velocity x
  188.     if( save_object->exists( "velx" ) )
  189.     {
  190.         velx = string_to_float( save_object->Get_Value( "velx" ) );
  191.     }
  192.  
  193.     // velocity y
  194.     if( save_object->exists( "vely" ) )
  195.     {
  196.         vely = string_to_float( save_object->Get_Value( "vely" ) );
  197.     }
  198.  
  199.     // visible
  200.     if( save_object->exists( "visible" ) )
  201.     {
  202.         Set_Visible( string_to_int( save_object->Get_Value( "visible" ) ) > 0 );
  203.     }
  204. }
  205.  
  206. cSave_Level_Object *cMoving_Platform :: Save_to_Savegame( void )
  207. {
  208.     cSave_Level_Object *save_object = new cSave_Level_Object();
  209.  
  210.     // default values
  211.     save_object->type = type;
  212.     save_object->properties.push_back( cSave_Level_Object_Property( "posx", int_to_string( static_cast<int>(startposx) ) ) );
  213.     save_object->properties.push_back( cSave_Level_Object_Property( "posy", int_to_string( static_cast<int>(startposy) ) ) );
  214.  
  215.     // direction
  216.     save_object->properties.push_back( cSave_Level_Object_Property( "direction", int_to_string( direction ) ) );
  217.  
  218.     // platform state
  219.     save_object->properties.push_back( cSave_Level_Object_Property( "platform_state", int_to_string( platform_state ) ) );
  220.  
  221.     // new position ( only save if needed )
  222.     if( startposx != posx || startposy != posy )
  223.     {
  224.         save_object->properties.push_back( cSave_Level_Object_Property( "new_posx", int_to_string( static_cast<int>(posx) ) ) );
  225.         save_object->properties.push_back( cSave_Level_Object_Property( "new_posy", int_to_string( static_cast<int>(posy) ) ) );
  226.     }
  227.  
  228.     // velocity
  229.     save_object->properties.push_back( cSave_Level_Object_Property( "velx", float_to_string( velx ) ) );
  230.     save_object->properties.push_back( cSave_Level_Object_Property( "vely", float_to_string( vely ) ) );
  231.  
  232.     // visible ( only save if needed )
  233.     if( !visible )
  234.     {
  235.         save_object->properties.push_back( cSave_Level_Object_Property( "visible", int_to_string( visible ) ) );
  236.     }
  237.  
  238.     return save_object;
  239. }
  240.  
  241. void cMoving_Platform :: Set_Massive_Type( MassiveType mtype )
  242. {
  243.     massivetype = mtype;
  244.  
  245.     if( massivetype == MASS_MASSIVE )
  246.     {
  247.         can_be_ground = 1;
  248.     }
  249.     else if( massivetype == MASS_PASSIVE )
  250.     {
  251.         can_be_ground = 0;
  252.     }
  253.     else if( massivetype == MASS_HALFMASSIVE )
  254.     {
  255.         can_be_ground = 1;
  256.     }
  257.     else if( massivetype == MASS_CLIMBABLE )
  258.     {
  259.         can_be_ground = 0;
  260.     }
  261.  
  262.     Create_Name();
  263. }
  264.  
  265. void cMoving_Platform :: Set_Direction( ObjectDirection dir, bool new_start_direction /* = 0 */ )
  266. {
  267.     cImageObjectSprite::Set_Direction( dir, new_start_direction );
  268.  
  269.     if( new_start_direction )
  270.     {
  271.         // changed direction
  272.         if( dir != start_direction )
  273.         {
  274.             // set back start position
  275.             Set_Pos( startposx, startposy );
  276.             // reset velocity
  277.             Set_Velocity( 0, 0 );
  278.         }
  279.  
  280.         // update name
  281.         Create_Name();
  282.     }
  283.  
  284.     // Set new velocity
  285.     Update_Velocity();
  286. }
  287.  
  288. void cMoving_Platform :: Set_Max_Distance( int nmax_distance )
  289. {
  290.     max_distance = nmax_distance;
  291.  
  292.     if( max_distance < 0 )
  293.     {
  294.         max_distance = 0;
  295.     }
  296. }
  297.  
  298. void cMoving_Platform :: Set_Speed( float val )
  299. {
  300.     speed = val;
  301.  
  302.     // set velocity
  303.     Update_Velocity();
  304.  
  305.     Create_Name();
  306. }
  307.  
  308. void cMoving_Platform :: Set_Touch_Time( float val )
  309. {
  310.     touch_time = val;
  311.  
  312.     if( touch_time < 0 )
  313.     {
  314.         touch_time = 0;
  315.     }
  316.  
  317.     Create_Name();
  318. }
  319.  
  320. void cMoving_Platform :: Set_Shake_Time( float val )
  321. {
  322.     shake_time = val;
  323.  
  324.     if( shake_time < 0 )
  325.     {
  326.         shake_time = 0;
  327.     }
  328. }
  329.  
  330. void cMoving_Platform :: Set_Touch_Move_Time( float val )
  331. {
  332.     touch_move_time = val;
  333.  
  334.     if( touch_move_time < 0 )
  335.     {
  336.         touch_move_time = 0;
  337.     }
  338.  
  339.     // set back start position
  340.     Set_Pos( startposx, startposy );
  341.     // reset velocity
  342.     Set_Velocity( 0, 0 );
  343.  
  344.     Create_Name();
  345. }
  346.  
  347. void cMoving_Platform :: Set_Middle_Count( int val )
  348. {
  349.     middle_count = val;
  350.  
  351.     if( middle_count < 0 )
  352.     {
  353.         middle_count = 0;
  354.     }
  355. }
  356.  
  357. void cMoving_Platform :: Set_Image_Top_Left( GL_Surface *surface )
  358. {
  359.     if( !surface )
  360.     {
  361.         return;
  362.     }
  363.  
  364.     images[0] = surface;
  365.     Update_Rect();
  366. }
  367.  
  368. void cMoving_Platform :: Set_Image_Top_Middle( GL_Surface *surface )
  369. {
  370.     if( !surface )
  371.     {
  372.         return;
  373.     }
  374.  
  375.     images[1] = surface;
  376.  
  377.     // middle image sets main image
  378.     curr_img = -1;
  379.     Set_Image( 1, 1 );
  380.     Update_Rect();
  381. }
  382.  
  383. void cMoving_Platform :: Set_Image_Top_Right( GL_Surface *surface )
  384. {
  385.     if( !surface )
  386.     {
  387.         return;
  388.     }
  389.  
  390.     images[2] = surface;
  391.     Update_Rect();
  392. }
  393.  
  394. void cMoving_Platform :: Update( void )
  395. {
  396.     if( !valid_update || !is_Player_range() )
  397.     {
  398.         return;
  399.     }
  400.  
  401.     // move time should be smaller than touch time because it should
  402.     // start moving (if it is moving) before shaking starts.
  403.     // if larger than touch time then the platform state will change 
  404.     // and touch_counter will never be more than move_time
  405.     if( touch_time || touch_move_time )
  406.     {
  407.         if( platform_state == PLATFORM_TOUCHED )
  408.         {
  409.             touch_counter += pFramerate->speedfactor;
  410.         }
  411.     }
  412.  
  413.     // if able to fall
  414.     if( touch_time )
  415.     {
  416.         if( platform_state == PLATFORM_TOUCHED && touch_counter > touch_time )
  417.         {
  418.             platform_state = PLATFORM_SHAKE;
  419.         }
  420.         else if( platform_state == PLATFORM_SHAKE )
  421.         {
  422.             shake_dir_counter += pFramerate->speedfactor;
  423.  
  424.             // move into opposite direction
  425.             if( shake_dir_counter > 0.8f )
  426.             {
  427.                 float move_x = 0;
  428.                 if( posx > startposx )
  429.                 {
  430.                     move_x = -3;
  431.                 }
  432.                 else
  433.                 {
  434.                     move_x = 3;
  435.                 }
  436.  
  437.                 // move
  438.                 col_pos.x -= move_x;
  439.                 Move( move_x, 0, 1 );
  440.  
  441.                 shake_dir_counter = 0;
  442.             }
  443.  
  444.             shake_counter += pFramerate->speedfactor;
  445.  
  446.             if( shake_counter > shake_time )
  447.             {
  448.                 platform_state = PLATFORM_FALL;
  449.             }
  450.         }
  451.         else if( platform_state == PLATFORM_FALL )
  452.         {
  453.             if( vely < 25 )
  454.             {
  455.                 vely += 2.1f * pFramerate->speedfactor;
  456.  
  457.                 // limit falling velocity
  458.                 if( vely > 25 )
  459.                 {
  460.                     vely = 25;
  461.                 }
  462.             }
  463.  
  464.             // drop objects when falling fast
  465.             if( can_be_ground && vely > 15 )
  466.             {
  467.                 can_be_ground = 0;
  468.             }
  469.  
  470.             if( posx > startposx )
  471.             {
  472.                 Add_Rotation_Z( 1.5f );
  473.             }
  474.             else
  475.             {
  476.                 Add_Rotation_Z( -1.5f );
  477.             }
  478.  
  479.             // below screen
  480.             if( col_rect.y + col_rect.h > pActive_Camera->limit_rect.y + game_res_h )
  481.             {
  482.                 platform_state = PLATFORM_STAY;
  483.                 Set_Visible( 0 );
  484.             }
  485.         }
  486.     }
  487.  
  488.     // if moving
  489.     if( speed && platform_state != PLATFORM_FALL && ( !touch_move_time || touch_counter > touch_move_time ) )
  490.     {
  491.         // distance to final position
  492.         float dist_to_final_pos = 0;
  493.  
  494.         if( direction == DIR_LEFT )
  495.         {
  496.             dist_to_final_pos = 0 - ( startposx - posx );
  497.         }
  498.         else if( direction == DIR_RIGHT )
  499.         {
  500.             dist_to_final_pos = max_distance + ( startposx - posx );
  501.         }
  502.         else if( direction == DIR_UP )
  503.         {
  504.             dist_to_final_pos = 0 - ( startposy - posy );
  505.         }
  506.         else if( direction == DIR_DOWN )
  507.         {
  508.             dist_to_final_pos = max_distance + ( startposy - posy );
  509.         }
  510.  
  511.         // reached final position
  512.         if( dist_to_final_pos <= 0 )
  513.         {
  514.             // unset velocity
  515.             Set_Velocity( 0, 0 );
  516.             // set new direction
  517.             Set_Direction( Get_Opposite_Direction( direction ) );
  518.         }
  519.         // slow down near final position
  520.         else if( dist_to_final_pos < max_distance * 0.2f )
  521.         {
  522.             if( direction == DIR_DOWN )
  523.             {
  524.                 if( vely > 0 )
  525.                 {
  526.                     // slow down
  527.                     if( vely > speed * 0.3f )
  528.                     {
  529.                         vely *= 1 - ( 0.05f * pFramerate->speedfactor );
  530.  
  531.                         // reached lowest value
  532.                         if( vely <= speed * 0.3f )
  533.                         {
  534.                             vely = speed * 0.3f;
  535.                         }
  536.                     }
  537.                 }
  538.                 else
  539.                 {
  540.                     // set lowest value
  541.                     vely = speed * 0.3f;
  542.                 }
  543.             }
  544.             else if( direction == DIR_UP )
  545.             {
  546.                 if( vely < 0 )
  547.                 {
  548.                     // slow down
  549.                     if( vely < -speed * 0.3f )
  550.                     {
  551.                         vely *= 1 - ( 0.05f * pFramerate->speedfactor );
  552.  
  553.                         // reached lowest value
  554.                         if( vely >= -speed * 0.3f )
  555.                         {
  556.                             vely = -speed * 0.3f;
  557.                         }
  558.                     }
  559.                 }
  560.                 else
  561.                 {
  562.                     // set lowest value
  563.                     vely = -speed * 0.3f;
  564.                 }
  565.             }
  566.             else if( direction == DIR_LEFT )
  567.             {
  568.                 if( velx < 0 )
  569.                 {
  570.                     // slow down
  571.                     if( velx < -speed * 0.3f )
  572.                     {
  573.                         velx *= 1 - ( 0.05f * pFramerate->speedfactor );
  574.  
  575.                         // reached lowest value
  576.                         if( velx >= -speed * 0.3f )
  577.                         {
  578.                             velx = -speed * 0.3f;
  579.                         }
  580.                     }
  581.                 }
  582.                 else
  583.                 {
  584.                     // set lowest value
  585.                     velx = -speed * 0.3f;
  586.                 }
  587.             }
  588.             else if( direction == DIR_RIGHT )
  589.             {
  590.                 if( velx > 0 )
  591.                 {
  592.                     // slow down
  593.                     if( velx > speed * 0.3f )
  594.                     {
  595.                         velx *= 1 - ( 0.05f * pFramerate->speedfactor );
  596.  
  597.                         // reached lowest value
  598.                         if( velx <= speed * 0.3f )
  599.                         {
  600.                             velx = speed * 0.3f;
  601.                         }
  602.                     }
  603.                 }
  604.                 else
  605.                 {
  606.                     // set lowest value
  607.                     velx = speed * 0.3f;
  608.                 }
  609.             }
  610.         }
  611.         // not near final position
  612.         else
  613.         {
  614.             Update_Velocity();
  615.         }
  616.     }
  617. }
  618.  
  619. void cMoving_Platform :: Draw( cSurfaceRequest *request /* = NULL */ )
  620. {
  621.     if( !valid_draw )
  622.     {
  623.         return;
  624.     }
  625.  
  626.     cSurfaceRequest *surface_request;
  627.     float x = 0;
  628.  
  629.     // top left
  630.     if( images[0] )
  631.     {
  632.         // Start
  633.         image = images[0];
  634.         start_image = images[0];
  635.         // create request
  636.  
  637.         surface_request = new cSurfaceRequest();
  638.         // draw only first image complete
  639.         cImageObjectSprite::Draw( surface_request );
  640.         surface_request->pos_x += x;
  641.         x += images[0]->w;
  642.         // add request
  643.         pRenderer->Add( surface_request );
  644.     }
  645.  
  646.     // top middle
  647.     if( images[1] )
  648.     {
  649.         // Middle
  650.         image = images[1];
  651.         start_image = images[1];
  652.         for( unsigned int i = 0; i < middle_count; i++ )
  653.         {
  654.             // create request
  655.             surface_request = new cSurfaceRequest();
  656.             cImageObjectSprite::Draw_Image( surface_request);
  657.             surface_request->pos_x += x;
  658.             x += images[1]->w;
  659.             // add request
  660.             pRenderer->Add( surface_request );
  661.         }
  662.     }
  663.  
  664.     // top right
  665.     if( images[2] )
  666.     {
  667.         // End
  668.         image = images[2];
  669.         start_image = images[2];
  670.         // create request
  671.         surface_request = new cSurfaceRequest();
  672.         cImageObjectSprite::Draw_Image( surface_request );
  673.         surface_request->pos_x += x;
  674.         //x += images[2]->w;
  675.         // add request
  676.         pRenderer->Add( surface_request );
  677.     }
  678.  
  679.     Update_Rect();
  680.     Update_Position_Rect();
  681.  
  682.     // draw distance rect
  683.     if( editor_level_enabled && speed )
  684.     {
  685.         if( start_direction == DIR_RIGHT || start_direction == DIR_LEFT )
  686.         {
  687.             pVideo->Draw_Rect( startposx - pActive_Camera->x, startposy - pActive_Camera->y, max_distance + col_rect.w, 15, posz - 0.000001f, &whitealpha128 );
  688.         }
  689.         else if( start_direction == DIR_DOWN || start_direction == DIR_UP )
  690.         {
  691.             pVideo->Draw_Rect( startposx - pActive_Camera->x, startposy - pActive_Camera->y, 15, max_distance + col_rect.h, posz - 0.000001f, &whitealpha128 );
  692.         }
  693.     }
  694. }
  695.  
  696. void cMoving_Platform :: Update_Rect( void )
  697. {
  698.     // clear
  699.     col_rect.w = 0;
  700.     rect.w = 0;
  701.  
  702.     // get width
  703.     if( images[0] )
  704.     {
  705.         rect.w += images[0]->w;
  706.     }
  707.     if( images[1] )
  708.     {
  709.         rect.w += images[1]->w * middle_count;
  710.     }
  711.     if( images[2] )
  712.     {
  713.         rect.w += images[2]->w;
  714.     }
  715.  
  716.     // set width
  717.     col_rect.w = rect.w;
  718.     start_rect.w = rect.w;
  719. }
  720.  
  721. void cMoving_Platform :: Update_Velocity( void )
  722. {
  723.     // set velocity
  724.     if( speed > 0 && ( !touch_move_time || touch_counter > touch_move_time ) )
  725.     {
  726.         if( direction == DIR_UP )
  727.         {
  728.             if( vely > -speed )
  729.             {
  730.                 vely += -speed * 0.1f * pFramerate->speedfactor;
  731.             }
  732.         }
  733.         else if( direction == DIR_DOWN )
  734.         {
  735.             if( vely < speed )
  736.             {
  737.                 vely += speed * 0.1f * pFramerate->speedfactor;
  738.             }
  739.         }
  740.         else if( direction == DIR_LEFT )
  741.         {
  742.             if( velx > -speed )
  743.             {
  744.                 velx += -speed * 0.1f * pFramerate->speedfactor;
  745.             }
  746.         }
  747.         else if( direction == DIR_RIGHT )
  748.         {
  749.             if( velx < speed )
  750.             {
  751.                 velx += speed * 0.1f * pFramerate->speedfactor;
  752.             }
  753.         }
  754.     }
  755.     else
  756.     {
  757.         // unset velocity
  758.         Set_Velocity( 0, 0 );
  759.     }
  760. }
  761.  
  762. bool cMoving_Platform :: Is_Update_Valid( void )
  763. {
  764.     // if not visible
  765.     if( !visible )
  766.     {
  767.         return 0;
  768.     }
  769.  
  770.     return 1;
  771. }
  772.  
  773. unsigned int cMoving_Platform :: Validate_Collision( cSprite *obj )
  774. {
  775.     if( obj->type == TYPE_PLAYER )
  776.     {
  777.         cMovingSprite *moving_sprite = static_cast<cMovingSprite *>(obj);
  778.  
  779.         // don't handle if not moving upwards or slower
  780.         if( moving_sprite->Is_on_Top( this ) && direction == DIR_UP && moving_sprite->vely > vely )
  781.         {
  782.             // halfmassive
  783.             if( massivetype == MASS_HALFMASSIVE )
  784.             {
  785.                 // only if no ground
  786.                 if( !moving_sprite->ground_object )
  787.                 {
  788.                     return 2;
  789.                 }
  790.             }
  791.             // massive
  792.             else if( massivetype == MASS_MASSIVE )
  793.             {
  794.                 // always pick up
  795.                 if( moving_sprite->ground_object != this )
  796.                 {
  797.                     moving_sprite->ground_object = this;
  798.                     return 0;
  799.                 }
  800.             }
  801.         }
  802.  
  803.         return 0;
  804.     }
  805.     if( obj->type == TYPE_BALL )
  806.     {
  807.         if( obj->Is_on_Top( this ) )
  808.         {
  809.             obj->Set_on_Top( this, 0 );
  810.  
  811.             return 1;
  812.         }
  813.  
  814.         return 0;
  815.     }
  816.  
  817.     return 0;
  818. }
  819.  
  820. void cMoving_Platform :: Handle_Collision_Player( cObjectCollision *collision )
  821. {
  822.     if( collision->direction == DIR_TOP )
  823.     {
  824.         // send collision
  825.         Send_Collision( collision );
  826.     }
  827.  
  828.     if( collision->direction == DIR_TOP )
  829.     {
  830.         if( ( touch_time || touch_move_time ) && platform_state == PLATFORM_STAY )
  831.         {
  832.             platform_state = PLATFORM_TOUCHED;
  833.         }
  834.  
  835.     }
  836. }
  837.  
  838. void cMoving_Platform :: Editor_Activate( void )
  839. {
  840.     CEGUI::WindowManager &wmgr = CEGUI::WindowManager::getSingleton();
  841.  
  842.     // max distance
  843.     CEGUI::Editbox *editbox = static_cast<CEGUI::Editbox *>(wmgr.createWindow( "TaharezLook/Editbox", "editor_moving_platform_max_distance" ));
  844.     Editor_Add( UTF8_("Distance"), UTF8_("Movable distance into its direction"), editbox, 120 );
  845.  
  846.     editbox->setText( int_to_string( max_distance ) );
  847.     editbox->subscribeEvent( CEGUI::Editbox::EventTextChanged, CEGUI::Event::Subscriber( &cMoving_Platform::Editor_Max_Distance_Key, this ) );
  848.  
  849.     // speed
  850.     editbox = static_cast<CEGUI::Editbox *>(wmgr.createWindow( "TaharezLook/Editbox", "editor_moving_platform_speed" ));
  851.     Editor_Add( UTF8_("Speed"), UTF8_("Maximum speed"), editbox, 120 );
  852.  
  853.     editbox->setText( float_to_string( speed ) );
  854.     editbox->subscribeEvent( CEGUI::Editbox::EventTextChanged, CEGUI::Event::Subscriber( &cMoving_Platform::Editor_Speed_Key, this ) );
  855.  
  856.     // touch time
  857.     editbox = static_cast<CEGUI::Editbox *>(wmgr.createWindow( "TaharezLook/Editbox", "editor_moving_platform_touch_time" ));
  858.     Editor_Add( UTF8_("Touch time"), UTF8_("Time when touched until shaking starts"), editbox, 120 );
  859.  
  860.     editbox->setText( float_to_string( touch_time ) );
  861.     editbox->subscribeEvent( CEGUI::Editbox::EventTextChanged, CEGUI::Event::Subscriber( &cMoving_Platform::Editor_Touch_Time_Key, this ) );
  862.  
  863.     // shake time
  864.     editbox = static_cast<CEGUI::Editbox *>(wmgr.createWindow( "TaharezLook/Editbox", "editor_moving_platform_shake_time" ));
  865.     Editor_Add( UTF8_("Shake time"), UTF8_("Time it's shaking until falling"), editbox, 120 );
  866.  
  867.     editbox->setText( float_to_string( shake_time ) );
  868.     editbox->subscribeEvent( CEGUI::Editbox::EventTextChanged, CEGUI::Event::Subscriber( &cMoving_Platform::Editor_Shake_Time_Key, this ) );
  869.  
  870.     // touch move time
  871.     editbox = static_cast<CEGUI::Editbox *>(wmgr.createWindow( "TaharezLook/Editbox", "editor_moving_platform_move_time" ));
  872.     Editor_Add( UTF8_("Touch move time"), UTF8_("If set does not move until this time has elapsed after touched"), editbox, 120 );
  873.  
  874.     editbox->setText( float_to_string( touch_move_time ) );
  875.     editbox->subscribeEvent( CEGUI::Editbox::EventTextChanged, CEGUI::Event::Subscriber( &cMoving_Platform::Editor_Touch_Move_Time_Key, this ) );
  876.  
  877.     // horizontal middle image count
  878.     editbox = static_cast<CEGUI::Editbox *>(wmgr.createWindow( "TaharezLook/Editbox", "editor_moving_platform_hor_middle_count" ));
  879.     Editor_Add( UTF8_("Hor image count"), UTF8_("Horizontal middle image count"), editbox, 120 );
  880.  
  881.     editbox->setText( int_to_string( middle_count ) );
  882.     editbox->subscribeEvent( CEGUI::Editbox::EventTextChanged, CEGUI::Event::Subscriber( &cMoving_Platform::Editor_Hor_Middle_Count_Key, this ) );
  883.  
  884.     // image top left
  885.     editbox = static_cast<CEGUI::Editbox *>(wmgr.createWindow( "TaharezLook/Editbox", "editor_moving_platform_image_top_left" ));
  886.     Editor_Add( UTF8_("Image top left"), UTF8_("Image top left"), editbox, 200 );
  887.  
  888.     editbox->setText( images[0]->Get_Filename( 1 ) );
  889.     editbox->subscribeEvent( CEGUI::Editbox::EventTextChanged, CEGUI::Event::Subscriber( &cMoving_Platform::Editor_Image_Top_Left_Key, this ) );
  890.  
  891.     // image top middle
  892.     editbox = static_cast<CEGUI::Editbox *>(wmgr.createWindow( "TaharezLook/Editbox", "editor_moving_platform_image_top_middle" ));
  893.     Editor_Add( UTF8_("Image top middle"), UTF8_("Image top middle"), editbox, 200 );
  894.  
  895.     editbox->setText( images[1]->Get_Filename( 1 ) );
  896.     editbox->subscribeEvent( CEGUI::Editbox::EventTextChanged, CEGUI::Event::Subscriber( &cMoving_Platform::Editor_Image_Top_Middle_Key, this ) );
  897.  
  898.     // image top right
  899.     editbox = static_cast<CEGUI::Editbox *>(wmgr.createWindow( "TaharezLook/Editbox", "editor_moving_platform_image_top_right" ));
  900.     Editor_Add( UTF8_("Image top right"), UTF8_("Image top right"), editbox, 200 );
  901.  
  902.     editbox->setText( images[2]->Get_Filename( 1 ) );
  903.     editbox->subscribeEvent( CEGUI::Editbox::EventTextChanged, CEGUI::Event::Subscriber( &cMoving_Platform::Editor_Image_Top_Right_Key, this ) );
  904.  
  905.     // init
  906.     Editor_Init();
  907. }
  908.  
  909. bool cMoving_Platform :: Editor_Max_Distance_Key( const CEGUI::EventArgs &event )
  910. {
  911.     const CEGUI::WindowEventArgs &windowEventArgs = static_cast<const CEGUI::WindowEventArgs&>( event );
  912.     string str_text = static_cast<CEGUI::Editbox *>( windowEventArgs.window )->getText().c_str();
  913.  
  914.     Set_Max_Distance( string_to_int( str_text ) );
  915.  
  916.     return 1;
  917. }
  918.  
  919. bool cMoving_Platform :: Editor_Speed_Key( const CEGUI::EventArgs &event )
  920. {
  921.     const CEGUI::WindowEventArgs &windowEventArgs = static_cast<const CEGUI::WindowEventArgs&>( event );
  922.     string str_text = static_cast<CEGUI::Editbox *>( windowEventArgs.window )->getText().c_str();
  923.  
  924.     Set_Speed( string_to_float( str_text ) );
  925.  
  926.     return 1;
  927. }
  928.  
  929. bool cMoving_Platform :: Editor_Touch_Time_Key( const CEGUI::EventArgs &event )
  930. {
  931.     const CEGUI::WindowEventArgs &windowEventArgs = static_cast<const CEGUI::WindowEventArgs&>( event );
  932.     string str_text = static_cast<CEGUI::Editbox *>( windowEventArgs.window )->getText().c_str();
  933.  
  934.     Set_Touch_Time( string_to_float( str_text ) );
  935.  
  936.     return 1;
  937. }
  938.  
  939. bool cMoving_Platform :: Editor_Shake_Time_Key( const CEGUI::EventArgs &event )
  940. {
  941.     const CEGUI::WindowEventArgs &windowEventArgs = static_cast<const CEGUI::WindowEventArgs&>( event );
  942.     string str_text = static_cast<CEGUI::Editbox *>( windowEventArgs.window )->getText().c_str();
  943.  
  944.     Set_Shake_Time( string_to_float( str_text ) );
  945.  
  946.     return 1;
  947. }
  948.  
  949. bool cMoving_Platform :: Editor_Touch_Move_Time_Key( const CEGUI::EventArgs &event )
  950. {
  951.     const CEGUI::WindowEventArgs &windowEventArgs = static_cast<const CEGUI::WindowEventArgs&>( event );
  952.     string str_text = static_cast<CEGUI::Editbox *>( windowEventArgs.window )->getText().c_str();
  953.  
  954.     Set_Touch_Move_Time( string_to_float( str_text ) );
  955.  
  956.     return 1;
  957. }
  958.  
  959. bool cMoving_Platform :: Editor_Hor_Middle_Count_Key( const CEGUI::EventArgs &event )
  960. {
  961.     const CEGUI::WindowEventArgs &windowEventArgs = static_cast<const CEGUI::WindowEventArgs&>( event );
  962.     string str_text = static_cast<CEGUI::Editbox *>( windowEventArgs.window )->getText().c_str();
  963.  
  964.     Set_Middle_Count( string_to_int( str_text ) );
  965.  
  966.     return 1;
  967. }
  968.  
  969. bool cMoving_Platform :: Editor_Image_Top_Left_Key( const CEGUI::EventArgs &event )
  970. {
  971.     const CEGUI::WindowEventArgs &windowEventArgs = static_cast<const CEGUI::WindowEventArgs&>( event );
  972.     string str_text = static_cast<CEGUI::Editbox *>( windowEventArgs.window )->getText().c_str();
  973.  
  974.     Set_Image_Top_Left( pVideo->Get_Surface( str_text ) );
  975.  
  976.     return 1;
  977. }
  978.  
  979. bool cMoving_Platform :: Editor_Image_Top_Middle_Key( const CEGUI::EventArgs &event )
  980. {
  981.     const CEGUI::WindowEventArgs &windowEventArgs = static_cast<const CEGUI::WindowEventArgs&>( event );
  982.     string str_text = static_cast<CEGUI::Editbox *>( windowEventArgs.window )->getText().c_str();
  983.  
  984.     Set_Image_Top_Middle( pVideo->Get_Surface( str_text ) );
  985.  
  986.     return 1;
  987. }
  988.  
  989. bool cMoving_Platform :: Editor_Image_Top_Right_Key( const CEGUI::EventArgs &event )
  990. {
  991.     const CEGUI::WindowEventArgs &windowEventArgs = static_cast<const CEGUI::WindowEventArgs&>( event );
  992.     string str_text = static_cast<CEGUI::Editbox *>( windowEventArgs.window )->getText().c_str();
  993.  
  994.     Set_Image_Top_Right( pVideo->Get_Surface( str_text ) );
  995.  
  996.     return 1;
  997. }
  998.  
  999. void cMoving_Platform :: Create_Name( void )
  1000. {
  1001.     name.clear();
  1002.  
  1003.     if( touch_time )
  1004.     {
  1005.         name = _("Falling ");
  1006.     }
  1007.     if( touch_move_time )
  1008.     {
  1009.         name += _("Delayed ");
  1010.     }
  1011.     if( speed )
  1012.     {
  1013.         name += _("Moving ");
  1014.     }
  1015.  
  1016.     name += _("Platform - ") + Get_Direction_Name( start_direction ) + " - " + Get_Massive_Type_Name( massivetype );
  1017. }
  1018.