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/sector.hpp"
22#include "util/reader_mapping.hpp"
23
24PneumaticPlatformChild::PneumaticPlatformChild(const ReaderMapping& mapping, bool left, PneumaticPlatform& parent) :
25 MovingSprite(mapping, "images/objects/platforms/small.sprite", LAYER_OBJECTS, COLGROUP_STATIC),
26 m_parent(parent),
27 m_left(left),
28 m_contacts()
29{
30 if (!m_left) {
31 set_pos(get_pos() + Vector(get_bbox().get_width(), 0));
32 }
33}
34
35PneumaticPlatformChild::~PneumaticPlatformChild()
36{
37}
38
39void
40PneumaticPlatformChild::update(float dt_sec)
41{
42 const float offset_y = m_left ? m_parent.m_offset_y : -m_parent.m_offset_y;
43 m_col.m_movement = Vector(0, (m_parent.m_start_y + offset_y) - get_pos().y);
44}
45
46HitResponse
47PneumaticPlatformChild::collision(GameObject& other, const CollisionHit& )
48{
49 // somehow the hit parameter does not get filled in, so to determine (hit.top == true) we do this:
50 auto mo = dynamic_cast<MovingObject*>(&other);
51 if (!mo) return FORCE_MOVE;
52 if ((mo->get_bbox().get_bottom()) > (m_col.m_bbox.get_top() + 2)) return FORCE_MOVE;
53
54 auto pl = dynamic_cast<Player*>(mo);
55 if (pl) {
56 if (pl->is_big()) m_contacts.insert(nullptr);
57 auto po = pl->get_grabbed_object();
58 auto pomo = dynamic_cast<MovingObject*>(po);
59 if (pomo) m_contacts.insert(pomo);
60 }
61
62 m_contacts.insert(&other);
63 return FORCE_MOVE;
64}
65
66void PneumaticPlatformChild::editor_delete()
67{
68 // removing a child removes the whole platform
69 m_parent.editor_delete();
70}
71
72PneumaticPlatform::PneumaticPlatform(const ReaderMapping& mapping) :
73 GameObject(mapping),
74 m_pos(),
75 m_sprite_name(),
76 m_start_y(),
77 m_speed_y(0),
78 m_offset_y(0),
79 m_children()
80{
81 mapping.get("x", m_pos.x);
82 mapping.get("y", m_pos.y);
83 mapping.get("sprite", m_sprite_name);
84
85 m_children.push_back(&d_sector->add<PneumaticPlatformChild>(mapping, true, *this));
86 m_children.push_back(&d_sector->add<PneumaticPlatformChild>(mapping, false, *this));
87
88 m_start_y = m_children[0]->get_pos().y;
89}
90
91PneumaticPlatform::~PneumaticPlatform()
92{
93}
94
95void
96PneumaticPlatform::draw(DrawingContext& context)
97{
98}
99
100void
101PneumaticPlatform::update(float dt_sec)
102{
103 const int contact_diff = static_cast<int>(m_children[0]->m_contacts.size()) - static_cast<int>(m_children[1]->m_contacts.size());
104 for (auto& child : m_children) {
105 child->m_contacts.clear();
106 }
107
108 const float gravity = Sector::get().get_gravity();
109
110 m_speed_y += (static_cast<float>(contact_diff) * dt_sec) * 12.8f;
111 m_speed_y -= (m_offset_y * dt_sec * 0.05f);
112 m_speed_y *= 1 - dt_sec;
113
114 m_offset_y += m_speed_y * dt_sec * gravity;
115
116 if (m_offset_y < -256) {
117 m_offset_y = -256;
118 m_speed_y = 0;
119 }
120
121 if (m_offset_y > 256) {
122 m_offset_y = 256;
123 m_speed_y = -0;
124 }
125}
126
127void
128PneumaticPlatform::editor_delete()
129{
130 // remove children
131 for (auto& child : m_children) {
132 child->remove_me();
133 }
134
135 // remove self
136 remove_me();
137}
138
139ObjectSettings
140PneumaticPlatform::get_settings()
141{
142 ObjectSettings result = GameObject::get_settings();
143
144 result.add_sprite(_("Sprite"), &m_sprite_name, "sprite", std::string("images/objects/platforms/small.sprite"));
145 result.add_float(_("X"), &m_pos.x, "x", 0.0f, OPTION_HIDDEN);
146 result.add_float(_("Y"), &m_pos.y, "y", 0.0f, OPTION_HIDDEN);
147
148 return result;
149}
150
151void
152PneumaticPlatform::after_editor_set()
153{
154 GameObject::after_editor_set();
155}
156
157/* EOF */
158