5677ef0c38c03ed232e7d77bc7f608b4dd79a3ac
[supertux.git] / src / badguy / owl.cpp
1 //  SuperTux
2 //  Copyright (C) 2008 Wolfgang Becker <uafr@gmx.de>
3 //  Copyright (C) 2010 Florian Forster <supertux at octo.it>
4 //
5 //  This program is free software: you can redistribute it and/or modify
6 //  it under the terms of the GNU General Public License as published by
7 //  the Free Software Foundation, either version 3 of the License, or
8 //  (at your option) any later version.
9 //
10 //  This program is distributed in the hope that it will be useful,
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //  GNU General Public License for more details.
14 //
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18 #include "badguy/owl.hpp"
19
20 #include "sprite/sprite.hpp"
21 #include "supertux/object_factory.hpp"
22 #include "supertux/sector.hpp"
23 #include "object/player.hpp"
24 #include "object/rock.hpp"
25 #include "util/reader.hpp"
26 #include "util/log.hpp"
27
28 #define FLYING_SPEED 120.0
29
30 Owl::Owl(const Reader& reader) :
31   BadGuy(reader, "images/creatures/owl/owl.sprite"),
32   carried_obj_name("rock"),
33   carried_object(NULL)
34 {
35   reader.get("carry", carried_obj_name);
36   set_action (dir == LEFT ? "left" : "right", /* loops = */ -1);
37 }
38
39 Owl::Owl(const Vector& pos, Direction d) :
40   BadGuy(pos, d, "images/creatures/owl/owl.sprite"),
41   carried_obj_name("rock"),
42   carried_object(NULL)
43 {
44   set_action (dir == LEFT ? "left" : "right", /* loops = */ -1);
45 }
46
47 void
48 Owl::initialize()
49 {
50   GameObject *game_object;
51
52   physic.set_velocity_x(dir == LEFT ? -FLYING_SPEED : FLYING_SPEED);
53   physic.enable_gravity(false);
54   sprite->set_action(dir == LEFT ? "left" : "right");
55
56   game_object = ObjectFactory::instance().create(carried_obj_name, get_pos(), dir);
57   if (game_object == NULL) {
58     log_fatal << "Creating \"" << carried_obj_name << "\" object failed." << std::endl;
59     return;
60   }
61
62   carried_object = dynamic_cast<Portable *> (game_object);
63   if (carried_object == NULL) {
64     log_warning << "Object is not portable: " << carried_obj_name << std::endl;
65     delete game_object;
66     return;
67   }
68
69   Sector::current ()->add_object (game_object);
70 } /* void initialize */
71
72 bool
73 Owl::is_above_player (void)
74 {
75   Player* player = Sector::current()->get_nearest_player (this->get_bbox ());
76   if (!player)
77     return false;
78
79   const Rectf& player_bbox = player->get_bbox();
80   const Rectf& owl_bbox = get_bbox();
81   if ((player_bbox.p1.y >= owl_bbox.p2.y) /* player is below us */
82       && (player_bbox.p2.x > owl_bbox.p1.x)
83       && (player_bbox.p1.x < owl_bbox.p2.x))
84     return true;
85   else
86     return false;
87 }
88
89 void
90 Owl::active_update (float elapsed_time)
91 {
92   BadGuy::active_update (elapsed_time);
93
94   if (carried_object != NULL) {
95     if (!is_above_player ()) {
96       Vector obj_pos = get_pos ();
97
98       obj_pos.y += bbox.get_height ();
99       carried_object->grab (*this, obj_pos, dir);
100     }
101     else { /* if (is_above_player) */
102       carried_object->ungrab (*this, dir);
103       carried_object = NULL;
104     }
105   }
106 }
107
108 bool
109 Owl::collision_squished(GameObject&)
110 {
111   Player* player = Sector::current()->get_nearest_player (this->get_bbox ());
112   if (player)
113     player->bounce (*this);
114
115   if (carried_object != NULL) {
116     carried_object->ungrab (*this, dir);
117     carried_object = NULL;
118   }
119
120   kill_fall ();
121   return true;
122 }
123
124 void
125 Owl::collision_solid(const CollisionHit& hit)
126 {
127   if(hit.top || hit.bottom) {
128     physic.set_velocity_y(0);
129   } else if(hit.left || hit.right) {
130     if (dir == LEFT) {
131       set_action ("right", /* loops = */ -1);
132       physic.set_velocity_x (FLYING_SPEED);
133     }
134     else {
135       set_action ("left", /* loops = */ -1);
136       physic.set_velocity_x (-FLYING_SPEED);
137     }
138   }
139 } /* void Owl::collision_solid */
140
141 HitResponse
142 Owl::collision_player(Player& player, const CollisionHit& hit)
143 {
144   //Hack to tell if we should die
145   HitResponse response = BadGuy::collision_player(player, hit);
146   if(response == FORCE_MOVE) {
147     if (carried_object != NULL) {
148       carried_object->ungrab (*this, dir);
149       carried_object = NULL;
150     }
151     kill_fall ();
152   }
153
154   return ABORT_MOVE;
155 }
156
157 /* vim: set sw=2 sts=2 et fdm=marker : */
158 /* EOF */