pingus-cvs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Pingus-CVS] CVS: Games/Pingus/src/worldmap graph.cxx,NONE,1.1 graph.hxx


From: grumbel
Subject: [Pingus-CVS] CVS: Games/Pingus/src/worldmap graph.cxx,NONE,1.1 graph.hxx,NONE,1.1 manager.cxx,NONE,1.1 manager.hxx,NONE,1.1 node.cxx,NONE,1.1 node.hxx,NONE,1.1 node_data.cxx,NONE,1.1 node_data.hxx,NONE,1.1 pingus.cxx,NONE,1.1 pingus.hxx,NONE,1.1 stat.cxx,NONE,1.1 stat.hxx,NONE,1.1 worldmap.cxx,NONE,1.1 worldmap.hxx,NONE,1.1 Makefile.am,1.3,1.4 PingusWorldMap.cc,1.41,NONE PingusWorldMap.hh,1.28,NONE PingusWorldMapGraph.cc,1.34,NONE PingusWorldMapGraph.hh,1.24,NONE PingusWorldMapManager.cc,1.25,NONE PingusWorldMapManager.hh,1.11,NONE PingusWorldMapNode.cc,1.6,NONE PingusWorldMapNode.hh,1.5,NONE PingusWorldMapNodeData.cc,1.5,NONE PingusWorldMapNodeData.hh,1.5,NONE PingusWorldMapPingus.cc,1.16,NONE PingusWorldMapPingus.hh,1.14,NONE PingusWorldMapStat.cc,1.8,NONE PingusWorldMapStat.hh,1.8,NONE
Date: 12 Jun 2002 19:03:36 -0000

Update of /usr/local/cvsroot/Games/Pingus/src/worldmap
In directory dark:/tmp/cvs-serv12708

Modified Files:
        Makefile.am 
Added Files:
        graph.cxx graph.hxx manager.cxx manager.hxx node.cxx node.hxx 
        node_data.cxx node_data.hxx pingus.cxx pingus.hxx stat.cxx 
        stat.hxx worldmap.cxx worldmap.hxx 
Removed Files:
        PingusWorldMap.cc PingusWorldMap.hh PingusWorldMapGraph.cc 
        PingusWorldMapGraph.hh PingusWorldMapManager.cc 
        PingusWorldMapManager.hh PingusWorldMapNode.cc 
        PingusWorldMapNode.hh PingusWorldMapNodeData.cc 
        PingusWorldMapNodeData.hh PingusWorldMapPingus.cc 
        PingusWorldMapPingus.hh PingusWorldMapStat.cc 
        PingusWorldMapStat.hh 
Log Message:
The big rename...

--- NEW FILE: graph.cxx ---
//  $Id: graph.cxx,v 1.1 2002/06/12 19:03:33 grumbel Exp $
//
//  Pingus - A free Lemmings clone
//  Copyright (C) 2000 Ingo Ruhnke <address@hidden>
//
//  This program is free software; you can redistribute it and/or
//  modify it under the terms of the GNU General Public License
//  as published by the Free Software Foundation; either version 2
//  of the License, or (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

#include <ClanLib/Display/Display/display.h>
#include "../system.hxx"
#include "../my_gettext.hxx"
#include "../pingus_error.hxx"
#include "../path_manager.hxx"
#include "../xml_plf.hxx"
#include "../console.hxx"
#include "../xml_helper.hxx"
#include "../string_converter.hxx"
#include "../sound.hxx"
#include "../game_session.hxx"
#include "manager.hxx"
#include "node.hxx"
#include "graph.hxx"

using namespace Pingus::WorldMap;

Graph::Graph ()
{
  music = "pingus-1.it";
  //graph = 0;
}

Graph::~Graph ()
{
  //llif (graph) delete graph;
}
 
void
Graph::parse_file (std::string filename)
{
  doc = xmlParseFile(filename.c_str());

  if (!doc) {
    throw PingusError (_("Graph: File not found: ") + filename);
  }    

  xmlNodePtr cur = doc->ROOT;

  if (cur != NULL && strcmp((const char*)cur->name, "pingus-worldmap") == 0)
    {
      cur = cur->children;
      
      while (cur != NULL)
        {
          if (xmlIsBlankNode(cur)) 
            {
              cur = cur->next;
              continue;
            }

          if (strcmp ((char*)cur->name, "node-list") == 0)
            {
              parse_node_list (cur);
            }
          else if (strcmp ((char*)cur->name, "surface") == 0)
            {
              parse_background (cur);
            }
          else if (strcmp ((char*)cur->name, "music") == 0)
            {
              parse_music (cur);
            }
          else
            {
              printf("Graph: Unhandled: %s\n", (char*)cur->name);
            }
          cur = cur->next;
        }      
    }
  
  xmlFreeDoc(doc);
}

void
Graph::parse_node_list (xmlNodePtr cur)
{
  cur = cur->children;
  while (cur != NULL)
    {
      if (xmlIsBlankNode(cur)) 
        {
          cur = cur->next;
          continue;
        }

      if (strcmp((char*)cur->name, "empty") == 0)
        {
          NodeData* data = EmptyNodeData::create (doc, cur);
          nodes.push_back (boost::shared_ptr<class Node>
                           (data->create ()));
          delete data;
        }
      else if (strcmp((char*)cur->name, "level") == 0)
        {
          NodeData* data = LevelNodeData::create (doc, cur);
          nodes.push_back (boost::shared_ptr<class Node>
                           (data->create ()));
          delete data;
        }
      else if (strcmp((char*)cur->name, "tube") == 0)
        {
          NodeData* data = TubeNodeData::create (doc, cur);
          nodes.push_back (boost::shared_ptr<class Node>
                           (data->create ()));
          delete data;
        }
      else
        {
          printf("Graph:parse_node_list: Unhandled: %s\n", (char*)cur->name);   
  
        }
      cur = cur->next;
    } 
}

void
Graph::parse_background (xmlNodePtr cur)
{
  bg_desc = XMLhelper::parse_surface(doc, cur);
}

void
Graph::parse_music (xmlNodePtr cur)
{
  char* file = (char*)xmlGetProp(cur, (xmlChar*)"file");

  if (file)
    music = file;
  else
    {
      std::cout << "Graph: No music file given" << std::endl;
    }
}

ResDescriptor 
Graph::get_background ()
{
  return bg_desc;
}

std::string 
Graph::get_music ()
{
  return music;
}

/*Graph<PingusWorldMapNode>* 
  Graph::get_graph ()
  {
  return graph;
  }*/

void
Graph::draw (const CL_Vector& offset)
{
  //float x_scale = CL_Display::get_width () / 800.0;
  //float y_scale = CL_Display::get_height () / 600.0;

  for (iterator i = nodes.begin();
       i != nodes.end();
       ++i)
    {
      for (iterator j = nodes.begin();
           j != nodes.end();
           ++j)
        {
          CL_Vector i_pos = (*i)->get_pos ();
          CL_Vector j_pos = (*j)->get_pos ();

          for (std::list<int>::iterator k = (*i)->get_links ().begin();
               k != (*i)->get_links ().end();
               ++k)
            if ((*j)->get_id () == *k)
              CL_Display::draw_line ((int)(j_pos.x + offset.x), (int)(j_pos.y + 
offset.y),
                                     (int)(i_pos.x + offset.x), (int)(i_pos.y + 
offset.y),
                                     1.0, 1.0, 1.0, 1.0);
        }
    }
}

/* Fade out, fixme, doesn't work at the moment 
   CL_SurfaceProvider* provider = new TargetProvider (target);
   CL_Surface* sur = CL_Surface::create (provider);

   for (int y = 0; y < CL_Display::get_height(); 
   y += CL_Display::get_height() / 40)
   {
   CL_System::keep_alive ();
   CL_Display::clear_display ();
   sur->put_screen (0, y);
   Display::flip_display ();
   }
                      
   delete sur;
   delete provider;
*/

/* EOF */

--- NEW FILE: graph.hxx ---
//  $Id: graph.hxx,v 1.1 2002/06/12 19:03:33 grumbel Exp $
// 
//  Pingus - A free Lemmings clone
//  Copyright (C) 2000 Ingo Ruhnke <address@hidden>
//
//  This program is free software; you can redistribute it and/or
//  modify it under the terms of the GNU General Public License
//  as published by the Free Software Foundation; either version 2
//  of the License, or (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
// 
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

#ifndef PINGUSWORLDMAPGRAPH_HH
#define PINGUSWORLDMAPGRAPH_HH

#include "../res_descriptor.hxx"
#include "../boost/smart_ptr.hpp"
#include "node.hxx"

class _xmlDoc;  typedef _xmlDoc*  xmlDocPtr;
class _xmlNode; typedef _xmlNode* xmlNodePtr;

namespace Pingus
{
  namespace WorldMap
  {

    class Graph
    {
    private:
      //Graph<Node>* graph;
      ResDescriptor bg_desc;
      std::string music;
      xmlDocPtr doc;
  
    public:
      std::list<boost::shared_ptr<Pingus::WorldMap::Node> >   nodes;
      typedef std::list<boost::shared_ptr<Pingus::WorldMap::Node> >::iterator 
iterator;

      Graph ();
      ~Graph ();
 
      ResDescriptor              get_background ();
      //Graph<Node>* get_graph ();
      std::string get_music ();
  
      void draw (const CL_Vector&);

      /// Some functions to parse the data out of an xml file
      //@{ 
      void parse_file (std::string filename);
    private:
      void parse_node_list (xmlNodePtr);
      void parse_music (xmlNodePtr);
      void parse_background (xmlNodePtr);
      //@}
    };
  }
}

#endif

/* EOF */

--- NEW FILE: manager.cxx ---
//  $Id: manager.cxx,v 1.1 2002/06/12 19:03:33 grumbel Exp $
//
//  Pingus - A free Lemmings clone
//  Copyright (C) 2000 Ingo Ruhnke <address@hidden>
//
//  This program is free software; you can redistribute it and/or
//  modify it under the terms of the GNU General Public License
//  as published by the Free Software Foundation; either version 2
//  of the License, or (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

#include <ClanLib/Display/Input/input.h>
#include "../path_manager.hxx"
#include "../delta_manager.hxx"
#include "../algo.hxx"
#include "../display.hxx"
#include "worldmap.hxx"
#include "manager.hxx"

using namespace Pingus;
using namespace Pingus::WorldMap;

WorldMapManager* WorldMapManager::current_manager;

WorldMapManager::WorldMapManager ()
{
  current_manager = this;
  is_init = false;
}

WorldMapManager::~WorldMapManager ()
{
}

void 
WorldMapManager::init ()
{
  if (!is_init)
    {
      //sur = PingusResource::load_surface ("volcano", "worldmaps");
      is_init = true;
    }
}

void
WorldMapManager::display ()
{
  on_button_press_slot   = CL_Input::sig_button_press ().connect (this, 
&WorldMapManager::on_button_press);
  on_button_release_slot = CL_Input::sig_button_release ().connect (this, 
&WorldMapManager::on_button_release);
  on_mouse_move_slot     = CL_Input::sig_mouse_move ().connect (this, 
&WorldMapManager::on_mouse_move);

  init ();

  worldmap = boost::shared_ptr<WorldMap::WorldMap>
    (new WorldMap::WorldMap (path_manager.complete("worldmaps/volcano.xml")));

  worldmap->init ();

  exit_worldmap = false;
  DeltaManager delta;
  while (!worldmap->do_exit ())
    {
      worldmap->draw ();
      worldmap->update (delta.getset ());

      if (new_worldmap.get ())
        {
          worldmap = new_worldmap;
          new_worldmap = boost::shared_ptr<WorldMap::WorldMap>();
        }

      CL_System::sleep (20);
      CL_System::keep_alive ();
      Display::flip_display ();
    }

  CL_Input::sig_button_press ().disconnect(on_button_press_slot);
  CL_Input::sig_button_release ().disconnect(on_button_release_slot);
  CL_Input::sig_mouse_move ().disconnect(on_mouse_move_slot);
}

void
WorldMapManager::on_mouse_move (CL_InputDevice *, int /*mouse_x*/, int 
/*mouse_y*/)
{
  //  std::cout << "mouse: " << mouse_x << " " << mouse_y << std::endl;  
}

void 
WorldMapManager::on_button_press (CL_InputDevice *device, const CL_Key &key)
{
  worldmap->on_button_press (device, key);
}

void 
WorldMapManager::on_button_release (CL_InputDevice * /*device*/, const CL_Key & 
/*key*/)
{
  //  std::cout << "key release: " << key.id << std::endl;
}

void
WorldMapManager::on_resize(int w, int h)
{
  std::cout << "Width: " << w << " Height: " << h << std::endl;
}

void 
WorldMapManager::change_map (std::string filename, int node)
{
  new_worldmap = boost::shared_ptr<WorldMap::WorldMap>
    (new WorldMap::WorldMap (path_manager.complete("worldmaps/" + filename)));
  new_worldmap->set_pingus (node);
}

/* EOF */

--- NEW FILE: manager.hxx ---
//  $Id: manager.hxx,v 1.1 2002/06/12 19:03:33 grumbel Exp $
// 
//  Pingus - A free Lemmings clone
//  Copyright (C) 2000 Ingo Ruhnke <address@hidden>
//
//  This program is free software; you can redistribute it and/or
//  modify it under the terms of the GNU General Public License
//  as published by the Free Software Foundation; either version 2
//  of the License, or (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
// 
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

#ifndef PINGUSWORLDMAPMANAGER_HH
#define PINGUSWORLDMAPMANAGER_HH

#include <ClanLib/Signals/slot.h>
#include "../boost/smart_ptr.hpp"

class CL_InputDevice;
class CL_Key;

namespace Pingus
{
  namespace WorldMap
  {
    class WorldMap;
  }

  /**  */
  class WorldMapManager
  {
  private:
    bool is_init;
    bool exit_worldmap;
    boost::shared_ptr<WorldMap::WorldMap> worldmap;
    boost::shared_ptr<WorldMap::WorldMap> new_worldmap;

    /// Some slots to manage the event handling
    //@{
    CL_Slot on_button_press_slot;
    CL_Slot on_button_release_slot;
    CL_Slot on_mouse_move_slot;
    CL_Slot on_resize_slot;
    //@}

    static WorldMapManager* current_manager;

  public:
    WorldMapManager ();
    ~WorldMapManager ();
  
  private:
    /// Load all required resources if not already done
    void init ();

    void on_button_press (CL_InputDevice *device, const CL_Key &key);
    void on_button_release (CL_InputDevice *device, const CL_Key &key);
    void on_mouse_move(CL_InputDevice *,int mouse_x, int mouse_y);
    void on_resize(int w, int h);

  public:
    /// Display the worldmap and let the user select a level
    void display ();
    void change_map (std::string filename, int node);

    static WorldMapManager* get_current () { return current_manager; } 
  };

}

#endif

/* EOF */




--- NEW FILE: node.cxx ---
//  $Id: node.cxx,v 1.1 2002/06/12 19:03:33 grumbel Exp $
//
//  Pingus - A free Lemmings clone
//  Copyright (C) 2000 Ingo Ruhnke <address@hidden>
//
//  This program is free software; you can redistribute it and/or
//  modify it under the terms of the GNU General Public License
//  as published by the Free Software Foundation; either version 2
//  of the License, or (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

#include "manager.hxx"
#include "node.hxx"
#include "../my_gettext.hxx"
#include "../path_manager.hxx"
#include "../system.hxx"
#include "../game_session.hxx"
#include "../game_session_result.hxx"
#include "../console.hxx"
#include "../xml_plf.hxx"
#include "../pingus_error.hxx"
#include "../sound.hxx"
#include "node.hxx"

using namespace Pingus::WorldMap;

TubeNode::TubeNode (const TubeNodeData& data)
  : TubeNodeData (data),
    worldmap_name ("pacman.xml"),
    tube ("worldmap/tube", "core")
{
  tube.set_align (-16, -32);
}


void 
TubeNode::on_click ()
{
  std::cout << "Not Supported" << std::endl;
  WorldMapManager::get_current ()->change_map (worldmap_name, link_node);
}

void 
TubeNode::draw (CL_Vector offset)
{
  tube.put_screen (pos + offset);
}

std::string
TubeNode::get_string ()
{
  return _("Tube");
}

LevelNode::LevelNode (const LevelNodeData& data)
  : LevelNodeData (data),
    green_dot ("worldmap/dot_green", "core"),
    red_dot ("worldmap/dot_red", "core"),
    invalid_dot ("worldmap/dot_invalid", "core"),
    dot_border ("Game/dot_border", "game"),
    green_flag ("worldmap/flaggreen", "core"),
    plf (0),
    invalid (false)
{
  //accessible = false;
  finished = false;

  green_flag.set_align (-24, -36);
  green_dot.set_align_center ();
  invalid_dot.set_align_center ();
  red_dot.set_align_center ();
  dot_border.set_align_center ();

  try 
    {
      plf = new XMLPLF (path_manager.complete (levelname));
    } 
  catch (PingusError& e) 
    {
      std::cout << "PingusWorldMapGraph: Caught PingusError (" << e.get_message 
() << ")" << std::endl;
      std::cout << "PingusWorldMapGraph: Failed to load '" << levelname << "', 
fallback to level1.xml" << std::endl;
      invalid = true;
    }
}

LevelNode::~LevelNode ()
{
  delete plf;
}

void 
LevelNode::on_click ()
{
  if (!invalid)
    {
      if (maintainer_mode) 
        std::cout << "Start a level...: " << levelname << std::endl;
                  
      PingusSound::play_sound(path_manager.complete("sounds/letsgo.wav"));
      /** We could reuse the plf here */
      PingusGameSession game (path_manager.complete(levelname));
      
      // Launch the game and wait until it is finished
      game.start ();

      if (game.get_result ().finished ())
        {
          finished = true;      
        }
      else
        {
          console.puts("Please try again!");
        }
    }
  else
    {
      std::cout << "LevelNode::on_click (): Error: level is invalid" << 
std::endl;
    }
}

void 
LevelNode::mark (bool value)
{
  finished = value;
}

void 
LevelNode::draw (CL_Vector offset)
{
  if (!levelname.empty())
    {
      if (!invalid)
        {
          if (/* accessible */ true) 
            {
              green_dot.put_screen (pos + offset);
              if (finished) {
                green_flag.put_screen (pos + offset);
              }
            }
          else
            {
              red_dot.put_screen (pos + offset);
            }
        }
      else
        {
          invalid_dot.put_screen (pos + offset);
        }
    }
}

std::string
LevelNode::get_string ()
{
  if (!invalid)
    return System::translate(plf->get_levelname ());
  else
    return _("invalid level");
}

PLF*
LevelNode::get_plf ()
{
  return plf;
}

/* EOF */

--- NEW FILE: node.hxx ---
//  $Id: node.hxx,v 1.1 2002/06/12 19:03:33 grumbel Exp $
// 
//  Pingus - A free Lemmings clone
//  Copyright (C) 2000 Ingo Ruhnke <address@hidden>
//
//  This program is free software; you can redistribute it and/or
//  modify it under the terms of the GNU General Public License
//  as published by the Free Software Foundation; either version 2
//  of the License, or (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
// 
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

#ifndef PINGUSWORLDMAPNODE_HH
#define PINGUSWORLDMAPNODE_HH

#include "../sprite.hxx"
#include "../globals.hxx"
#include "node_data.hxx"

class CL_Vector;
class PLF;

namespace Pingus
{
  namespace WorldMap
  {
    /** An object on the worldmap */
    class Node 
    {
    public:
      /** should links or nodes be accessible? */
      bool accessible;
  
      Node () {}
      virtual ~Node () {}

      virtual void on_click () =0;
      virtual void mark (bool /*value*/) {}
      virtual void draw (CL_Vector /*offset*/) {}
      virtual std::string get_string () =0;

      virtual int  get_id () =0;
      virtual CL_Vector get_pos () =0;
      virtual std::list<int>& get_links () =0;
    };

    /** A wrap object which brings you to the next worldmap */
    class TubeNode
      : public Node,
        public TubeNodeData
    {
    public:
      std::string worldmap_name;
      Sprite tube;
      int link_node;
    public:  
      TubeNode (const TubeNodeData&);
      void on_click ();
      void draw (CL_Vector offset);
      std::string get_string ();

      /** FIXME: this looks unnecesarry, could probally replaced by
          FIXME: templates or something like that */
      int  get_id () { return NodeData::get_id (); }
      CL_Vector get_pos () { return NodeData::get_pos (); }
      std::list<int>& get_links () { return NodeData::get_links (); }
    };

    /** The entrance to a level */
    class LevelNode
      :  public Pingus::WorldMap::Node,
         public Pingus::WorldMap::LevelNodeData
    {
    private:
      Sprite green_dot;
      Sprite red_dot;
      Sprite invalid_dot;
      Sprite dot_border;
      Sprite green_flag;

      PLF* plf;
  
      /** true if the level is invalid, which means that the levelfile
          could not be loaded or had errors. false is the default */
      bool invalid;

    public:
      bool finished;
      PLF* get_plf ();

      LevelNode (const LevelNodeData&);
      virtual ~LevelNode ();
      void on_click ();
      void mark (bool value);
      void draw (CL_Vector offset);
      std::string get_string ();


      /** FIXME: this looks unnecesarry, could probally replaced by
          FIXME: templates or something like that */
      int  get_id () { return NodeData::get_id (); }
      CL_Vector get_pos () { return NodeData::get_pos (); }
      std::list<int>& get_links () { return NodeData::get_links (); }
    };
  }
}

#endif

/* EOF */

--- NEW FILE: node_data.cxx ---
//  $Id: node_data.cxx,v 1.1 2002/06/12 19:03:33 grumbel Exp $
//
//  Pingus - A free Lemmings clone
//  Copyright (C) 2000 Ingo Ruhnke <address@hidden>
//
//  This program is free software; you can redistribute it and/or
//  modify it under the terms of the GNU General Public License
//  as published by the Free Software Foundation; either version 2
//  of the License, or (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

#include "../string_converter.hxx"
#include "../xml_helper.hxx"
#include "node.hxx"

using namespace Pingus::WorldMap;

Node*
NodeData::create ()
{
  /* FIXME: This looks clearly like a design bug. This class should
     FIXME: probally be split of even more */
  assert (!"Node* create (): This should never be reached!");
  return 0; 
}

Node*
TubeNodeData::create ()
{
  return new TubeNode (*this);
}

Node*
LevelNodeData::create ()
{
  return new LevelNode (*this);
}

Node*
EmptyNodeData::create ()
{
  return 0;//FIXME:new EmptyNode (*this);
}

NodeData*
NodeData::create(xmlDocPtr doc, xmlNodePtr cur)
{
  NodeData* node = new NodeData ();
  
  char* id = (char*)xmlGetProp(cur, (xmlChar*)"id");
  if (id)
    node->id = StringConverter::to_int (id);
  else
    std::cout << "PingusWorldMapGraph::parse_node: no node id given" << 
std::endl;

  /* Accesibility should probally be placed on the links?!
  char* accessible = (char*)xmlGetProp(cur, (xmlChar*)"accessible");
  if (accessible)
    node->accessible = StringConverter::to_int (accessible);
  */

  cur = cur->children;

  while (cur != NULL)
    {
      if (xmlIsBlankNode(cur)) 
        {
          cur = cur->next;
          continue;
        }

      if (strcmp((char*)cur->name, "position") == 0)
        {
          node->pos = XMLhelper::parse_vector (doc, cur);
        }
      else if (strcmp((char*)cur->name, "link") == 0)
        {
          char* id = (char*)xmlGetProp(cur, (xmlChar*)"id");
          if (id)
            node->links.push_back(StringConverter::to_int (id));
          else
            std::cout << "PingusWorldMapGraph::parse_node: no id given" << 
std::endl;       
        }
      else
        {
          printf("PingusWorldMapGraph:parse_node: Unhandled: %s\n", 
(char*)cur->name);    
        }

      cur = cur->next;
    }  

  return node;
}

TubeNodeData*
TubeNodeData::create(xmlDocPtr doc, xmlNodePtr cur)
{
  TubeNodeData* node = new TubeNodeData ();

  cur = cur->children;
  
  while (cur != NULL)
    {
      if (xmlIsBlankNode(cur)) 
        {
          cur = cur->next;
          continue;
        }

      if (strcmp((char*)cur->name, "node") == 0)
        {
          NodeData* node_data = NodeData::create (doc, cur);
          node->assign(*node_data);
          delete node_data;
        }
      else if (strcmp((char*)cur->name, "worldmap") == 0)
        {
          char* link_node = (char*)xmlGetProp(cur, (xmlChar*)"linknode");
          if (link_node)
            from_string (link_node, node->link_node);
          else
            std::cout << "PingusWorldMapGraph::parse_tube: no node 'linknode' 
given" << std::endl;

          node->worldmap = XMLhelper::parse_string (doc, cur);
        }
      else if (strcmp((char*)cur->name, "link") == 0)
        {
          char* id = (char*)xmlGetProp(cur, (xmlChar*)"id");
          if (id)
            node->links.push_back(StringConverter::to_int (id));
          else
            std::cout << "PingusWorldMapGraph::parse_node: no id given" << 
std::endl;       
        }
      else
        {
          std::cout << "PingusWorldMapGraph: unhandled" << std::endl;
        }

      cur = cur->next;
    }
  return node;
}


LevelNodeData*
LevelNodeData::create(xmlDocPtr doc, xmlNodePtr cur)
{
  LevelNodeData* node = new LevelNodeData ();

  cur = cur->children;
  
  while (cur != NULL)
    {
      if (xmlIsBlankNode(cur)) 
        {
          cur = cur->next;
          continue;
        }

      if (strcmp((char*)cur->name, "node") == 0)
        {
          NodeData* node_data = NodeData::create (doc, cur);
          node->assign(*node_data);
          delete node_data;
        }
      else if (strcmp((char*)cur->name, "level") == 0)
        {
          char* level = (char*)xmlGetProp(cur, (xmlChar*)"name");
          if (level)
            node->levelname = std::string("levels/") + level;
          else
            std::cout << "PingusWorldMapGraph::parse_node: no levelname given" 
<< std::endl;
        }
      else
        {
          std::cout << "PingusWorldMapLevelNodeData::create: unhandled" << 
std::endl;
        }

      cur = cur->next;
    }
  
  return node;  
}

NodeData* 
EmptyNodeData::create(xmlDocPtr /*doc*/, xmlNodePtr /*cur*/)
{
  return new EmptyNodeData ();
}

/* EOF */

--- NEW FILE: node_data.hxx ---
//  $Id: node_data.hxx,v 1.1 2002/06/12 19:03:33 grumbel Exp $
// 
//  Pingus - A free Lemmings clone
//  Copyright (C) 2000 Ingo Ruhnke <address@hidden>
//
//  This program is free software; you can redistribute it and/or
//  modify it under the terms of the GNU General Public License
//  as published by the Free Software Foundation; either version 2
//  of the License, or (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
// 
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

#ifndef PINGUSWORLDMAPNODEDATA_HH
#define PINGUSWORLDMAPNODEDATA_HH

#include <list>
#include <string>
#include <ClanLib/Core/Math/cl_vector.h>

class _xmlDoc;  typedef _xmlDoc*  xmlDocPtr;
class _xmlNode; typedef _xmlNode* xmlNodePtr;


/* Wannabe syntax of worldmaps:
   ----------------------------

   <level id="1" accessible="1">
   <node>
   <position>
   <x-pos>50</x-pos>
   <y-pos>377</y-pos>
   </position>
   <link id="2"/>
   </node>
      
   <level name="level1.xml"/>
   </level>

   <tube id="...">
   <node>
   ...
*/

namespace Pingus 
{
  namespace WorldMap 
  {
    class Node;

    /** Node */
    class NodeData
    {
    protected:
      /** The id of this node, id's have to be uniq in a worldmap */
      int id;

      /** List of connections to other node, the int values are the id's
          of other nodes */
      std::list<int> links;  

      /** The position of the node in the worldmap, pos.z is used for
          z-sorting */
      CL_Vector pos;

    public:
      virtual ~NodeData () {}

      int       get_id () { return id; } 
      CL_Vector get_pos () { return pos; } 
      std::list<int>& get_links () { return links; } 

      void assign (const NodeData& data) 
      {
        id    = data.id;
        links = data.links;
        pos   = data.pos;
      }
      virtual Node* create ();

      static NodeData* create(xmlDocPtr doc, xmlNodePtr cur);
    };

    /** EmptyNode */ 
    class EmptyNodeData
      : public NodeData
    {
    protected:
    public:
      virtual ~EmptyNodeData () {}

      virtual Node* create ();

      static NodeData* create(xmlDocPtr doc, xmlNodePtr cur);
    };

    /** Level */
    class LevelNodeData
      : public NodeData
    {
    protected:
      /** The filename of the level to start 

      FIXME: Is the filename relative to the worldmap directory,
      FIXME: relative to the ~/.pingus/ directory or what?
      */
      std::string levelname;
    public:
      virtual ~LevelNodeData () {}

      virtual Node* create ();

      static LevelNodeData* create(xmlDocPtr doc, xmlNodePtr cur);
      void write_xml(std::ofstream* xml) {}
    };

    /** Tube */
    class TubeNodeData
      : public NodeData
    {
    protected:
      /** The world to which this tupe 'beams' */
      std::string worldmap;
  
      /** The node id in the worldmap to which this tube beams/links */
      int link_node;
    public:
      virtual ~TubeNodeData () {}

      virtual Node* create ();

      static TubeNodeData* create(xmlDocPtr doc, xmlNodePtr cur);
    };
  }
}

#endif

/* EOF */




--- NEW FILE: pingus.cxx ---
//  $Id: pingus.cxx,v 1.1 2002/06/12 19:03:33 grumbel Exp $
//
//  Pingus - A free Lemmings clone
//  Copyright (C) 2000 Ingo Ruhnke <address@hidden>
//
//  This program is free software; you can redistribute it and/or
//  modify it under the terms of the GNU General Public License
//  as published by the Free Software Foundation; either version 2
//  of the License, or (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

#include <cmath>

#include "../pingus_resource.hxx"
#include "pingus.hxx"
#include "../boost/smart_ptr.hpp"

using namespace Pingus::WorldMap;

PingusWorldMapPingus::PingusWorldMapPingus ()
  : sprite ("Pingus/walker0", "pingus", 20.0f, Sprite::RIGHT)
{
  sprite.set_align (-sprite.get_width()/2,  4 - sprite.get_height());
  is_left = false;
}

PingusWorldMapPingus::~PingusWorldMapPingus ()
{
}

void 
PingusWorldMapPingus::set_position (boost::shared_ptr<Node> node)
{
  pos = node->get_pos ();
  current_node = node.get ();
}

void 
PingusWorldMapPingus::walk_to (Node* node)
{
  ///pos = node.pos;
  targets.push (node);
}

void
PingusWorldMapPingus::draw (const CL_Vector& offset)
{
  sprite.set_direction (is_left ? Sprite::LEFT : Sprite::RIGHT);
  sprite.put_screen (pos + offset);
}

bool
PingusWorldMapPingus::is_walking ()
{
  return false;
}

void
PingusWorldMapPingus::update (float delta)
{
  sprite.update (delta);

  if (!targets.empty ())
    {
      CL_Vector t_pos = targets.front ()->get_pos ();

      // Pingus found the target node
      if (pos.x > t_pos.x - 3
          && pos.x < t_pos.x + 3
          && pos.y > t_pos.y - 3
          && pos.y < t_pos.y + 3)
        { 
          pos = t_pos;
          current_node = targets.front();
          targets.pop ();
        }
      // Pingus needs to walk a bit to find the right node
      else
        {
          float x_off = t_pos.x - pos.x;
          float y_off = t_pos.y - pos.y;

          float x_delta = x_off * 45.0 / sqrt(x_off * x_off  + y_off * y_off);
          float y_delta = y_off * 45.0 / sqrt(x_off * x_off  + y_off * y_off);
     
          current_node = 0;
 
          if (x_delta > 0)
            is_left = false;
          else
            is_left = true;

          pos.x += x_delta * delta;
          pos.y += y_delta * delta;
        }  
    }
}

Node*
PingusWorldMapPingus::get_node ()
{
  return current_node;
}

/* EOF */

--- NEW FILE: pingus.hxx ---
//  $Id: pingus.hxx,v 1.1 2002/06/12 19:03:33 grumbel Exp $
// 
//  Pingus - A free Lemmings clone
//  Copyright (C) 2000 Ingo Ruhnke <address@hidden>
//
//  This program is free software; you can redistribute it and/or
//  modify it under the terms of the GNU General Public License
//  as published by the Free Software Foundation; either version 2
//  of the License, or (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
// 
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

#ifndef PINGUSWORLDMAPPINGUS_HH
#define PINGUSWORLDMAPPINGUS_HH

#include <queue>
#include "node.hxx"

namespace boost {
  template <class T> class shared_ptr;
}

/** This is the representation of the horde of Pingus which will walk
    on the worldmap */
class PingusWorldMapPingus
{
private:
  Sprite sprite;
  CL_Vector pos;
  std::queue<Pingus::WorldMap::Node*> targets;
  bool is_left;
  Pingus::WorldMap::Node* current_node;

public:
  PingusWorldMapPingus ();
  ~PingusWorldMapPingus ();

  void draw (const CL_Vector& offset);
  void update (float delta);
  void walk_to (Pingus::WorldMap::Node* node);
  bool is_walking ();
  void set_position (boost::shared_ptr<Pingus::WorldMap::Node> node);
  CL_Vector get_pos () { return pos; }
  Pingus::WorldMap::Node* get_node ();
};

#endif

/* EOF */

--- NEW FILE: stat.cxx ---
//  $Id: stat.cxx,v 1.1 2002/06/12 19:03:33 grumbel Exp $
//
//  Pingus - A free Lemmings clone
//  Copyright (C) 2000 Ingo Ruhnke <address@hidden>
//
//  This program is free software; you can redistribute it and/or
//  modify it under the terms of the GNU General Public License
//  as published by the Free Software Foundation; either version 2
//  of the License, or (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

#include <fstream>
#include <iostream>
#include "../system.hxx"
#include "../string_converter.hxx"
#include "../pingus_error.hxx"
#include "../xml_helper.hxx"
#include "stat.hxx"

using namespace Pingus::WorldMap;

PingusWorldMapNodeStat::PingusWorldMapNodeStat ()
{
  id = -1;
  finished = false;
  accessible = false;
  percentage = 25;
}

PingusWorldMapStat::PingusWorldMapStat (std::string worldmap_name)
  : is_empty (true)
{
  filename = System::get_statdir () + "stat/" + worldmap_name;

  if (System::exist (filename))
    {
      parse_file (filename);
      is_empty = false;
    }
}

void 
PingusWorldMapStat::parse_file (std::string filename)
{
  doc = xmlParseFile(filename.c_str());

  if (doc == NULL)
    throw PingusError("Couldn't open \"" + filename + "\" or syntax error.");

  xmlNodePtr cur = doc->ROOT;

  if (cur && strcmp((const char*)cur->name, "pingus-worldmap-stat") == 0) 
    {
      cur = cur->children;
      while (cur != NULL)
        {
          if (xmlIsBlankNode(cur)) 
            {
              cur = cur->next;
              continue;
            }

          if (strcmp((char*)cur->name, "node") == 0)
            {
              parse_node (cur);
            }
          else
            {
              std::cout << "PingusWorldMapStat: Unhandled:" << cur->name << 
std::endl;
            }
          
          cur = cur->next;
        }
    }
  else
    {
      std::cout << "Not a pingus-worldmap-stat: " << cur->name << std::endl;
    }

  xmlFreeDoc(doc);
}

void 
PingusWorldMapStat::parse_node (xmlNodePtr cur)
{
  PingusWorldMapNodeStat node;
  char* id         = (char*)xmlGetProp(cur, (xmlChar*)"id");
  char* accessible = (char*)xmlGetProp(cur, (xmlChar*)"accessible");
  char* finished   = (char*)xmlGetProp(cur, (xmlChar*)"finished");
  char* checksum   = (char*)xmlGetProp(cur, (xmlChar*)"checksum");

  //std::cout << "Parsing node: " << cur->name << std::endl;

  if (id) {
    from_string (id, node.id);
    free (id);
  } else {
    std::cout << "PingusWorldMapStat: id missing" << std::endl;
  }
  
  if (accessible) {
    node.accessible = StringConverter::to_int (accessible);
    free (accessible);    
  }
  
  if (finished) {
    node.finished = StringConverter::to_int (finished);
    free (finished);  
  }
  
  if (checksum) {
    //node.checksum = StringConverter::to_int (checksum);
    free (checksum);
  }

  stats[node.id] = node;
}

PingusWorldMapStat::~PingusWorldMapStat ()
{
}

bool 
PingusWorldMapStat::finished (int id)
{
  return stats[id].finished;
}

bool 
PingusWorldMapStat::accessible (int id)
{
  return stats[id].accessible;
}

void
PingusWorldMapStat::save (std::list<boost::shared_ptr<Node> >& nodes)
{
  std::ofstream out (filename.c_str ());
  
  if (!out)
    std::cout << "PingusWorldMapStat: Unexpected IO ERROR" << std::endl;
  else
    {
      out << "<pingus-worldmap-stat>" << std::endl;
      for (Graph::iterator i = nodes.begin ();
           i != nodes.end (); ++i)
        {
          LevelNode* node = dynamic_cast<LevelNode*>((*i).get ());

          if (node)
            {
              out << "  <node id=\"" << node->get_id () << "\" "
                //<< "accessible=\"" << node->accessible  << "\" "
                  << "finished=\"" << node->finished  << "\" "
                  << "checksum=\"not-impl\""
                  << "/>" << std::endl;
            }
        }
      out << "</pingus-worldmap-stat>" << std::endl;
    }
}

/* EOF */

--- NEW FILE: stat.hxx ---
//  $Id: stat.hxx,v 1.1 2002/06/12 19:03:33 grumbel Exp $
// 
//  Pingus - A free Lemmings clone
//  Copyright (C) 2000 Ingo Ruhnke <address@hidden>
//
//  This program is free software; you can redistribute it and/or
//  modify it under the terms of the GNU General Public License
//  as published by the Free Software Foundation; either version 2
//  of the License, or (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
// 
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

#ifndef PINGUSWORLDMAPSTAT_HH
#define PINGUSWORLDMAPSTAT_HH

#include <map>
#include "graph.hxx"

class _xmlDoc;  typedef _xmlDoc*  xmlDocPtr;
class _xmlNode; typedef _xmlNode* xmlNodePtr;


/** This class holds the information on a level's completeness, etc.
    It's only here for internal use by PingusWorldMapStat. */
class PingusWorldMapNodeStat
{
public:
  PingusWorldMapNodeStat ();

  int id;
  std::string levelfile;
  std::string checksum;
  bool finished;
  bool accessible;
  int  percentage;
};

/** Loads a status file and gives you access to the information, which
    levels where finished and how far they are finished. */
class PingusWorldMapStat
{
private:
  bool is_empty;
  std::map<int, PingusWorldMapNodeStat> stats;
  std::string filename;
  xmlDocPtr doc;

  /** Load the given file */
  void parse_file (std::string filename);
  
  /** Parse a given node */
  void parse_node (xmlNodePtr);

public:
  PingusWorldMapStat (std::string worldmap_name);
  ~PingusWorldMapStat ();  

  /** Save the given nodes status to the file from which they are
      loaded */
  void save (std::list<boost::shared_ptr<Pingus::WorldMap::Node> >& nodes);

  /// @return true if the node is finished
  bool finished (int id);
  
  /// @return true if the node with the given id is accessible, false otherwise
  bool accessible (int id);

  ///
  bool empty () { return is_empty; } 
};

#endif

/* EOF */

--- NEW FILE: worldmap.cxx ---
//  $Id: worldmap.cxx,v 1.1 2002/06/12 19:03:33 grumbel Exp $
//
//  Pingus - A free Lemmings clone
//  Copyright (C) 2000 Ingo Ruhnke <address@hidden>
//
//  This program is free software; you can redistribute it and/or
//  modify it under the terms of the GNU General Public License
//  as published by the Free Software Foundation; either version 2
//  of the License, or (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

#include <ClanLib/Core/System/system.h>
#include <ClanLib/Display/Display/display.h>
#include <ClanLib/Display/Input/input.h>
#include <ClanLib/Display/Input/keyboard.h>
#include <ClanLib/Display/Font/font.h>
#include <ClanLib/Display/Input/mouse.h>
#include "../path_manager.hxx"
#include "../pingus_error.hxx"
#include "../system.hxx"
#include "../globals.hxx"
#include "../display.hxx"
#include "../target_provider.hxx"
#include "../pingus_resource.hxx"
#include "../globals.hxx"
#include "../algo.hxx"
#include "../game_session.hxx"
#include "../blitter.hxx"
#include "../sound.hxx"
#include "../console.hxx"
#include "worldmap.hxx"
#include "pingus.hxx"

using namespace Pingus::WorldMap;

WorldMap::WorldMap (std::string filename) :
  font (PingusResource::load_font ("Fonts/pingus_small", "fonts")),
  green_dot ("worldmap/dot_green", "core"),
  red_dot ("worldmap/dot_red", "core"),
  dot_border ("Game/dot_border", "game"),
  green_flag ("worldmap/flaggreen", "core"),
  catch_input (true),
  do_quit (false),
  last_node (0)
{
  green_flag.set_align (-24, -36);
  green_dot.set_align_center ();
  red_dot.set_align_center ();
  dot_border.set_align_center ();

  graph_data.parse_file (filename);

  background = PingusResource::load_surface (graph_data.get_background ());

  //background = Blitter::scale_surface (background, CL_Display::get_width (), 
CL_Display::get_height ());
  
  pingus = new PingusWorldMapPingus;

  stat = boost::shared_ptr<PingusWorldMapStat>
    (new PingusWorldMapStat (System::basename(filename)));
  
  if (!stat->empty ())
    {
      for (GraphIter i = graph_data.nodes.begin ();
           i != graph_data.nodes.end ();
           ++i)
        {
          (*i)->mark(stat->finished ((*i)->get_id ()));
      
          if (!(*i)->accessible)
            (*i)->accessible = stat->accessible ((*i)->get_id ());
        }
      
      pingus->set_position (*graph_data.nodes.begin ());
    }
  else
    {
      pingus->set_position (*graph_data.nodes.begin ());
    }
}

WorldMap::~WorldMap ()
{
  //delete graph;
  delete pingus;
}

void 
WorldMap::save ()
{
  std::cout << "PingusWorldMap:save()" << std::endl;
  stat->save (graph_data.nodes);
}

CL_Vector 
WorldMap::get_offset ()
{
  // FIXME: Handling of background smaller than screen isn't handled
  assert (pingus);

  CL_Vector offset = pingus->get_pos ();
  offset *= -1.0;

  if (CL_Display::get_width () <= int(background.get_width ()))
    {
      offset.x += float(CL_Display::get_width ())/2;
      // When offset is larger then zero the background wouldn't fill the
      // complet screen, so we reset.
      if (offset.x > 0) offset.x = 0;
      if (offset.x < float(CL_Display::get_width ()) - background.get_width ())
        offset.x = float(CL_Display::get_width ()) - background.get_width ();
    } 
  else
    {
      offset.x = (float(CL_Display::get_width ()) - background.get_width ()) / 
2.0f;
    }

  if (CL_Display::get_height () <= int(background.get_height ()))
    {
      offset.y += float(CL_Display::get_height ())/2;
      if (offset.y > 0) offset.y = 0;
      if (offset.y < float(CL_Display::get_height ()) - background.get_height 
())
        offset.y = float(CL_Display::get_height ()) - background.get_height ();
    }
  else
    {
      offset.y = (float(CL_Display::get_height ()) - background.get_height ()) 
/ 2.0f;
    }
  
  return offset;
}

void
WorldMap::init ()
{
  std::cout << "PingusWorldMap::init" << std::endl;
  if (!graph_data.get_music ().empty ())
    PingusSound:: play_music (path_manager.complete("music/" + 
graph_data.get_music ()));
}

void 
WorldMap::disable_button_events ()
{
  catch_input = false;
}
  
void 
WorldMap::enable_button_events ()
{
  catch_input = true;
}

void 
WorldMap::on_button_press (CL_InputDevice *device, const CL_Key &key)
{
  if (!catch_input) return;

  if (device == CL_Input::keyboards[0])
    {
      switch(key.id)
        {
        case CL_KEY_ESCAPE:
          do_quit = true;
          break;
        default:
          break;
        }
    }
  else if (device == CL_Input::pointers[0])
    {
      CL_Vector offset = get_offset ();
      
      switch (key.id)
        {
        case CL_MOUSE_LEFTBUTTON:
          {
            NodePtr node
              = get_node ((int) (key.x - offset.x), (int) (key.y - offset.y));

            if (node.get() && !node->accessible)
              {
                PingusSound::play_sound("sounds/chink.wav");
              }
            else if (node.get() && node->accessible)
              {
                Pingus::WorldMap::Node* pingus_node = pingus->get_node ();
                if (maintainer_mode)
                  {
                    std::cout << "Click on: " << node->get_id () << std::endl;
                    std::cout << "Pingu at: " << pingus_node->get_id () << 
std::endl;
                  }

                if (pingus_node && pingus_node->get_id () == node->get_id ())
                  {
                    disable_button_events ();
                    node->on_click ();
                    
                    // FIXME: Ugly marking code... should be rewritten
                    for (std::list<int>::iterator k = node->get_links 
().begin();
                         k != node->get_links ().end();
                         ++k)
                      {
                        for (GraphIter i = graph_data.nodes.begin ();
                             i != graph_data.nodes.end ();
                             ++i)
                          {
                            if ((*i)->get_id () == *k)
                              (*i)->accessible = true;
                          }
                      }
                    
                    // Save the changes
                    save ();
      
                    enable_button_events ();
                  }
                else
                  {
                    pingus->walk_to (node.get ());
                  }
              }
            else
              {
                if (maintainer_mode)
                  std::cout << "no id clicked" << std::endl;
              }
          }
          break;
        case CL_MOUSE_MIDDLEBUTTON:
          {
            if (maintainer_mode)
              {
                std::cout << "<position>" << std::endl;
                std::cout << "  <x-pos>" << key.x - offset.x << "</x-pos>" << 
std::endl;
                std::cout << "  <y-pos>" << key.y - offset.y << "</y-pos>" << 
std::endl;
                std::cout << "</position>" << std::endl;
              }
          }
          break;
        case CL_MOUSE_RIGHTBUTTON:
          {
            //Node* node = get_node (key.x - offset.x, key.y - offset.y);

            /*if (node) {
              std::cout << "Node: " << node->id << std::endl;
              } else {
              std::cout << "No node selected" << std::endl;
              }*/
          }
          break;
        }
    }
}
 
void 
WorldMap::on_button_release (CL_InputDevice * /*device*/, const CL_Key & 
/*key*/)
{
  if (!catch_input) return;
}

void
WorldMap::start_level (Pingus::WorldMap::Node* /*node*/)
{

}

void
WorldMap::draw ()
{
  CL_Vector offset = get_offset ();
  
  if (offset.x > 0)
    CL_Display::clear_display ();

  background.put_screen ((int) offset.x, (int) offset.y);

  if (last_node.get () && last_node->accessible)
    {
      dot_border.put_screen (last_node->get_pos () + offset);
      
      font->print_center (CL_Display::get_width ()/2, CL_Display::get_height () 
- 40,
                          last_node->get_string().c_str ());

      /*
      if (last_node->finished)
        font->print_center (CL_Display::get_width ()/2, CL_Display::get_height 
() - 20,
                            "100%");
      else
        font->print_center (CL_Display::get_width ()/2, CL_Display::get_height 
() - 20,
                            "0%");
      */
    }

  graph_data.draw(offset);

  for (GraphIter i = graph_data.nodes.begin ();
       i != graph_data.nodes.end ();
       ++i)
    {
      (*i)->draw (get_offset ());
    }

  NodePtr node
    = get_node (CL_Mouse::get_x () - (int) offset.x,
                CL_Mouse::get_y () - (int) offset.y);
  // The mouse is over a node
  if (node.get ())
    {
      last_node = node;
      last_node_time = CL_System::get_time ();
    }
  else
    {
      if (last_node_time + 300 < CL_System::get_time ())
        {
          last_node = NodePtr(0);
        }
    }
 
  pingus->draw (offset);
}

void
WorldMap::update (float delta)
{
  pingus->update (delta);
}

boost::shared_ptr<Pingus::WorldMap::Node>
WorldMap::get_node (int x, int y)
{
  for (GraphIter i = graph_data.nodes.begin ();
       i != graph_data.nodes.end ();
       i++)
    {
      CL_Vector pos = (*i)->get_pos ();

      if (   pos.x - (int)(red_dot.get_width()/2) - 3 < x
             && pos.x + (int)(red_dot.get_width()/2) + 3 > x
             && pos.y - (int)(red_dot.get_width()/2) - 3 < y
             && pos.y + (int)(red_dot.get_width()/2) + 3 > y)
        {
          if (!(*i)->get_string ().empty ())
            return *i;
        }
    }
  return NodePtr(0);
}

void 
WorldMap::set_pingus (int node_id)
{
  for (GraphIter i = graph_data.nodes.begin ();
       i != graph_data.nodes.end ();
       i++)
    {
      if ((*i)->get_id () == node_id)
        {
          pingus->set_position (*i);
          return;
        }
    }
}

bool
WorldMap::do_exit () 
{
  return do_quit; 
}

/* EOF */

--- NEW FILE: worldmap.hxx ---
//  $Id: worldmap.hxx,v 1.1 2002/06/12 19:03:33 grumbel Exp $
// 
//  Pingus - A free Lemmings clone
//  Copyright (C) 2000 Ingo Ruhnke <address@hidden>
//
//  This program is free software; you can redistribute it and/or
//  modify it under the terms of the GNU General Public License
//  as published by the Free Software Foundation; either version 2
//  of the License, or (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
// 
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

#ifndef PINGUSWORLDMAP_HH
#define PINGUSWORLDMAP_HH

#include "stat.hxx"

class CL_Key;
class CL_Font;
class CL_InputDevice;
class PingusWorldMapPingus;

namespace Pingus
{
  namespace WorldMap
  {

    /** A class for loading, displaying and managing the worldmap. */
    class WorldMap
    {
    private:
      CL_Surface background;
      CL_Font*   font;

      Sprite green_dot;
      Sprite red_dot;
      Sprite dot_border;
      Sprite green_flag; 

      //Graph<PingusWorldMapNode>* graph;
      Graph graph_data;
      typedef Graph::iterator GraphIter;

      PingusWorldMapPingus* pingus;
  
      bool catch_input;

      bool do_quit;
      boost::shared_ptr<Pingus::WorldMap::Node> last_node;
      typedef boost::shared_ptr<Pingus::WorldMap::Node> NodePtr;
      unsigned int last_node_time;
  
      boost::shared_ptr<PingusWorldMapStat> stat;
    public:
      /** Load a worldmap from a given worldmap description file */
      WorldMap (std::string filename);

      /** Destruct the worldmap */
      ~WorldMap ();

      /** Launch the level at the given node
          @param node The current node from which the level should be started */
      void start_level (Pingus::WorldMap::Node* node);

      /** Start up the music and other things that need only to me run
          once on startup of a new WorldMap */
      void init ();

      /** Save the current status to a file */
      void save ();
  
      /** React on button press:
          - calculate which level was clicked
          - calculate the shortest path
          - let the pingu walk */
      void on_button_press (CL_InputDevice *device, const CL_Key &key);
 
      /** React on button release */
      void on_button_release (CL_InputDevice *device, const CL_Key &key);

      /** Disable all event catching */
      void disable_button_events ();
  
      /** Enable all event catching */
      void enable_button_events ();
  
      /** Draw the world worldmap */
      void draw ();
  
      /** Returns true if the worldmap is finished and the
          PingusWorldMapManager can quit */
      bool do_exit ();

      /** Let the woldmap do some stuff, like animating smoke, playing
          sounds or reacting on special events */
      void update (float delta);

      /** Returns a pointer to the node under the given coordinates */
      NodePtr get_node (int x, int y);
  
      /** Callculate the offset which is used for drawing and collision
          detection. The offset will be used for scrolling when the
          background is larger than the screen. 
          @return the currently used draw offset */
      CL_Vector get_offset ();

      /** Set the pingu to the given node with 'id' */
      void set_pingus (int node_id);
    };

  }
}

#endif

/* EOF */

Index: Makefile.am
===================================================================
RCS file: /usr/local/cvsroot/Games/Pingus/src/worldmap/Makefile.am,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- Makefile.am 4 Jun 2002 21:23:42 -0000       1.3
+++ Makefile.am 12 Jun 2002 19:03:33 -0000      1.4
@@ -19,20 +19,10 @@
 
 noinst_LIBRARIES = libpingus_worldmap.a
 
-libpingus_worldmap_a_SOURCES =    \
-       PingusWorldMap.cc         \
-       PingusWorldMap.hh         \
-        PingusWorldMapManager.cc  \
-        PingusWorldMapManager.hh  \
-        PingusWorldMapGraph.cc    \
-        PingusWorldMapGraph.hh    \
-        PingusWorldMapPingus.cc   \
-        PingusWorldMapPingus.hh   \
-        PingusWorldMapStat.hh     \
-        PingusWorldMapStat.cc     \
-        PingusWorldMapNode.hh     \
-        PingusWorldMapNode.cc     \
-        PingusWorldMapNodeData.hh \
-        PingusWorldMapNodeData.cc
+libpingus_worldmap_a_SOURCES = \
+graph.hxx    node.hxx      pingus.hxx  worldmap.hxx \
+manager.hxx  node_data.hxx  stat.hxx \
+graph.cxx    node.cxx      pingus.cxx  worldmap.cxx \
+manager.cxx  node_data.cxx  stat.cxx
 
 # EOF #

--- PingusWorldMap.cc DELETED ---

--- PingusWorldMap.hh DELETED ---

--- PingusWorldMapGraph.cc DELETED ---

--- PingusWorldMapGraph.hh DELETED ---

--- PingusWorldMapManager.cc DELETED ---

--- PingusWorldMapManager.hh DELETED ---

--- PingusWorldMapNode.cc DELETED ---

--- PingusWorldMapNode.hh DELETED ---

--- PingusWorldMapNodeData.cc DELETED ---

--- PingusWorldMapNodeData.hh DELETED ---

--- PingusWorldMapPingus.cc DELETED ---

--- PingusWorldMapPingus.hh DELETED ---

--- PingusWorldMapStat.cc DELETED ---

--- PingusWorldMapStat.hh DELETED ---




reply via email to

[Prev in Thread] Current Thread [Next in Thread]