Merged changes from branches/supertux-milestone2-grumbel/ to trunk/supertux/
[supertux.git] / src / object / pneumatic_platform.cpp
1 //  SuperTux - PneumaticPlatform
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 "object/pneumatic_platform.hpp"
18
19 #include "object/player.hpp"
20 #include "object/portable.hpp"
21 #include "supertux/object_factory.hpp"
22 #include "supertux/sector.hpp"
23
24 PneumaticPlatform::PneumaticPlatform(const Reader& reader) :
25   MovingSprite(reader, LAYER_OBJECTS, COLGROUP_STATIC), 
26   master(0), 
27   slave(0), 
28   start_y(0),
29   offset_y(0), 
30   speed_y(0)
31 {
32   start_y = get_pos().y;
33 }
34
35 PneumaticPlatform::PneumaticPlatform(PneumaticPlatform* master) :
36   MovingSprite(*master), 
37   master(master), 
38   slave(this), 
39   start_y(master->start_y),
40   offset_y(-master->offset_y), 
41   speed_y(0)
42 {
43   set_pos(get_pos() + Vector(master->get_bbox().get_width(), 0));
44   master->master = master;
45   master->slave = this;
46 }
47
48 PneumaticPlatform::~PneumaticPlatform() 
49 {
50   if ((this == master) && (master)) {
51     slave->master = 0;
52     slave->slave = 0;
53   }
54   if ((master) && (this == slave)) {
55     master->master = 0;
56     master->slave = 0;
57   }
58   master = 0;
59   slave = 0;
60 }
61
62 HitResponse
63 PneumaticPlatform::collision(GameObject& other, const CollisionHit& )
64 {
65
66   // somehow the hit parameter does not get filled in, so to determine (hit.top == true) we do this:
67   MovingObject* mo = dynamic_cast<MovingObject*>(&other);
68   if (!mo) return FORCE_MOVE;
69   if ((mo->get_bbox().p2.y) > (get_bbox().p1.y + 2)) return FORCE_MOVE;
70
71   Player* pl = dynamic_cast<Player*>(mo);
72   if (pl) {
73     if (pl->is_big()) contacts.insert(0);
74     Portable* po = pl->get_grabbed_object();
75     MovingObject* pomo = dynamic_cast<MovingObject*>(po);
76     if (pomo) contacts.insert(pomo);
77   }
78
79   contacts.insert(&other);
80   return FORCE_MOVE;
81 }
82
83 void
84 PneumaticPlatform::update(float elapsed_time)
85 {
86   if (!slave) {
87     Sector::current()->add_object(new PneumaticPlatform(this));
88     return;
89   }
90   if (!master) {
91     return;
92   }
93   if (this == slave) {
94     offset_y = -master->offset_y;
95     movement = Vector(0, (start_y + offset_y) - get_pos().y);
96   }
97   if (this == master) {
98     int contact_diff = contacts.size() - slave->contacts.size();
99     contacts.clear();
100     slave->contacts.clear();
101
102     speed_y += ((float)contact_diff * elapsed_time) * 128.0f;
103     speed_y -= (offset_y * elapsed_time * 0.5f);
104     speed_y *= 1 - elapsed_time;
105     offset_y += speed_y * elapsed_time;
106     if (offset_y < -256) { offset_y = -256; speed_y = 0; } 
107     if (offset_y > 256) { offset_y = 256; speed_y = -0; } 
108     movement = Vector(0, (start_y + offset_y) - get_pos().y);
109   }
110 }
111
112 IMPLEMENT_FACTORY(PneumaticPlatform, "pneumatic-platform");
113
114 /* EOF */