3 // SuperTux - A Jump'n Run
4 // Copyright (C) 2004 Matthias Braun <matze@braunis.de
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 #include "lispwriter.h"
27 Camera::Camera(Player* newplayer, Level* newlevel)
28 : player(newplayer), level(newlevel), scrollchange(NONE)
41 Camera::set_translation(const Vector& newtranslation)
43 translation = newtranslation;
47 Camera::write(LispWriter& writer)
49 writer.start_list("camera");
52 writer.write_string("mode", "normal");
53 } else if(mode == AUTOSCROLL) {
54 writer.write_string("mode", "autoscroll");
55 } else if(mode == MANUAL) {
56 writer.write_string("mode", "manual");
59 writer.end_list("camera");
62 static const float EPSILON = .00001;
63 static const float max_speed_y = 1.4;
66 Camera::action(float elapsed_time)
69 scroll_normal(elapsed_time);
70 else if(mode == AUTOSCROLL)
71 scroll_autoscroll(elapsed_time);
75 Camera::scroll_normal(float elapsed_time)
77 assert(level != 0 && player != 0);
79 // check that we don't have division by zero later
80 if(elapsed_time < EPSILON)
83 bool do_y_scrolling = true;
85 if(player->dying || level->height == 19)
86 do_y_scrolling = false;
90 if(player->fall_mode == Player::JUMPING)
91 target_y = player->last_ground_y + player->base.height;
93 target_y = player->base.y + player->base.height;
95 float delta_y = translation.y - (target_y - screen->h/2);
96 float speed_y = delta_y / elapsed_time;
98 if(player->fall_mode != Player::FALLING
99 && player->fall_mode != Player::TRAMPOLINE_JUMP) {
100 if(speed_y > max_speed_y)
101 speed_y = max_speed_y;
102 else if(speed_y < -max_speed_y)
103 speed_y = -max_speed_y;
106 translation.y -= speed_y * elapsed_time;
108 // don't scroll before the start or after the level's end
109 if(translation.y > level->height * 32 - screen->h)
110 translation.y = level->height * 32 - screen->h;
111 if(translation.y < 0)
115 if((player->dir == ::LEFT && scrollchange == RIGHT)
116 || (player->dir == ::RIGHT && scrollchange == LEFT))
118 if(player->base.x < translation.x + screen->w/3 && level->back_scrolling)
120 else if(player->base.x > translation.x + screen->w/3*2)
121 scrollchange = RIGHT;
124 if(scrollchange == LEFT)
125 target_x = player->base.x - screen->w/3*2;
126 else if(scrollchange == RIGHT)
127 target_x = player->base.x - screen->w/3;
129 target_x = translation.x;
131 float delta_x = translation.x - target_x;
132 float speed_x = delta_x / elapsed_time;
134 float maxv = 1 + fabsf(player->physic.get_velocity_x() * 1.3);
137 else if(speed_x < -maxv)
140 translation.x -= speed_x * elapsed_time;
142 // don't scroll before the start or after the level's end
143 if(translation.x > level->width * 32 - screen->w)
144 translation.x = level->width * 32 - screen->w;
145 if(translation.x < 0)
150 Camera::scroll_autoscroll(float elapsed_time)