changeset 181:56ac89189bc4

fixed time handling in fife: - the time scaling method was unreliable when changing the time factors (jumping in the moment of the change) - replaced much calls to SDL_GetTicks with TimerManager::instance()->getTime() - some other time related cleanup
author spq@33b003aa-7bff-0310-803a-e67f0ece8222
date Sat, 31 Jan 2009 04:15:43 +0000
parents 66bd7f8c541e
children bcc93e17f978
files engine/core/model/metamodel/timeprovider.cpp engine/core/model/metamodel/timeprovider.h engine/core/model/metamodel/timeprovider.i engine/core/model/structures/instance.cpp engine/core/model/structures/instance.h engine/core/model/structures/instance.i engine/core/model/structures/layer.cpp engine/core/util/time/timemanager.cpp engine/core/view/camera.cpp engine/core/view/renderers/genericrenderer.cpp
diffstat 10 files changed, 84 insertions(+), 54 deletions(-) [+]
line wrap: on
line diff
--- a/engine/core/model/metamodel/timeprovider.cpp	Fri Jan 30 00:58:43 2009 +0000
+++ b/engine/core/model/metamodel/timeprovider.cpp	Sat Jan 31 04:15:43 2009 +0000
@@ -35,7 +35,8 @@
 namespace FIFE {
 	TimeProvider::TimeProvider(TimeProvider* master): 
 		m_master(master), 
-		m_multiplier(1.0) { 
+		m_multiplier(1.0) {
+		m_time_static = m_time_scaled = master ? master->getGameTime() : TimeManager::instance()->getTime();
 	}
 	
 	TimeProvider::~TimeProvider() {}
@@ -44,6 +45,8 @@
 		if (multiplier < 0.0) {
 			throw NotSupported("Negative time multiplier are not supported");
 		}
+		m_time_static = getPreciseGameTime();
+		m_time_scaled = m_master ? m_master->getPreciseGameTime() : static_cast<float>(TimeManager::instance()->getTime());
 		m_multiplier = multiplier;
 	}
 	
@@ -59,14 +62,14 @@
 		}
 	}
 	
-	unsigned int TimeProvider::getGameTicks() const {
-		if (m_master) {
-			return m_master->getGameTicks();
-		} else {
-			return TimeManager::instance()->getTime();
-		}
+	unsigned int TimeProvider::getGameTime() const {
+		return static_cast<unsigned int>(getPreciseGameTime());
 	}
-
+	
+	double TimeProvider::getPreciseGameTime() const {
+		return m_time_static + m_multiplier * ((m_master ? m_master->getPreciseGameTime() : static_cast<float>(TimeManager::instance()->getTime())) - m_time_scaled);
+	}
+	
 	unsigned int scaleTime(float multiplier, unsigned int ticks) {
 		return static_cast<unsigned int>(static_cast<float>(ticks) * multiplier);
 	}
--- a/engine/core/model/metamodel/timeprovider.h	Fri Jan 30 00:58:43 2009 +0000
+++ b/engine/core/model/metamodel/timeprovider.h	Sat Jan 31 04:15:43 2009 +0000
@@ -60,13 +60,18 @@
 		 */
 		float getTotalMultiplier() const;
 		
-		/** Returns current game ticks. Fetched from furthest master to reduce system calls.
+		/** Returns current game ticks, already scaled.
 		 */
-		unsigned int getGameTicks() const;
+		unsigned int getGameTime() const;
 		
 	private:
 		TimeProvider* m_master;
 		float m_multiplier;
+		double m_time_static, m_time_scaled; 
+		
+		/** Returns current game ticks, already scaled, more precise.
+		 */
+		double getPreciseGameTime() const;
 	};
 	
 	/** Utility function to calculate time scaling. Mostly done to avoid littering other code
--- a/engine/core/model/metamodel/timeprovider.i	Fri Jan 30 00:58:43 2009 +0000
+++ b/engine/core/model/metamodel/timeprovider.i	Sat Jan 31 04:15:43 2009 +0000
@@ -33,6 +33,6 @@
 		void setMultiplier(float multiplier);
 		float getMultiplier() const;
 		float getTotalMultiplier() const;
-		unsigned int getGameTicks() const;
+		unsigned int getGameTime() const;
 	};
 }
--- a/engine/core/model/structures/instance.cpp	Fri Jan 30 00:58:43 2009 +0000
+++ b/engine/core/model/structures/instance.cpp	Sat Jan 31 04:15:43 2009 +0000
@@ -32,6 +32,7 @@
 #include "util/log/logger.h"
 #include "util/base/exception.h"
 #include "util/math/fife_math.h"
+#include "util/time/timemanager.h"
 #include "model/metamodel/grids/cellgrid.h"
 #include "model/metamodel/abstractpather.h"
 #include "model/metamodel/action.h"
@@ -52,8 +53,8 @@
 			m_target(NULL), 
 			m_speed(0), 
 			m_repeating(false),
-			m_action_start_time(SDL_GetTicks()),
-			m_prev_call_time(m_action_start_time),
+			m_action_start_time(0),
+			m_prev_call_time(0),
 			m_pather_session_id(-1),
 			m_pather(pather),
 			m_leader(NULL) {}
@@ -78,8 +79,6 @@
 		unsigned int m_action_start_time;
 		// ticks since last call
 		unsigned int m_prev_call_time;
-		// current time for action processing (set by Instance::update), optimized to avoid multiple calls to GetTicks
-		unsigned int m_cur_time;
 		// session id for pather
 		int m_pather_session_id;
 		// pather
@@ -93,8 +92,8 @@
 		SayInfo(const std::string& txt, unsigned int duration):
 			m_txt(txt),
 			m_duration(duration),
-			m_start_time(SDL_GetTicks()) {
-		}
+			m_start_time(0) {}
+
 		std::string m_txt;
 		unsigned int m_duration;
 		unsigned int m_start_time;
@@ -251,6 +250,7 @@
 			m_activity->m_actioninfo = NULL;
 			throw NotFound(std::string("action ") + action_name + " not found");
 		}
+		m_activity->m_actioninfo->m_prev_call_time = m_activity->m_actioninfo->m_action_start_time = getRuntime();
 	}
 
 	void Instance::move(const std::string& action_name, const Location& target, const double speed) {
@@ -286,6 +286,7 @@
 		
 		if (text != "") {
 			m_activity->m_sayinfo = new SayInfo(text, duration);
+			m_activity->m_sayinfo->m_start_time = getRuntime();
 		}
 	}
 
@@ -308,7 +309,7 @@
 		FL_DBG(_log, "Moving...");
 		ActionInfo* info = m_activity->m_actioninfo;
 		// timeslice for this movement
-		unsigned int timedelta = scaleTime(getTotalTimeMultiplier(), info->m_cur_time - info->m_prev_call_time);
+		unsigned int timedelta = m_activity->m_timeprovider->getGameTime() - info->m_prev_call_time;
 		FL_DBG(_log, LMsg("timedelta ") <<  timedelta << " prevcalltime " << info->m_prev_call_time);
 		// how far we can travel
 		double distance_to_travel = (static_cast<double>(timedelta) / 1000.0) * info->m_speed;
@@ -331,7 +332,7 @@
 		return false;
 	}
 
-	InstanceChangeInfo Instance::update(unsigned int curticks) {
+	InstanceChangeInfo Instance::update() {
 		if (!m_activity) {
 			return ICHANGE_NO_CHANGES;
 		}
@@ -339,14 +340,9 @@
 		if (!m_activity->m_timeprovider) {
 			bindTimeProvider();
 		}
-		
-		if (curticks == 0) {
-			curticks = SDL_GetTicks();
-		}
 		ActionInfo* info = m_activity->m_actioninfo;
 		if (info) {
-			info->m_cur_time = curticks;
-			FL_DBG(_log, LMsg("updating instance, ticks = ") << curticks);
+			FL_DBG(_log, "updating instance");
 
 			if (info->m_target) {
 				FL_DBG(_log, "action contains target for movement");
@@ -361,20 +357,20 @@
 				}
 			} else {
 				FL_DBG(_log, "action does not contain target for movement");
-				if (scaleTime(getTotalTimeMultiplier(), curticks - info->m_action_start_time) >= info->m_action->getDuration()) {
+				if (m_activity->m_timeprovider->getGameTime() - info->m_action_start_time >= info->m_action->getDuration()) {
 					if (info->m_repeating) {
-						info->m_action_start_time = curticks;
+						info->m_action_start_time = m_activity->m_timeprovider->getGameTime();
 					} else {
 						finalizeAction();
 					}
 				}
 			}
 
-			m_activity->m_actioninfo->m_prev_call_time = curticks;
+			m_activity->m_actioninfo->m_prev_call_time = m_activity->m_timeprovider->getGameTime();
 		}
 		if (m_activity->m_sayinfo) {
 			if (m_activity->m_sayinfo->m_duration > 0) {
-				if (scaleTime(getTotalTimeMultiplier(), curticks - m_activity->m_sayinfo->m_start_time) > m_activity->m_sayinfo->m_duration) {
+				if (m_activity->m_timeprovider->getGameTime() >= m_activity->m_sayinfo->m_start_time + m_activity->m_sayinfo->m_duration) {
 					say("");
 				}
 			}
@@ -432,13 +428,15 @@
 		return *m_facinglocation;
 	}
 
-	int Instance::getActionRuntime() const {
+	unsigned int Instance::getActionRuntime() {
 		if (m_activity && m_activity->m_actioninfo) {
-			return SDL_GetTicks() - m_activity->m_actioninfo->m_action_start_time;
+			if(!m_activity->m_timeprovider)
+				bindTimeProvider();
+			return m_activity->m_timeprovider->getGameTime() - m_activity->m_actioninfo->m_action_start_time;
 		}
-		return -1;
+		return getRuntime();
 	}
-	
+
 	void Instance::bindTimeProvider() {
 		float multiplier = 1.0;
 		if (m_activity->m_timeprovider) {
@@ -458,12 +456,12 @@
 		}
 		m_activity->m_timeprovider->setMultiplier(multiplier);
 	}
-	
+
 	void Instance::refresh() {
 		initializeChanges();
 		bindTimeProvider();
 	}
-	
+
 	void Instance::setTimeMultiplier(float multip) {
 		initializeChanges();
 		if (!m_activity->m_timeprovider) {
@@ -471,19 +469,39 @@
 		}
 		m_activity->m_timeprovider->setMultiplier(multip);
 	}
-	
+
 	float Instance::getTimeMultiplier() {
 		if (m_activity && m_activity->m_timeprovider) {
 			return m_activity->m_timeprovider->getMultiplier();
 		}
 		return 1.0;
 	}
-	
+
 	float Instance::getTotalTimeMultiplier() {
 		if (m_activity && m_activity->m_timeprovider) {
 			return m_activity->m_timeprovider->getTotalMultiplier();
 		}
+		if (m_location.getLayer()) {
+			Map* map = m_location.getLayer()->getMap();
+			if (map && map->getTimeProvider()) {
+				return map->getTimeProvider()->getTotalMultiplier();
+			}
+		}
 		return 1.0;
 	}
+
+	unsigned int Instance::getRuntime() {
+		if (m_activity) {
+			if(!m_activity->m_timeprovider)
+				bindTimeProvider();
+			return m_activity->m_timeprovider->getGameTime();
+		}
+		if (m_location.getLayer()) {
+			Map* map = m_location.getLayer()->getMap();
+			if (map && map->getTimeProvider()) {
+				return map->getTimeProvider()->getGameTime();
+			}
+		}
+		return TimeManager::instance()->getTime();
+	}
 }
-
--- a/engine/core/model/structures/instance.h	Fri Jan 30 00:58:43 2009 +0000
+++ b/engine/core/model/structures/instance.h	Sat Jan 31 04:15:43 2009 +0000
@@ -185,7 +185,7 @@
 		 *  In case there is no current action, returns -1
 		 * @return action runtime
 		 */
-		int getActionRuntime() const;
+		unsigned int getActionRuntime();
 
 		/** Performs given named action to the instance. While performing the action
 		 *  moves instance to given target with given speed
@@ -221,12 +221,11 @@
 		const std::string* getSayText() const;
 
 		/** Updates the instance related to the current action
-		 * @param curticks current tick count of the system
 		 * @note call this only once in engine update cycle, so that tracking between
 		 *  current position and previous position keeps in sync.
 		 * @returns marked changes
 		 */
-		InstanceChangeInfo update(unsigned int curticks=0);
+		InstanceChangeInfo update();
 		
 		/** Sets visualization to be used. Transfers ownership.
 		 */
@@ -248,6 +247,11 @@
 		*/
 		float getTotalTimeMultiplier();
 		
+		/** Gets the scaled runtime in milliseconds
+		 * @return runtime
+		 */
+		unsigned int getRuntime();
+
 		/** Refreshes instance e.g. in case location is updated directly (not via setLocation)
 		 * In this case e.g. instance's master time provider is changed, so it needs to be updated
 		 */
--- a/engine/core/model/structures/instance.i	Fri Jan 30 00:58:43 2009 +0000
+++ b/engine/core/model/structures/instance.i	Sat Jan 31 04:15:43 2009 +0000
@@ -84,13 +84,14 @@
 		void setFacingLocation(const Location& loc);
 		Location getFacingLocation();
 		Location& getFacingLocationRef();
-		int getActionRuntime() const;
+		unsigned int getActionRuntime();
 		void move(const std::string& action_name, const Location& target, const double speed);
 		void act(const std::string& action_name, const Location& direction, bool repeating=false);
 		void follow(const std::string& action_name, Instance* leader, const double speed);
 		void say(const std::string& text, unsigned int duration=0);
 		void setTimeMultiplier(float multip);
 		float getTimeMultiplier();
+		unsigned int getRuntime();
 		void refresh();
 		InstanceChangeInfo getChangeInfo();
 		
--- a/engine/core/model/structures/layer.cpp	Fri Jan 30 00:58:43 2009 +0000
+++ b/engine/core/model/structures/layer.cpp	Sat Jan 31 04:15:43 2009 +0000
@@ -203,10 +203,9 @@
 
 	bool Layer::update() {
 		m_changedinstances.clear();
-		unsigned int curticks = SDL_GetTicks();
 		std::vector<Instance*>::iterator it = m_instances.begin();
 		for(; it != m_instances.end(); ++it) {
-			if ((*it)->update(curticks) != ICHANGE_NO_CHANGES) {
+			if ((*it)->update() != ICHANGE_NO_CHANGES) {
 				m_changedinstances.push_back(*it);
 				m_changed = true;
 			}
--- a/engine/core/util/time/timemanager.cpp	Fri Jan 30 00:58:43 2009 +0000
+++ b/engine/core/util/time/timemanager.cpp	Sat Jan 31 04:15:43 2009 +0000
@@ -54,10 +54,12 @@
 		if (m_current_time == 0) {
 			m_current_time = SDL_GetTicks();
 			avg_multiplier = 0;
+			m_time_delta = 0;
+		} else {
+			m_time_delta = m_current_time;
+			m_current_time = SDL_GetTicks();
+			m_time_delta = m_current_time - m_time_delta;
 		}
-		m_time_delta = m_current_time;
-		m_current_time = SDL_GetTicks();
-		m_time_delta = m_current_time - m_time_delta;
 		m_average_frame_time = m_average_frame_time * avg_multiplier +
 			double(m_time_delta) * (1.0 - avg_multiplier);
 
--- a/engine/core/view/camera.cpp	Fri Jan 30 00:58:43 2009 +0000
+++ b/engine/core/view/camera.cpp	Sat Jan 31 04:15:43 2009 +0000
@@ -484,8 +484,6 @@
 		//	return;
 		//}
 		
-		const unsigned long curtime = TimeManager::instance()->getTime();
-		
 		// update each layer
 		m_renderbackend->pushClipArea(getViewPort());
 		
@@ -534,9 +532,8 @@
 				if (action) {
 					FL_DBG(_log, "Instance has action");
 					int animation_id = action->getVisual<ActionVisual>()->getAnimationIndexByAngle(angle);
-
 					Animation& animation = m_apool->getAnimation(animation_id);
-					int animtime = scaleTime(instance->getTotalTimeMultiplier(), instance->getActionRuntime()) % animation.getDuration();
+					unsigned int animtime = instance->getActionRuntime() % animation.getDuration();
 					image = animation.getFrameByTimestamp(animtime);
 				} else {
 					FL_DBG(_log, "No action");
@@ -550,7 +547,7 @@
 						if (action) {
 							int animation_id = action->getVisual<ActionVisual>()->getAnimationIndexByAngle(angle);
 							Animation& animation = m_apool->getAnimation(animation_id);
-							int animtime = scaleTime(instance->getTotalTimeMultiplier(), curtime) % animation.getDuration();
+							unsigned int animtime = instance->getRuntime() % animation.getDuration();
 							image = animation.getFrameByTimestamp(animtime);
 						}
 					}
--- a/engine/core/view/renderers/genericrenderer.cpp	Fri Jan 30 00:58:43 2009 +0000
+++ b/engine/core/view/renderers/genericrenderer.cpp	Sat Jan 31 04:15:43 2009 +0000
@@ -35,6 +35,7 @@
 #include "video/image.h"
 #include "util/math/fife_math.h"
 #include "util/log/logger.h"
+#include "util/time/timemanager.h"
 #include "model/metamodel/grids/cellgrid.h"
 #include "model/metamodel/timeprovider.h"
 #include "model/structures/instance.h"
@@ -246,13 +247,13 @@
 		GenericRendererElementInfo(),
 		m_anchor(anchor),
 		m_animation(animation),
-		m_start_time(SDL_GetTicks()),
+		m_start_time(TimeManager::instance()->getTime()),
 		m_time_scale(1.0) {
 	}
 	void GenericRendererAnimationInfo::render(Camera* cam, Layer* layer, std::vector<Instance*>& instances, RenderBackend* renderbackend, ImagePool* imagepool, AnimationPool* animpool) {
 		Point p = m_anchor.getCalculatedPoint(cam, layer, instances);
 		Animation& animation = animpool->getAnimation(m_animation);
-		int animtime = scaleTime(m_time_scale, SDL_GetTicks() - m_start_time) % animation.getDuration();
+		int animtime = scaleTime(m_time_scale, TimeManager::instance()->getTime() - m_start_time) % animation.getDuration();
 		Image* img = animation.getFrameByTimestamp(animtime);
 		Rect r;
 		r.x = p.x-img->getWidth()/2;