2525#include " math/random.hpp"
2626#include " math/util.hpp"
2727#include " object/player.hpp"
28+ #include " supertux/constants.hpp"
2829#include " supertux/gameconfig.hpp"
2930#include " supertux/globals.hpp"
3031#include " supertux/level.hpp"
@@ -82,7 +83,9 @@ Camera::Camera(const std::string& name) :
8283 m_scale_easing(),
8384 m_scale_anchor(),
8485 m_minimum_scale(1 .f),
85- m_enfore_minimum_scale(false )
86+ m_enfore_minimum_scale(false ),
87+ m_last_translation(0 .0f , 0 .0f ),
88+ m_last_scale(1 .0f )
8689{
8790}
8891
@@ -118,7 +121,9 @@ Camera::Camera(const ReaderMapping& reader) :
118121 m_scale_easing(),
119122 m_scale_anchor(),
120123 m_minimum_scale(1 .f),
121- m_enfore_minimum_scale(false )
124+ m_enfore_minimum_scale(false ),
125+ m_last_translation(0 .0f , 0 .0f ),
126+ m_last_scale(1 .0f )
122127{
123128 std::string modename;
124129
@@ -207,6 +212,26 @@ Camera::check_state()
207212 PathObject::check_state ();
208213}
209214
215+ void Camera::reset_prediction_state ()
216+ {
217+ m_last_translation = get_translation ();
218+ m_last_scale = get_current_scale ();
219+ }
220+
221+ std::pair<Vector, float >
222+ Camera::get_predicted_transform (float time_offset) const
223+ {
224+ if (g_config->frame_prediction ) {
225+ // TODO: extrapolate forwards instead of interpolating over the last frame
226+ float x = time_offset * LOGICAL_FPS;
227+ Vector translation = get_translation () * x + (1 .f - x) * m_last_translation;
228+ float scale = get_current_scale () * x + (1 .f - x) * m_last_scale;
229+ return std::pair (translation, scale);
230+ } else {
231+ return std::pair (get_translation (), get_current_scale ());
232+ }
233+ }
234+
210235const Vector
211236Camera::get_translation () const
212237{
218243Camera::set_translation_centered (const Vector& translation)
219244{
220245 m_translation = translation - m_screen_size.as_vector () / 2 ;
246+ reset_prediction_state ();
221247}
222248
223249Rectf
@@ -237,6 +263,7 @@ Camera::reset(const Vector& tuxpos)
237263 keep_in_bounds (m_translation);
238264
239265 m_cached_translation = m_translation;
266+ reset_prediction_state ();
240267}
241268
242269void
@@ -286,6 +313,7 @@ Camera::scroll_to(const Vector& goal, float scrolltime)
286313 m_translation.x = goal.x ;
287314 m_translation.y = goal.y ;
288315 m_mode = Mode::MANUAL;
316+ reset_prediction_state ();
289317 return ;
290318 }
291319
@@ -301,6 +329,10 @@ Camera::scroll_to(const Vector& goal, float scrolltime)
301329void
302330Camera::update (float dt_sec)
303331{
332+ // For use by camera position prediction
333+ m_last_scale = get_current_scale ();
334+ m_last_translation = get_translation ();
335+
304336 // Fetch the current screen size from the VideoSystem. The main loop always
305337 // processes input and window events, updates game logic, and then draws zero
306338 // or more frames, in that order, so this screen size will be used by the next
@@ -357,6 +389,8 @@ Camera::keep_in_bounds(const Rectf& bounds)
357389
358390 // Remove any scale factor we may have added in the checks above.
359391 m_translation -= scale_factor;
392+
393+ reset_prediction_state ();
360394}
361395
362396void
@@ -750,6 +784,8 @@ Camera::ease_scale(float scale, float time, easing ease, AnchorPoint anchor)
750784 m_scale = scale;
751785 if (m_mode == Mode::MANUAL)
752786 m_translation = m_scale_target_translation;
787+
788+ reset_prediction_state ();
753789 }
754790}
755791
0 commit comments