1// SuperTux - Unstable Tile
2// Copyright (C) 2006 Matthias Braun <matze@braunis.de>
3// Copyright (C) 2006 Christoph Sommer <christoph.sommer@2006.expires.deltadevelopment.de>
4// Copyright (C) 2010 Florian Forster <supertux at octo.it>
5//
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10//
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.
15//
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <http://www.gnu.org/licenses/>.
18
19#include "object/unstable_tile.hpp"
20
21#include "object/explosion.hpp"
22#include "object/player.hpp"
23#include "sprite/sprite.hpp"
24#include "supertux/constants.hpp"
25
26UnstableTile::UnstableTile(const ReaderMapping& mapping) :
27 MovingSprite(mapping, "images/objects/unstable_tile/snow.sprite", LAYER_TILES, COLGROUP_STATIC),
28 physic(),
29 state(STATE_NORMAL),
30 slowfall_timer()
31{
32 m_sprite->set_action("normal");
33 physic.set_gravity_modifier(.98f);
34 physic.enable_gravity(false);
35}
36
37HitResponse
38UnstableTile::collision(GameObject& other, const CollisionHit& )
39{
40 if (state == STATE_NORMAL) {
41 Player* player = dynamic_cast<Player*> (&other);
42 if (player != nullptr &&
43 player->get_bbox().get_bottom() < m_col.m_bbox.get_top() + SHIFT_DELTA) {
44 shake ();
45 }
46
47 if (dynamic_cast<Explosion*> (&other)) {
48 shake ();
49 }
50 }
51 return FORCE_MOVE;
52}
53
54void UnstableTile::shake()
55{
56 if (state != STATE_NORMAL)
57 return;
58
59 if (m_sprite->has_action ("shake")) {
60 state = STATE_SHAKE;
61 set_action ("shake", /* loops = */ 1);
62 }
63 else {
64 dissolve ();
65 }
66}
67
68void UnstableTile::dissolve()
69{
70 if ((state != STATE_NORMAL) && (state != STATE_SHAKE))
71 return;
72
73 if (m_sprite->has_action ("dissolve")) {
74 state = STATE_DISSOLVE;
75 set_action ("dissolve", /* loops = */ 1);
76 }
77 else {
78 slow_fall ();
79 }
80}
81
82void UnstableTile::slow_fall()
83{
84 /* Only enter slow-fall if neither shake nor dissolve is available. */
85 if (state != STATE_NORMAL) {
86 fall_down ();
87 return;
88 }
89
90 if (m_sprite->has_action ("fall-down")) {
91 state = STATE_SLOWFALL;
92 set_action ("fall-down", /* loops = */ 1);
93 physic.set_gravity_modifier (.10f);
94 physic.enable_gravity (true);
95 slowfall_timer = 0.5f; /* Fall slowly for half a second. */
96 }
97 else {
98 remove_me ();
99 }
100}
101
102void UnstableTile::fall_down()
103{
104 if (state == STATE_FALL)
105 return;
106
107 if (m_sprite->has_action ("fall-down")) {
108 state = STATE_FALL;
109 set_action ("fall-down", /* loops = */ 1);
110 physic.set_gravity_modifier (.98f);
111 physic.enable_gravity (true);
112 }
113 else {
114 remove_me ();
115 }
116}
117
118void
119UnstableTile::update(float dt_sec)
120{
121 switch (state)
122 {
123 case STATE_NORMAL:
124 break;
125
126 case STATE_SHAKE:
127 if (m_sprite->animation_done())
128 dissolve ();
129 break;
130
131 case STATE_DISSOLVE:
132 if (m_sprite->animation_done()) {
133 /* dissolving is done. Set to non-solid. */
134 set_group (COLGROUP_DISABLED);
135 fall_down ();
136 }
137 break;
138
139 case STATE_SLOWFALL:
140 if (slowfall_timer >= dt_sec)
141 slowfall_timer -= dt_sec;
142 else /* Switch to normal falling procedure */
143 fall_down ();
144 m_col.m_movement = physic.get_movement (dt_sec);
145 break;
146
147 case STATE_FALL:
148 if (m_sprite->animation_done())
149 remove_me ();
150 else
151 m_col.m_movement = physic.get_movement (dt_sec);
152 break;
153 }
154}
155
156/* EOF */
157