object/unstable_tile.[ch]pp: Implement third state, "shake".
[supertux.git] / src / object / unstable_tile.cpp
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 #include "supertux/object_factory.hpp"
26
27 UnstableTile::UnstableTile(const Reader& lisp) :
28   MovingSprite(lisp, LAYER_TILES, COLGROUP_STATIC), 
29   physic(),
30   state(STATE_NORMAL)
31 {
32   sprite->set_action("normal");
33   physic.set_gravity_modifier (.98);
34   physic.enable_gravity (false);
35 }
36
37 HitResponse
38 UnstableTile::collision(GameObject& other, const CollisionHit& )
39 {
40   if(state == STATE_NORMAL) {
41     Player* player = dynamic_cast<Player*> (&other);
42     if(player != NULL &&
43        player->get_bbox().get_bottom() < get_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
54 void UnstableTile::shake (void)
55 {
56   if (state != STATE_NORMAL)
57     return;
58
59   if (sprite->has_action ("shake")) {
60     state = STATE_SHAKE;
61     this->set_action ("shake", /* loops = */ 1);
62   }
63   else {
64     dissolve ();
65   }
66 }
67
68 void UnstableTile::dissolve (void)
69 {
70   if ((state != STATE_NORMAL) && (state != STATE_SHAKE))
71     return;
72
73   if (sprite->has_action ("dissolve")) {
74     state = STATE_DISSOLVE;
75     this->set_action ("dissolve", /* loops = */ 1);
76   }
77   else {
78     fall_down ();
79   }
80 }
81
82 void UnstableTile::fall_down (void)
83 {
84   if ((state != STATE_NORMAL)
85       && (state != STATE_SHAKE)
86       && (state != STATE_DISSOLVE))
87     return;
88
89   if (sprite->has_action ("fall-down")) {
90     state = STATE_FALL;
91     this->set_action ("fall-down", /* loops = */ 1);
92     physic.enable_gravity (true);
93   }
94   else {
95     remove_me ();
96   }
97 }
98
99 void
100 UnstableTile::update(float elapsed_time)
101 {
102   switch (state)
103   {
104     case STATE_NORMAL:
105       break;
106
107     case STATE_SHAKE:
108       if (sprite->animation_done())
109         dissolve ();
110       break;
111
112     case STATE_DISSOLVE:
113       if (sprite->animation_done()) {
114         /* dissolving is done. Set to non-solid. */
115         set_group (COLGROUP_DISABLED);
116         fall_down ();
117       }
118       break;
119
120     case STATE_FALL:
121       if (sprite->animation_done())
122         remove_me ();
123       else
124         movement = physic.get_movement (elapsed_time);
125       break;
126   }
127 }
128
129 /* EOF */