Pass player object in to BonusBlock rather than using Sector's global one.
[supertux.git] / src / trigger / door.cpp
1 //  SuperTux
2 //  Copyright (C) 2006 Matthias Braun <matze@braunis.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 "audio/sound_manager.hpp"
18 #include "object/player.hpp"
19 #include "sprite/sprite_manager.hpp"
20 #include "supertux/game_session.hpp"
21 #include "supertux/object_factory.hpp"
22 #include "supertux/sector.hpp"
23 #include "trigger/door.hpp"
24 #include "util/reader.hpp"
25
26 Door::Door(const Reader& reader) :
27   state(CLOSED),
28   target_sector(),
29   target_spawnpoint(),
30   script(),
31   sprite(),
32   stay_open_timer()
33 {
34   reader.get("x", bbox.p1.x);
35   reader.get("y", bbox.p1.y);
36   reader.get("sector", target_sector);
37   reader.get("spawnpoint", target_spawnpoint);
38
39   reader.get("script", script);
40
41   sprite = sprite_manager->create("images/objects/door/door.sprite");
42   sprite->set_action("closed");
43   bbox.set_size(sprite->get_current_hitbox_width(), sprite->get_current_hitbox_height());
44
45   sound_manager->preload("sounds/door.wav");
46 }
47
48 Door::Door(int x, int y, std::string sector, std::string spawnpoint) :
49   state(CLOSED),
50   target_sector(),
51   target_spawnpoint(),
52   script(),
53   sprite(),
54   stay_open_timer()
55 {
56   bbox.set_pos(Vector(x, y));
57   target_sector = sector;
58   target_spawnpoint = spawnpoint;
59
60   sprite = sprite_manager->create("images/objects/door/door.sprite");
61   sprite->set_action("closed");
62   bbox.set_size(sprite->get_current_hitbox_width(), sprite->get_current_hitbox_height());
63
64   sound_manager->preload("sounds/door.wav");
65 }
66
67 Door::~Door()
68 {
69 }
70
71 void
72 Door::update(float )
73 {
74   switch (state) {
75     case CLOSED:
76       break;
77     case OPENING:
78       // if door has finished opening, start timer and keep door open
79       if(sprite->animation_done()) {
80         state = OPEN;
81         sprite->set_action("open");
82         stay_open_timer.start(1.0);
83       }
84       break;
85     case OPEN:
86       // if door was open long enough, start closing it
87       if (stay_open_timer.check()) {
88         state = CLOSING;
89         sprite->set_action("closing", 1);
90       }
91       break;
92     case CLOSING:
93       // if door has finished closing, keep it shut
94       if(sprite->animation_done()) {
95         state = CLOSED;
96         sprite->set_action("closed");
97       }
98       break;
99   }
100 }
101
102 void
103 Door::draw(DrawingContext& context)
104 {
105   sprite->draw(context, bbox.p1, LAYER_BACKGROUNDTILES+1);
106 }
107
108 void
109 Door::event(Player& , EventType type)
110 {
111   switch (state) {
112     case CLOSED:
113       // if door was activated, start opening it
114       if (type == EVENT_ACTIVATE) {
115         state = OPENING;
116         sound_manager->play("sounds/door.wav");
117         sprite->set_action("opening", 1);
118       }
119       break;
120     case OPENING:
121       break;
122     case OPEN:
123       break;
124     case CLOSING:
125       break;
126   }
127 }
128
129 HitResponse
130 Door::collision(GameObject& other, const CollisionHit& hit)
131 {
132   switch (state) {
133     case CLOSED:
134       break;
135     case OPENING:
136       break;
137     case OPEN:
138     {
139       // if door is open and was touched by a player, teleport the player
140       Player* player = dynamic_cast<Player*> (&other);
141       if (player) {
142         state = CLOSING;
143         sprite->set_action("closing", 1);
144         if(!script.empty()) {
145           std::istringstream stream(script);
146           Sector::current()->run_script(stream, "Door");
147         }
148
149         if(!target_sector.empty()) {
150           GameSession::current()->respawn(target_sector, target_spawnpoint);
151         }
152       }
153     }
154     break;
155     case CLOSING:
156       break;
157   }
158
159   return TriggerBase::collision(other, hit);
160 }
161
162 /* EOF */