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

  1. /***************************************************************************
  2.  * layer.cpp  -  Overworld Layer 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 "../overworld/world_layer.h"
  17. #include "../video/renderer.h"
  18. #include "../core/game_core.h"
  19. #include "../core/camera.h"
  20. #include "../overworld/overworld.h"
  21. #include "../core/sprite_manager.h"
  22. #include "../core/i18n.h"
  23.  
  24. /* *** *** *** *** *** *** *** *** Layer Line Point *** *** *** *** *** *** *** *** *** */
  25.  
  26. cLayer_Line_Point :: cLayer_Line_Point( SpriteType ntype )
  27. : cSprite()
  28. {
  29.     sprite_array = ARRAY_PASSIVE;
  30.     type = ntype;
  31.     massivetype = MASS_PASSIVE;
  32.     posz = 0.087f;
  33.  
  34.     if( type == TYPE_OW_LINE_START )
  35.     {
  36.         posz += 0.001f;
  37.         color = orange;
  38.         name = _("Line Start Point");
  39.     }
  40.     else
  41.     {
  42.         color = red;
  43.         name = _("Line End Point");
  44.     }
  45.  
  46.     rect.w = 4;
  47.     rect.h = 4;
  48.     col_rect.w = rect.w;
  49.     col_rect.h = rect.h;
  50.     start_rect.w = rect.w;
  51.     start_rect.h = rect.h;
  52.  
  53.     Update_Position_Rect();
  54.  
  55.     player_range = 0;
  56. }
  57.  
  58. cLayer_Line_Point :: ~cLayer_Line_Point( void )
  59. {
  60.  
  61. }
  62.  
  63. void cLayer_Line_Point :: Draw( cSurfaceRequest *request /* = NULL */ )
  64. {
  65.     if( !pOverworld_Manager->draw_layer )
  66.     {
  67.         return;
  68.     }
  69.  
  70.     // point rect
  71.     pVideo->Draw_Rect( col_rect.x - pActive_Camera->x, col_rect.y - pActive_Camera->y, col_rect.w, col_rect.h, posz, &color );
  72. }
  73.  
  74. void cLayer_Line_Point :: Editor_Activate( void )
  75. {
  76.     CEGUI::WindowManager &wmgr = CEGUI::WindowManager::getSingleton();
  77.  
  78.     // origin
  79.     CEGUI::Editbox *editbox = static_cast<CEGUI::Editbox *>(wmgr.createWindow( "TaharezLook/Editbox", "layer_line_origin" ));
  80.     Editor_Add( UTF8_("Waypoint origin"), UTF8_("Waypoint origin"), editbox, 100 );
  81.  
  82.     editbox->setText( int_to_string( static_cast<cLayer_Line *>(line)->origin ) );
  83.     editbox->subscribeEvent( CEGUI::Editbox::EventKeyUp, CEGUI::Event::Subscriber( &cLayer_Line_Point::Editor_Origin_Key, this ) );
  84.  
  85.     // init
  86.     Editor_Init();
  87. }
  88.  
  89. bool cLayer_Line_Point :: Editor_Origin_Key( const CEGUI::EventArgs &event )
  90. {
  91.     const CEGUI::WindowEventArgs &windowEventArgs = static_cast<const CEGUI::WindowEventArgs&>( event );
  92.     string str_text = static_cast<CEGUI::Editbox *>( windowEventArgs.window )->getText().c_str();
  93.  
  94.     static_cast<cLayer_Line *>(line)->origin = string_to_int( str_text );
  95.  
  96.     return 1;
  97. }
  98.  
  99. float cLayer_Line_Point :: Get_Line_Pos_X( void )
  100. {
  101.     return posx + ( col_rect.w * 0.5f );
  102. }
  103.  
  104. float cLayer_Line_Point :: Get_Line_Pos_Y( void )
  105. {
  106.     return posy + ( col_rect.h * 0.5f );
  107. }
  108.  
  109. /* *** *** *** *** *** *** *** *** Layer Line *** *** *** *** *** *** *** *** *** */
  110.  
  111. cLayer_Line :: cLayer_Line( void )
  112. {
  113.     anim_type = 0;
  114.     origin = 0;
  115.  
  116.     start = new cLayer_Line_Point( TYPE_OW_LINE_START );
  117.     start->line = (void *)this;
  118.     pActive_Overworld->sprite_manager->Add( start );
  119.  
  120.  
  121.     end = new cLayer_Line_Point( TYPE_OW_LINE_END );
  122.     end->line = (void *)this;
  123.     pActive_Overworld->sprite_manager->Add( end );
  124. }
  125.  
  126. cLayer_Line :: ~cLayer_Line( void )
  127. {
  128.     // delete points
  129.     pActive_Overworld->sprite_manager->Delete( start, 1 );
  130.     pActive_Overworld->sprite_manager->Delete( end, 1 );
  131. }
  132.  
  133. void cLayer_Line :: Draw( void )
  134. {
  135.     // create request
  136.     cLineRequest *line_request = new cLineRequest();
  137.  
  138.     // drawing color
  139.     Color color = darkgreen;
  140.  
  141.     // if active
  142.     if( pOverworld_Player->current_line >= 0 && pActive_Overworld->pLayer->objects[pOverworld_Player->current_line] == this )
  143.     {
  144.         color = lightblue;
  145.     }
  146.  
  147.     pVideo->Draw_Line( start->Get_Line_Pos_X() - pActive_Camera->x, start->Get_Line_Pos_Y() - pActive_Camera->y, end->Get_Line_Pos_X() - pActive_Camera->x, end->Get_Line_Pos_Y() - pActive_Camera->y, 0.085f, &color, line_request );
  148.     line_request->line_width = 6;
  149.  
  150.     // add request
  151.     pRenderer->Add( line_request );
  152. }
  153.  
  154. GL_line cLayer_Line :: Get_Line( void )
  155. {
  156.     return GL_line( start->posx + ( start->col_rect.w * 0.5f ), start->posy + ( start->col_rect.h * 0.5f ), end->posx + ( end->col_rect.w * 0.5f ), end->posy + ( end->col_rect.h * 0.5f ) );
  157. }
  158.  
  159. cWaypoint *cLayer_Line :: Get_End_Waypoint( void )
  160. {
  161.     int wp_num = pActive_Overworld->Get_Waypoint_Collision( &end->col_rect );
  162.     // no waypoint collision
  163.     if( wp_num < 0 )
  164.     {
  165.         cLayer_Line *line_col = pActive_Overworld->pLayer->Get_Line_Collision_Start( &end->col_rect );
  166.  
  167.         // line collision
  168.         if( line_col )
  169.         {
  170.             // follow line
  171.             return line_col->Get_End_Waypoint();
  172.         }
  173.     }
  174.  
  175.     // return Waypoint
  176.     return pActive_Overworld->Get_Waypoint( wp_num );
  177. }
  178.  
  179. /* *** *** *** *** *** *** *** *** Line Collision *** *** *** *** *** *** *** *** *** */
  180.  
  181. cLine_collision :: cLine_collision( void )
  182. {
  183.     line = NULL;
  184.     line_number = -2;
  185.     difference = 0;
  186. }
  187.  
  188. /* *** *** *** *** *** *** *** *** Near Line Collision *** *** *** *** *** *** *** *** *** */
  189.  
  190. cNearLine_collision :: cNearLine_collision( void )
  191. {
  192.     line_number = -2;
  193.     start = 0;
  194. }
  195.  
  196. /* *** *** *** *** *** *** *** *** Contact Collision *** *** *** *** *** *** *** *** *** */
  197.  
  198. void cContact_collision :: clear( void )
  199. {
  200.     contact = 0;
  201.     line_hor = cLine_collision();
  202.     line_ver = cLine_collision();
  203. }
  204.  
  205. int cContact_collision :: Get_Best_Line( ObjectDirection dir )
  206. {
  207.     // favor vertical
  208.     if( dir == DIR_LEFT || dir == DIR_RIGHT )
  209.     {
  210.         if( line_ver.line_number >= 0 && line_ver.difference < line_hor.difference )
  211.         {
  212.             return line_ver.line_number;
  213.         }
  214.         else if( line_hor.line_number >= 0 )
  215.         {
  216.             return line_hor.line_number;
  217.         }
  218.         else
  219.         {
  220.             return line_ver.line_number;
  221.         }
  222.     }
  223.     // favor horizontal
  224.     else if( dir == DIR_UP || dir == DIR_DOWN )
  225.     {
  226.         if( line_hor.line_number >= 0 && line_hor.difference < line_ver.difference )
  227.         {
  228.             return line_hor.line_number;
  229.         }
  230.         else if( line_ver.line_number >= 0 )
  231.         {
  232.             return line_ver.line_number;
  233.         }
  234.         else
  235.         {
  236.             return line_hor.line_number;
  237.         }
  238.     }
  239.  
  240.     return -2;
  241. }
  242.  
  243. /* *** *** *** *** *** *** *** *** Layer *** *** *** *** *** *** *** *** *** */
  244.  
  245. cLayer :: cLayer( void )
  246. {
  247.  
  248. }
  249.  
  250. cLayer :: ~cLayer( void )
  251. {
  252.     Delete_All();
  253. }
  254.  
  255. void cLayer :: Load( string filename )
  256. {
  257.     Delete_All();
  258.  
  259.     try
  260.     {
  261.         // parse layer
  262.         CEGUI::System::getSingleton().getXMLParser()->parseXMLFile( *this, filename.c_str(), DATA_DIR "/" GAME_SCHEMA_DIR "/World/Lines.xsd", "" );
  263.     }
  264.     // catch CEGUI Exceptions
  265.     catch( CEGUI::Exception &ex )
  266.     {
  267.         printf( "Loading Line Layer %s CEGUI Exception %s\n", filename.c_str(), ex.getMessage().c_str() );
  268.         debugdisplay->Set_Text( _("Line Layer Loading failed : ") + (string)ex.getMessage().c_str() );
  269.     }
  270. }
  271.  
  272. bool cLayer :: Save( string filename )
  273. {
  274.     ofstream file( filename.c_str(), ios::out | ios::trunc );
  275.  
  276.     if( !file )
  277.     {
  278.         debugdisplay->Set_Text( _("Couldn't save world layer ") + filename );
  279.         return 0;
  280.     }
  281.  
  282.     // xml info
  283.     file << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
  284.     // begin layer
  285.     file << "<layer>" << std::endl;
  286.  
  287.     // lines
  288.     for( LayerLineList::iterator itr = objects.begin(), itr_end = objects.end(); itr != itr_end; ++itr )
  289.     {
  290.         cLayer_Line *line = (*itr);
  291.  
  292.         // begin line
  293.         file << "\t<line>" << std::endl;
  294.             // start
  295.             file << "\t\t<Property name=\"X1\" value=\"" << static_cast<int>(line->start->Get_Line_Pos_X()) << "\" />" << std::endl;
  296.             file << "\t\t<Property name=\"Y1\" value=\"" << static_cast<int>(line->start->Get_Line_Pos_Y()) << "\" />" << std::endl;
  297.             // end
  298.             file << "\t\t<Property name=\"X2\" value=\"" << static_cast<int>(line->end->Get_Line_Pos_X()) << "\" />" << std::endl;
  299.             file << "\t\t<Property name=\"Y2\" value=\"" << static_cast<int>(line->end->Get_Line_Pos_Y()) << "\" />" << std::endl;
  300.             // origin
  301.             file << "\t\t<Property name=\"origin\" value=\"" << line->origin << "\" />" << std::endl;
  302.         // end line
  303.         file << "\t</line>" << std::endl;
  304.     }
  305.  
  306.     // end layer
  307.     file << "</layer>" << std::endl;
  308.     file.close();
  309.  
  310.     return 1;
  311. }
  312.  
  313. void cLayer :: Draw( void )
  314. {
  315.     if( !pOverworld_Manager->draw_layer )
  316.     {
  317.         return;
  318.     }
  319.  
  320.     for( LayerLineList::iterator itr = objects.begin(), itr_end = objects.end(); itr != itr_end; ++itr )
  321.     {
  322.         // draw line
  323.         (*itr)->Draw();
  324.     }
  325. }
  326.  
  327. cLayer_Line *cLayer :: Get_Line_Collision_Start( GL_rect *line_rect )
  328. {
  329.     for( LayerLineList::iterator itr = objects.begin(), itr_end = objects.end(); itr != itr_end; ++itr )
  330.     {
  331.         // get pointer
  332.         cLayer_Line *layer_line = (*itr);
  333.  
  334.         // check line 1
  335.         if( Col_Box( line_rect, &layer_line->start->col_rect ) )
  336.         {
  337.             return layer_line;
  338.         }
  339.     }
  340.  
  341.     return NULL;
  342. }
  343.  
  344. cLine_collision cLayer :: Get_Line_Collision_Direction( float x, float y, ObjectDirection dir, float dir_size /* = 10 */, unsigned int check_size /* = 10 */ )
  345. {
  346.     if( dir == DIR_UP )
  347.     {
  348.         y -= dir_size;
  349.     }
  350.     else if( dir == DIR_DOWN )
  351.     {
  352.         y += dir_size;
  353.     }
  354.     else if( dir == DIR_RIGHT )
  355.     {
  356.         x += dir_size;
  357.     }
  358.     else if( dir == DIR_LEFT )
  359.     {
  360.         x -= dir_size;
  361.     }
  362.  
  363.     if( dir == DIR_LEFT || dir == DIR_RIGHT )
  364.     {
  365.         return pActive_Overworld->pLayer->Get_Nearest( x, y, DIR_VERTICAL, check_size );
  366.     }
  367.     else if( dir == DIR_UP || dir == DIR_DOWN )
  368.     {
  369.         return pActive_Overworld->pLayer->Get_Nearest( x, y, DIR_HORIZONTAL, check_size );
  370.     }
  371.  
  372.     // invalid direction
  373.     return cLine_collision();
  374. }
  375.  
  376. cLine_collision cLayer :: Get_Nearest( float x, float y, ObjectDirection dir /* = DIR_HORIZONTAL */, unsigned int check_size /* = 15 */, int only_origin_id /* = -1 */ )
  377. {
  378.     for( LayerLineList::iterator itr = objects.begin(), itr_end = objects.end(); itr != itr_end; ++itr )
  379.     {
  380.         // get pointer
  381.         cLayer_Line *layer_line = (*itr);
  382.  
  383.         // line is not from waypoint
  384.         if( only_origin_id >= 0 && only_origin_id != layer_line->origin )
  385.         {
  386.             continue;
  387.         }
  388.  
  389.         cLine_collision col = Get_Nearest_Line( layer_line, x, y, dir, check_size );
  390.  
  391.         // found
  392.         if( col.line )
  393.         {
  394.             return col;
  395.         }
  396.     }
  397.  
  398.     // none found
  399.     return cLine_collision();
  400. }
  401.  
  402. cLine_collision cLayer :: Get_Nearest_Line( cLayer_Line *map_layer_line, float x, float y, ObjectDirection dir /* = DIR_HORIZONTAL */, unsigned int check_size /* = 15  */ )
  403. {
  404.     GL_line line_1, line_2;
  405.  
  406.     // create map line
  407.     GL_line map_line = map_layer_line->Get_Line();
  408.  
  409.     // check into both directions from inside
  410.     for( float csize = 0; csize < check_size; csize++ )
  411.     {
  412.         line_1.x1 = x;
  413.         line_1.y1 = y;
  414.         line_1.x2 = x;
  415.         line_1.y2 = y;
  416.         line_2 = line_1;
  417.  
  418.         // set line size
  419.         if( dir == DIR_HORIZONTAL )
  420.         {
  421.             line_1.x1 += csize;
  422.             line_2.x2 -= csize;
  423.         }
  424.         else // vertical
  425.         {
  426.             line_1.y1 += csize;
  427.             line_2.y2 -= csize;
  428.         }
  429.  
  430.         // debug drawing
  431.         if( pOverworld_Manager->debugmode && pOverworld_Manager->draw_layer )
  432.         {
  433.             // create request
  434.             cLineRequest *line_request = new cLineRequest();
  435.             pVideo->Draw_Line( line_1.x1 - pActive_Camera->x, line_1.y1 - pActive_Camera->y, line_1.x2 - pActive_Camera->x, line_1.y2 - pActive_Camera->y, map_layer_line->start->posz + 0.001f, &white, line_request );
  436.             line_request->line_width = 2;
  437.             line_request->render_count = 50;
  438.             // add request
  439.             pRenderer->Add( line_request );
  440.  
  441.             // create request
  442.             line_request = new cLineRequest();
  443.             pVideo->Draw_Line( line_2.x1 - pActive_Camera->x, line_2.y1 - pActive_Camera->y, line_2.x2 - pActive_Camera->x, line_2.y2 - pActive_Camera->y, map_layer_line->start->posz + 0.001f, &black, line_request );
  444.             line_request->line_width = 2;
  445.             line_request->render_count = 50;
  446.             // add request
  447.             pRenderer->Add( line_request );
  448.         }
  449.  
  450.         // check direction line 1
  451.         if( Col_Line( &line_1, &map_line ) )
  452.         {
  453.             cLine_collision col = cLine_collision();
  454.  
  455.             col.line = map_layer_line;
  456.             col.line_number = Get_Array_Num( map_layer_line );
  457.             col.difference = csize;
  458.  
  459.             // found
  460.             return col;
  461.         }
  462.  
  463.         // check direction line 2
  464.         if( Col_Line( &line_2, &map_line ) )
  465.         {
  466.             cLine_collision col = cLine_collision();
  467.  
  468.             col.line = map_layer_line;
  469.             col.line_number = Get_Array_Num( map_layer_line );
  470.             col.difference = -csize;
  471.  
  472.             // found
  473.             return col;
  474.         }
  475.     }
  476.  
  477.     // not found
  478.     return cLine_collision();
  479. }
  480.  
  481. // XML element start
  482. void cLayer :: elementStart( const CEGUI::String &element, const CEGUI::XMLAttributes &attributes )
  483. {
  484.     // Property of an Element
  485.     if( element == "Property" )
  486.     {
  487.         xml_attributes.add( attributes.getValueAsString( "name" ), attributes.getValueAsString( "value" ) );
  488.     }
  489. }
  490.  
  491. // XML element end
  492. void cLayer :: elementEnd( const CEGUI::String &element )
  493. {
  494.     if( element != "Property" )
  495.     {
  496.         if( element == "line" )
  497.         {
  498.             handle_line( xml_attributes );
  499.         }
  500.         else if( element == "layer" )
  501.         {
  502.             // ignore
  503.         }
  504.         else if( element.length() )
  505.         {
  506.             printf( "Warning : Overworld Layer Unknown element : %s\n", element.c_str() );
  507.         }
  508.  
  509.         // clear
  510.         xml_attributes = CEGUI::XMLAttributes();
  511.     }
  512. }
  513.  
  514. void cLayer :: handle_line( const CEGUI::XMLAttributes &attributes )
  515. {
  516.     // create
  517.     cLayer_Line *item = new cLayer_Line();
  518.     
  519.     // Start
  520.     item->start->Set_Pos( static_cast<float>(attributes.getValueAsInteger( "X1" )) - 2, static_cast<float>(attributes.getValueAsInteger( "Y1" )) - 2, 1 );
  521.     // End
  522.     item->end->Set_Pos( static_cast<float>(attributes.getValueAsInteger( "X2" )) - 2, static_cast<float>(attributes.getValueAsInteger( "Y2" )) - 2, 1 );
  523.     // origin
  524.     item->origin = attributes.getValueAsInteger( "origin" );
  525.  
  526.     // add
  527.     Add( item );
  528. }
  529.