src/badguy/owl.cpp

Go to the documentation of this file.
00001 //  SuperTux
00002 //  Copyright (C) 2008 Wolfgang Becker <uafr@gmx.de>
00003 //  Copyright (C) 2010 Florian Forster <supertux at octo.it>
00004 //
00005 //  This program is free software: you can redistribute it and/or modify
00006 //  it under the terms of the GNU General Public License as published by
00007 //  the Free Software Foundation, either version 3 of the License, or
00008 //  (at your option) any later version.
00009 //
00010 //  This program is distributed in the hope that it will be useful,
00011 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 //  GNU General Public License for more details.
00014 //
00015 //  You should have received a copy of the GNU General Public License
00016 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00017 
00018 #include "badguy/owl.hpp"
00019 
00020 #include "sprite/sprite.hpp"
00021 #include "supertux/object_factory.hpp"
00022 #include "supertux/sector.hpp"
00023 #include "object/anchor_point.hpp"
00024 #include "object/player.hpp"
00025 #include "object/rock.hpp"
00026 #include "util/reader.hpp"
00027 #include "util/log.hpp"
00028 
00029 #define FLYING_SPEED 120.0
00030 #define ACTIVATION_DISTANCE 128.0
00031 
00032 Owl::Owl(const Reader& reader) :
00033   BadGuy(reader, "images/creatures/owl/owl.sprite", LAYER_OBJECTS + 1),
00034   carried_obj_name("skydive"),
00035   carried_object(NULL)
00036 {
00037   reader.get("carry", carried_obj_name);
00038   set_action (dir == LEFT ? "left" : "right", /* loops = */ -1);
00039 }
00040 
00041 Owl::Owl(const Vector& pos, Direction d) :
00042   BadGuy(pos, d, "images/creatures/owl/owl.sprite", LAYER_OBJECTS + 1),
00043   carried_obj_name("skydive"),
00044   carried_object(NULL)
00045 {
00046   set_action (dir == LEFT ? "left" : "right", /* loops = */ -1);
00047 }
00048 
00049 void
00050 Owl::initialize()
00051 {
00052   GameObject *game_object;
00053 
00054   physic.set_velocity_x(dir == LEFT ? -FLYING_SPEED : FLYING_SPEED);
00055   physic.enable_gravity(false);
00056   sprite->set_action(dir == LEFT ? "left" : "right");
00057 
00058   game_object = ObjectFactory::instance().create(carried_obj_name, get_pos(), dir);
00059   if (game_object == NULL) {
00060     log_fatal << "Creating \"" << carried_obj_name << "\" object failed." << std::endl;
00061     return;
00062   }
00063 
00064   carried_object = dynamic_cast<Portable *> (game_object);
00065   if (carried_object == NULL) {
00066     log_warning << "Object is not portable: " << carried_obj_name << std::endl;
00067     delete game_object;
00068     return;
00069   }
00070 
00071   Sector::current ()->add_object (game_object);
00072 } /* void initialize */
00073 
00074 bool
00075 Owl::is_above_player (void)
00076 {
00077   Player* player = Sector::current()->get_nearest_player (this->get_bbox ());
00078   if (!player)
00079     return false;
00080 
00081   /* Let go of carried objects a short while *before* Tux is below us. This
00082    * makes it more likely that we'll hit him. */
00083   float x_offset = (dir == LEFT) ? ACTIVATION_DISTANCE : -ACTIVATION_DISTANCE;
00084 
00085   const Rectf& player_bbox = player->get_bbox();
00086   const Rectf& owl_bbox = get_bbox();
00087 
00088   if ((player_bbox.p1.y >= owl_bbox.p2.y) /* player is below us */
00089       && ((player_bbox.p2.x + x_offset) > owl_bbox.p1.x)
00090       && ((player_bbox.p1.x + x_offset) < owl_bbox.p2.x))
00091     return true;
00092   else
00093     return false;
00094 }
00095 
00096 void
00097 Owl::active_update (float elapsed_time)
00098 {
00099   BadGuy::active_update (elapsed_time);
00100 
00101   if (carried_object != NULL) {
00102     if (!is_above_player ()) {
00103       Vector obj_pos = get_anchor_pos (bbox, ANCHOR_BOTTOM);
00104       obj_pos.x -= 16.0; /* FIXME: Actually do use the half width of the carried object here. */
00105       obj_pos.y += 3.0; /* Move a little away from the hitbox (the body). Looks nicer. */
00106 
00107       carried_object->grab (*this, obj_pos, dir);
00108     }
00109     else { /* if (is_above_player) */
00110       carried_object->ungrab (*this, dir);
00111       carried_object = NULL;
00112     }
00113   }
00114 }
00115 
00116 bool
00117 Owl::collision_squished(GameObject&)
00118 {
00119   Player* player = Sector::current()->get_nearest_player (this->get_bbox ());
00120   if (player)
00121     player->bounce (*this);
00122 
00123   if (carried_object != NULL) {
00124     carried_object->ungrab (*this, dir);
00125     carried_object = NULL;
00126   }
00127 
00128   kill_fall ();
00129   return true;
00130 }
00131 
00132 void
00133 Owl::collision_solid(const CollisionHit& hit)
00134 {
00135   if(hit.top || hit.bottom) {
00136     physic.set_velocity_y(0);
00137   } else if(hit.left || hit.right) {
00138     if (dir == LEFT) {
00139       set_action ("right", /* loops = */ -1);
00140       dir = RIGHT;
00141       physic.set_velocity_x (FLYING_SPEED);
00142     }
00143     else {
00144       set_action ("left", /* loops = */ -1);
00145       dir = LEFT;
00146       physic.set_velocity_x (-FLYING_SPEED);
00147     }
00148   }
00149 } /* void Owl::collision_solid */
00150 
00151 /* vim: set sw=2 sts=2 et fdm=marker : */
00152 /* EOF */

Generated on Mon Jun 9 03:38:17 2014 for SuperTux by  doxygen 1.5.1