eed38db532105a9f57c7777f9653b62cd28abf52
[supertux.git] / src / badguy / stumpy.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 "stumpy.hpp"
23
24 #include "poisonivy.hpp"
25 #include "random_generator.hpp"
26 #include "object/sprite_particle.hpp"
27 #include "lisp/writer.hpp"
28 #include "object_factory.hpp"
29 #include "audio/sound_manager.hpp"
30 #include "sector.hpp"
31
32 #include <math.h>
33
34 static const float WALKSPEED = 120;
35 static const float INVINCIBLE_TIME = 1;
36
37 Stumpy::Stumpy(const lisp::Lisp& reader)
38   : WalkingBadguy(reader, "images/creatures/mr_tree/stumpy.sprite","left","right"), mystate(STATE_NORMAL)
39 {
40   walk_speed = WALKSPEED;
41   max_drop_height = 16;
42   sound_manager->preload("sounds/mr_treehit.ogg");
43 }
44
45 Stumpy::Stumpy(const Vector& pos, Direction d)
46   : WalkingBadguy(pos, d, "images/creatures/mr_tree/stumpy.sprite","left","right"), mystate(STATE_INVINCIBLE)
47 {
48   walk_speed = WALKSPEED;
49   max_drop_height = 16;
50   sound_manager->preload("sounds/mr_treehit.ogg");
51   invincible_timer.start(INVINCIBLE_TIME);
52 }
53
54
55 void
56 Stumpy::write(lisp::Writer& writer)
57 {
58   writer.start_list("stumpy");
59   WalkingBadguy::write(writer);
60   writer.end_list("stumpy");
61 }
62
63 void
64 Stumpy::initialize()
65 {
66   switch (mystate) {
67     case STATE_INVINCIBLE:
68       sprite->set_action(dir == LEFT ? "dizzy-left" : "dizzy-right");
69       bbox.set_size(sprite->get_current_hitbox_width(), sprite->get_current_hitbox_height());
70       physic.set_velocity_x(0);
71       break;
72     case STATE_NORMAL:
73       WalkingBadguy::initialize();
74       break;
75   }
76 }
77
78 void
79 Stumpy::active_update(float elapsed_time)
80 {
81   switch (mystate) {
82     case STATE_INVINCIBLE:
83       if (invincible_timer.check()) {
84         mystate = STATE_NORMAL;
85         WalkingBadguy::initialize();
86       }
87       BadGuy::active_update(elapsed_time);
88       break;
89     case STATE_NORMAL:
90       WalkingBadguy::active_update(elapsed_time);
91       break;
92   }
93 }
94
95 bool
96 Stumpy::collision_squished(GameObject& object)
97 {
98
99   // if we're still invincible, we ignore the hit
100   if (mystate == STATE_INVINCIBLE) {
101     sound_manager->play("sounds/mr_treehit.ogg", get_pos());
102     Player* player = dynamic_cast<Player*>(&object);
103     if (player) player->bounce(*this);
104     return true;
105   }
106
107   // if we can die, we do
108   if (mystate == STATE_NORMAL) {
109     sprite->set_action(dir == LEFT ? "squished-left" : "squished-right");
110     set_size(sprite->get_current_hitbox_width(), sprite->get_current_hitbox_height());
111     kill_squished(object);
112     // spawn some particles
113     // TODO: provide convenience function in MovingSprite or MovingObject?
114     for (int i = 0; i < 25; i++) {
115       Vector ppos = bbox.get_middle();
116       float angle = systemRandom.randf(-M_PI_2, M_PI_2);
117       float velocity = systemRandom.randf(45, 90);
118       float vx = sin(angle)*velocity;
119       float vy = -cos(angle)*velocity;
120       Vector pspeed = Vector(vx, vy);
121       Vector paccel = Vector(0, 100);
122       Sector::current()->add_object(new SpriteParticle("images/objects/particles/bark.sprite", "default", ppos, ANCHOR_MIDDLE, pspeed, paccel, LAYER_OBJECTS-1));
123     }
124
125     return true;
126
127   }
128
129   //TODO: exception?
130   return true;
131 }
132
133 void
134 Stumpy::collision_solid(const CollisionHit& hit)
135 {
136   update_on_ground_flag(hit);
137
138   switch (mystate) {
139     case STATE_INVINCIBLE:
140       if(hit.top || hit.bottom) {
141         physic.set_velocity_y(0);
142       }
143       if(hit.left || hit.right) {
144         physic.set_velocity_x(0);
145       }
146       break;
147     case STATE_NORMAL:
148       WalkingBadguy::collision_solid(hit);
149       break;
150   }
151 }
152
153 HitResponse
154 Stumpy::collision_badguy(BadGuy& badguy, const CollisionHit& hit)
155 {
156   switch (mystate) {
157     case STATE_INVINCIBLE:
158       if(hit.top || hit.bottom) {
159         physic.set_velocity_y(0);
160       }
161       if(hit.left || hit.right) {
162         physic.set_velocity_x(0);
163       }
164       return CONTINUE;
165       break;
166     case STATE_NORMAL:
167       return WalkingBadguy::collision_badguy(badguy, hit);
168       break;
169   }
170   return CONTINUE;
171 }
172
173 IMPLEMENT_FACTORY(Stumpy, "stumpy")