-renamed ViewPort to Camera
authorMatthias Braun <matze@braunis.de>
Mon, 24 May 2004 21:02:44 +0000 (21:02 +0000)
committerMatthias Braun <matze@braunis.de>
Mon, 24 May 2004 21:02:44 +0000 (21:02 +0000)
-removed type() function from GameObject, you should better use C++ RTTI:
  * casting: BadGuy* badguy = dynamic_cast<BadGuy*> (object);
  * comparing for specific type if(typeid(object) == typeid(BadGuy))
  * getting the name typeid(object).name()
-moved camera handling into Camera class
-tweaked camera behaviour. Look for details in
  http://netpanzer.berlios.de/supertux/index.php/Camera
 Horizontal scrolling seems to be nicely now, vertical scrolling is still a bit
 too hectically...

SVN-Revision: 1309

28 files changed:
src/Makefile.am
src/background.cpp
src/background.h
src/badguy.cpp
src/badguy.h
src/button.cpp
src/camera.cpp [new file with mode: 0644]
src/camera.h [new file with mode: 0644]
src/display_manager.cpp
src/display_manager.h
src/drawable.h
src/game_object.h
src/gameloop.cpp
src/gameobjs.cpp
src/gameobjs.h
src/leveleditor.cpp
src/particlesystem.cpp
src/particlesystem.h
src/player.cpp
src/player.h
src/special.cpp
src/special.h
src/tilemap.cpp
src/tilemap.h
src/viewport.cpp [deleted file]
src/viewport.h [deleted file]
src/world.cpp
src/world.h

index 275b810..23427d0 100644 (file)
@@ -77,8 +77,8 @@ music_manager.cpp \
 music_manager.h \
 musicref.cpp \
 musicref.h \
-viewport.cpp \
-viewport.h \
+camera.cpp \
+camera.h \
 game_object.cpp \
 game_object.h \
 display_manager.h \
index 5ebb6c5..975bff9 100644 (file)
@@ -19,7 +19,7 @@
 #include "background.h"
 
 #include "globals.h"
-#include "viewport.h"
+#include "camera.h"
 #include "display_manager.h"
 
 Background::Background(DisplayManager& displaymanager)
@@ -53,7 +53,7 @@ Background::set_gradient(Color top, Color bottom)
 }
 
 void
-Background::draw(ViewPort& viewport, int )
+Background::draw(Camera& viewport, int )
 {
   if(bgtype == BACKGROUND_GRADIENT) {
     drawgradient(gradient_top, gradient_bottom);
index e154392..45af0e0 100644 (file)
@@ -40,12 +40,9 @@ public:
 
   void set_gradient(Color top, Color bottom);
 
-  virtual std::string type() const
-  { return "Background"; }
-
   virtual void action(float elapsed_time);
 
-  virtual void draw(ViewPort& viewport, int layer);
+  virtual void draw(Camera& viewport, int layer);
 
 private:
   int bgtype;
index 0bd1337..0e4b7de 100644 (file)
@@ -35,7 +35,7 @@
 #include "gameloop.h"
 #include "display_manager.h"
 #include "lispwriter.h"
-#include "viewport.h"
+#include "camera.h"
 
 Sprite* img_mriceblock_flat_left;
 Sprite* img_mriceblock_flat_right;
@@ -316,8 +316,7 @@ BadGuy::action_mriceblock(double elapsed_time)
       check_horizontal_bump();
       if(mode == KICK && changed != dir)
         {
-          float scroll_x = World::current()->displaymanager
-            .get_viewport().get_translation().x;
+          float scroll_x = World::current()->camera->get_translation().x;
           
           /* handle stereo sound (number 10 should be tweaked...)*/
           if (base.x < scroll_x + screen->w/2 - 10)
@@ -518,8 +517,7 @@ BadGuy::action_bomb(double elapsed_time)
       dying = DYING_NOT; // now the bomb hurts
       timer.start(EXPLODETIME);
 
-      float scroll_x = World::current()->displaymanager
-        .get_viewport().get_translation().x;                 
+      float scroll_x = World::current()->camera->get_translation().x;                 
 
       /* play explosion sound */  // FIXME: is the stereo all right? maybe we should use player cordinates...
       if (base.x < scroll_x + screen->w/2 - 10)
@@ -753,10 +751,8 @@ BadGuy::action_snowball(double elapsed_time)
 void
 BadGuy::action(float elapsed_time)
 {
-  float scroll_x = World::current()->displaymanager
-    .get_viewport().get_translation().x;
-  float scroll_y = World::current()->displaymanager
-    .get_viewport().get_translation().y;
+  float scroll_x = World::current()->camera->get_translation().x;
+  float scroll_y = World::current()->camera->get_translation().y;
   
   // BadGuy fall below the ground
   if (base.y > World::current()->get_level()->height * 32) {
@@ -836,7 +832,7 @@ BadGuy::action(float elapsed_time)
 }
 
 void
-BadGuy::draw(ViewPort& viewport, int)
+BadGuy::draw(Camera& viewport, int)
 {
   float scroll_x = viewport.get_translation().x;
   float scroll_y = viewport.get_translation().y;
index 6ffafda..9c504e8 100644 (file)
@@ -118,10 +118,8 @@ public:
   virtual void write(LispWriter& writer);
 
   virtual void action(float frame_ratio);
-  virtual void draw(ViewPort& viewport, int layer);
+  virtual void draw(Camera& viewport, int layer);
   virtual void collision(const MovingObject& other, int type);
-  virtual std::string type() const
-  { return "BadGuy"; };
 
   void collision(void* p_c_object, int c_object,
                  CollisionType type = COLLISION_NORMAL);
index 6467474..27697c9 100644 (file)
@@ -24,7 +24,7 @@
 #include "screen.h"
 #include "globals.h"
 #include "button.h"
-#include "viewport.h"
+#include "camera.h"
 
 Timer Button::popup_timer;
 
@@ -87,7 +87,7 @@ void Button::draw()
 
   if(drawable)
   {
-    ViewPort viewport;
+    Camera viewport;
     viewport.set_translation(Vector(rect.x, rect.y));
     drawable->draw(viewport, 0);
   }
diff --git a/src/camera.cpp b/src/camera.cpp
new file mode 100644 (file)
index 0000000..d3c6603
--- /dev/null
@@ -0,0 +1,154 @@
+//  $Id$
+//
+//  SuperTux -  A Jump'n Run
+//  Copyright (C) 2004 Matthias Braun <matze@braunis.de
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  of the License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  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 "camera.h"
+
+#include <math.h>
+#include "lispwriter.h"
+#include "player.h"
+#include "level.h"
+#include "globals.h"
+
+Camera::Camera(Player* newplayer, Level* newlevel)
+  : player(newplayer), level(newlevel), scrollchange(NONE)
+{
+  if(!player || !level)
+    mode = MANUAL;
+  else
+    mode = NORMAL;
+}
+
+Camera::~Camera()
+{
+}
+
+void
+Camera::set_translation(const Vector& newtranslation)
+{
+  translation = newtranslation;
+}
+
+void
+Camera::write(LispWriter& writer)
+{
+  writer.start_list("camera");
+  
+  if(mode == NORMAL) {
+    writer.write_string("mode", "normal");
+  } else if(mode == AUTOSCROLL) {
+    writer.write_string("mode", "autoscroll");
+  } else if(mode == MANUAL) {
+    writer.write_string("mode", "manual");
+  }
+                     
+  writer.end_list("camera");
+}
+
+static const float EPSILON = .00001;
+static const float max_speed_y = 1.4;
+
+void
+Camera::action(float elapsed_time)
+{
+  if(mode == NORMAL)
+    scroll_normal(elapsed_time);
+  else if(mode == AUTOSCROLL)
+    scroll_autoscroll(elapsed_time);
+}
+
+void
+Camera::scroll_normal(float elapsed_time)
+{
+  assert(level != 0 && player != 0);
+  
+  // check that we don't have division by zero later
+  if(elapsed_time < EPSILON)
+    return;
+
+  bool do_y_scrolling = true;
+
+  if(player->dying)
+    do_y_scrolling = false;
+
+  if(do_y_scrolling) {
+    float target_y;
+    if(player->fall_mode == Player::JUMPING)
+      target_y = player->last_ground_y + player->base.height;
+    else
+      target_y = player->base.y + player->base.height;
+
+    float delta_y = translation.y - (target_y - screen->h/2);
+    float speed_y = delta_y / elapsed_time;
+
+    if(player->fall_mode != Player::FALLING 
+        && player->fall_mode != Player::TRAMPOLINE_JUMP) {
+      if(speed_y > max_speed_y)
+        speed_y = max_speed_y;
+      else if(speed_y < -max_speed_y)
+        speed_y = -max_speed_y;
+    }
+
+    translation.y -= speed_y * elapsed_time;
+
+    // don't scroll before the start or after the level's end
+    if(translation.y > level->height * 32 - screen->h)
+      translation.y = level->height * 32 - screen->h;
+    if(translation.y < 0)
+      translation.y = 0; 
+  }
+
+  if((player->dir == ::LEFT && scrollchange == RIGHT)
+      || (player->dir == ::RIGHT && scrollchange == LEFT))
+    scrollchange = NONE;
+  if(player->base.x < translation.x + screen->w/3)
+    scrollchange = LEFT;
+  else if(player->base.x > translation.x + screen->w/3*2)
+    scrollchange = RIGHT;
+
+  float target_x;
+  if(scrollchange == LEFT)
+    target_x = player->base.x - screen->w/3*2;
+  else if(scrollchange == RIGHT)
+    target_x = player->base.x - screen->w/3;
+  else
+    target_x = translation.x;
+
+  float delta_x = translation.x - target_x;
+  float speed_x = delta_x / elapsed_time;
+
+  float maxv = 1 + fabsf(player->physic.get_velocity_x() * 2);
+  printf("SX: %f MV: %f.\n", player->physic.get_velocity_x(), maxv);
+  if(speed_x > maxv)
+    speed_x = maxv;
+  else if(speed_x < -maxv)
+    speed_x = -maxv;
+  
+  translation.x -= speed_x * elapsed_time;
+
+  // don't scroll before the start or after the level's end
+  if(translation.x > level->width * 32 - screen->w)
+    translation.x = level->width * 32 - screen->w;
+  if(translation.x < 0)
+    translation.x = 0;   
+}
+
+void
+Camera::scroll_autoscroll(float elapsed_time)
+{
+  // TODO
+}
diff --git a/src/camera.h b/src/camera.h
new file mode 100644 (file)
index 0000000..aaa8e19
--- /dev/null
@@ -0,0 +1,81 @@
+//  $Id$
+//
+//  SuperTux -  A Jump'n Run
+//  Copyright (C) 2004 Matthias Braun <matze@braunis.de
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  of the License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  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.
+#ifndef __VIEWPORT_H__
+#define __VIEWPORT_H__
+
+#include "vector.h"
+#include "game_object.h"
+#include "serializable.h"
+
+class LispReader;
+class Player;
+class Level;
+
+class Camera : public GameObject, public Serializable
+{
+public:
+  Camera(Player* player = 0, Level* level = 0);
+  virtual ~Camera();
+
+  /** transforms a coordinate in world space to screen space.
+   * Basically you have to apply this function to each coordinate that you want
+   * to display on screen.
+   */
+  Vector world2screen(const Vector& worldpos) const
+  {
+    return worldpos - translation;                   
+  }                                                  
+
+  /// parse camera mode from lisp file
+  void parse_camera(LispReader& reader);
+  /// write camera mode to a lisp file
+  virtual void write(LispWriter& writer);
+
+  /** returns the current translation (=scroll) vector of the viewport */
+  const Vector& get_translation() const
+  { return translation; }
+  /** set the curren translation vector of the viewport */
+  void set_translation(const Vector& translation);
+
+  virtual void action(float elapsed_time);
+
+  enum CameraMode
+  {
+    NORMAL, AUTOSCROLL, MANUAL
+  };
+
+private:
+  void scroll_normal(float elapsed_time);
+  void scroll_autoscroll(float elapsed_time);
+
+  enum LeftRightScrollChange
+  {
+    NONE, LEFT, RIGHT
+  };
+    
+  Vector translation;
+
+  Player* player;
+  Level* level;
+  CameraMode mode;
+  LeftRightScrollChange scrollchange;
+};
+
+#endif
+
index 3aa27ec..3a9b660 100644 (file)
@@ -51,10 +51,10 @@ DisplayManager::remove_drawable(Drawable* drawable)
 }
 
 void
-DisplayManager::draw()
+DisplayManager::draw(Camera& camera)
 {
   for(DisplayList::iterator i = displaylist.begin(); i != displaylist.end();
       ++i)
-    i->object->draw(viewport, i->layer);
+    i->object->draw(camera, i->layer);
 }
 
index d86fd5e..29cc10b 100644 (file)
@@ -22,7 +22,7 @@
 #include <vector>
 
 #include "drawable.h"
-#include "viewport.h"
+#include "camera.h"
 
 // some constants for predefined layer values
 enum {
@@ -51,10 +51,7 @@ public:
 
   void remove_drawable(Drawable* object);
 
-  void draw();
-
-  ViewPort& get_viewport()
-  { return viewport; }
+  void draw(Camera& camera);
 
 private:
   class DrawingQueueEntry {
@@ -74,7 +71,6 @@ private:
 
   typedef std::vector<DrawingQueueEntry> DisplayList;
   DisplayList displaylist;
-  ViewPort viewport;
 };
 
 #endif
index 7c4eef0..d96f200 100644 (file)
@@ -19,7 +19,7 @@
 #ifndef __DRAWABLE_H__
 #define __DRAWABLE_H__
 
-class ViewPort;
+class Camera;
 
 /** interface for all game objects that can be drawn on screen.
  */
@@ -28,7 +28,7 @@ class Drawable
 public:
   /** This function draws the object on screen.
    */                                              
-  virtual void draw(ViewPort& viewport, int layer) = 0;
+  virtual void draw(Camera& viewport, int layer) = 0;
 };
 
 #endif
index 644baaa..d2824b5 100644 (file)
@@ -41,11 +41,6 @@ public:
   GameObject();
   virtual ~GameObject();
 
-  /** returns the name of the objecttype, this is mainly usefull for the editor.
-   * For the coding part you should use C++ RTTI (ie. typeid and dynamic_cast)
-   * instead.
-   */
-  virtual std::string type() const = 0;
   /** This function is called once per frame and allows the object to update
    * it's state. The elapsed_time is the time since the last frame and should be
    * the base for all timed things.
index 766223d..d42c205 100644 (file)
@@ -147,7 +147,7 @@ GameSession::levelintro(void)
   
   char str[60];
 
-  ViewPort dummy;
+  Camera dummy;
   world->background->draw(dummy, LAYER_BACKGROUND0);
 
   sprintf(str, "%s", world->get_level()->name.c_str());
@@ -719,7 +719,7 @@ GameSession::drawresultscreen(void)
 {
   char str[80];
 
-  ViewPort dummy;
+  Camera dummy;
   world->background->draw(dummy, LAYER_BACKGROUND0);  
 
   blue_text->drawf("Result:", 0, 200, A_HMIDDLE, A_TOP, 1);
index 6a707ef..743d9cb 100644 (file)
@@ -47,7 +47,7 @@ BouncyDistro::action(float elapsed_time)
 }
 
 void
-BouncyDistro::draw(ViewPort& viewport, int )
+BouncyDistro::draw(Camera& viewport, int )
 {
   img_distro[0]->draw(viewport.world2screen(position));
 }
@@ -71,7 +71,7 @@ BrokenBrick::action(float elapsed_time)
 }
 
 void
-BrokenBrick::draw(ViewPort& viewport, int )
+BrokenBrick::draw(Camera& viewport, int )
 {
   SDL_Rect src, dest;
   src.x = rand() % 16;
@@ -110,7 +110,7 @@ BouncyBrick::action(float elapsed_time)
 }
 
 void
-BouncyBrick::draw(ViewPort& viewport, int)
+BouncyBrick::draw(Camera& viewport, int)
 {
   Tile::draw(viewport.world2screen(position + Vector(0, offset)), shape);
 }
@@ -135,7 +135,7 @@ FloatingScore::action(float elapsed_time)
 }
 
 void
-FloatingScore::draw(ViewPort& viewport, int )
+FloatingScore::draw(Camera& viewport, int )
 {
   gold_text->draw(str, viewport.world2screen(position));
 }
@@ -174,7 +174,7 @@ Trampoline::write(LispWriter& writer)
 }
 
 void
-Trampoline::draw(ViewPort& viewport, int )
+Trampoline::draw(Camera& viewport, int )
 {
   img_trampoline[frame]->draw(viewport.world2screen(Vector(base.x, base.y)));
   frame = 0;
@@ -264,8 +264,10 @@ Trampoline::collision(void *p_c_object, int c_object, CollisionType type)
         else
           frame = 0;
 
-        if (squish_amount < 20)
+        if (squish_amount < 20) {
           pplayer_c->physic.set_velocity_y(power);
+          pplayer_c->fall_mode = Player::TRAMPOLINE_JUMP;
+        }
         else if (pplayer_c->physic.get_velocity_y() < 0)
           pplayer_c->physic.set_velocity_y(-squish_amount/32);
       }
@@ -316,7 +318,7 @@ FlyingPlatform::write(LispWriter& writer)
 }
 
 void
-FlyingPlatform::draw(ViewPort& viewport, int )
+FlyingPlatform::draw(Camera& viewport, int )
 {
 img_flying_platform->draw(viewport.world2screen(Vector(base.x, base.y)));
 }
index bc0d0e7..ff2e31e 100644 (file)
@@ -42,9 +42,7 @@ class BouncyDistro : public GameObject, public Drawable
 public:
   BouncyDistro(DisplayManager& displaymanager, const Vector& pos);
   virtual void action(float elapsed_time);
-  virtual void draw(ViewPort& viewport, int layer);
-  virtual std::string type() const
-  { return "BouncyDistro"; };
+  virtual void draw(Camera& viewport, int layer);
 
 private:
   Vector position;
@@ -65,10 +63,7 @@ public:
       const Vector& pos, const Vector& movement);
 
   virtual void action(float elapsed_time);
-  virtual void draw(ViewPort& viewport, int layer);
-
-  virtual std::string type() const
-  { return "BrokenBrick"; };
+  virtual void draw(Camera& viewport, int layer);
 
 private:
   Timer timer;
@@ -82,11 +77,8 @@ class BouncyBrick : public GameObject, public Drawable
 public:
   BouncyBrick(DisplayManager& displaymanager, const Vector& pos);
   virtual void action(float elapsed_time);
-  virtual void draw(ViewPort& viewport, int layer);
+  virtual void draw(Camera& viewport, int layer);
   
-  virtual std::string type() const
-  { return "BouncyBrick"; };
-
 private:
   Vector position;
   float offset;   
@@ -100,9 +92,7 @@ public:
   FloatingScore(DisplayManager& displaymanager, const Vector& pos, int s);
   
   virtual void action(float elapsed_time);
-  virtual void draw(ViewPort& viewport, int layer);
-  virtual std::string type() const
-  { return "FloatingScore"; };
+  virtual void draw(Camera& viewport, int layer);
 
 private:
   Vector position;
@@ -117,9 +107,7 @@ public:
  
   virtual void write(LispWriter& writer);
   virtual void action(float frame_ratio);
-  virtual void draw(ViewPort& viewport, int layer);
-  virtual std::string type() const
-  { return "Trampoline"; };
+  virtual void draw(Camera& viewport, int layer);
 
   virtual void collision(const MovingObject& other, int);
   void collision(void *p_c_object, int c_object, CollisionType type);
@@ -139,9 +127,7 @@ public:
  
   virtual void write(LispWriter& writer);
   virtual void action(float frame_ratio);
-  virtual void draw(ViewPort& viewport, int layer);
-  virtual std::string type() const
-  { return "Trampoline"; };
+  virtual void draw(Camera& viewport, int layer);
 
   virtual void collision(const MovingObject& other, int);
   void collision(void *p_c_object, int c_object, CollisionType type);
index 543bbc3..fdc3433 100644 (file)
@@ -19,6 +19,7 @@
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 #include <map>
+#include <typeinfo>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -942,8 +943,7 @@ void le_drawlevel()
   Uint8 a;
 
   /* Draw the real background */
-  le_world->background->draw(le_world->displaymanager.get_viewport(),
-      LAYER_BACKGROUND0);
+  le_world->background->draw(*le_world->camera, LAYER_BACKGROUND0);
 
   if(le_current.IsTile())
   {
@@ -1012,7 +1012,7 @@ void le_drawlevel()
       continue;
     
     /* to support frames: img_bsod_left[(frame / 5) % 4] */
-    ViewPort viewport;
+    Camera viewport;
     viewport.set_translation(Vector(pos_x, pos_y));
     badguy->draw(viewport, 0);
   }
@@ -1028,7 +1028,8 @@ void le_change_object_properties(GameObject *pobj)
   Menu* object_properties_menu = new Menu();
   bool loop = true;
 
-  object_properties_menu->additem(MN_LABEL,pobj->type() + " Properties",0,0);
+  std::string type = typeid(pobj).name();
+  object_properties_menu->additem(MN_LABEL, type + " Properties",0,0);
   object_properties_menu->additem(MN_HL,"",0,0);
 
   BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
@@ -1510,15 +1511,17 @@ void le_checkevents()
             if(le_current.IsObject())
             {
               le_level_changed  = true;
-              std::string type = le_current.obj->type();
+              BadGuy* pbadguy = dynamic_cast<BadGuy*>(le_current.obj);
 
-              if(type == "BadGuy")
+              if(pbadguy)
               {
-                ViewPort viewport(le_world->displaymanager.get_viewport());
+                Camera& camera = *le_world->camera;
                 DisplayManager dummy;
-                BadGuy* pbadguy = dynamic_cast<BadGuy*>(le_current.obj);
 
-                le_world->bad_guys.push_back(new BadGuy(dummy, pbadguy->kind, cursor_x + viewport.get_translation().x, cursor_y + viewport.get_translation().y));
+                le_world->bad_guys.push_back(
+                    new BadGuy(dummy, pbadguy->kind,
+                      cursor_x + camera.get_translation().x,
+                      cursor_y + camera.get_translation().y));
                 le_world->gameobjects.push_back(le_world->bad_guys.back());
               }
             }
@@ -1678,11 +1681,11 @@ void le_change(float x, float y, int tm, unsigned int c)
       /* if there is a bad guy over there, remove it */
       // XXX TODO
       for(std::vector<GameObject*>::iterator it = le_world->gameobjects.begin();
-            it != le_world->gameobjects.end(); ++it)
-        if ((*it)->type() == "BadGuy")
+            it != le_world->gameobjects.end(); ++it) {
+        BadGuy* badguy = dynamic_cast<BadGuy*>((*it));
+        if (badguy)
         {
-          BadGuy* pbadguy = dynamic_cast<BadGuy*>((*it));
-          if(rectcollision(cursor_base, pbadguy->base))
+          if(rectcollision(cursor_base, badguy->base))
           {
             delete (*it);
             //le_world->bad_guys.erase(it);
@@ -1690,6 +1693,7 @@ void le_change(float x, float y, int tm, unsigned int c)
             break;
           }
         }
+      }
 
       break;
     case SQUARE:
@@ -1724,9 +1728,9 @@ void le_change(float x, float y, int tm, unsigned int c)
       for(std::vector<GameObject*>::iterator it = le_world->gameobjects.begin();
           it != le_world->gameobjects.end(); ++it /* will be at end of loop */)
       {
-        if ((*it)->type() == "BadGuy")
+        MovingObject* pmobject = dynamic_cast<MovingObject*> (*it);       
+        if (pmobject)
         {
-          MovingObject* pmobject = dynamic_cast<MovingObject*> (*it);
           if(pmobject->base.x/32 >= x1 && pmobject->base.x/32 <= x2
               && pmobject->base.y/32 >= y1 && pmobject->base.y/32 <= y2)
           {
index 8370536..7604d32 100644 (file)
@@ -25,7 +25,7 @@
 #include "world.h"
 #include "level.h"
 #include "scene.h"
-#include "viewport.h"
+#include "camera.h"
 #include "display_manager.h"
 
 ParticleSystem::ParticleSystem(DisplayManager& displaymanager)
@@ -44,7 +44,7 @@ ParticleSystem::~ParticleSystem()
     }
 }
 
-void ParticleSystem::draw(ViewPort& viewport, int layer)
+void ParticleSystem::draw(Camera& viewport, int layer)
 {
     std::vector<Particle*>::iterator i;
     for(i = particles.begin(); i != particles.end(); ++i) {
index 4f21a5c..8bd117a 100644 (file)
@@ -48,7 +48,7 @@ public:
     ParticleSystem(DisplayManager& displaymanager);
     virtual ~ParticleSystem();
     
-    virtual void draw(ViewPort& view, int layer);
+    virtual void draw(Camera& view, int layer);
 
 protected:
     class Particle
index e8b4c2c..7cae89b 100644 (file)
@@ -101,6 +101,8 @@ Player::init()
   duck = false;
 
   dying   = DYING_NOT;
+  last_ground_y = 0;
+  fall_mode = ON_GROUND;
   jumping = false;
   can_jump = true;
   butt_jump = false;
@@ -415,6 +417,17 @@ Player::handle_horizontal_input()
 void
 Player::handle_vertical_input()
 {
+  // set fall mode...
+  if(on_ground()) {
+    fall_mode = ON_GROUND;
+    last_ground_y = base.y;
+  } else {
+    if(base.y > last_ground_y)
+      fall_mode = FALLING;
+    else if(fall_mode == ON_GROUND)
+      fall_mode = JUMPING;
+  }
+
   // Press jump key
   if(input.up == DOWN && can_jump && on_ground())
     {
@@ -596,7 +609,7 @@ Player::grabdistros()
 }
 
 void
-Player::draw(ViewPort& viewport, int layer)
+Player::draw(Camera& viewport, int layer)
 {
   PlayerSprite* sprite;
           
@@ -857,9 +870,9 @@ Player::is_dying()
 bool Player::is_dead()
 {
   float scroll_x =
-    World::current()->displaymanager.get_viewport().get_translation().x;
+    World::current()->camera->get_translation().x;
   float scroll_y =
-    World::current()->displaymanager.get_viewport().get_translation().y;
+    World::current()->camera->get_translation().y;
   if(base.y > screen->h + scroll_y || base.y > World::current()->get_level()->height*32 ||
       base.x < scroll_x - AUTOSCROLL_DEAD_INTERVAL)  // can happen in auto-scrolling
     return true;
@@ -877,7 +890,7 @@ Player::remove_powerups()
 }
 
 void
-Player::check_bounds(ViewPort& viewport,
+Player::check_bounds(Camera& viewport,
     bool back_scrolling, bool hor_autoscroll)
 {
   /* Keep tux in bounds: */
index 95b1a56..04473f2 100644 (file)
@@ -112,6 +112,7 @@ class Player : public MovingObject, public Drawable
 public:
   enum HurtMode { KILL, SHRINK };
   enum Power { NONE_POWER, FIRE_POWER, ICE_POWER };
+  enum FallMode { ON_GROUND, JUMPING, TRAMPOLINE_JUMP, FALLING };
 
   player_input_type  input;
   int got_power;
@@ -123,6 +124,9 @@ public:
   Direction dir;
   Direction old_dir;
 
+  float last_ground_y;
+  FallMode fall_mode;
+
   bool jumping;
   bool can_jump;
   bool butt_jump;
@@ -148,18 +152,16 @@ public:
   void grabdistros();
 
   virtual void action(float elapsed_time);
-  virtual void draw(ViewPort& viewport, int layer);
+  virtual void draw(Camera& viewport, int layer);
   virtual void collision(const MovingObject& other_object,
       int collision_type);
-  virtual std::string type() const
-  { return "Player"; }
 
   void collision(void* p_c_object, int c_object);
   void kill(HurtMode mode);
   void is_dying();
   bool is_dead();
   void player_remove_powerups();
-  void check_bounds(ViewPort& viewport, bool back_scrolling, bool hor_autoscroll);
+  void check_bounds(Camera& viewport, bool back_scrolling, bool hor_autoscroll);
   bool on_ground();
   bool under_solid();
   bool tiles_on_air(int tiles);
index b2fffe5..6bbbc7c 100644 (file)
@@ -96,9 +96,9 @@ Bullet::action(float elapsed_time)
     physic.set_velocity_y(-9);
 
   float scroll_x =
-    World::current()->displaymanager.get_viewport().get_translation().x;
+    World::current()->camera->get_translation().x;
   float scroll_y =
-    World::current()->displaymanager.get_viewport().get_translation().y;
+    World::current()->camera->get_translation().y;
   if (base.x < scroll_x ||
       base.x > scroll_x + screen->w ||
       base.y < scroll_y ||
@@ -112,7 +112,7 @@ Bullet::action(float elapsed_time)
 }
 
 void 
-Bullet::draw(ViewPort& viewport, int )
+Bullet::draw(Camera& viewport, int )
 {
   if(kind == FIRE_BULLET)
     img_firebullet->draw(viewport.world2screen(Vector(base.x, base.y)));
@@ -187,9 +187,9 @@ Upgrade::action(float elapsed_time)
 
   /* Away from the screen? Kill it! */
   float scroll_x =
-    World::current()->displaymanager.get_viewport().get_translation().x;
+    World::current()->camera->get_translation().x;
   float scroll_y =                                                        
-    World::current()->displaymanager.get_viewport().get_translation().y;
+    World::current()->camera->get_translation().y;
   
   if(base.x < scroll_x - X_OFFSCREEN_DISTANCE ||
       base.x > scroll_x + screen->w + X_OFFSCREEN_DISTANCE ||
@@ -243,7 +243,7 @@ Upgrade::action(float elapsed_time)
 }
 
 void
-Upgrade::draw(ViewPort& viewport, int)
+Upgrade::draw(Camera& viewport, int)
 {
   SDL_Rect dest;
 
index 5ea0d59..304d209 100644 (file)
@@ -53,14 +53,11 @@ public:
   virtual ~Upgrade();
   
   virtual void action(float frame_ratio);
-  virtual void draw(ViewPort& viewport, int layer);
+  virtual void draw(Camera& viewport, int layer);
 
   virtual void collision(const MovingObject& other, int);
   void collision(void* p_c_object, int c_object, CollisionType type);
 
-  virtual std::string type() const
-  { return "Upgrade"; };
-  
 private:
   void bump(Player* player);
 };
@@ -77,12 +74,10 @@ public:
       int kind);
   
   virtual void action(float frame_ratio);
-  virtual void draw(ViewPort& viewport, int layer);
+  virtual void draw(Camera& viewport, int layer);
   void collision(int c_object);
 
   virtual void collision(const MovingObject& other_object, int type);
-  virtual std::string type() const
-  { return "Bullet"; };
 
   int kind;        
   
index 1af2fb5..bb6a0ba 100644 (file)
@@ -42,7 +42,7 @@ TileMap::action(float )
 }
 
 void
-TileMap::draw(ViewPort& viewport, int layer)
+TileMap::draw(Camera& viewport, int layer)
 {
   std::vector<unsigned int>* tiles;
   switch(layer) {
index 334a7e3..a1cc142 100644 (file)
@@ -34,9 +34,7 @@ public:
   virtual ~TileMap();
 
   virtual void action(float elapsed_time);
-  virtual void draw(ViewPort& viewport, int layer);
-  virtual std::string type() const
-  { return "TileMap"; }
+  virtual void draw(Camera& viewport, int layer);
   
 private:
   Level* level;
diff --git a/src/viewport.cpp b/src/viewport.cpp
deleted file mode 100644 (file)
index 658a9e5..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-//  $Id$
-//
-//  SuperTux -  A Jump'n Run
-//  Copyright (C) 2004 Matthias Braun <matze@braunis.de
-//
-//  This program is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU General Public License
-//  as published by the Free Software Foundation; either version 2
-//  of the License, or (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-//  GNU General Public License for more details.
-//
-//  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 "viewport.h"
-
-ViewPort::ViewPort()
-{
-}
-
-ViewPort::~ViewPort()
-{
-}
-
-void
-ViewPort::set_translation(const Vector& newtranslation)
-{
-  translation = newtranslation;
-}
-
diff --git a/src/viewport.h b/src/viewport.h
deleted file mode 100644 (file)
index b7a12ac..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-//  $Id$
-//
-//  SuperTux -  A Jump'n Run
-//  Copyright (C) 2004 Matthias Braun <matze@braunis.de
-//
-//  This program is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU General Public License
-//  as published by the Free Software Foundation; either version 2
-//  of the License, or (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-//  GNU General Public License for more details.
-//
-//  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.
-#ifndef __VIEWPORT_H__
-#define __VIEWPORT_H__
-
-#include "vector.h"
-
-class ViewPort
-{
-public:
-  ViewPort();
-  ~ViewPort();
-
-  Vector world2screen(const Vector& worldpos) const
-  {
-    return worldpos - translation;
-  }
-    
-  /** returns the current translation (=scroll) vector of the viewport */
-  const Vector& get_translation() const
-  { return translation; }
-
-  void set_translation(const Vector& translation);
-
-private:
-  Vector translation;
-};
-
-#endif
-
index 91acb66..01a998f 100644 (file)
@@ -33,7 +33,7 @@
 #include "tile.h"
 #include "resources.h"
 #include "gameobjs.h"
-#include "viewport.h"
+#include "camera.h"
 #include "display_manager.h"
 #include "background.h"
 #include "tilemap.h"
@@ -52,11 +52,11 @@ World::World(const std::string& filename)
   level->load(filename, this);
 
   tux = new Player(displaymanager);
-  gameobjects.push_back(tux);
+  add_object(tux);
 
   set_defaults();
 
-  get_level()->load_gfx();
+  level->load_gfx();
   // add background
   activate_particle_systems();
   background = new Background(displaymanager);
@@ -65,14 +65,17 @@ World::World(const std::string& filename)
   } else {
     background->set_gradient(level->bkgd_top, level->bkgd_bottom);
   }
-  gameobjects.push_back(background);
+  add_object(background);
 
   // add tilemap
-  gameobjects.push_back(new TileMap(displaymanager, get_level()));
-  get_level()->load_song();
+  add_object(new TileMap(displaymanager, level));
+  level->load_song();
 
   apply_bonuses();
 
+  camera = new Camera(tux, level);
+  add_object(camera);
+
   scrolling_timer.init(true);
 }
 
@@ -217,7 +220,7 @@ void
 World::draw()
 {
   /* Draw objects */
-  displaymanager.draw();
+  displaymanager.draw(*camera);
 }
 
 void
@@ -229,9 +232,8 @@ World::action(float elapsed_time)
   for(size_t i = 0; i < gameobjects.size(); ++i)
     gameobjects[i]->action(elapsed_time);
 
-  tux->check_bounds(displaymanager.get_viewport(),
+  tux->check_bounds(*camera,
       level->back_scrolling, (bool)level->hor_autoscroll_speed);
-  scrolling(elapsed_time);                                                      
 
   /* Handle all possible collisions. */
   collision_handler();
@@ -288,35 +290,59 @@ World::action(float elapsed_time)
 // should be less than screen->h/2 (300)
 #define Y_SPACE 250
 
+static const float max_speed_y = 1.4;
+
 // the time it takes to move the camera (in ms)
 #define CHANGE_DIR_SCROLL_SPEED 2000
 
+static const float EPSILON = .0001;
+
+#if 0
 /* This functions takes cares of the scrolling */
 void World::scrolling(float elapsed_time)
 {
-  float scroll_x = displaymanager.get_viewport().get_translation().x;
-  float scroll_y = displaymanager.get_viewport().get_translation().y;
+  if(elapsed_time < EPSILON)
+    return;
+  
+  Vector scroll = displaymanager.get_viewport().get_translation();
+  bool do_y_scrolling = true;
+
+  if(tux->dying)
+    do_y_scrolling = false;
   
   /* Y-axis scrolling */
+  if(do_y_scrolling) {
+    float target_y;
+    // upwards we target the y position of the platforms tux stands on
+    if(tux->fall_mode != Player::FALLING)
+      target_y = tux->last_ground_y + tux->base.height;
+    else
+      target_y = tux->base.y + tux->base.height;
 
-  float tux_pos_y = tux->base.y + (tux->base.height/2);
+    float delta_y = scroll.y - (target_y - (screen->h/2));
+    float speed_y = delta_y / elapsed_time;
 
-  if(level->height > VISIBLE_TILES_Y-1 && !tux->dying)
-    {
-    if (scroll_y < tux_pos_y - (screen->h - Y_SPACE))
-      scroll_y = tux_pos_y - (screen->h - Y_SPACE);
-    else if (scroll_y > tux_pos_y - Y_SPACE)
-      scroll_y = tux_pos_y - Y_SPACE;
-    }
+    float max = max_speed_y;
+    if(fabsf(delta_y) > float(screen->h)/5.0)
+      max *= 5;
+    
+    if(speed_y > max)
+      speed_y = max;
+    else if(speed_y < -max)
+      speed_y = -max;
 
-  // this code prevent the screen to scroll before the start or after the level's end
-  if(scroll_y > level->height * 32 - screen->h)
-    scroll_y = level->height * 32 - screen->h;
-  if(scroll_y < 0)
-    scroll_y = 0;
+    scroll.y -= speed_y * elapsed_time;
+    
+    // don't scroll before the start or after the level's end
+    if(scroll.y > level->height * 32 - screen->h)
+      scroll.y = level->height * 32 - screen->h;
+    if(scroll.y < 0)
+      scroll.y = 0;
+  }
 
   /* X-axis scrolling */
 
+#if 0
   /* Auto scrolling */
   if(level->hor_autoscroll_speed)
   {
@@ -324,7 +350,7 @@ void World::scrolling(float elapsed_time)
     displaymanager.get_viewport().set_translation(Vector(scroll_x, scroll_y));
     return;
   }
-
+#endif
 
   /* Horizontal backscrolling */
   float tux_pos_x = tux->base.x + (tux->base.width/2);
@@ -371,31 +397,32 @@ void World::scrolling(float elapsed_time)
     float number = 2.5/(elapsed_time * CHANGE_DIR_SCROLL_SPEED/1000)*exp((CHANGE_DIR_SCROLL_SPEED-scrolling_timer.get_left())/1400.);
     if(left) number *= -1.;
 
-    scroll_x += number
+    scroll.x += number
            + constant1 * tux->physic.get_velocity_x() * elapsed_time
            + constant2 * tux->physic.get_acceleration_x() * elapsed_time *
             elapsed_time;
 
-    if ((right && final_scroll_x - scroll_x < 0) || (left && final_scroll_x - scroll_x > 0))
-      scroll_x = final_scroll_x;
-    
+    if ((right && final_scroll_x - scroll.x < 0) || (left && final_scroll_x -
+          scroll.x > 0))
+      scroll.x = final_scroll_x;
   }
   else
   {
-    if (right && scroll_x < tux_pos_x - (screen->w - X_SPACE))
-      scroll_x = tux_pos_x - (screen->w - X_SPACE);
-    else if (left && scroll_x > tux_pos_x - X_SPACE && level->back_scrolling)
-      scroll_x = tux_pos_x - X_SPACE;
+    if (right && scroll.x < tux_pos_x - (screen->w - X_SPACE))
+      scroll.x = tux_pos_x - (screen->w - X_SPACE);
+    else if (left && scroll.x > tux_pos_x - X_SPACE && level->back_scrolling)
+      scroll.x = tux_pos_x - X_SPACE;
   }
 
-  // this code prevent the screen to scroll before the start or after the level's end
-  if(scroll_x > level->width * 32 - screen->w)
-    scroll_x = level->width * 32 - screen->w;
-  if(scroll_x < 0)
-    scroll_x = 0;
+  // don't scroll before the start or after the level's end
+  if(scroll.x > level->width * 32 - screen->w)
+    scroll.x = level->width * 32 - screen->w;
+  if(scroll.x < 0)
+    scroll.x = 0;
 
-  displaymanager.get_viewport().set_translation(Vector(scroll_x, scroll_y));
+  displaymanager.get_viewport().set_translation(scroll);
 }
+#endif
 
 void
 World::collision_handler()
index 80ed880..661cb08 100644 (file)
@@ -64,6 +64,7 @@ public:
   std::vector<Bullet*> bullets;
   std::vector<GameObject*> gameobjects;
 
+  Camera* camera;
   DisplayManager displaymanager;
 
 public:
@@ -84,7 +85,6 @@ public:
 
   void draw();
   void action(float elapsed_time);
-  void scrolling(float elapsed_time);   // camera scrolling
 
   void play_music(int musictype);
   int get_music_type();