- added read_string and read_int_vector to LispReader
authorIngo Ruhnke <grumbel@gmx.de>
Fri, 19 Mar 2004 23:03:07 +0000 (23:03 +0000)
committerIngo Ruhnke <grumbel@gmx.de>
Fri, 19 Mar 2004 23:03:07 +0000 (23:03 +0000)
- added worldmap

SVN-Revision: 263

src/lispreader.cpp
src/lispreader.h
src/worldmap.cpp [new file with mode: 0644]
src/worldmap.h [new file with mode: 0644]

index 1db09ed..c1145cc 100644 (file)
@@ -21,6 +21,7 @@
  * Boston, MA 02111-1307, USA.
  */
 
+#include <string>
 #include <assert.h>
 #include <ctype.h>
 #include <stdlib.h>
@@ -1058,6 +1059,34 @@ LispReader::read_float (const char* name, float* f)
 }
 
 bool
+LispReader::read_int_vector (const char* name, std::vector<int>* vec)
+{
+  lisp_object_t* obj = search_for (name);
+  if (obj)
+    {
+      while(!lisp_nil_p(obj))
+        {
+          vec->push_back(lisp_integer(lisp_car(obj)));
+          obj = lisp_cdr(obj);
+        }
+      return true;
+    }
+  return false;    
+}
+
+bool
+LispReader::read_string (const char* name, std::string* str)
+{
+  lisp_object_t* obj = search_for (name);
+  if (obj)
+    {
+      *str = lisp_string(lisp_car(obj));
+      return true;
+    }
+  return false;  
+}
+
+bool
 LispReader::read_bool (const char* name, bool* b)
 {
   lisp_object_t* obj = search_for (name);
index d427414..ddf5eec 100644 (file)
@@ -25,6 +25,7 @@
 #define __LISPREADER_H__
 
 #include <stdio.h>
+#include <string>
 #include <vector>
 
 #define LISP_STREAM_FILE       1
@@ -165,6 +166,8 @@ class LispReader
     /** cur == ((pos 1 2 3) (id 12 3 4)...) */
     LispReader (lisp_object_t* l);
 
+    bool read_int_vector (const char* name, std::vector<int>* vec);
+    bool read_string (const char* name, std::string* str);
     bool read_int (const char* name, int* i);
     bool read_float (const char* name, float* f);
     bool read_bool (const char* name, bool* b);
diff --git a/src/worldmap.cpp b/src/worldmap.cpp
new file mode 100644 (file)
index 0000000..d4a024c
--- /dev/null
@@ -0,0 +1,340 @@
+//  $Id$
+//
+//  Pingus - A free Lemmings clone
+//  Copyright (C) 2002 Ingo Ruhnke <grumbel@gmx.de>
+//
+//  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 <vector>
+#include <assert.h>
+#include "texture.h"
+#include "screen.h"
+#include "lispreader.h"
+#include "worldmap.h"
+
+namespace WorldMapNS {
+
+TileManager* TileManager::instance_  = 0;
+
+TileManager::TileManager()
+{
+  lisp_stream_t stream;
+  FILE* in = fopen(DATA_PREFIX "tiles/antarctica.scm", "r");
+  assert(in);
+  lisp_stream_init_file (&stream, in);
+  lisp_object_t* root_obj = lisp_read (&stream);
+  
+  if (strcmp(lisp_symbol(lisp_car(root_obj)), "supertux-worldmap-tiles") == 0)
+    {
+      lisp_object_t* cur = lisp_cdr(root_obj);
+
+      while(!lisp_nil_p(cur))
+        {
+          lisp_object_t* element = lisp_car(cur);
+
+          lisp_dump (element, stdout);
+          if (strcmp(lisp_symbol(lisp_car(element)), "tile") == 0)
+            {
+              int id = 0;
+              std::string filename = "<invalid>";
+
+              Tile* tile = new Tile;             
+              tile->north = true;
+              tile->east  = true;
+              tile->south = true;
+              tile->west  = true;
+              tile->stop  = true;
+  
+              LispReader reader(lisp_cdr(element));
+              reader.read_int("id",  &id);
+              reader.read_bool("north", &tile->north);
+              reader.read_bool("south", &tile->south);
+              reader.read_bool("west",  &tile->west);
+              reader.read_bool("east",  &tile->east);
+              reader.read_bool("stop",  &tile->stop);
+              reader.read_string("image",  &filename);
+
+              texture_load(&tile->sprite, 
+                           const_cast<char*>((std::string(DATA_PREFIX "/images/worldmap/") + filename).c_str()), 
+                           USE_ALPHA);
+
+              if (id >= tiles.size())
+                tiles.resize(id+1);
+
+              tiles[id] = tile;
+            }
+          else
+            {
+              puts("Unhandled symbol");
+            }
+
+          cur = lisp_cdr(cur);
+        }
+    }
+  else
+    {
+      assert(0);
+    }
+}
+
+Tile*
+TileManager::get(int i)
+{
+  assert(i >=0 && i < tiles.size());
+  return tiles[i];
+}
+
+WorldMap::WorldMap()
+{
+  quit = false;
+  width  = 20;
+  height = 15;
+  tux_moving = false;
+  tilemap.resize(width * height);
+  
+  tilemap[0] = 5;
+  tilemap[1] = 1;
+  tilemap[2] = 6;
+  tilemap[3] = 1;
+  tilemap[4] = 3;
+  tilemap[4+20] = 2;
+  tilemap[4+40] = 7;
+  tilemap[4+60] = 2;
+  tilemap[4+80] = 4;
+
+  texture_load(&tux_sprite, DATA_PREFIX "/images/worldmap/tux.png", USE_ALPHA);
+
+  tux_offset = 0;
+
+  tux_tile_pos.x = 0;
+  tux_tile_pos.y = 0;
+
+  input_direction = NONE;
+  tux_direction = NONE;
+  enter_level = false;
+}
+
+WorldMap::~WorldMap()
+{
+}
+
+void
+WorldMap::get_input()
+{
+  SDL_Event event;
+
+  enter_level = false;
+
+  while (SDL_PollEvent(&event))
+    {
+      switch(event.type)
+        {
+        case SDL_QUIT:
+          quit = true;
+          break;
+          
+        case SDL_KEYDOWN:
+          switch(event.key.keysym.sym)
+            {
+            case SDLK_ESCAPE:
+              quit = true;
+              break;
+            case SDLK_LCTRL:
+            case SDLK_RETURN:
+              if (!tux_moving)
+                enter_level = true;
+              break;
+            }
+          break;
+        }
+    }
+
+  Uint8 *keystate = SDL_GetKeyState(NULL);
+  
+  input_direction = NONE;
+  
+  if (keystate[SDLK_LEFT])
+    input_direction = WEST;
+  else if (keystate[SDLK_RIGHT])
+    input_direction = EAST;
+  else if (keystate[SDLK_UP])
+    input_direction = NORTH;
+  else if (keystate[SDLK_DOWN])
+    input_direction = SOUTH;
+}
+
+void
+WorldMap::update()
+{
+  float speed = 4.5;
+
+  if (enter_level)
+    {
+      puts("Enter the current level");
+    }
+  else
+    {
+      if (!tux_moving)
+        {
+          // FIXME: Cleanup, seperate tux
+          switch(input_direction)
+            {
+            case WEST:
+              if (at(tux_tile_pos)->west)
+                {
+                  tux_tile_pos.x -= 1;
+                  tux_moving = true;
+                  tux_direction = input_direction;
+                }
+              break;
+            case EAST:
+              if (at(tux_tile_pos)->east)
+                {
+                  tux_tile_pos.x += 1;
+                  tux_moving = true;
+                  tux_direction = input_direction;
+                }
+              break;
+            case NORTH:
+              if (at(tux_tile_pos)->north)
+                {
+                  tux_tile_pos.y -= 1;
+                  tux_moving = true;
+                  tux_direction = input_direction;
+                }
+              break;
+            case SOUTH:
+              if (at(tux_tile_pos)->south)
+                {
+                  tux_tile_pos.y += 1;
+                  tux_moving = true;
+                  tux_direction = input_direction;
+                }
+              break;
+            case NONE:
+              tux_moving = false;
+              tux_offset = 0;
+              tux_direction = input_direction;
+              break;
+            }
+        }
+      else
+        {
+          tux_offset += speed;
+
+          if (tux_offset > 32)
+            {
+              tux_offset -= 32;
+
+              if (at(tux_tile_pos)->stop)
+                {
+                  tux_direction = NONE;
+                  tux_moving = false;
+                }
+              else
+                {
+                  // FIXME: Cleanup, seperate tux
+                  switch(tux_direction)
+                    {
+                    case WEST:
+                      if (at(tux_tile_pos)->west)
+                        tux_tile_pos.x -= 1;
+                      break;
+                    case EAST:
+                      if (at(tux_tile_pos)->east)
+                        tux_tile_pos.x += 1;
+                      break;
+                    case NORTH:
+                      if (at(tux_tile_pos)->north)
+                        tux_tile_pos.y -= 1;
+                      break;
+                    case SOUTH:
+                      if (at(tux_tile_pos)->south)
+                        tux_tile_pos.y += 1;
+                      break;
+                    }                      
+                }
+            }
+        }
+    }
+}
+
+Tile*
+WorldMap::at(Point p)
+{
+  assert(p.x >= 0 
+         && p.x < width
+         && p.y >= 0
+         && p.y < height);
+  return TileManager::instance()->get(tilemap[width * p.y + p.x]);
+}
+
+void
+WorldMap::draw()
+{
+  for(int y = 0; y < height; ++y)
+    for(int x = 0; x < width; ++x)
+      {
+        Tile* tile = at(Point(x, y));
+        texture_draw(&tile->sprite, x*32, y*32, NO_UPDATE);
+      }
+
+  
+  float x = tux_tile_pos.x * 32;
+  float y = tux_tile_pos.y * 32;
+
+  switch(tux_direction)
+    {
+    case WEST:
+      x -= tux_offset - 32;
+      break;
+    case EAST:
+      x += tux_offset - 32;
+      break;
+    case NORTH:
+      y -= tux_offset - 32;
+      break;
+    case SOUTH:
+      y += tux_offset - 32;
+      break;
+    }
+
+  texture_draw(&tux_sprite, (int)x, (int)y, NO_UPDATE);
+  flipscreen();
+}
+
+void
+WorldMap::display()
+{
+  quit = false;
+
+  while(!quit) {
+    draw();
+    get_input();
+    update();
+    SDL_Delay(20);
+  }
+}
+
+} // namespace WorldMapNS
+
+void worldmap_run()
+{
+  WorldMapNS::WorldMap worldmap;
+  
+  worldmap.display();
+}
+
+/* EOF */
diff --git a/src/worldmap.h b/src/worldmap.h
new file mode 100644 (file)
index 0000000..ba29482
--- /dev/null
@@ -0,0 +1,120 @@
+//  $Id$
+// 
+//  SuperTux
+//  Copyright (C) 2004 Ingo Ruhnke <grumbel@gmx.de>
+//
+//  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 HEADER_WORLDMAP_HXX
+#define HEADER_WORLDMAP_HXX
+
+#include <vector>
+#include <string>
+
+namespace WorldMapNS {
+
+struct Point
+{
+  Point() : x(0), y(0) {}
+
+  Point(int x_, int y_)
+    : x(x_), y(y_) {}
+
+  int x;
+  int y;
+};
+
+struct Pointf
+{
+  float x;
+  float y;
+};
+
+struct Tile
+{
+  texture_type sprite;
+
+  // Directions in which Tux is allowed to walk from this tile
+  bool north;
+  bool east;
+  bool south;
+  bool west;
+
+  /** Stop on this tile or walk over it? */
+  bool stop;
+};
+
+class TileManager
+{
+private:
+  typedef std::vector<Tile*> Tiles;
+  Tiles tiles;
+  static TileManager* instance_ ;
+
+ TileManager();
+public:
+  static TileManager* instance() { return instance_ ? instance_ : instance_ = new TileManager(); }
+
+  void load();
+  Tile* get(int i);
+};
+
+/** */
+class WorldMap
+{
+private:
+  texture_type tux_sprite;
+  bool quit;
+  std::vector<int> tilemap;
+  int width;
+  int height;
+
+  enum Direction { NONE, WEST, EAST, NORTH, SOUTH };
+  Direction tux_direction;
+  Point tux_tile_pos;
+  /** Length by which tux is away from its current tile, length is in
+      input_direction direction */
+  float tux_offset;
+  bool tux_moving;
+
+  Direction input_direction;
+  bool enter_level;
+
+  Tile* at(Point pos);
+public:
+  WorldMap();
+  ~WorldMap();
+
+  /** Busy loop */
+  void display();
+  
+  void get_input();
+
+  /** Update Tux position */
+  void update();
+
+  /** Draw one frame */
+  void draw();
+};
+
+} // namespace WorldMapNS
+
+void worldmap_run();
+
+#endif
+
+/* Local Variables: */
+/* mode:c++ */
+/* End */