ReplayReader.cpp

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 
00012 #include "ReplayReader.h"
00013 #include "InputHandler.h"
00014 #include <Debug.h>
00015 
00016 namespace Engine
00017 {
00018 
00019 ReplayReader::ReplayReader(std::istream & data)
00020     :   load_scene(0)
00021 {
00022     // Read metadata
00023     std::string stage;
00024     std::getline(data, stage);
00025     
00026     std::size_t number_of_cars;
00027     data >> number_of_cars;
00028     DEBUG_MESSAGE("Replay has " << number_of_cars << " car(s).");
00029     game_scene_devices_list.reserve(number_of_cars);
00030     for (unsigned int i = 0; i < number_of_cars; i++)
00031     {
00032         // The identifier was a pointer to the input device that recorded the
00033         // replay. It is not valid across sessions, so use a long int.
00034         long unsigned int car_identifier;
00035         data >> car_identifier;
00036         unsigned int car_model;
00037         data >> car_model;
00038         
00039         boost::shared_ptr<Engine::InputDeviceReplay> new_device(new Engine::InputDeviceReplay());
00040         devices.push_back(new_device);
00041         Engine::InputHandler::iterator it = new_device->get_handle();
00042         input_map.insert(std::pair<long unsigned int, Engine::InputHandler::iterator>(car_identifier, it));
00043         
00044         game_scene_devices_list.push_back(std::make_pair(it, car_model));
00045     }
00046     // Fill the list of events using data on the stream
00047     ReadEvents(data);
00048     
00049     // create scene to load game.
00050     load_scene = new Engine::LoadScene<Engine::GameScene, ReplayReader> (game_scene_devices_list, stage);
00051     load_scene->set_done_notifier(this);
00052 }
00053 
00054 void ReplayReader::operator()(GameScene * scene_in)
00055 {
00056     scene = scene_in;
00057     // monitor ticks so that we can submit events at the right time.
00058     scene->get_world().add_tick_observer(this);
00059     // we don't want to save a replay of the replay.
00060     scene->set_save_replay(false);
00061     // Process events that happen before the first tick.
00062     posttick();
00063 }
00064 
00065 ReplayReader::~ReplayReader()
00066 {
00067     delete load_scene;
00068 }
00069 
00070 Scene * ReplayReader::get_scene()
00071 {
00072     return load_scene;
00073 }
00074 
00075 void ReplayReader::posttick()
00076 {
00077     if (current_iterator == replay_events.end())
00078     {
00079         // no more events.
00080         return;
00081     }
00082     // We want to recreate each event on the tick one before it was recorded,
00083     // since the cars have already postticked this physics tick, and normally
00084     // the input they receive is before the posttick.
00085     
00086     // This is <= even though in most cases it should be exactly equal.
00087     // This is so that the first tick works.
00088     while (current_iterator->tick_number <= scene->get_world().get_tick_number() + 1)
00089     {
00090         // process this event, and start waiting for the next.
00091         // The car identifier for this event might not have been assigned a
00092         // car if the replay file was corrupt.
00093         std::map<long unsigned int, Engine::InputHandler::iterator>::iterator
00094                 input_map_iterator =
00095                             input_map.find(current_iterator->car_identifier);
00096         if (input_map_iterator != input_map.end())
00097         {
00098             dynamic_cast<Engine::InputDeviceReplay *>(*input_map_iterator->second)->
00099                     relay(current_iterator->type, current_iterator->value);
00100         }
00101         current_iterator++;
00102     }
00103 }
00104 
00105 void ReplayReader::ReadEvents(std::istream & source)
00106 {
00107     while (source.good())
00108     {
00109         ReplayEvent event;
00110         int type_enum;
00111         source >> event.tick_number
00112                >> event.car_identifier
00113                >> type_enum
00114                >> event.value;
00115         event.type = InputReport::ReportType(type_enum);
00116         if (!(source.fail()||source.bad()))
00117         {
00118             replay_events.push_back(event);
00119         }
00120     }
00121     current_iterator = replay_events.begin();
00122     DEBUG_MESSAGE("Replay has " << replay_events.size() << " events.");
00123 }
00124 
00125 }

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.