music_manager.h \
musicref.cpp \
musicref.h \
-viewport.cpp \
-viewport.h \
+camera.cpp \
+camera.h \
game_object.cpp \
game_object.h \
display_manager.h \
#include "background.h"
#include "globals.h"
-#include "viewport.h"
+#include "camera.h"
#include "display_manager.h"
Background::Background(DisplayManager& displaymanager)
}
void
-Background::draw(ViewPort& viewport, int )
+Background::draw(Camera& viewport, int )
{
if(bgtype == BACKGROUND_GRADIENT) {
drawgradient(gradient_top, gradient_bottom);
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;
#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;
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)
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)
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) {
}
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;
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);
#include "screen.h"
#include "globals.h"
#include "button.h"
-#include "viewport.h"
+#include "camera.h"
Timer Button::popup_timer;
if(drawable)
{
- ViewPort viewport;
+ Camera viewport;
viewport.set_translation(Vector(rect.x, rect.y));
drawable->draw(viewport, 0);
}
--- /dev/null
+// $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
+}
--- /dev/null
+// $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
+
}
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);
}
#include <vector>
#include "drawable.h"
-#include "viewport.h"
+#include "camera.h"
// some constants for predefined layer values
enum {
void remove_drawable(Drawable* object);
- void draw();
-
- ViewPort& get_viewport()
- { return viewport; }
+ void draw(Camera& camera);
private:
class DrawingQueueEntry {
typedef std::vector<DrawingQueueEntry> DisplayList;
DisplayList displaylist;
- ViewPort viewport;
};
#endif
#ifndef __DRAWABLE_H__
#define __DRAWABLE_H__
-class ViewPort;
+class Camera;
/** interface for all game objects that can be drawn on screen.
*/
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
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.
char str[60];
- ViewPort dummy;
+ Camera dummy;
world->background->draw(dummy, LAYER_BACKGROUND0);
sprintf(str, "%s", world->get_level()->name.c_str());
{
char str[80];
- ViewPort dummy;
+ Camera dummy;
world->background->draw(dummy, LAYER_BACKGROUND0);
blue_text->drawf("Result:", 0, 200, A_HMIDDLE, A_TOP, 1);
}
void
-BouncyDistro::draw(ViewPort& viewport, int )
+BouncyDistro::draw(Camera& viewport, int )
{
img_distro[0]->draw(viewport.world2screen(position));
}
}
void
-BrokenBrick::draw(ViewPort& viewport, int )
+BrokenBrick::draw(Camera& viewport, int )
{
SDL_Rect src, dest;
src.x = rand() % 16;
}
void
-BouncyBrick::draw(ViewPort& viewport, int)
+BouncyBrick::draw(Camera& viewport, int)
{
Tile::draw(viewport.world2screen(position + Vector(0, offset)), shape);
}
}
void
-FloatingScore::draw(ViewPort& viewport, int )
+FloatingScore::draw(Camera& viewport, int )
{
gold_text->draw(str, viewport.world2screen(position));
}
}
void
-Trampoline::draw(ViewPort& viewport, int )
+Trampoline::draw(Camera& viewport, int )
{
img_trampoline[frame]->draw(viewport.world2screen(Vector(base.x, base.y)));
frame = 0;
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);
}
}
void
-FlyingPlatform::draw(ViewPort& viewport, int )
+FlyingPlatform::draw(Camera& viewport, int )
{
img_flying_platform->draw(viewport.world2screen(Vector(base.x, base.y)));
}
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;
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;
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;
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;
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);
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);
// 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>
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())
{
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);
}
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);
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());
}
}
/* 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);
break;
}
}
+ }
break;
case SQUARE:
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)
{
#include "world.h"
#include "level.h"
#include "scene.h"
-#include "viewport.h"
+#include "camera.h"
#include "display_manager.h"
ParticleSystem::ParticleSystem(DisplayManager& displaymanager)
}
}
-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) {
ParticleSystem(DisplayManager& displaymanager);
virtual ~ParticleSystem();
- virtual void draw(ViewPort& view, int layer);
+ virtual void draw(Camera& view, int layer);
protected:
class Particle
duck = false;
dying = DYING_NOT;
+ last_ground_y = 0;
+ fall_mode = ON_GROUND;
jumping = false;
can_jump = true;
butt_jump = false;
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())
{
}
void
-Player::draw(ViewPort& viewport, int layer)
+Player::draw(Camera& viewport, int layer)
{
PlayerSprite* sprite;
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;
}
void
-Player::check_bounds(ViewPort& viewport,
+Player::check_bounds(Camera& viewport,
bool back_scrolling, bool hor_autoscroll)
{
/* Keep tux in bounds: */
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;
Direction dir;
Direction old_dir;
+ float last_ground_y;
+ FallMode fall_mode;
+
bool jumping;
bool can_jump;
bool butt_jump;
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);
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 ||
}
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)));
/* 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 ||
}
void
-Upgrade::draw(ViewPort& viewport, int)
+Upgrade::draw(Camera& viewport, int)
{
SDL_Rect dest;
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);
};
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;
}
void
-TileMap::draw(ViewPort& viewport, int layer)
+TileMap::draw(Camera& viewport, int layer)
{
std::vector<unsigned int>* tiles;
switch(layer) {
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;
+++ /dev/null
-// $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;
-}
-
+++ /dev/null
-// $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
-
#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"
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);
} 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);
}
World::draw()
{
/* Draw objects */
- displaymanager.draw();
+ displaymanager.draw(*camera);
}
void
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();
// 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)
{
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);
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()
std::vector<Bullet*> bullets;
std::vector<GameObject*> gameobjects;
+ Camera* camera;
DisplayManager displaymanager;
public:
void draw();
void action(float elapsed_time);
- void scrolling(float elapsed_time); // camera scrolling
void play_music(int musictype);
int get_music_type();