fd25e985b2b0f9fb86fc411d88cfd460ef73930c
[supertux.git] / src / badguy / plant.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 "plant.hpp"
23
24 #include "lisp/writer.hpp"
25 #include "object_factory.hpp"
26 #include "object/player.hpp"
27 #include "sprite/sprite.hpp"
28
29 static const float WALKSPEED = 80;
30 static const float WAKE_TIME = .5;
31
32 Plant::Plant(const lisp::Lisp& reader)
33         : BadGuy(reader, "images/creatures/plant/plant.sprite")
34 {
35   state = PLANT_SLEEPING;
36 }
37
38 void
39 Plant::write(lisp::Writer& writer)
40 {
41   writer.start_list("plant");
42
43   writer.write("x", start_position.x);
44   writer.write("y", start_position.y);
45
46   writer.end_list("plant");
47 }
48
49 void
50 Plant::initialize()
51 {
52   //FIXME: turns sspiky around for debugging
53   dir = dir == LEFT ? RIGHT : LEFT;
54
55   state = PLANT_SLEEPING;
56   physic.set_velocity_x(0);
57   sprite->set_action(dir == LEFT ? "sleeping-left" : "sleeping-right");
58 }
59
60 void
61 Plant::collision_solid(const CollisionHit& hit)
62 {
63   if(hit.top || hit.bottom) {
64     physic.set_velocity_y(0);
65   } else if(hit.left || hit.right) {
66     dir = dir == LEFT ? RIGHT : LEFT;
67     sprite->set_action(dir == LEFT ? "left" : "right");
68     physic.set_velocity_x(-physic.get_velocity_x());
69   }
70 }
71
72 HitResponse
73 Plant::collision_badguy(BadGuy& , const CollisionHit& hit)
74 {
75   if(state != PLANT_WALKING) return CONTINUE;
76
77   if(hit.left || hit.right) {
78     dir = dir == LEFT ? RIGHT : LEFT;
79     sprite->set_action(dir == LEFT ? "left" : "right");
80     physic.set_velocity_x(-physic.get_velocity_x());
81   }
82
83   return CONTINUE;
84 }
85
86 void
87 Plant::active_update(float elapsed_time) {
88   BadGuy::active_update(elapsed_time);
89
90   if(state == PLANT_SLEEPING) {
91
92     Player* player = this->get_nearest_player();
93     if (player) {
94       Rect mb = this->get_bbox();
95       Rect pb = player->get_bbox();
96
97       bool inReach_left = (pb.p2.x >= mb.p2.x-((dir == LEFT) ? 256 : 0));
98       bool inReach_right = (pb.p1.x <= mb.p1.x+((dir == RIGHT) ? 256 : 0));
99       bool inReach_top = (pb.p2.y >= mb.p2.y);
100       bool inReach_bottom = (pb.p1.y <= mb.p1.y);
101
102       if (inReach_left && inReach_right && inReach_top && inReach_bottom) {
103         // wake up
104         sprite->set_action(dir == LEFT ? "waking-left" : "waking-right");
105         if(!timer.started()) timer.start(WAKE_TIME);
106         state = PLANT_WAKING;
107       }
108     }
109   }
110
111   if(state == PLANT_WAKING) {
112     if(timer.check()) {
113       // start walking
114       sprite->set_action(dir == LEFT ? "left" : "right");
115       physic.set_velocity_x(dir == LEFT ? -WALKSPEED : WALKSPEED);
116       state = PLANT_WALKING;
117     }
118   }
119
120 }
121
122 IMPLEMENT_FACTORY(Plant, "plant")