Owl: Implement carrying around of "Portable" objects.
[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/rock.hpp"
24 #include "util/reader.hpp"
25 #include "util/log.hpp"
26
27 #define FLYING_SPEED 120.0
28
29 Owl::Owl(const Reader& reader) :
30   BadGuy(reader, "images/creatures/owl/owl.sprite"),
31   carried_obj_name("rock"),
32   carried_object(NULL)
33 {
34   reader.get("carry", carried_obj_name);
35   set_action (dir == LEFT ? "left" : "right", /* loops = */ -1);
36 }
37
38 Owl::Owl(const Vector& pos, Direction d) :
39   BadGuy(pos, d, "images/creatures/owl/owl.sprite"),
40   carried_obj_name("rock"),
41   carried_object(NULL)
42 {
43   set_action (dir == LEFT ? "left" : "right", /* loops = */ -1);
44 }
45
46 void
47 Owl::initialize()
48 {
49   GameObject *game_object;
50
51   physic.set_velocity_x(dir == LEFT ? -FLYING_SPEED : FLYING_SPEED);
52   physic.enable_gravity(false);
53   sprite->set_action(dir == LEFT ? "left" : "right");
54
55   game_object = ObjectFactory::instance().create(carried_obj_name, get_pos(), dir);
56   if (game_object == NULL) {
57     log_fatal << "Creating \"" << carried_obj_name << "\" object failed." << std::endl;
58     return;
59   }
60
61   carried_object = dynamic_cast<Portable *> (game_object);
62   if (carried_object == NULL) {
63     log_warning << "Object is not portable: " << carried_obj_name << std::endl;
64     delete game_object;
65     return;
66   }
67
68   Sector::current ()->add_object (game_object);
69 } /* void initialize */
70
71 void
72 Owl::active_update (float elapsed_time)
73 {
74   BadGuy::active_update (elapsed_time);
75
76   if (carried_object != NULL) {
77     Vector obj_pos = get_pos ();
78     
79     obj_pos.y += bbox.get_height ();
80     carried_object->grab (*this, obj_pos, dir);
81   }
82 }
83
84 bool
85 Owl::collision_squished(GameObject&)
86 {
87   if (carried_object != NULL) {
88     carried_object->ungrab (*this, dir);
89     carried_object = NULL;
90   }
91   kill_fall ();
92   return true;
93 }
94
95 void
96 Owl::collision_solid(const CollisionHit& hit)
97 {
98   if(hit.top || hit.bottom) {
99     physic.set_velocity_y(0);
100   } else if(hit.left || hit.right) {
101     if (dir == LEFT) {
102       set_action ("right", /* loops = */ -1);
103       physic.set_velocity_x (FLYING_SPEED);
104     }
105     else {
106       set_action ("left", /* loops = */ -1);
107       physic.set_velocity_x (-FLYING_SPEED);
108     }
109   }
110 } /* void Owl::collision_solid */
111
112 HitResponse
113 Owl::collision_player(Player& player, const CollisionHit& hit)
114 {
115   //Hack to tell if we should die
116   HitResponse response = BadGuy::collision_player(player, hit);
117   if(response == FORCE_MOVE) {
118     if (carried_object != NULL) {
119       carried_object->ungrab (*this, dir);
120       carried_object = NULL;
121     }
122     kill_fall ();
123   }
124
125   return ABORT_MOVE;
126 }
127
128 /* vim: set sw=2 sts=2 et fdm=marker : */
129 /* EOF */