src/object/path_walker.cpp

Go to the documentation of this file.
00001 //  SuperTux
00002 //  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
00003 //
00004 //  This program is free software: you can redistribute it and/or modify
00005 //  it under the terms of the GNU General Public License as published by
00006 //  the Free Software Foundation, either version 3 of the License, or
00007 //  (at your option) any later version.
00008 //
00009 //  This program is distributed in the hope that it will be useful,
00010 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 //  GNU General Public License for more details.
00013 //
00014 //  You should have received a copy of the GNU General Public License
00015 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00016 
00017 #include "object/path_walker.hpp"
00018 
00019 #include <math.h>
00020 #include <assert.h>
00021 
00022 PathWalker::PathWalker(const Path* path, bool running) :
00023   path(path), 
00024   running(running), 
00025   current_node_nr(0), 
00026   next_node_nr(0), 
00027   stop_at_node_nr(running?-1:0), 
00028   node_time(0),
00029   node_mult(),
00030   walking_speed(1.0)
00031 {
00032   node_mult = 1 / path->nodes[0].time;
00033   next_node_nr = path->nodes.size() > 1 ? 1 : 0;
00034 }
00035 
00036 PathWalker::~PathWalker()
00037 {
00038 }
00039 
00040 Vector
00041 PathWalker::advance(float elapsed_time)
00042 {
00043   if (!running) return path->nodes[current_node_nr].position;
00044 
00045   assert(elapsed_time >= 0);
00046 
00047   elapsed_time *= fabsf(walking_speed);
00048 
00049   const Path::Node* current_node = & (path->nodes[current_node_nr]);
00050   while(node_time + elapsed_time * node_mult >= 1) {
00051     elapsed_time -= (1 - node_time) / node_mult;
00052 
00053     if(walking_speed > 0) {
00054       advance_node();
00055     } else if(walking_speed < 0) {
00056       goback_node();
00057     }
00058 
00059     current_node = & (path->nodes[current_node_nr]);
00060     node_time = 0;
00061     if(walking_speed > 0) {
00062       node_mult = 1 / current_node->time;
00063     } else {
00064       node_mult = 1 / path->nodes[next_node_nr].time;
00065     }
00066   }
00067 
00068   node_time += elapsed_time * node_mult;
00069 
00070   return get_pos();
00071 }
00072 
00073 Vector
00074 PathWalker::get_pos()
00075 {
00076   const Path::Node* current_node = & (path->nodes[current_node_nr]);
00077   const Path::Node* next_node = & (path->nodes[next_node_nr]);
00078   Vector new_pos = current_node->position +
00079     (next_node->position - current_node->position) * node_time;
00080 
00081   return new_pos;
00082 }
00083 
00084 void
00085 PathWalker::goto_node(int node_no)
00086 {
00087   if (node_no == stop_at_node_nr) return;
00088   running = true;
00089   stop_at_node_nr = node_no;
00090 }
00091 
00092 void
00093 PathWalker::start_moving()
00094 {
00095   running = true;
00096   stop_at_node_nr = -1;
00097 }
00098 
00099 void
00100 PathWalker::stop_moving()
00101 {
00102   stop_at_node_nr = next_node_nr;
00103 }
00104 
00105 void
00106 PathWalker::advance_node()
00107 {
00108   current_node_nr = next_node_nr;
00109   if (static_cast<int>(current_node_nr) == stop_at_node_nr) running = false;
00110 
00111   if(next_node_nr + 1 < path->nodes.size()) {
00112     next_node_nr++;
00113     return;
00114   }
00115 
00116   switch(path->mode) {
00117     case Path::ONE_SHOT:
00118       next_node_nr = path->nodes.size() - 1;
00119       walking_speed = 0;
00120       return;
00121 
00122     case Path::PING_PONG:
00123       walking_speed = -walking_speed;
00124       next_node_nr = path->nodes.size() > 1 ? path->nodes.size() - 2 : 0;
00125       return;
00126 
00127     case Path::CIRCULAR:
00128       next_node_nr = 0;
00129       return;
00130   }
00131 
00132   // we shouldn't get here
00133   assert(false);
00134   next_node_nr = path->nodes.size() - 1;
00135   walking_speed = 0;
00136 }
00137 
00138 void
00139 PathWalker::goback_node()
00140 {
00141   current_node_nr = next_node_nr;
00142 
00143   if(next_node_nr > 0) {
00144     next_node_nr--;
00145     return;
00146   }
00147 
00148   switch(path->mode) {
00149     case Path::PING_PONG:
00150       walking_speed = -walking_speed;
00151       next_node_nr = path->nodes.size() > 1 ? 1 : 0;
00152       return;
00153     default:
00154       break;
00155   }
00156 
00157   assert(false);
00158   next_node_nr = 0;
00159   walking_speed = 0;
00160 }
00161 
00162 /* EOF */

Generated on Mon Jun 9 03:38:19 2014 for SuperTux by  doxygen 1.5.1