ActionController.cpp

Go to the documentation of this file.
00001 ////////////////////////////////////////////////////////////////////////////////
00002 //    Scorched3D (c) 2000-2009
00003 //
00004 //    This file is part of Scorched3D.
00005 //
00006 //    Scorched3D 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 2 of the License, or
00009 //    (at your option) any later version.
00010 //
00011 //    Scorched3D 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 Scorched3D; if not, write to the Free Software
00018 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 ////////////////////////////////////////////////////////////////////////////////
00020 
00021 #include <engine/ActionController.h>
00022 #include <engine/ScorchedContext.h>
00023 #include <movement/TargetMovement.h>
00024 #include <common/Logger.h>
00025 #include <common/OptionsScorched.h>
00026 #include <list>
00027 
00028 ActionController::ActionController() : 
00029         GameStateI("ActionController"),
00030         speed_(1), referenceCount_(0), time_(0), 
00031         context_(0), lastTraceTime_(0),
00032         actionTracing_(false), stepTime_(0),
00033         actionEvents_(false), actionProfiling_(false),
00034         stopImmediately_(false),
00035         actionNumber_(0)
00036 {
00037 
00038 }
00039 
00040 ActionController::~ActionController()
00041 {
00042 
00043 }
00044 
00045 void ActionController::clear(bool warn)
00046 {
00047         // New actions
00048         std::list<Action *>::iterator newItor;
00049         for (newItor = newActions_.begin();
00050                 newItor != newActions_.end();
00051                 newItor++)
00052         {
00053                 Action *act = *newItor;
00054                 if (warn)
00055                 {
00056                         Logger::log(S3D::formatStringBuffer("Warning: removing added timed out action %s, %s",
00057                                 act->getActionType().c_str(), (act->getReferenced()?"Ref":"UnRef")));
00058                 }
00059                 delete act;
00060         }
00061         newActions_.clear();
00062 
00063         // New Last actions
00064         for (newItor = newLastActions_.begin();
00065                 newItor != newLastActions_.end();
00066                 newItor++)
00067         {
00068                 Action *act = *newItor;
00069                 if (warn)
00070                 {
00071                         Logger::log(S3D::formatStringBuffer("Warning: removing added timed out action %s, %s",
00072                                 act->getActionType().c_str(), (act->getReferenced()?"Ref":"UnRef")));
00073                 }
00074                 delete act;
00075         }
00076         newLastActions_.clear();
00077 
00078         // Current actions
00079         for (int a=0; a<actions_.actionCount; a++)
00080         {
00081                 Action *act = actions_.actions[a];
00082                 if (warn)
00083                 {
00084                         Logger::log(S3D::formatStringBuffer("Warning: removing added timed out action %s, %s",
00085                                 act->getActionType().c_str(), (act->getReferenced()?"Ref":"UnRef")));
00086                 }
00087                 delete act;
00088         }
00089         actions_.clear();
00090 
00091         // Ref count
00092         referenceCount_ = 0;
00093 }
00094 
00095 bool ActionController::allEvents()
00096 {
00097         // Criteria to add more events :-
00098         // Check that there are referenced actions in the simulation,
00099         // and that these referenced actions are not events
00100         std::list<Action *>::iterator newItor;
00101         for (newItor = newActions_.begin();
00102                 newItor != newActions_.end();
00103                 newItor++)
00104         {
00105                 Action *act = *newItor;
00106                 if (!act->getActionEvent() &&
00107                         act->getReferenced()) return false;
00108         }
00109         for (int a=0; a<actions_.actionCount; a++)
00110         {
00111                 Action *act = actions_.actions[a];
00112                 if (!act->getActionEvent() &&
00113                         act->getReferenced()) return false;
00114         }
00115         return true;
00116 }
00117 
00118 void ActionController::logActions()
00119 {
00120         Logger::log(S3D::formatStringBuffer("ActionLog : Time %.2f, New %i, New Last %i, Ref %i",
00121                 time_.asFloat(),
00122                 (int) newActions_.size(), 
00123                 (int) newLastActions_.size(),
00124                 referenceCount_));
00125         for (int a=0; a<actions_.actionCount; a++)
00126         {
00127                 Action *act = actions_.actions[a];
00128                 Logger::log(S3D::formatStringBuffer("Action : %s", act->getActionType().c_str()));
00129         }
00130 }
00131 
00132 void ActionController::logProfiledActions()
00133 {
00134         if (!actionProfiling_) return;
00135 
00136         Logger::log("Logging Profiled Actions --------------------");
00137         int totalCount = 0;
00138         std::map<std::string, int>::iterator itor;
00139         for (itor =  actionProfile_.begin();
00140                 itor != actionProfile_.end();
00141                 itor++)
00142         {
00143                 const std::string &name = (*itor).first;
00144                 int count = (*itor).second;
00145                 totalCount += count;
00146                 Logger::log(S3D::formatStringBuffer("%s - %i", name.c_str(), count));
00147         }
00148         Logger::log(S3D::formatStringBuffer("Total - %i", totalCount));
00149         Logger::log("---------------------------------------------");
00150 
00151         actionProfile_.clear();
00152 }
00153 
00154 bool ActionController::noReferencedActions()
00155 {
00156         bool finished = 
00157                 newActions_.empty() && 
00158                 newLastActions_.empty() &&
00159                 (referenceCount_ == 0);
00160 
00161         if (actionTracing_)
00162         {
00163                 if (time_ - lastTraceTime_ > 5)
00164                 {
00165                         lastTraceTime_ = time_;
00166                         logActions();
00167                 }
00168         }
00169 
00170         return finished;
00171 }
00172 
00173 void ActionController::resetTime()
00174 {
00175         time_ = 0;
00176         lastTraceTime_ = 0;
00177         stepTime_ = 0;
00178 
00179         syncCheck_.clear();
00180 }
00181 
00182 void ActionController::setScorchedContext(ScorchedContext *context)
00183 {
00184         context_ = context;
00185 }
00186 
00187 void ActionController::setFast(fixed speedMult)
00188 {
00189         speed_ = speedMult;
00190 }
00191 
00192 void ActionController::addSyncCheck(const std::string &msg)
00193 {
00194         if (!stopImmediately_) return;
00195 
00196         DIALOG_ASSERT(context_->getOptionsGame().getActionSyncCheck());
00197         syncCheck_.push_back(msg);
00198 }
00199 
00200 void ActionController::addAction(Action *action)
00201 {
00202         action->setScorchedContext(context_);
00203         action->setActionStartTime(time_);
00204         action->setActionEvent(actionEvents_);
00205 
00206         if (action->getReferenced())
00207         {
00208                 action->setActionNumber(++actionNumber_);
00209                 if (context_->getOptionsGame().getActionSyncCheck())
00210                 {
00211                         std::string actionType = action->getActionType();
00212                         std::string actionDetails = action->getActionDetails();
00213                         addSyncCheck(
00214                                 S3D::formatStringBuffer("Add Action : %i %s:%s", 
00215                                         time_.getInternal(), 
00216                                         actionType.c_str(), 
00217                                         actionDetails.c_str()));
00218                 }
00219         }
00220 
00221         newActions_.push_back(action);
00222 
00223         if (actionProfiling_)
00224         {
00225                 std::map<std::string, int>::iterator findItor =
00226                         actionProfile_.find(action->getActionType());
00227                 if (findItor == actionProfile_.end())
00228                 {
00229                         actionProfile_[action->getActionType()] = 1;
00230                 }
00231                 else
00232                 {
00233                         (*findItor).second++;
00234                 }       
00235         }
00236 }
00237 
00238 void ActionController::addLastAction(Action *action)
00239 {
00240         newLastActions_.push_back(action);
00241 }
00242 
00243 void ActionController::addNewLastActions()
00244 {
00245         if (newActions_.empty() &&
00246                 referenceCount_ == 0)
00247         {
00248                 while (!newLastActions_.empty())
00249                 {
00250                         Action *action = newLastActions_.front(); 
00251                         addAction(action);                      
00252                         newLastActions_.pop_front();
00253                 }
00254         }
00255 }
00256 
00257 void ActionController::addNewActions()
00258 {
00259         while (!newActions_.empty())
00260         {
00261                 Action *action = newActions_.front(); 
00262 
00263                 action->setScorchedContext(context_);
00264                 action->setActionStartTime(time_);
00265                 if (action->getReferenced()) referenceCount_ ++;
00266 
00267                 action->init();
00268                 actions_.push_back(action);
00269 
00270                 newActions_.pop_front();
00271         }
00272 }
00273 
00274 void ActionController::draw(const unsigned state)
00275 {
00276         // Itterate and draw all of the actions
00277         for (int a=0; a<actions_.actionCount; a++)
00278         {
00279                 Action *act = actions_.actions[a];
00280                 act->draw();
00281         }
00282 }
00283 
00284 void ActionController::simulate(const unsigned state, float ft)
00285 {
00286         fixed frameTime = fixed::fromFloat(ft);
00287 
00288         frameTime *= speed_;
00289 
00290         // As this simulator gives differing results dependant on
00291         // step size, always ensure step size is the same
00292         stepTime_ += frameTime;
00293 
00294         // step size = 1.0 / physics fps = steps per second
00295         const fixed stepSize = fixed(1) / fixed(context_->getOptionsGame().getPhysicsFPS());
00296         while (stepTime_ >= stepSize && !(stopImmediately_ && noReferencedActions()))
00297         {
00298                 time_ += stepSize;
00299                 stepActions(stepSize);
00300 
00301                 // More time has passed
00302                 stepTime_ -= stepSize;
00303         }
00304 }
00305 
00306 void ActionController::stepActions(fixed frameTime)
00307 {
00308         // Ensure any new last actions are added
00309         addNewLastActions();
00310 
00311         // Ensure any new actions are added
00312         addNewActions();
00313 
00314         // Add any new events (if allowed)
00315         if (time_ < 10 && !allEvents())
00316         {
00317                 actionEvents_ = true;
00318                 events_.simulate(frameTime, *context_);
00319                 actionEvents_ = false;
00320         }
00321 
00322         // Move the targets
00323         context_->getTargetMovement().simulate(*context_, frameTime);
00324 
00325         // Itterate and draw all of the actions
00326         int keepcount=0;
00327         for (int a=0; a<actions_.actionCount; a++)
00328         {
00329                 Action *act = actions_.actions[a];
00330                 bool remove = false;
00331                 act->simulate(frameTime, remove);
00332 
00333                 // Ensure that no referenced actions over do their time
00334                 if (act->getReferenced())
00335                 {
00336                         if ((time_ - act->getActionStartTime() > 30))
00337                         {
00338                                 Logger::log(S3D::formatStringBuffer("Warning: removing timed out action %s",
00339                                         act->getActionType().c_str()));
00340                                 remove = true;
00341                         }
00342                 }
00343 
00344                 // If this action has finished add to list to be removed
00345                 if (remove)
00346                 {
00347                         if (act->getReferenced())
00348                         {
00349                                 referenceCount_--;
00350                                 if (referenceCount_<0) referenceCount_ = 0;
00351 
00352                                 if (context_->getOptionsGame().getActionSyncCheck())
00353                                 {
00354                                         std::string actionType = act->getActionType();
00355                                         std::string actionDetails = act->getActionDetails();
00356                                         addSyncCheck(
00357                                                 S3D::formatStringBuffer("Rm Action : %i %s:%s", 
00358                                                         time_.getInternal(), 
00359                                                         actionType.c_str(), 
00360                                                         actionDetails.c_str()));
00361                                 }
00362                         }
00363 
00364                         delete act;
00365                 }
00366                 else
00367                 {
00368                         actions_.actions[keepcount] = act;
00369                         keepcount++;
00370                 }
00371         }
00372         actions_.actionCount = keepcount;
00373 }
00374 

Generated on Mon Feb 16 15:14:49 2009 for Scorched3D by  doxygen 1.5.3