src/badguy/willowisp.cpp

Go to the documentation of this file.
00001 //  SuperTux - "Will-O-Wisp" Badguy
00002 //  Copyright (C) 2006 Christoph Sommer <christoph.sommer@2006.expires.deltadevelopment.de>
00003 //
00004 //  This program is free software: you can redistribute it and/or modify
00005 //  it under the terms of the GNU General Public License as published by
00006 //  the Free Software Foundation, either version 3 of the License, or
00007 //  (at your option) any later version.
00008 //
00009 //  This program is distributed in the hope that it will be useful,
00010 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 //  GNU General Public License for more details.
00013 //
00014 //  You should have received a copy of the GNU General Public License
00015 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00016 
00017 #include "badguy/willowisp.hpp"
00018 
00019 #include "audio/sound_manager.hpp"
00020 #include "audio/sound_source.hpp"
00021 #include "object/lantern.hpp"
00022 #include "object/path_walker.hpp"
00023 #include "object/player.hpp"
00024 #include "scripting/squirrel_util.hpp"
00025 #include "sprite/sprite.hpp"
00026 #include "supertux/game_session.hpp"
00027 #include "supertux/object_factory.hpp"
00028 #include "supertux/sector.hpp"
00029 #include "util/reader.hpp"
00030 
00031 static const float FLYSPEED = 64; 
00032 static const float TRACK_RANGE = 384; 
00033 static const float VANISH_RANGE = 512; 
00034 static const std::string SOUNDFILE = "sounds/willowisp.wav";
00035 
00036 WillOWisp::WillOWisp(const Reader& reader) :
00037   BadGuy(reader, "images/creatures/willowisp/willowisp.sprite", LAYER_FLOATINGOBJECTS), 
00038   mystate(STATE_IDLE), 
00039   target_sector("main"), 
00040   target_spawnpoint("main"),
00041   hit_script(),
00042   sound_source(),
00043   path(),
00044   walker(),
00045   flyspeed(),
00046   track_range(),
00047   vanish_range()
00048 {
00049   bool running = false;
00050   flyspeed     = FLYSPEED;
00051   track_range  = TRACK_RANGE;
00052   vanish_range = VANISH_RANGE;
00053 
00054   reader.get("sector", target_sector);
00055   reader.get("spawnpoint", target_spawnpoint);
00056   reader.get("name", name);
00057   reader.get("flyspeed", flyspeed);
00058   reader.get("track-range", track_range);
00059   reader.get("vanish-range", vanish_range);
00060   reader.get("hit-script", hit_script);
00061   reader.get("running", running);
00062 
00063   const lisp::Lisp* pathLisp = reader.get_lisp("path");
00064   if(pathLisp != NULL) {
00065     path.reset(new Path());
00066     path->read(*pathLisp);
00067     walker.reset(new PathWalker(path.get(), running));
00068     if(running)
00069       mystate = STATE_PATHMOVING_TRACK;
00070   }
00071 
00072   countMe = false;
00073   sound_manager->preload(SOUNDFILE);
00074   sound_manager->preload("sounds/warp.wav");
00075 
00076   sprite->set_action("idle");
00077 }
00078 
00079 void
00080 WillOWisp::draw(DrawingContext& context)
00081 {
00082   sprite->draw(context, get_pos(), layer);
00083 
00084   context.push_target();
00085   context.set_target(DrawingContext::LIGHTMAP);
00086 
00087   sprite->draw(context, get_pos(), layer);
00088 
00089   context.pop_target();
00090 }
00091 
00092 void
00093 WillOWisp::active_update(float elapsed_time)
00094 {
00095   Player* player = get_nearest_player();
00096   if (!player) return;
00097   Vector p1 = this->get_pos() + (this->get_bbox().p2 - this->get_bbox().p1) / 2;
00098   Vector p2 = player->get_pos() + (player->get_bbox().p2 - player->get_bbox().p1) / 2;
00099   Vector dist = (p2 - p1);
00100 
00101   switch(mystate) {
00102     case STATE_STOPPED:
00103       break;
00104 
00105     case STATE_IDLE:
00106       if (dist.norm() <= track_range) {
00107         mystate = STATE_TRACKING;
00108       }
00109       break;
00110 
00111     case STATE_TRACKING:
00112       if (dist.norm() > vanish_range) {
00113         vanish();
00114       } else if (dist.norm() >= 1) {
00115         Vector dir = dist.unit();
00116         movement = dir * elapsed_time * flyspeed;
00117       } else {
00118         /* We somehow landed right on top of the player without colliding.
00119          * Sit tight and avoid a division by zero. */
00120       }
00121       sound_source->set_position(get_pos());
00122       break;
00123 
00124     case STATE_WARPING:
00125       if(sprite->animation_done()) {
00126         remove_me();
00127       }
00128 
00129     case STATE_VANISHING: {
00130       Vector dir = dist.unit();
00131       movement = dir * elapsed_time * flyspeed;
00132       if(sprite->animation_done()) {
00133         remove_me();
00134       }
00135       break;
00136     }
00137 
00138     case STATE_PATHMOVING:
00139     case STATE_PATHMOVING_TRACK:
00140       if(walker.get() == NULL)
00141         return;
00142       movement = walker->advance(elapsed_time) - get_pos();
00143       if(mystate == STATE_PATHMOVING_TRACK && dist.norm() <= track_range) {
00144         mystate = STATE_TRACKING;
00145       }
00146       break;
00147 
00148     default:
00149       assert(false);
00150   }
00151 }
00152 
00153 void
00154 WillOWisp::activate()
00155 {
00156   sound_source.reset(sound_manager->create_sound_source(SOUNDFILE));
00157   sound_source->set_position(get_pos());
00158   sound_source->set_looping(true);
00159   sound_source->set_gain(2.0);
00160   sound_source->set_reference_distance(32);
00161   sound_source->play();
00162 }
00163 
00164 void
00165 WillOWisp::deactivate()
00166 {
00167   sound_source.reset(NULL);
00168 
00169   switch (mystate) {
00170     case STATE_STOPPED:
00171     case STATE_IDLE:
00172     case STATE_PATHMOVING:
00173     case STATE_PATHMOVING_TRACK:
00174       break;
00175     case STATE_TRACKING:
00176       mystate = STATE_IDLE;
00177       break;
00178     case STATE_WARPING:
00179     case STATE_VANISHING:
00180       remove_me();
00181       break;
00182   }
00183 }
00184 
00185 void
00186 WillOWisp::vanish()
00187 {
00188   mystate = STATE_VANISHING;
00189   sprite->set_action("vanishing", 1);
00190   set_colgroup_active(COLGROUP_DISABLED);
00191 }
00192 
00193 bool
00194 WillOWisp::collides(GameObject& other, const CollisionHit& ) {
00195   Lantern* lantern = dynamic_cast<Lantern*>(&other);
00196 
00197   if (lantern && lantern->is_open())
00198     return true;
00199 
00200   if (dynamic_cast<Player*>(&other))
00201     return true;
00202 
00203   return false;
00204 }
00205 
00206 HitResponse
00207 WillOWisp::collision_player(Player& player, const CollisionHit& ) {
00208   if(player.is_invincible())
00209     return ABORT_MOVE;
00210 
00211   if (mystate != STATE_TRACKING)
00212     return ABORT_MOVE;
00213 
00214   mystate = STATE_WARPING;
00215   sprite->set_action("warping", 1);
00216 
00217   if(hit_script != "") {
00218     std::istringstream stream(hit_script);
00219     Sector::current()->run_script(stream, "hit-script");
00220   } else {
00221     GameSession::current()->respawn(target_sector, target_spawnpoint);
00222   }
00223   sound_manager->play("sounds/warp.wav");
00224 
00225   return CONTINUE;
00226 }
00227 
00228 void
00229 WillOWisp::goto_node(int node_no)
00230 {
00231   walker->goto_node(node_no);
00232   if(mystate != STATE_PATHMOVING && mystate != STATE_PATHMOVING_TRACK) {
00233     mystate = STATE_PATHMOVING;
00234   }
00235 }
00236 
00237 void
00238 WillOWisp::start_moving()
00239 {
00240   walker->start_moving();
00241 }
00242 
00243 void
00244 WillOWisp::stop_moving()
00245 {
00246   walker->stop_moving();
00247 }
00248 
00249 void
00250 WillOWisp::set_state(const std::string& new_state)
00251 {
00252   if(new_state == "stopped") {
00253     mystate = STATE_STOPPED;
00254   } else if(new_state == "idle") {
00255     mystate = STATE_IDLE;
00256   } else if(new_state == "move_path") {
00257     mystate = STATE_PATHMOVING;
00258     walker->start_moving();
00259   } else if(new_state == "move_path_track") {
00260     mystate = STATE_PATHMOVING_TRACK;
00261     walker->start_moving();
00262   } else if(new_state == "normal") {
00263     mystate = STATE_IDLE;
00264   } else if(new_state == "vanish") {
00265     vanish();
00266   } else {
00267     std::ostringstream msg;
00268     msg << "Can't set unknown willowisp state '" << new_state << "', should "
00269       "be stopped, move_path, move_path_track or normal";
00270     throw new std::runtime_error(msg.str());
00271   }
00272 }
00273 
00274 void
00275 WillOWisp::expose(HSQUIRRELVM vm, SQInteger table_idx)
00276 {
00277   if (name.empty())
00278     return;
00279 
00280   std::cout << "Expose me '" << name << "'\n";
00281   scripting::WillOWisp* _this = static_cast<scripting::WillOWisp*> (this);
00282   expose_object(vm, table_idx, _this, name);
00283 }
00284   
00285 void
00286 WillOWisp::unexpose(HSQUIRRELVM vm, SQInteger table_idx)
00287 {
00288   if (name.empty())
00289     return;
00290 
00291   std::cout << "UnExpose me '" << name << "'\n";
00292   scripting::unexpose_object(vm, table_idx, name);
00293 }
00294 
00295 /* EOF */

Generated on Mon Apr 14 03:38:19 2014 for SuperTux by  doxygen 1.5.1