Merged changes from branches/supertux-milestone2-grumbel/ to trunk/supertux/
[supertux.git] / src / trigger / climbable.cpp
1 //  SuperTux - Climbable area
2 //  Copyright (C) 2007 Christoph Sommer <christoph.sommer@2007.expires.deltadevelopment.de>
3 //
4 //  This program is free software: you can redistribute it and/or modify
5 //  it under the terms of the GNU General Public License as published by
6 //  the Free Software Foundation, either version 3 of the License, or
7 //  (at your option) any later version.
8 //
9 //  This program is distributed in the hope that it will be useful,
10 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 //  GNU General Public License for more details.
13 //
14 //  You should have received a copy of the GNU General Public License
15 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
17 #include "trigger/climbable.hpp"
18
19 #include "object/player.hpp"
20 #include "supertux/main.hpp"
21 #include "supertux/object_factory.hpp"
22 #include "util/gettext.hpp"
23 #include "util/reader.hpp"
24
25 namespace {
26 const float GRACE_DX = 8; // how far off may the player's bounding-box be x-wise
27 const float GRACE_DY = 8; // how far off may the player's bounding-box be y-wise
28 const float ACTIVATE_TRY_FOR = 1; // how long to try correcting mis-alignment of player and climbable before giving up
29 const float POSITION_FIX_AX = 50; // x-wise acceleration applied to player when trying to align player and Climbable
30 const float POSITION_FIX_AY = 50; // y-wise acceleration applied to player when trying to align player and Climbable
31 }
32
33 Climbable::Climbable(const Reader& reader)
34   : climbed_by(0)
35 {
36   reader.get("x", bbox.p1.x);
37   reader.get("y", bbox.p1.y);
38   float w = 32, h = 32;
39   reader.get("width", w);
40   reader.get("height", h);
41   bbox.set_size(w, h);
42 }
43
44 Climbable::Climbable(const Rect& area)
45   : climbed_by(0)
46 {
47   bbox = area;
48 }
49
50 Climbable::~Climbable()
51 {
52   if (climbed_by) {
53     climbed_by->stop_climbing(*this);
54     climbed_by = 0;
55   }
56 }
57
58 void 
59 Climbable::update(float /*elapsed_time*/)
60 {
61   if (!climbed_by) return;
62
63   if (!may_climb(*climbed_by)) {
64     climbed_by->stop_climbing(*this);
65     climbed_by = 0;
66   }
67 }
68
69 void
70 Climbable::draw(DrawingContext& context)
71 {
72   if (climbed_by) {
73     context.push_transform();
74     context.set_translation(Vector(0, 0));
75     Vector pos = Vector(0, SCREEN_HEIGHT/2 - normal_font->get_height()/2);
76     context.draw_center_text(normal_font, _("Up we go..."), pos, LAYER_GUI, Climbable::text_color);
77     context.pop_transform();
78   }
79 }
80
81 void
82 Climbable::event(Player& player, EventType type)
83 {
84   if ((type == EVENT_ACTIVATE) || (activate_try_timer.started())) {
85     if(player.get_grabbed_object() == NULL){
86       if(may_climb(player)) {
87         climbed_by = &player;
88         player.start_climbing(*this);
89         activate_try_timer.stop();
90       } else {
91         if (type == EVENT_ACTIVATE) activate_try_timer.start(ACTIVATE_TRY_FOR);
92         if (player.get_bbox().p1.x < get_bbox().p1.x - GRACE_DX) player.add_velocity(Vector(POSITION_FIX_AX,0));
93         if (player.get_bbox().p2.x > get_bbox().p2.x + GRACE_DX) player.add_velocity(Vector(-POSITION_FIX_AX,0));
94         if (player.get_bbox().p1.y < get_bbox().p1.y - GRACE_DY) player.add_velocity(Vector(0,POSITION_FIX_AY));
95         if (player.get_bbox().p2.y > get_bbox().p2.y + GRACE_DY) player.add_velocity(Vector(0,-POSITION_FIX_AY));
96       }
97     }
98   }
99   if(type == EVENT_LOSETOUCH) {
100     player.stop_climbing(*this);
101     climbed_by = 0;
102   }
103 }
104
105 bool
106 Climbable::may_climb(Player& player) 
107 {
108   if (player.get_bbox().p1.x < get_bbox().p1.x - GRACE_DX) return false;
109   if (player.get_bbox().p2.x > get_bbox().p2.x + GRACE_DX) return false;
110   if (player.get_bbox().p1.y < get_bbox().p1.y - GRACE_DY) return false;
111   if (player.get_bbox().p2.y > get_bbox().p2.y + GRACE_DY) return false;
112   return true;
113 }
114
115 IMPLEMENT_FACTORY(Climbable, "climbable");
116
117 /* EOF */