00001 00005 /* Copyright © 2009, 2010 James Legg. 00006 This program is free software: you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation, either version 3 of the License, or 00009 (at your option) any later version. 00010 */ 00011 #ifndef RACER_ENGINE_LOAD_SCENE_H 00012 #define RACER_ENGINE_LOAD_SCENE_H 00013 00014 #include "GameScene.h" 00015 #include "InputHandler.h" 00016 #include "InputDeviceAI.h" 00017 #include "../MainLoop.h" 00018 #include "../UI/BasicFonts.h" 00019 #include "../Graphics/Window.h" 00020 00021 #include <libtrack/Track.h> 00022 #include <libtrack/Texture.h> 00023 00024 #include <GL/gl.h> 00025 00026 #include <boost/shared_ptr.hpp> 00027 00028 #include <vector> 00029 #include <string> 00030 #include <fstream> 00031 00032 namespace Engine 00033 { 00034 00035 template <class T> 00036 class daft_function_object 00037 { 00038 public: 00039 void operator()(T * in) {}; 00040 }; 00041 00047 template <class T = GameScene, class Q = daft_function_object<T> > 00048 class LoadScene : public Engine::Scene 00049 { 00050 public: 00057 LoadScene(std::vector<std::pair<InputHandler::iterator, unsigned int> > input_devices, 00058 std::string filename, 00059 unsigned int number_of_ais = 0) 00060 : blanked(false) 00061 , track_filename(filename) 00062 , input_devices(input_devices) 00063 , function_object(0) 00064 , done(false) 00065 , error(false) 00066 , m_number_of_ais(number_of_ais) 00067 { 00068 main_loop = 0; 00069 } 00070 00071 virtual ~LoadScene() 00072 { 00073 } 00074 00075 virtual void take_input(InputReport & report) 00076 { 00077 // ignore input, unless there is an error. 00078 if (error) 00079 { 00080 // Try to quit, unless it could be noise causing the event. 00081 // An analgue joystick could output noise, but pushing it far 00082 // enough will report a menu movement. 00083 switch(report.get_report_type()) 00084 { 00085 case InputReport::RT_MENU_UP: 00086 case InputReport::RT_MENU_DOWN: 00087 case InputReport::RT_MENU_LEFT: 00088 case InputReport::RT_MENU_RIGHT: 00089 case InputReport::RT_MENU_SELECT: 00090 case InputReport::RT_MENU_BACK: 00091 if (main_loop) 00092 { 00093 main_loop->pop_scene(); 00094 }; 00095 break; 00096 default: 00097 break; // possibly noise. 00098 }; 00099 } 00100 } 00101 00102 virtual void update_logic(unsigned int milliseconds_elapsed) 00103 { 00104 // wait until the screen has been blanked before trying any long 00105 // operations. 00106 if (!blanked) return; 00107 if (error) return; // doesn't work, don't try again. 00108 assert(!done); 00109 // load the track and its theme. 00110 try 00111 { 00112 track_file = boost::shared_ptr<std::ifstream>(new std::ifstream(track_filename.c_str())); 00113 if (!track_file->good()) 00114 { 00115 throw std::ios_base::failure("Unable to read track file " + track_filename + "."); 00116 } 00117 track_file->exceptions (std::ifstream::eofbit | std::ifstream::failbit | std::ifstream::badbit); 00118 std::getline(*track_file, theme_filename); 00119 theme_file = boost::shared_ptr<std::ifstream>(new std::ifstream(theme_filename.c_str())); 00120 if (!theme_file->good()) 00121 { 00122 throw std::ios_base::failure("Unable to read theme file " + theme_filename + " required by track " + track_filename + "."); 00123 } 00124 theme_file->exceptions (std::ifstream::eofbit | std::ifstream::failbit | std::ifstream::badbit); 00125 theme = boost::shared_ptr<Track::Theme>(new Track::Theme(*theme_file)); 00126 track = boost::shared_ptr<Track::Track>(new Track::Track(*track_file, *theme)); 00127 track->set_filename(track_filename); 00128 00129 // load theme textures used in the track. 00130 const Track::Path & path = track->get_path(); 00131 typedef boost::graph_traits<Track::Path::Graph>::edge_iterator EdgeIterator; 00132 std::pair<EdgeIterator, EdgeIterator> edge_range; 00133 for (edge_range = boost::edges(path.graph); 00134 edge_range.first != edge_range.second; 00135 edge_range.first++) 00136 { 00137 const Track::PathEdge & edge = path.graph[*(edge_range.first)]; 00138 edge.segment->get_texture().make_cache(); 00139 edge.make_cache(); 00140 } 00141 typedef boost::graph_traits<Track::Path::Graph>::vertex_iterator VertexIterator; 00142 std::pair<VertexIterator, VertexIterator> vertex_range; 00143 for (vertex_range = boost::vertices(path.graph); 00144 vertex_range.first != vertex_range.second; 00145 vertex_range.first++) 00146 { 00147 const Track::PathVertex & vertex = path.graph[*(vertex_range.first)]; 00148 vertex.get_segment()->get_texture().make_cache(); 00149 vertex.get_segment()->get_graphics_mesh().get_faces().make_cache(); 00150 } 00151 00152 // make the AI graph for the track. 00153 track->update_ai_mesh(); 00154 00155 // Add some AI players 00157 for (unsigned int ai = 0; ai < m_number_of_ais; ai++) 00158 { 00159 m_ai_devices.push_back(boost::shared_ptr<InputDeviceAI>(new InputDeviceAI())); 00160 input_devices.push_back(std::pair<InputHandler::iterator, unsigned int>( 00161 m_ai_devices.back()->get_handle(), 00162 ai%2)); // ai alterenatly uses both cars 00163 } 00164 00165 // create the game scene 00166 game_scene = boost::shared_ptr<T>(new T(input_devices, *track)); 00167 game_scene->attach_main_loop(*main_loop); 00168 if (function_object) 00169 { 00170 (*function_object)(&(*game_scene)); 00171 } 00172 main_loop->push_scene(*game_scene); 00173 // now game scene will have finished, quit the load scene too. 00174 main_loop->pop_scene(); 00175 done = true; 00176 } 00177 catch (std::ios_base::failure e) 00178 { 00179 std::cerr << "Failed to load track " << track_filename <<":" << std::endl 00180 << e.what() << std::endl; 00181 error = true; 00182 } 00183 catch (ThemeChangedError e) 00184 { 00185 std::cerr << "Failed to load track (" << track_filename <<")," << std::endl 00186 << " since it requires theme elements which do not exist." << std::endl 00187 << " The linked theme is " << theme_filename << "." << std::endl; 00188 error = true; 00189 } 00190 catch (CorruptedError e) 00191 { 00192 std::cerr << "Failed to load track (" << track_filename <<")," << std::endl 00193 << " since it is incositant with itself." << std::endl; 00194 error = true; 00195 } 00196 catch (NewVersionError e) 00197 { 00198 std::cerr << "Failed to load track (" << track_filename <<")," << std::endl 00199 << " since it has been written with a newer version of racer." << std::endl; 00200 error = true; 00201 } 00202 catch (DepreciatedVersionError e) 00203 { 00204 std::cerr << "Failed to load track (" << track_filename <<")," << std::endl 00205 << " since it contains depreciated features." << std::endl; 00206 error = true; 00207 } 00208 catch (FormError e) 00209 { 00210 std::cerr << "Failed to load track (" << track_filename <<")," << std::endl 00211 << " since it is not in the expected format." << std::endl; 00212 error = true; 00213 } 00214 } 00215 00216 virtual void draw() 00217 { 00218 glClearColor(0, 0, 0, 0); 00219 glClear(GL_COLOR_BUFFER_BIT); 00220 blanked = true; 00221 if (error) 00222 { 00223 // Tell user when track cannot be loaded. 00224 Graphics::Window::get_instance().set_ortho_projection(); 00225 glLoadIdentity(); 00226 glPushMatrix(); 00227 glTranslatef(100, 120, 0); 00228 UI::BasicFonts::get_instance().big_font.Render("Failed to load track."); 00229 glPopMatrix(); 00230 glTranslatef(100, 90, 0); 00231 UI::BasicFonts::get_instance().small_font.Render("See terminal window for more information."); 00232 } 00233 } 00234 00235 virtual void do_sound() 00236 { 00237 } 00238 00240 void set_done_notifier(Q * function_object_in) 00241 { 00242 function_object = function_object_in; 00243 } 00244 private: 00245 bool blanked; 00247 std::string track_filename; 00248 boost::shared_ptr<std::ifstream> track_file; 00250 std::string theme_filename; 00251 boost::shared_ptr<std::ifstream> theme_file; 00253 boost::shared_ptr<Track::Theme> theme; 00255 boost::shared_ptr<Track::Track> track; 00256 00258 std::vector<boost::shared_ptr<Engine::InputDeviceAI> > m_ai_devices; 00259 00261 std::vector<std::pair<InputHandler::iterator, unsigned int> > input_devices; 00262 00263 boost::shared_ptr<T> game_scene; 00264 00266 Q * function_object; 00267 00268 bool done; 00269 00271 bool error; 00272 00274 unsigned int m_number_of_ais; 00275 }; 00276 00277 } // namespace Engine 00278 00279 #endif // RACER_ENGINE_LOAD_SCENE_H
Generated at Mon Sep 6 00:41:12 2010 by Doxygen version 1.4.7 for Racer version svn335.