Experiments with InfoBlock no longer pausing the game
authorChristoph Sommer <mail@christoph-sommer.de>
Tue, 10 Apr 2007 20:06:14 +0000 (20:06 +0000)
committerChristoph Sommer <mail@christoph-sommer.de>
Tue, 10 Apr 2007 20:06:14 +0000 (20:06 +0000)
SVN-Revision: 4974

src/object/infoblock.cpp
src/object/infoblock.hpp

index c332f3a..770d69c 100644 (file)
 #include "lisp/lisp.hpp"
 #include "sector.hpp"
 #include "log.hpp"
+#include "object/player.hpp"
 
 InfoBlock::InfoBlock(const lisp::Lisp& lisp)
-  : Block(sprite_manager->create("images/objects/bonus_block/infoblock.sprite"))
+  : Block(sprite_manager->create("images/objects/bonus_block/infoblock.sprite")), shown_pct(0), dest_pct(0)
 {
   Vector pos;
   lisp.get("x", pos.x);
@@ -42,6 +43,7 @@ InfoBlock::InfoBlock(const lisp::Lisp& lisp)
   //stopped = false;
   //ringing = new AmbientSound(get_pos(), 0.5, 300, 1, "sounds/phone.wav");
   //Sector::current()->add_object(ringing);
+  infoBox.reset(new InfoBox(message));
 }
 
 InfoBlock::~InfoBlock()
@@ -52,11 +54,93 @@ void
 InfoBlock::hit(Player& )
 {
   start_bounce();
+
   //if (!stopped) {
   //  ringing->remove_me();
   //  stopped = true;
   //}
-  GameSession::current()->display_info_box(message);
+
+  if (dest_pct != 1) {
+
+    // first hide all other InfoBlocks' messages in same sector
+    Sector* parent = Sector::current();
+    if (!parent) return;
+    for (Sector::GameObjects::iterator i = parent->gameobjects.begin(); i != parent->gameobjects.end(); i++) {
+      InfoBlock* block = dynamic_cast<InfoBlock*>(*i);
+      if (!block) continue;
+      if (block != this) block->hide_message();
+    }
+
+    // show our message
+    show_message();
+
+  } else {
+    hide_message();
+  }
+}
+
+Player*
+InfoBlock::get_nearest_player()
+{
+  // FIXME: does not really return nearest player
+
+  std::vector<Player*> players = Sector::current()->get_players();
+  for (std::vector<Player*>::iterator playerIter = players.begin(); playerIter != players.end(); ++playerIter) {
+    Player* player = *playerIter;
+    return player;
+  }
+
+  return 0;
+}
+
+void
+InfoBlock::update(float delta)
+{
+  if (delta == 0) return;
+
+  // hide message if player is too far away
+  if (dest_pct > 0) {
+    Player* player = get_nearest_player();
+    if (player) {
+      Vector p1 = this->get_pos() + (this->get_bbox().p2 - this->get_bbox().p1) / 2;
+      Vector p2 = player->get_pos() + (player->get_bbox().p2 - player->get_bbox().p1) / 2;
+      Vector dist = (p2 - p1);
+      float d = dist.norm();
+      if (d > 128) dest_pct = 0;
+    }
+  }
+
+  // handle soft fade-in and fade-out
+  if (shown_pct != dest_pct) {
+    if (dest_pct > shown_pct) shown_pct = std::min(shown_pct + 2*delta, dest_pct);
+    if (dest_pct < shown_pct) shown_pct = std::max(shown_pct - 2*delta, dest_pct);
+  }
+}
+
+void
+InfoBlock::draw(DrawingContext& context)
+{
+  Block::draw(context);
+
+  if (shown_pct > 0) {
+    context.push_transform();
+    context.set_translation(Vector(0, 0));
+    context.set_alpha(shown_pct);
+    infoBox->draw(context);
+    context.pop_transform();
+  }
+}
+
+void
+InfoBlock::show_message()
+{
+  dest_pct = 1;
+}
+
+void
+InfoBlock::hide_message()
+{
+  dest_pct = 0;
 }
 
 IMPLEMENT_FACTORY(InfoBlock, "infoblock")
index 7f9b051..65eaf16 100644 (file)
 
 #include "block.hpp"
 //#include "object/ambient_sound.hpp"
+#include "textscroller.hpp"
 
 class InfoBlock : public Block
 {
 public:
   InfoBlock(const lisp::Lisp& lisp);
   virtual ~InfoBlock();
+  void update(float elapsed_time);
+  void draw(DrawingContext& context);
+
+  void show_message();
+  void hide_message();
 
 protected:
   virtual void hit(Player& player);
   std::string message;
   //AmbientSound* ringing;
   //bool stopped;
+  float shown_pct; /**< Value in the range of 0..1, depending on how much of the infobox is currently shown */
+  float dest_pct; /**< With each call to update(), shown_pct will slowly transition to this value */
+  std::auto_ptr<InfoBox> infoBox;
+
+  Player* get_nearest_player();
 };
 
 #endif