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 }
Generated at Mon Sep 6 00:41:12 2010 by Doxygen version 1.4.7 for Racer version svn335.