61c8b12d77edfeb192f87e97a7341058bc3b9061
[supertux.git] / src / badguy / nolok_01.cpp
1 //  $Id$
2 // 
3 //  SuperTux
4 //  Copyright (C) 2005 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
19 //  02111-1307, USA.
20
21 #include <config.h>
22
23 #include "nolok_01.h"
24 #include "badguy/bouncing_snowball.h"
25 #include "trigger/door.h"
26
27 #define WALK_TIME 2.5
28 #define SHOOT_TIME 0.4
29 #define JUMP_TIME 0.5
30 #define INITIAL_HITPOINTS 3
31 #define INITIAL_BULLET_HP 10
32
33 static const float WALKSPEED = 90;
34
35 //TODO: Create sprite, limit max number of snowballs
36 Nolok_01::Nolok_01(const lisp::Lisp& reader)
37 {
38   reader.get("x", start_position.x);
39   reader.get("y", start_position.y);
40   bbox.set_size(31.8, 63.8);
41   sprite = sprite_manager->create("dummyguy");
42 }
43
44 Nolok_01::Nolok_01(float pos_x, float pos_y)
45 {
46   start_position.x = pos_x;
47   start_position.y = pos_y;
48   bbox.set_size(31.8, 63.8);
49   sprite = sprite_manager->create("dummyguy");
50 }
51
52 void
53 Nolok_01::write(lisp::Writer& writer)
54 {
55   writer.start_list("nolok_01");
56
57   writer.write_float("x", start_position.x);
58   writer.write_float("y", start_position.y);
59
60   writer.end_list("nolok_01");
61 }
62
63 void
64 Nolok_01::activate()
65 {
66   hitpoints = INITIAL_HITPOINTS;
67   bullet_hitpoints = INITIAL_BULLET_HP;
68   physic.set_velocity_x(dir == LEFT ? -WALKSPEED : WALKSPEED);
69   sprite->set_action(dir == LEFT ? "left" : "right");
70   action = WALKING;
71   action_timer.start(WALK_TIME);
72 }
73
74 void
75 Nolok_01::active_action(float elapsed_time)
76 {
77    if (action_timer.check()) {
78      switch (action) {       
79        case WALKING:
80         {
81          sprite->set_action("jump");
82          physic.set_velocity_y(700);
83          action = JUMPING;
84          action_timer.start(JUMP_TIME);
85          break;
86         }
87        case JUMPING:
88        {
89         sprite->set_action("throw");
90         action = SHOOTING;
91         action_timer.start(SHOOT_TIME);
92         break;
93        }
94        case SHOOTING:
95        {
96         Sector::current()->add_object(new BouncingSnowball(get_pos().x - 64, get_pos().y, LEFT));
97         Sector::current()->add_object(new BouncingSnowball(get_pos().x + 64, get_pos().y, RIGHT));
98         physic.set_velocity_x(dir == LEFT ? -WALKSPEED : WALKSPEED);
99         sprite->set_action(dir == LEFT ? "left" : "right");
100         action = WALKING;
101         action_timer.start(WALK_TIME);
102         break;
103        }
104      }
105    }
106    movement = physic.get_movement(elapsed_time);
107 }
108
109 bool
110 Nolok_01::collision_squished(Player& player)
111 {
112   bool result = false;
113   player.bounce(*this);
114   if (hitpoints <= 0) {
115     bullet_hitpoints = 0;
116     sprite->set_action("dead"); 
117     kill_squished(player);
118     Sector::current()->add_object(new Door((int)get_pos().x+32, 512, "sector1", "main2"));
119     result = true;
120   }
121   return result;
122 }
123
124 HitResponse
125 Nolok_01::collision_solid(GameObject& , const CollisionHit& hit)
126 {
127   if(fabsf(hit.normal.y) > .5){ // hit floor or roof?
128     if (action != JUMPING) physic.set_velocity_y(0);
129   } else { // hit right or left
130     dir = dir == LEFT ? RIGHT : LEFT;
131     sprite->set_action(dir == LEFT ? "left" : "right");
132     physic.set_velocity_x(-physic.get_velocity_x());
133   }
134
135   return CONTINUE;
136 }
137
138 //TODO: Hitpoint count incorrect when combining squishing and shooting
139 void
140 Nolok_01::kill_fall()
141 {
142   bullet_hitpoints--;
143   if (bullet_hitpoints <= 0) {
144    hitpoints = 0;
145    sound_manager->play_sound("fall", this,
146                              Sector::current()->player->get_pos());
147    physic.set_velocity_y(0);
148    physic.enable_gravity(true);
149    set_state(STATE_FALLING);
150    Sector::current()->add_object(new Door((int)get_pos().x+32, 512, "sector1", "main2"));
151   }
152 }
153
154 IMPLEMENT_FACTORY(Nolok_01, "nolok_01")