LoadScene.h

Go to the documentation of this file.
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

Get Racer at SourceForge.net. Fast, secure and Free Open Source software downloads

Generated at Mon Sep 6 00:41:12 2010 by Doxygen version 1.4.7 for Racer version svn335.