Back to index

supertuxkart  0.5+dfsg1
replay_buffers.cpp
Go to the documentation of this file.
00001 //  $Id$
00002 //
00003 //  SuperTuxKart - a fun racing game with go-kart
00004 //  Copyright (C) 2007 Maik Semder <ikework@gmx.de>
00005 //
00006 //  This program is free software; you can redistribute it and/or
00007 //  modify it under the terms of the GNU General Public License
00008 //  as published by the Free Software Foundation; either version 2
00009 //  of the License, or (at your option) any later version.
00010 //
00011 //  This program is distributed in the hope that it will be useful,
00012 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //  GNU General Public License for more details.
00015 //
00016 //  You should have received a copy of the GNU General Public License
00017 //  along with this program; if not, write to the Free Software
00018 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00019 
00020 #ifdef HAVE_GHOST_REPLAY
00021 
00022 #include <cassert>
00023 
00024 
00025 #include "replay_base.hpp"
00026 #include "replay_buffers.hpp"
00027 
00028 #define REPLAY_SAVE_STATISTIC
00029 
00030 ReplayBuffers::ReplayBuffers()
00031 : m_number_karts(0),
00032   m_BufferFrame(),
00033   m_BufferKartState()
00034 {
00035 }
00036 
00037 ReplayBuffers::~ReplayBuffers()
00038 {
00039     destroy();
00040 }
00041 
00042 void ReplayBuffers::destroy()
00043 {
00044     m_BufferFrame.destroy();
00045     m_BufferKartState.destroy();
00046     m_number_karts = 0;
00047 }
00048 
00049 bool ReplayBuffers::init( unsigned int number_karts, 
00050                           size_t number_preallocated_frames )
00051 {
00052     m_number_karts = number_karts;
00053 
00054     if( !m_BufferFrame.init( number_preallocated_frames ) ) return false;
00055     if( !m_BufferKartState.init( number_preallocated_frames, number_karts ) ) return false;
00056 
00057     return true;
00058 }
00059 
00060 ReplayFrame* 
00061 ReplayBuffers::getNewFrame()
00062 {
00063     // make sure initialization was called properly
00064     assert( m_BufferFrame.getNumberObjectsUsed() == m_BufferKartState.getNumberArraysUsed() );
00065 
00066     if( !isHealthy() ) return NULL;
00067 
00068     ReplayFrame* frame = m_BufferFrame.getNewObject();
00069     if( !frame ) return NULL;
00070 
00071     // get current karts-array
00072     ReplayKartState* karts_array = m_BufferKartState.getNewArray();
00073     if( !karts_array ) return NULL;
00074     
00075     frame->p_kart_states = karts_array;
00076 
00077     return frame;
00078 }
00079 
00080 bool ReplayBuffers::saveReplayHumanReadable( FILE *fd ) const
00081 {
00082     if( !isHealthy() ) return false;
00083 
00084     if( fprintf( fd, "frames: %u\n", getNumberFrames() ) < 1 ) return false;
00085     
00086 #ifdef REPLAY_SAVE_STATISTIC
00087     float time_step_min = 9999999.0f, time_step_max = 0.0f, time_last;
00088 #endif
00089 
00090     unsigned int frame_idx, kart_idx;
00091     ReplayFrame const *frame;
00092     ReplayKartState const *kart;
00093     for( frame_idx = 0; frame_idx < getNumberFrames(); ++frame_idx )
00094     {
00095         frame = getFrameAt( frame_idx );
00096         if( fprintf( fd, "frame %u  time %f\n", frame_idx, frame->time ) < 1 ) return false;
00097 
00098         for( kart_idx = 0; kart_idx < m_number_karts; ++kart_idx )
00099         {
00100             kart = frame->p_kart_states + kart_idx;
00101 
00102             if( fprintf( fd, "\tkart %u: %f,%f,%f,%f,%f,%f\n", kart_idx, 
00103                      kart->position.xyz[0], kart->position.xyz[1], kart->position.xyz[2],
00104                      kart->position.hpr[0], kart->position.hpr[1], kart->position.hpr[2] ) < 1 ) return false;   
00105         }
00106 
00107 #ifdef REPLAY_SAVE_STATISTIC
00108         if( frame_idx )
00109         {
00110             float diff = frame->time - time_last;
00111             if( diff < time_step_min ) time_step_min = diff;
00112             if( diff > time_step_max ) time_step_max = diff;
00113         }
00114         time_last = frame->time;
00115 #endif
00116     }
00117 
00118 #ifdef REPLAY_SAVE_STATISTIC
00119     float time_step_avg;
00120     if( getNumberFrames() > 1 )
00121     {
00122         time_step_avg = time_last / ( getNumberFrames() - 1 );
00123     }
00124     else
00125     {
00126         time_step_avg = -1.0f;
00127     }
00128     fprintf( fd, "\n# statistic time-steps:\n# \tmin: %f\n# \tmax: %f\n# \tavg: %f\n", time_step_min, time_step_max, time_step_avg );
00129 #endif
00130 
00131     return true;
00132 }
00133 
00134 bool ReplayBuffers::loadReplayHumanReadable( FILE *fd, unsigned int number_karts )
00135 {
00136     size_t frames;
00137     if( fscanf( fd, "frames: %u\n", &frames ) != 1 ) return false;
00138 
00139     if( !init( number_karts, frames ) ) return false;
00140 
00141     assert( m_number_karts );
00142     unsigned int frame_idx, kart_idx, tmp;
00143     ReplayFrame *frame;
00144     ReplayKartState *kart;
00145     for( frame_idx = 0; frame_idx < frames; ++frame_idx )
00146     {
00147         // if we are here, it cant fail, since enough objects have to be allocated above
00148         frame = getNewFrame();
00149         assert( frame );
00150 
00151         if( fscanf( fd, "frame %u  time %f\n", &tmp, &frame->time ) != 2 ) return false;
00152 
00153         for( kart_idx = 0; kart_idx < m_number_karts; ++kart_idx )
00154         {
00155             kart = frame->p_kart_states + kart_idx;
00156 
00157             if( fscanf( fd, "\tkart %u: %f,%f,%f,%f,%f,%f\n", &tmp, 
00158                      &kart->position.xyz[0], &kart->position.xyz[1], &kart->position.xyz[2],
00159                      &kart->position.hpr[0], &kart->position.hpr[1], &kart->position.hpr[2] ) != 7 ) return false;   
00160         }
00161     }
00162 
00163     assert( frames == getNumberFrames() );
00164     assert( m_BufferFrame.getNumberObjectsUsed() == getNumberFrames() );
00165     assert( m_BufferKartState.getNumberArraysUsed() == getNumberFrames() );
00166 
00167     // there should be no reallocation ..
00168     assert( m_BufferFrame.getNumberBlocks() == 1 );
00169     assert( m_BufferKartState.getNumberBlocks() == 1 );
00170 
00171     return true;
00172 }
00173 
00174 
00175 
00176 #endif // HAVE_GHOST_REPLAY