644906dbebe8567778a93616d97e8c7cfdaa2ac4
[supertux.git] / src / trigger / door.cpp
1 //  $Id$
2 //
3 //  SuperTux
4 //  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
5 //
6 //  This program is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU General Public License
8 //  as published by the Free Software Foundation; either version 2
9 //  of the License, or (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, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19
20 #include <config.h>
21
22 #include "door.hpp"
23 #include "game_session.hpp"
24 #include "resources.hpp"
25 #include "object_factory.hpp"
26 #include "sprite/sprite.hpp"
27 #include "sprite/sprite_manager.hpp"
28 #include "video/drawing_context.hpp"
29 #include "lisp/lisp.hpp"
30 #include "lisp/writer.hpp"
31 #include "audio/sound_manager.hpp"
32
33 Door::Door(const lisp::Lisp& reader)
34         : state(CLOSED)
35 {
36   reader.get("x", bbox.p1.x);
37   reader.get("y", bbox.p1.y);
38   reader.get("sector", target_sector);
39   reader.get("spawnpoint", target_spawnpoint);
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 {
51   bbox.set_pos(Vector(x, y));
52   target_sector = sector;
53   target_spawnpoint = spawnpoint;
54
55   sprite = sprite_manager->create("images/objects/door/door.sprite");
56   sprite->set_action("closed");
57   bbox.set_size(sprite->get_current_hitbox_width(), sprite->get_current_hitbox_height());
58
59   sound_manager->preload("sounds/door.wav");
60 }
61
62 Door::~Door()
63 {
64   delete sprite;
65 }
66
67 void
68 Door::write(lisp::Writer& writer)
69 {
70   writer.start_list("door");
71
72   writer.write("x", bbox.p1.x);
73   writer.write("y", bbox.p1.y);
74   writer.write("width", bbox.get_width());
75   writer.write("height", bbox.get_height());
76
77   writer.write("sector", target_sector);
78   writer.write("spawnpoint", target_spawnpoint);
79
80   writer.end_list("door");
81 }
82
83 void
84 Door::update(float )
85 {
86   switch (state) {
87     case CLOSED:
88       break;
89     case OPENING:
90       // if door has finished opening, start timer and keep door open
91       if(sprite->animation_done()) {
92         state = OPEN;
93         sprite->set_action("open");
94        stay_open_timer.start(1.0);
95       }
96       break;
97     case OPEN:
98       // if door was open long enough, start closing it
99       if (stay_open_timer.check()) {
100         state = CLOSING;
101         sprite->set_action("closing", 1);
102       }
103       break;
104     case CLOSING:
105       // if door has finished closing, keep it shut
106       if(sprite->animation_done()) {
107         state = CLOSED;
108         sprite->set_action("closed");
109       }
110       break;
111   }
112 }
113
114 void
115 Door::draw(DrawingContext& context)
116 {
117   sprite->draw(context, bbox.p1, LAYER_BACKGROUNDTILES+1);
118 }
119
120 void
121 Door::event(Player& , EventType type)
122 {
123   switch (state) {
124     case CLOSED:
125       // if door was activated, start opening it
126       if (type == EVENT_ACTIVATE) {
127         state = OPENING;
128         sound_manager->play("sounds/door.wav");
129         sprite->set_action("opening", 1);
130       }
131       break;
132     case OPENING:
133       break;
134     case OPEN:
135       break;
136     case CLOSING:
137       break;
138   }
139 }
140
141 HitResponse
142 Door::collision(GameObject& other, const CollisionHit& hit)
143 {
144   switch (state) {
145     case CLOSED:
146       break;
147     case OPENING:
148       break;
149     case OPEN:
150       {
151         // if door is open and was touched by a player, teleport the player
152         Player* player = dynamic_cast<Player*> (&other);
153         if (player) {
154           state = CLOSING;
155           sprite->set_action("closing", 1);
156           GameSession::current()->respawn(target_sector, target_spawnpoint);
157         }
158       }
159       break;
160     case CLOSING:
161       break;
162   }
163
164   return TriggerBase::collision(other, hit);
165 }
166
167 IMPLEMENT_FACTORY(Door, "door");