- Use obstacks for memory allocation for lispfiles and DrawingRequests,
[supertux.git] / src / object / camera.cpp
index c3023df..e4fd50a 100644 (file)
@@ -16,7 +16,6 @@
 //  You should have received a copy of the GNU General Public License
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
 #include <config.h>
 
 #include <stdexcept>
@@ -40,8 +39,8 @@
 #include "path_walker.hpp"
 
 namespace {
-  enum CameraStyle { CameraStyleYI, CameraStyleKD };
-  const CameraStyle cameraStyle = CameraStyleKD;
+  enum CameraStyle { CameraStyleYI, CameraStyleKD, CameraStyleEXP };
+  const CameraStyle cameraStyle = CameraStyleYI;
 }
 
 Camera::Camera(Sector* newsector, std::string name)
@@ -172,7 +171,7 @@ Camera::scroll_to(const Vector& goal, float scrolltime)
   mode = SCROLLTO;
 }
 
-static const float EPSILON = .00001;
+static const float EPSILON = .00001f;
 static const float max_speed_y = 140;
 
 void
@@ -204,10 +203,14 @@ Camera::keep_in_bounds(Vector& translation)
     translation.y = height - SCREEN_HEIGHT;
   if(translation.y < 0)
     translation.y = 0;
+  if (height < SCREEN_HEIGHT)
+    translation.y = height/2.0 - SCREEN_HEIGHT/2.0;
   if(translation.x > width - SCREEN_WIDTH)
     translation.x = width - SCREEN_WIDTH;
   if(translation.x < 0)
     translation.x = 0;
+  if (width < SCREEN_WIDTH)
+    translation.x = width/2.0 - SCREEN_WIDTH/2.0;
 }
 
 void
@@ -257,9 +260,53 @@ Camera::update_scroll_normal_kd(float elapsed_time)
   shake();
 }
 
+template<typename T>
+T clamp(T min, T max, T val)
+{
+  if(val < min)
+    return min;
+  if(val > max)
+    return max;
+
+  return val;
+}
+
+void
+Camera::update_scroll_normal_exp(float elapsed_time)
+{
+  static const Vector camera_speed = Vector(300, 100);
+
+  Player* player = sector->player;
+  const Vector& player_pos = player->get_bbox().get_middle();
+  static Vector last_player_pos = player_pos;
+  static Vector camera_delta = Vector(0, 0);
+
+  (void) elapsed_time;
+
+  Vector player_delta_x = player_pos - last_player_pos;
+  last_player_pos = player_pos;
+
+  Vector camera_delta_antic = Vector(0, 0) + player_delta_x * 25;
+  Vector myspeed = (camera_delta_antic - camera_delta) / elapsed_time;
+  myspeed.x = clamp(-camera_speed.x, camera_speed.x, myspeed.x);
+  myspeed.y = clamp(-camera_speed.y, camera_speed.y, myspeed.y);
+
+  camera_delta += myspeed * elapsed_time;
+
+  translation.x = camera_delta.x + player_pos.x - 0.5f * SCREEN_WIDTH;
+  translation.y = camera_delta.y + player_pos.y - 0.5f * SCREEN_HEIGHT;
+
+  keep_in_bounds(translation);
+  shake();
+}
+
 void
 Camera::update_scroll_normal(float elapsed_time)
 {
+  if (cameraStyle == CameraStyleEXP) {
+    update_scroll_normal_exp(elapsed_time);
+    return;
+  }
   if (cameraStyle == CameraStyleKD) {
     update_scroll_normal_kd(elapsed_time);
     return;
@@ -318,11 +365,11 @@ Camera::update_scroll_normal(float elapsed_time)
   // when suddenly changing directions while scrolling into the other direction.
   // abort scrolling, since tux might be going left/right at a relatively small
   // part of the map (like when jumping upwards)
-  
 
-  // Find out direction in which the player walks: We want to try and show a 
+
+  // Find out direction in which the player walks: We want to try and show a
   // bit more of what's in front of the player and less of what's behind
-  LeftRightScrollChange walkDirection;  
+  LeftRightScrollChange walkDirection;
   if (player->physic.get_velocity_x() < -EPSILON) walkDirection = LEFT;
   else if (player->physic.get_velocity_x() > EPSILON) walkDirection = RIGHT;
   else if (player->dir == ::LEFT) walkDirection = LEFT;