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 /****** Vertical Scrolling part ******/
84 bool do_y_scrolling = true;
86 if(player->dying || level->height == 19)
87 do_y_scrolling = false;
90 // target_y is the high we target our scrolling at. This is not always the
91 // high of the player, but if he is jumping upwards we should use the
92 // position where he last touched the ground.
94 if(player->fall_mode == Player::JUMPING)
95 target_y = player->last_ground_y + player->base.height;
97 target_y = player->base.y + player->base.height;
99 // delta_y is the distance we'd have to travel to directly reach target_y
100 float delta_y = translation.y - (target_y - screen->h/2);
101 // speed is the speed the camera would need to reach target_y in this frame
102 float speed_y = delta_y / elapsed_time;
104 // limit the camera speed when jumping upwards
105 if(player->fall_mode != Player::FALLING
106 && player->fall_mode != Player::TRAMPOLINE_JUMP) {
107 if(speed_y > max_speed_y)
108 speed_y = max_speed_y;
109 else if(speed_y < -max_speed_y)
110 speed_y = -max_speed_y;
113 // finally scroll with calculated speed
114 translation.y -= speed_y * elapsed_time;
116 // don't scroll before the start or after the level's end
117 if(translation.y > level->height * 32 - screen->h)
118 translation.y = level->height * 32 - screen->h;
119 if(translation.y < 0)
123 /****** Horizontal scrolling part *******/
125 // our camera is either in leftscrolling, rightscrolling or nonscrollingmode.
127 // when suddenly changing directions while scrolling into the other direction.
128 // abort scrolling, since tux might be going left/right at a relatively small
129 // part of the map (like when jumping upwards)
130 if((player->dir == ::LEFT && scrollchange == RIGHT)
131 || (player->dir == ::RIGHT && scrollchange == LEFT))
133 // when in left 1/3rd of screen scroll left
134 if(player->base.x < translation.x + screen->w/3 && level->back_scrolling)
136 // scroll right when in right 1/3rd of screen
137 else if(player->base.x > translation.x + screen->w/3*2)
138 scrollchange = RIGHT;
140 // calculate our scroll target depending on scroll mode
142 if(scrollchange == LEFT)
143 target_x = player->base.x - screen->w/3*2;
144 else if(scrollchange == RIGHT)
145 target_x = player->base.x - screen->w/3;
147 target_x = translation.x;
149 // that's the distance we would have to travel to reach target_x
150 float delta_x = translation.x - target_x;
151 // the speed we'd need to travel to reach target_x in this frame
152 float speed_x = delta_x / elapsed_time;
155 float maxv = 1 + fabsf(player->physic.get_velocity_x() * 1.3);
158 else if(speed_x < -maxv)
162 translation.x -= speed_x * elapsed_time;
164 // don't scroll before the start or after the level's end
165 if(translation.x > level->width * 32 - screen->w)
166 translation.x = level->width * 32 - screen->w;
167 if(translation.x < 0)
172 Camera::scroll_autoscroll(float elapsed_time)