9c5ad78e2b52fe4fde3f00c2c2c558c35c1d279d
[supertux.git] / src / badguy / mriceblock.cpp
1 #include <config.h>
2
3 #include "mriceblock.h"
4 #include "object/block.h"
5
6 static const float WALKSPEED = 80;
7 static const float KICKSPEED = 500;
8 static const int MAXSQUISHES = 10;
9
10 MrIceBlock::MrIceBlock(const lisp::Lisp& reader)
11   : ice_state(ICESTATE_NORMAL), squishcount(0)
12 {
13   reader.get("x", start_position.x);
14   reader.get("y", start_position.y);
15   bbox.set_size(31.8, 31.8);
16   sprite = sprite_manager->create("mriceblock");
17   set_direction = false;
18 }
19
20 MrIceBlock::MrIceBlock(float pos_x, float pos_y, Direction d)
21   : ice_state(ICESTATE_NORMAL), squishcount(0)
22 {
23   start_position.x = pos_x;
24   start_position.y = pos_y;
25   bbox.set_size(31.8, 31.8);
26   sprite = sprite_manager->create("mriceblock");
27   set_direction = true;
28   initial_direction = d;
29 }
30
31 void
32 MrIceBlock::write(lisp::Writer& writer)
33 {
34   writer.start_list("mriceblock");
35
36   writer.write_float("x", get_pos().x);
37   writer.write_float("y", get_pos().y);
38
39   writer.end_list("mriceblock");
40 }
41
42 void
43 MrIceBlock::activate()
44 {
45   if (set_direction) {dir = initial_direction;}
46   physic.set_velocity_x(dir == LEFT ? -WALKSPEED : WALKSPEED);
47   sprite->set_action(dir == LEFT ? "left" : "right");
48 }
49
50 void
51 MrIceBlock::active_action(float elapsed_time)
52 {
53   if(ice_state == ICESTATE_FLAT && flat_timer.check()) {
54     printf("unflat.\n");
55     ice_state = ICESTATE_NORMAL;
56     physic.set_velocity_x(dir == LEFT ? -WALKSPEED : WALKSPEED);
57     sprite->set_action(dir == LEFT ? "left" : "right");
58   }
59   BadGuy::active_action(elapsed_time);
60 }
61
62 HitResponse
63 MrIceBlock::collision_solid(GameObject& object, const CollisionHit& hit)
64 {
65   if(fabsf(hit.normal.y) > .5) { // floor or roof
66     physic.set_velocity_y(0);
67     return CONTINUE;
68   }
69   // hit left or right
70   switch(ice_state) {
71     case ICESTATE_NORMAL:
72       dir = dir == LEFT ? RIGHT : LEFT;
73       sprite->set_action(dir == LEFT ? "left" : "right");
74       physic.set_velocity_x(-physic.get_velocity_x());       
75       break;
76     case ICESTATE_KICKED: {
77       BonusBlock* bonusblock = dynamic_cast<BonusBlock*> (&object);
78       if(bonusblock) {
79         bonusblock->try_open();
80       }
81       Brick* brick = dynamic_cast<Brick*> (&object);
82       if(brick) {
83         brick->try_break();
84       }
85       
86       dir = dir == LEFT ? RIGHT : LEFT;
87       sprite->set_action(dir == LEFT ? "flat-left" : "flat-right");
88       physic.set_velocity_x(-physic.get_velocity_x());
89       SoundManager::get()->play_sound(IDToSound(SND_RICOCHET), get_pos(),
90           Sector::current()->player->get_pos());
91       break;
92     }
93     case ICESTATE_FLAT:
94       physic.set_velocity_x(0);
95       break;
96   }
97
98   return CONTINUE;
99 }
100
101 HitResponse
102 MrIceBlock::collision_badguy(BadGuy& badguy, const CollisionHit& hit)
103 {
104   switch(ice_state) {
105     case ICESTATE_NORMAL:
106       if(fabsf(hit.normal.x) > .8) {
107         dir = dir == LEFT ? RIGHT : LEFT;
108         sprite->set_action(dir == LEFT ? "left" : "right");
109         physic.set_velocity_x(-physic.get_velocity_x());               
110       }
111       return CONTINUE;
112     case ICESTATE_FLAT:
113       return FORCE_MOVE;
114     case ICESTATE_KICKED:
115       badguy.kill_fall();
116       return FORCE_MOVE;
117     default:
118       assert(false);
119   }
120
121   return ABORT_MOVE;
122 }
123
124 bool
125 MrIceBlock::collision_squished(Player& player)
126 {
127   switch(ice_state) {
128     case ICESTATE_KICKED:
129     case ICESTATE_NORMAL:
130       squishcount++;
131       if(squishcount >= MAXSQUISHES) {
132         kill_fall();
133         return true;
134       }
135
136       // flatten
137       SoundManager::get()->play_sound(IDToSound(SND_STOMP), get_pos(),
138           player.get_pos());
139       physic.set_velocity_x(0);
140       physic.set_velocity_y(0); 
141       
142       sprite->set_action(dir == LEFT ? "flat-left" : "flat-right");
143       flat_timer.start(4);
144       ice_state = ICESTATE_FLAT;
145       printf("flat.\n");
146       break;
147     case ICESTATE_FLAT:
148       // kick
149       SoundManager::get()->play_sound(IDToSound(SND_KICK), this,
150           player.get_pos());
151
152       if(player.get_pos().x < get_pos().x) {
153         dir = RIGHT;
154       } else {
155         dir = LEFT;
156       }
157       physic.set_velocity_x(dir == LEFT ? -KICKSPEED : KICKSPEED);
158       sprite->set_action(dir == LEFT ? "flat-left" : "flat-right");
159       ice_state = ICESTATE_KICKED;
160       printf("kicked.\n");
161       break;
162   }
163
164   player.bounce(*this);
165   return true;
166 }
167