From 537b2ae5ee0a47eb361b5e651b048e917c7f8d5a Mon Sep 17 00:00:00 2001 From: Ingo Ruhnke Date: Fri, 19 Mar 2004 23:03:07 +0000 Subject: [PATCH] - added read_string and read_int_vector to LispReader - added worldmap SVN-Revision: 263 --- src/lispreader.cpp | 29 +++++ src/lispreader.h | 3 + src/worldmap.cpp | 340 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/worldmap.h | 120 +++++++++++++++++++ 4 files changed, 492 insertions(+) create mode 100644 src/worldmap.cpp create mode 100644 src/worldmap.h diff --git a/src/lispreader.cpp b/src/lispreader.cpp index 1db09ed9e..c1145cc6e 100644 --- a/src/lispreader.cpp +++ b/src/lispreader.cpp @@ -21,6 +21,7 @@ * Boston, MA 02111-1307, USA. */ +#include #include #include #include @@ -1058,6 +1059,34 @@ LispReader::read_float (const char* name, float* f) } bool +LispReader::read_int_vector (const char* name, std::vector* 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); diff --git a/src/lispreader.h b/src/lispreader.h index d42741468..ddf5eec1c 100644 --- a/src/lispreader.h +++ b/src/lispreader.h @@ -25,6 +25,7 @@ #define __LISPREADER_H__ #include +#include #include #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* 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 index 000000000..d4a024c28 --- /dev/null +++ b/src/worldmap.cpp @@ -0,0 +1,340 @@ +// $Id$ +// +// Pingus - A free Lemmings clone +// Copyright (C) 2002 Ingo Ruhnke +// +// 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 +#include +#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 = ""; + + 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((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 index 000000000..ba2948268 --- /dev/null +++ b/src/worldmap.h @@ -0,0 +1,120 @@ +// $Id$ +// +// SuperTux +// Copyright (C) 2004 Ingo Ruhnke +// +// 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 +#include + +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 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 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 */ -- 2.11.0