(name (_ "Welcome to Antarctica"))
(author "SuperTux Team")
(license "GPL 2+ / CC-by-sa 3.0")
+ (tilesets
+ (tileset
+ (file "images/tiles/tiles.stts")
+ (start 0)
+ (end 2153)
+ (offset 0)
+ )
+ )
(sector
(name "main")
(music "music/chipdisko.ogg")
(solid #f)
(width 310)
(height 19)
- (tilesets
- (tileset
- (file "images/tiles/tiles.stts")
- (start 0)
- (end 2153)
- (offset 0)
- )
- )
(tiles
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
(solid #t)
(width 310)
(height 19)
- (tilesets
- (tileset
- (file "images/tiles/tiles.stts")
- (start 0)
- (end 2153)
- (offset 0)
- )
- )
(tiles
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 11 11 11 11 11 11 11 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 133 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 132 132 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 86 87 88 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 86 87 88 0 0 0 0 0 0 0 0 0 0 0 0 0 0 77 77 77 77 77 77 77 77 77 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 86 87 88 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 11 11 11 11 11 11 11 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 86 87 88 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 133 0 85 86 87 88 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 132 132 0 0 0 0 0
(solid #f)
(width 310)
(height 19)
- (tilesets
- (tileset
- (file "images/tiles/tiles.stts")
- (start 0)
- (end 2153)
- (offset 0)
- )
- )
(tiles
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
(name "secret")
(width 310)
(height 19)
- (tilesets
- (tileset
- (file "images/tiles/tiles.stts")
- (start 0)
- (end 2153)
- (offset 0)
- )
- )
(tiles
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
for(size_t y = 0; y < tilemap->get_height()/2; ++y) {
// swap tiles
int y2 = tilemap->get_height()-1-y;
- const Tile* t1 = tilemap->get_tile(x, y);
- const Tile* t2 = tilemap->get_tile(x, y2);
- tilemap->change(x, y, t2->getID());
- tilemap->change(x, y2, t1->getID());
+ uint32_t t1 = tilemap->get_tile_id(x, y);
+ uint32_t t2 = tilemap->get_tile_id(x, y2);
+ tilemap->change(x, y, t2);
+ tilemap->change(x, y2, t1);
}
}
if(tilemap->get_drawing_effect() != 0) {
#include "physic.hpp"
#include "sector.hpp"
#include "tile.hpp"
+#include "tile_set.hpp"
+#include "tile_manager.hpp"
#include "resources.hpp"
#include "file_system.hpp"
#include "object/gameobjs.hpp"
using namespace std;
Level::Level()
- : name("noname"), author("Mr. X")
+ : name("noname"), author("Mr. X"), tileset(NULL), free_tileset(false)
{
}
+Level::~Level()
+{
+ for(Sectors::iterator i = sectors.begin(); i != sectors.end(); ++i)
+ delete *i;
+ if(free_tileset)
+ delete tileset;
+}
+
void
Level::load(const std::string& filepath)
{
return;
}
+ const lisp::Lisp* tilesets_lisp = level->get_lisp("tilesets");
+ if(tilesets_lisp != NULL) {
+ tileset = tile_manager->parse_tileset_definition(*tilesets_lisp);
+ free_tileset = true;
+ }
+ std::string tileset_name;
+ if(level->get("tileset", tileset_name)) {
+ if(tileset != NULL) {
+ log_warning << "multiple tilesets specified in level" << std::endl;
+ } else {
+ tileset = tile_manager->get_tileset(tileset_name);
+ }
+ }
+ /* load default tileset */
+ if(tileset == NULL) {
+ tileset = tile_manager->get_tileset("images/tiles.strf");
+ }
+ current_tileset = tileset;
+
contact = "";
license = "";
if(version > 2) {
log_warning << "level format newer than application" << std::endl;
}
+ } else if(token == "tileset" || token == "tilesets") {
+ continue;
} else if(token == "name") {
iter.value()->get(name);
} else if(token == "author") {
}
}
- if (license == "") log_warning << "The level author did not specify a license for this level. You might not be allowed to share it." << std::endl;
+ if (license == "") {
+ log_warning << "The level author did not specify a license for this level. You might not be allowed to share it." << std::endl;
+ }
} catch(std::exception& e) {
std::stringstream msg;
msg << "Problem when reading level '" << filepath << "': " << e.what();
throw std::runtime_error(msg.str());
}
+
+ current_tileset = NULL;
}
void
delete writer;
}
-Level::~Level()
-{
- for(Sectors::iterator i = sectors.begin(); i != sectors.end(); ++i)
- delete *i;
-}
-
void
Level::add_sector(Sector* sector)
{
class Lisp;
}
+class TileSet;
+
/**
* Represents a collection of Sectors running in a single GameSession.
*
class Level
{
public:
+ typedef std::vector<Sector*> Sectors;
+
std::string name;
std::string author;
std::string contact;
std::string license;
std::string on_menukey_script;
- typedef std::vector<Sector*> Sectors;
- Sectors sectors;
- Statistics stats;
+ Sectors sectors;
+ Statistics stats;
+ TileSet *tileset;
+ bool free_tileset;
public:
Level();
size_t get_sector_count();
Sector* get_sector(size_t num);
+ const TileSet *get_tileset() const
+ { return tileset; }
+
int get_total_coins();
int get_total_badguys();
#include "level.hpp"
#include "tile.hpp"
#include "resources.hpp"
-#include "tile_manager.hpp"
#include "lisp/lisp.hpp"
#include "lisp/list_iterator.hpp"
#include "lisp/writer.hpp"
#include "object_factory.hpp"
#include "main.hpp"
#include "log.hpp"
+#include "tile_set.hpp"
+#include "tile_manager.hpp"
#include "scripting/tilemap.hpp"
#include "scripting/squirrel_util.hpp"
-TileMap::TileMap()
- : tilemanager(0), solid(false), speed_x(1), speed_y(1), width(0), height(0), z_pos(0), x_offset(0), y_offset(0),
- drawing_effect(NO_EFFECT), alpha(1.0), current_alpha(1.0), remaining_fade_time(0),
+TileMap::TileMap(const TileSet *new_tileset)
+ : tileset(new_tileset), solid(false), speed_x(1), speed_y(1), width(0),
+ height(0), z_pos(0), x_offset(0), y_offset(0), drawing_effect(NO_EFFECT),
+ alpha(1.0), current_alpha(1.0), remaining_fade_time(0),
draw_target(DrawingContext::NORMAL)
{
}
TileMap::TileMap(const lisp::Lisp& reader)
- : tilemanager(0), solid(false), speed_x(1), speed_y(1), width(-1), height(-1), z_pos(0),
- x_offset(0), y_offset(0),
- drawing_effect(NO_EFFECT), alpha(1.0), current_alpha(1.0),
- remaining_fade_time(0),
+ : solid(false), speed_x(1), speed_y(1), width(-1),
+ height(-1), z_pos(0), x_offset(0), y_offset(0), drawing_effect(NO_EFFECT),
+ alpha(1.0), current_alpha(1.0), remaining_fade_time(0),
draw_target(DrawingContext::NORMAL)
{
- tilemanager = new TileManager();
+ tileset = current_tileset;
+ assert(tileset != NULL);
- reader.get("name", name);
- reader.get("z-pos", z_pos);
- reader.get("solid", solid);
- reader.get("speed", speed_x);
+ reader.get("name", name);
+ reader.get("z-pos", z_pos);
+ reader.get("solid", solid);
+ reader.get("speed", speed_x);
reader.get("speed-y", speed_y);
-
+
if(solid && ((speed_x != 1) || (speed_y != 1))) {
log_warning << "Speed of solid tilemap is not 1. fixing" << std::endl;
speed_x = 1;
if(width < 0 || height < 0)
throw std::runtime_error("Invalid/No width/height specified in tilemap.");
- const lisp::Lisp* tilesets_reader = reader.get_lisp("tilesets");
- if (tilesets_reader) {
- lisp::ListIterator iter(tilesets_reader);
- while(iter.next()) {
- const std::string& token = iter.item();
- if(token != "tileset") {
- log_warning << "Skipping unrecognized token \"" << token << "\" in tilemap's tilesets list" << std::endl;
- continue;
- }
- const lisp::Lisp* tileset_reader = iter.lisp();
- std::string file;
- unsigned int start = 0;
- unsigned int end = std::numeric_limits<unsigned int>::max();
- int offset = 0;
- if (!tileset_reader->get("file", file)) {
- log_warning << "Skipping tileset import without file name" << std::endl;
- continue;
- }
- tileset_reader->get("start", start);
- tileset_reader->get("end", end);
- tileset_reader->get("offset", offset);
- tilemanager->load_tileset(file, start, end, offset);
- }
- } else {
- log_warning << "No tilesets list in tilemap, loading default tiles" << std::endl;
- if (loading_worldmap) {
- tilemanager->load_tileset("images/worldmap.strf", 0, std::numeric_limits<unsigned int>::max(), 0);
- } else {
- tilemanager->load_tileset("images/tiles.strf", 0, std::numeric_limits<unsigned int>::max(), 0);
- }
- }
-
if(!reader.get_vector("tiles", tiles))
throw std::runtime_error("No tiles in tilemap.");
throw std::runtime_error("wrong number of tiles in tilemap.");
}
- // make sure all tiles are loaded
+ // make sure all tiles used on the tilemap are loaded
for(Tiles::iterator i = tiles.begin(); i != tiles.end(); ++i)
- tilemanager->get(*i);
+ tileset->get(*i);
}
-TileMap::TileMap(std::string name, int z_pos, bool solid, size_t width, size_t height)
- : tilemanager(0), solid(solid), speed_x(1), speed_y(1), width(0), height(0), z_pos(z_pos),
- x_offset(0), y_offset(0), drawing_effect(NO_EFFECT), alpha(1.0),
- current_alpha(1.0), remaining_fade_time(0),
- draw_target(DrawingContext::NORMAL)
+TileMap::TileMap(const TileSet *new_tileset, std::string name, int z_pos,
+ bool solid, size_t width, size_t height)
+ : tileset(new_tileset), solid(solid), speed_x(1), speed_y(1), width(0),
+ height(0), z_pos(z_pos), x_offset(0), y_offset(0),
+ drawing_effect(NO_EFFECT), alpha(1.0), current_alpha(1.0),
+ remaining_fade_time(0), draw_target(DrawingContext::NORMAL)
{
this->name = name;
TileMap::~TileMap()
{
- delete tilemanager;
}
void
for(pos.x = start_x, tx = tsx; pos.x < end_x; pos.x += 32, ++tx) {
for(pos.y = start_y, ty = tsy; pos.y < end_y; pos.y += 32, ++ty) {
if ((tx < 0) || (ty < 0)) continue;
- const Tile* tile = tilemanager->get(tiles[ty*width + tx]);
+ const Tile* tile = tileset->get(tiles[ty*width + tx]);
assert(tile != 0);
tile->draw(context, pos, z_pos);
}
// make sure all tiles are loaded
for(Tiles::iterator i = tiles.begin(); i != tiles.end(); ++i)
- tilemanager->get(*i);
+ tileset->get(*i);
}
void
this->solid = solid;
}
-const Tile*
-TileMap::get_tile(int x, int y) const
+uint32_t
+TileMap::get_tile_id(int x, int y) const
{
if(x < 0 || x >= width || y < 0 || y >= height) {
//log_warning << "tile outside tilemap requested" << std::endl;
- return tilemanager->get(0);
+ return 0;
}
- return tilemanager->get(tiles[y*width + x]);
+ return tiles[y*width + x];
+}
+
+
+const Tile*
+TileMap::get_tile(int x, int y) const
+{
+ uint32_t id = get_tile_id(x, y);
+ return tileset->get(id);
+}
+
+uint32_t
+TileMap::get_tile_id_at(const Vector& pos) const
+{
+ return get_tile_id(int(pos.x - x_offset)/32, int(pos.y - y_offset)/32);
}
const Tile*
TileMap::get_tile_at(const Vector& pos) const
{
- return get_tile(int(pos.x - x_offset)/32, int(pos.y - y_offset)/32);
+ uint32_t id = get_tile_id_at(pos);
+ return tileset->get(id);
}
void
void
TileMap::change_all(uint32_t oldtile, uint32_t newtile)
{
- for (size_t x = 0; x < get_width(); x++)
+ for (size_t x = 0; x < get_width(); x++) {
for (size_t y = 0; y < get_height(); y++) {
- if (get_tile(x,y)->getID() == oldtile) change(x,y,newtile);
+ if (get_tile_id(x,y) != oldtile)
+ continue;
+
+ change(x,y,newtile);
}
+ }
}
void
return this->current_alpha;
}
-bool TileMap::loading_worldmap; /**< FIXME: hack to make TileMap load default tileset if none was set */
-
IMPLEMENT_FACTORY(TileMap, "tilemap");
class Level;
class TileManager;
class Tile;
+class TileSet;
/**
* This class is reponsible for drawing the level tiles
class TileMap : public GameObject, public Serializable, public ScriptInterface
{
public:
- TileMap();
+ TileMap(const TileSet *tileset);
TileMap(const lisp::Lisp& reader);
- TileMap(std::string name, int z_pos, bool solid_, size_t width_, size_t height_);
+ TileMap(const TileSet *tileset, std::string name, int z_pos, bool solid_,
+ size_t width_, size_t height_);
virtual ~TileMap();
virtual void write(lisp::Writer& writer);
const Tile* get_tile(int x, int y) const;
/// returns tile at position pos (in world coordinates)
const Tile* get_tile_at(const Vector& pos) const;
+ /// returns tile in row y and column y (of the tilemap)
+ uint32_t get_tile_id(int x, int y) const;
+ /// returns tile at position pos (in world coordinates)
+ uint32_t get_tile_id_at(const Vector& pos) const;
void change(int x, int y, uint32_t newtile);
/// changes all tiles with the given ID
void change_all(uint32_t oldtile, uint32_t newtile);
- TileManager* get_tilemanager() const
- {
- return tilemanager;
- }
-
void set_drawing_effect(DrawingEffect effect)
{
drawing_effect = effect;
*/
float get_alpha();
- static bool loading_worldmap; /**< FIXME: hack to make TileMap load default tileset if none was set */
private:
+ const TileSet *tileset;
+
typedef std::vector<uint32_t> Tiles;
Tiles tiles;
-private:
- TileManager* tilemanager;
bool solid;
float speed_x;
float speed_y;
#include "gui/button.hpp"
#include "resources.hpp"
#include "file_system.hpp"
+#include "tile_manager.hpp"
#include "object/gameobjs.hpp"
#include "object/player.hpp"
Button::info_font = white_small_text;
+ tile_manager = new TileManager();
sprite_manager = new SpriteManager();
/* Tuxes: */
#include "script_interface.hpp"
#include "log.hpp"
#include "main.hpp"
+#include "level.hpp"
Sector* Sector::_current = 0;
void
Sector::parse(const lisp::Lisp& sector)
{
-
- TileMap::loading_worldmap = false;
-
bool has_background = false;
lisp::ListIterator iter(§or);
while(iter.next()) {
void
Sector::parse_old_format(const lisp::Lisp& reader)
{
-
- TileMap::loading_worldmap = false;
-
name = "main";
reader.get("gravity", gravity);
std::vector<unsigned int> tiles;
if(reader.get_vector("interactive-tm", tiles)
|| reader.get_vector("tilemap", tiles)) {
- TileMap* tilemap = new TileMap();
+ TileMap* tilemap = new TileMap(level->get_tileset());
tilemap->set(width, height, tiles, LAYER_TILES, true);
// replace tile id 112 (old invisible tile) with 1311 (new invisible tile)
for(size_t x=0; x < tilemap->get_width(); ++x) {
for(size_t y=0; y < tilemap->get_height(); ++y) {
- const Tile* tile = tilemap->get_tile(x, y);
- if(tile->getID() == 112) tilemap->change(x, y, 1311);
+ uint32_t id = tilemap->get_tile_id(x, y);
+ if(id == 112)
+ tilemap->change(x, y, 1311);
}
}
}
if(reader.get_vector("background-tm", tiles)) {
- TileMap* tilemap = new TileMap();
+ TileMap* tilemap = new TileMap(level->get_tileset());
tilemap->set(width, height, tiles, LAYER_BACKGROUNDTILES, false);
if (height < 19) tilemap->resize(width, 19);
add_object(tilemap);
}
if(reader.get_vector("foreground-tm", tiles)) {
- TileMap* tilemap = new TileMap();
+ TileMap* tilemap = new TileMap(level->get_tileset());
tilemap->set(width, height, tiles, LAYER_FOREGROUNDTILES, false);
// fill additional space in foreground with tiles of ID 2035 (lightmap/black)
TileMap* solids = *i;
for(size_t x=0; x < solids->get_width(); ++x) {
for(size_t y=0; y < solids->get_height(); ++y) {
- const Tile* tile = solids->get_tile(x, y);
+ uint32_t id = solids->get_tile_id(x, y);
+ const Tile *tile = solids->get_tile(x, y);
Vector pos(solids->get_x_offset() + x*32, solids->get_y_offset() + y*32);
- if(tile->getID() == 112) {
+ if(id == 112) {
add_object(new InvisibleBlock(pos));
solids->change(x, y, 0);
} else if(tile->getAttributes() & Tile::COIN) {
if (!tm) continue;
for(size_t x=0; x < tm->get_width(); ++x) {
for(size_t y=0; y < tm->get_height(); ++y) {
- const Tile* tile = tm->get_tile(x, y);
+ uint32_t id = tm->get_tile_id(x, y);
Vector pos(tm->get_x_offset() + x*32, tm->get_y_offset() + y*32);
Vector center(pos.x + 16, pos.y + 16);
// torch
- if (tile->getID() == 1517) {
+ if (id == 1517) {
float pseudo_rnd = (float)((int)pos.x % 10) / 10;
add_object(new PulsingLight(center, 1.0f + pseudo_rnd, 0.9f, 1.0f, Color(1.0f, 1.0f, 0.6f, 1.0f)));
}
// lava or lavaflow
- if ((tile->getID() == 173) || (tile->getID() == 1700) || (tile->getID() == 1705) || (tile->getID() == 1706)) {
+ if ((id == 173) || (id == 1700) || (id == 1705) || (id == 1706)) {
// space lights a bit
- if (((tm->get_tile(x-1, y)->getID() != tm->get_tile(x,y)->getID())
- && (tm->get_tile(x, y-1)->getID() != tm->get_tile(x,y)->getID()))
+ if (((tm->get_tile_id(x-1, y)) != tm->get_tile_id(x,y))
+ && (tm->get_tile_id(x, y-1) != tm->get_tile_id(x,y))
|| ((x % 3 == 0) && (y % 3 == 0))) {
float pseudo_rnd = (float)((int)pos.x % 10) / 10;
add_object(new PulsingLight(center, 1.0f + pseudo_rnd, 0.8f, 1.0f, Color(1.0f, 0.3f, 0.0f, 1.0f)));
#include "lisp/lisp.hpp"
#include "tile.hpp"
+#include "tile_set.hpp"
#include "resources.hpp"
#include "timer.hpp"
#include "math/vector.hpp"
#include "log.hpp"
-Tile::Tile()
- : id(0), attributes(0), data(0), anim_fps(1)
+Tile::Tile(const TileSet *new_tileset)
+ : tileset(new_tileset), attributes(0), data(0), anim_fps(1)
{
}
-Tile::Tile(unsigned int id, Uint32 attributes, const ImageSpec& imagespec)
- : id(id), attributes(attributes), data(0), anim_fps(1)
+Tile::Tile(const TileSet *new_tileset, Uint32 attributes, const ImageSpec& imagespec)
+ : tileset(new_tileset), attributes(attributes), data(0), anim_fps(1)
{
imagespecs.push_back(imagespec);
}
}
}
-void
+uint32_t
Tile::parse(const lisp::Lisp& reader)
{
+ uint32_t id;
if(!reader.get("id", id)) {
throw std::runtime_error("Missing tile-id.");
}
const lisp::Lisp* images = reader.get_lisp("images");
if(images)
parse_images(*images);
+
+ return id;
}
void
cur->get(file);
imagespecs.push_back(ImageSpec(file, Rect(0, 0, 0, 0)));
} else if(cur->get_type() == lisp::Lisp::TYPE_CONS &&
- cur->get_car()->get_type() == lisp::Lisp::TYPE_SYMBOL &&
+ cur->get_car()->get_type() == lisp::Lisp::TYPE_SYMBOL &&
cur->get_car()->get_symbol() == "region") {
const lisp::Lisp* ptr = cur->get_cdr();
}
void
-Tile::load_images(const std::string& tilesetpath)
+Tile::load_images()
{
+ const std::string& tiles_path = tileset->tiles_path;
+
assert(images.size() == 0);
for(std::vector<ImageSpec>::iterator i = imagespecs.begin(); i !=
imagespecs.end(); ++i) {
const ImageSpec& spec = *i;
Surface* surface;
- std::string file = tilesetpath + spec.file;
+ std::string file = tiles_path + spec.file;
if(spec.rect.get_width() <= 0) {
surface = new Surface(file);
} else {
namespace lisp { class Lisp; }
+class TileSet;
class DrawingContext;
/**
};
private:
- unsigned int id;
-
+ const TileSet *tileset;
std::vector<ImageSpec> imagespecs;
- std::vector<Surface*> images;
+ std::vector<Surface*> images;
/// tile attributes
uint32_t attributes;
/** Draw a tile on the screen */
void draw(DrawingContext& context, const Vector& pos, int z_pos) const;
- unsigned int getID() const
- { return id; }
-
uint32_t getAttributes() const
{ return attributes; }
}
protected:
- friend class TileManager;
- Tile();
- Tile(unsigned int id, Uint32 attributes, const ImageSpec& imagespec);
+ friend class TileSet;
+ Tile(const TileSet *tileset);
+ Tile(const TileSet *tileset, Uint32 attributes, const ImageSpec& imagespec);
- void load_images(const std::string& tilesetpath);
+ void load_images();
/// parses the tile and returns it's id number
- void parse(const lisp::Lisp& reader);
+ uint32_t parse(const lisp::Lisp& reader);
void parse_images(const lisp::Lisp& cur);
};
#include "lisp/parser.hpp"
#include "lisp/list_iterator.hpp"
#include "tile.hpp"
+#include "tile_set.hpp"
#include "tile_manager.hpp"
#include "resources.hpp"
+TileManager *tile_manager = NULL;
+TileSet *current_tileset = NULL;
+
TileManager::TileManager()
{
- tiles.resize(1, 0);
- tiles[0] = new Tile();
}
TileManager::~TileManager()
{
- for(Tiles::iterator i = tiles.begin(); i != tiles.end(); ++i)
- delete *i;
- tiles.clear();
}
-void TileManager::load_tileset(std::string filename, unsigned int start, unsigned int end, int offset)
+TileSet* TileManager::get_tileset(const std::string &filename)
{
+ TileSets::const_iterator i = tilesets.find(filename);
+ if(i != tilesets.end())
+ return i->second;
-#ifdef DEBUG
- Uint32 ticks = SDL_GetTicks();
-#endif
-
- std::string::size_type t = filename.rfind('/');
- if(t == std::string::npos) {
- tiles_path = "";
- } else {
- tiles_path = filename.substr(0, t+1);
- }
+ std::auto_ptr<TileSet> tileset (new TileSet(filename));
+ tilesets.insert(std::make_pair(filename, tileset.get()));
- lisp::Parser parser;
- const lisp::Lisp* root = parser.parse(filename);
+ return tileset.release();
+}
- const lisp::Lisp* tiles_lisp = root->get_lisp("supertux-tiles");
- if(!tiles_lisp)
- throw std::runtime_error("file is not a supertux tiles file.");
+TileSet* TileManager::parse_tileset_definition(const lisp::Lisp& reader)
+{
+ std::auto_ptr<TileSet> result(new TileSet());
- lisp::ListIterator iter(tiles_lisp);
+ lisp::ListIterator iter(&reader);
while(iter.next()) {
- if(iter.item() == "tile") {
- Tile* tile = new Tile();
- tile->parse(*(iter.lisp()));
-
- if ((tile->id < start) || (tile->id > end)) {
- delete tile;
- continue;
- }
- tile->id += offset;
-
- if(tile->id >= tiles.size())
- tiles.resize(tile->id+1, 0);
-
- if(tiles[tile->id] != 0) {
- log_warning << "Tile with ID " << tile->id << " redefined" << std::endl;
- delete tile;
- } else {
- tiles[tile->id] = tile;
- }
- } else if(iter.item() == "tilegroup") {
- TileGroup tilegroup;
- const lisp::Lisp* tilegroup_lisp = iter.lisp();
- tilegroup_lisp->get("name", tilegroup.name);
- tilegroup_lisp->get_vector("tiles", tilegroup.tiles);
- tilegroups.insert(tilegroup);
- } else if (iter.item() == "tiles") {
- // List of ids (use 0 if the tile should be ignored)
- std::vector<unsigned int> ids;
- // List of attributes of the tile
- std::vector<unsigned int> attributes;
- std::string image;
-
- // width and height of the image in tile units, this is used for two
- // purposes:
- // a) so we don't have to load the image here to know its dimensions
- // b) so that the resulting 'tiles' entry is more robust,
- // ie. enlarging the image won't break the tile id mapping
- // FIXME: height is actually not used, since width might be enough for
- // all purposes, still feels somewhat more natural this way
- unsigned int width = 0;
- unsigned int height = 0;
-
- iter.lisp()->get_vector("ids", ids);
- iter.lisp()->get_vector("attributes", attributes);
- iter.lisp()->get("image", image);
- iter.lisp()->get("width", width);
- iter.lisp()->get("height", height);
+ const std::string& token = iter.item();
+ if(token != "tileset") {
+ log_warning << "Skipping unrecognized token \"" << token << "\" in tileset definition" << std::endl;
+ continue;
+ }
+ const lisp::Lisp* tileset_reader = iter.lisp();
- if (ids.size() != attributes.size())
- {
- std::ostringstream err;
- err << "Number of ids (" << ids.size() << ") and attributes (" << attributes.size()
- << ") missmatch for image '" << image << "', but must be equal";
- throw std::runtime_error(err.str());
- }
+ std::string file;
+ if (!tileset_reader->get("file", file)) {
+ log_warning << "Skipping tileset import without file name" << std::endl;
+ continue;
+ }
- for(std::vector<unsigned int>::size_type i = 0; i < ids.size() && i < width*height; ++i)
- {
- if (ids[i])
- {
- if ((ids[i] < start) || (ids[i] > end)) {
- continue;
- }
- ids[i] += offset;
- if(ids[i] >= tiles.size())
- tiles.resize(ids[i]+1, 0);
+ const TileSet *tileset = get_tileset(file);
- int x = 32*(i % width);
- int y = 32*(i / width);
- Tile* tile = new Tile(ids[i], attributes[i], Tile::ImageSpec(image, Rect(x, y, x + 32, y + 32)));
- if (tiles[ids[i]] == 0) {
- tiles[ids[i]] = tile;
- } else {
- log_warning << "Tile with ID " << ids[i] << " redefined" << std::endl;
- delete tile;
- }
- }
- }
+ uint32_t start = 0;
+ uint32_t end = std::numeric_limits<uint32_t>::max();
+ uint32_t offset = 0;
+ tileset_reader->get("start", start);
+ tileset_reader->get("end", end);
+ tileset_reader->get("offset", offset);
- } else if(iter.item() == "properties") {
- // deprecated
- } else {
- log_warning << "Unknown symbol '" << iter.item() << "' tile defintion file" << std::endl;
- }
+ result->merge(tileset, start, end, offset);
}
- if (0)
- { // enable this if you want to see a list of free tiles
- log_info << "Last Tile ID is " << tiles.size()-1 << std::endl;
- int last = -1;
- for(int i = 0; i < int(tiles.size()); ++i)
- {
- if (tiles[i] == 0 && last == -1)
- {
- last = i;
- }
- else if (tiles[i] && last != -1)
- {
- log_info << "Free Tile IDs (" << i - last << "): " << last << " - " << i-1 << std::endl;
- last = -1;
- }
- }
- }
-
-#ifdef DEBUG
- log_debug << "Tiles loaded in " << (SDL_GetTicks() - ticks) / 1000.0 << " seconds" << std::endl;
-#endif
-
+ return result.release();
}
+
// $Id$
//
// SuperTux
-// Copyright (C) 2004 Tobias Glaesser <tobi.web@gmx.de>
-// Copyright (C) 2006 Matthias Braun <matze@braunis.de>
+// Copyright (C) 2008 Matthias Braun <matze@braunis.de>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms 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_TILE_MANAGER_HPP
+#define HEADER_TILE_MANAGER_HPP
-#ifndef HEADER_TILE_MANAGER_HXX
-#define HEADER_TILE_MANAGER_HXX
-
-#include <set>
#include <vector>
#include <string>
#include <map>
#include <stdint.h>
#include <assert.h>
#include "log.hpp"
-#include "tile.hpp"
-struct TileGroup
-{
- friend bool operator<(const TileGroup& lhs, const TileGroup& rhs)
- { return lhs.name < rhs.name; };
- friend bool operator>(const TileGroup& lhs, const TileGroup& rhs)
- { return lhs.name > rhs.name; };
+namespace lisp {
+class Lisp;
+}
- std::string name;
- std::vector<int> tiles;
-};
+class TileSet;
class TileManager
{
private:
- typedef std::vector<Tile*> Tiles;
- Tiles tiles;
-
- std::set<TileGroup> tilegroups;
-
- std::string tiles_path;
-
+ typedef std::map<std::string, TileSet*> TileSets;
+ TileSets tilesets;
public:
TileManager();
~TileManager();
- /**
- * Load tileset from "filename".
- * Import starts at the file's tile id "start", ends at tile id "end" with all loaded tile ids being offset by "offset"
- */
- void load_tileset(std::string filename, unsigned int start, unsigned int end, int offset);
-
- const std::set<TileGroup>& get_tilegroups() const
- {
- return tilegroups;
- }
+ TileSet* get_tileset(const std::string &filename);
- const Tile* get(uint32_t id) const
- {
- //FIXME: Commenting out tiles in sprites.strf makes tiles.size() fail - it's being set to the first tile commented out.
- assert(id < tiles.size());
- Tile* tile = tiles[id];
- if(!tile) {
- log_warning << "Invalid tile: " << id << std::endl;
- return tiles[0];
- }
-
- if(tile->images.size() == 0 && tile->imagespecs.size() != 0)
- tile->load_images(tiles_path);
-
- return tile;
- }
-
- uint32_t get_max_tileid() const
- {
- return tiles.size();
- }
-
- int get_default_width() const
- {
- return 32;
- }
-
- int get_default_height() const
- {
- return 32;
- }
+ TileSet* parse_tileset_definition(const lisp::Lisp& reader);
};
+extern TileManager *tile_manager;
+/** this is only set while loading a map */
+extern TileSet *current_tileset;
+
#endif
#include "sprite_change.hpp"
#include "control/joystickkeyboardcontroller.hpp"
#include "scripting/squirrel_util.hpp"
+#include "tile.hpp"
#include "main.hpp"
namespace WorldMapNS
#include "main.hpp"
#include "spawn_point.hpp"
#include "file_system.hpp"
+#include "tile_manager.hpp"
+#include "tile_set.hpp"
#include "gui/menu.hpp"
#include "gui/mousecursor.hpp"
#include "control/joystickkeyboardcontroller.hpp"
//---------------------------------------------------------------------------
WorldMap::WorldMap(const std::string& filename, const std::string& force_spawnpoint)
- : tux(0), ambient_light( 1.0f, 1.0f, 1.0f, 1.0f ), force_spawnpoint(force_spawnpoint), in_level(false)
+ : tux(0), tileset(NULL), free_tileset(false),
+ ambient_light( 1.0f, 1.0f, 1.0f, 1.0f ), force_spawnpoint(force_spawnpoint),
+ in_level(false)
{
- tile_manager.reset(new TileManager());
- //"images/worldmap.strf");
-
tux = new Tux(this);
add_object(tux);
{
using namespace Scripting;
+ if(free_tileset)
+ delete tileset;
+
for(GameObjects::iterator i = game_objects.begin();
i != game_objects.end(); ++i) {
GameObject* object = *i;
lisp::Parser parser;
const lisp::Lisp* root = parser.parse(map_filename);
- const lisp::Lisp* lisp = root->get_lisp("supertux-level");
- if(!lisp)
+ const lisp::Lisp* level = root->get_lisp("supertux-level");
+ if(level == NULL)
throw std::runtime_error("file isn't a supertux-level file.");
- lisp->get("name", name);
+ level->get("name", name);
- const lisp::Lisp* sector = lisp->get_lisp("sector");
+ const lisp::Lisp* sector = level->get_lisp("sector");
if(!sector)
throw std::runtime_error("No sector sepcified in worldmap file.");
+ const lisp::Lisp* tilesets_lisp = level->get_lisp("tilesets");
+ if(tilesets_lisp != NULL) {
+ tileset = tile_manager->parse_tileset_definition(*tilesets_lisp);
+ free_tileset = true;
+ }
+ std::string tileset_name;
+ if(level->get("tileset", tileset_name)) {
+ if(tileset != NULL) {
+ log_warning << "multiple tilesets specified in level" << std::endl;
+ } else {
+ tileset = tile_manager->get_tileset(tileset_name);
+ }
+ }
+ /* load default tileset */
+ if(tileset == NULL) {
+ tileset = tile_manager->get_tileset("images/worldmap.strf");
+ }
+ current_tileset = tileset;
+
lisp::ListIterator iter(sector);
while(iter.next()) {
if(iter.item() == "tilemap") {
-
- TileMap::loading_worldmap = true;
-
add_object(new TileMap(*(iter.lisp())));
} else if(iter.item() == "background") {
add_object(new Background(*(iter.lisp())));
log_warning << "Unknown token '" << iter.item() << "' in worldmap" << std::endl;
}
}
+ current_tileset = NULL;
+
if(solid_tilemaps.size() == 0)
throw std::runtime_error("No solid tilemap specified");
private:
Tux* tux;
+ TileSet *tileset;
+ bool free_tileset;
+
static WorldMap* current_;
std::auto_ptr<Menu> worldmap_menu;
GameObjects game_objects;
std::list<TileMap*> solid_tilemaps;
- std::auto_ptr<TileManager> tile_manager;
-
public:
/** Variables to deal with the passive map messages */
Timer passive_message_timer;